Skip to content

Commit 32bcd02

Browse files
istep 8.6 as powerbus.c (#82)
* soc/power9/mvpd.c: rename several variables Change-Id: If092c16bf39195c065fd979894ec02dd94a2f250 Signed-off-by: Sergii Dmytruk <[email protected]> * soc/power9/mvpd.c: extract mvpd_get_keyword() Change-Id: I22d4d380b878af1fa4bde4ceda79c970efad9093 Signed-off-by: Sergii Dmytruk <[email protected]> * soc/power9/mvpd.c: add mvpd_extract_keyword() Change-Id: I1a6dfa7fbd90bb9528b70d8f469c4a66f62697a1 Signed-off-by: Sergii Dmytruk <[email protected]> * soc/power9: implement istep 8.6 as powerbus.c Change-Id: I04b4a384fb0ea4bb4071ddd5f1ab3c6d1417363a Signed-off-by: Sergii Dmytruk <[email protected]> * soc/power9/istep_13_8.c: use powerbus.c unit Change-Id: I0efe478537ec03afe71677e3d64d7468cd552162 Signed-off-by: Sergii Dmytruk <[email protected]> * soc/power9/powerbus.c: assume EPS_TYPE_LE Change-Id: Ie9ba1aee13794218c8f71d52104cdcf9a4e7e365 Signed-off-by: Sergii Dmytruk <[email protected]> * soc/power9/mvpd.c: add mvpd_get_voltage_data() Change-Id: Ie7550e4158a7483a938c6fbe90abae77361c723b Signed-off-by: Sergii Dmytruk <[email protected]> * Review corrections Change-Id: I223bbfcb9dbdd43eff0b022a3d7968de06052b52 Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent 250fb36 commit 32bcd02

File tree

6 files changed

+464
-33
lines changed

6 files changed

+464
-33
lines changed

src/include/cpu/power/mvpd.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,44 @@
66
#include <stdbool.h>
77
#include <stdint.h>
88

9+
/* Single bucket within #V keyword of version 3 */
10+
struct voltage_data
11+
{
12+
uint16_t freq;
13+
uint16_t vdd_voltage;
14+
uint16_t idd_current;
15+
uint16_t vcs_voltage;
16+
uint16_t ics_current;
17+
} __attribute__((__packed__));
18+
19+
/* Single bucket within #V keyword of version 3 */
20+
struct voltage_bucket_data
21+
{
22+
uint8_t id;
23+
24+
struct voltage_data nominal;
25+
struct voltage_data powersave;
26+
struct voltage_data turbo;
27+
struct voltage_data ultra_turbo;
28+
struct voltage_data powerbus;
29+
30+
uint16_t sort_power_normal;
31+
uint16_t sort_power_turbo;
32+
33+
uint8_t reserved[6];
34+
} __attribute__((__packed__));
35+
36+
#define VOLTAGE_DATA_VERSION 3
37+
#define VOLTAGE_BUCKET_COUNT 6
38+
39+
/* #V of LRP[0-5] in MVPD */
40+
struct voltage_kwd
41+
{
42+
uint8_t version;
43+
uint8_t pnp[3];
44+
struct voltage_bucket_data buckets[VOLTAGE_BUCKET_COUNT];
45+
} __attribute__((__packed__));
46+
947
struct region_device;
1048

1149
void mvpd_pnor_main(void);
@@ -16,6 +54,15 @@ void mvpd_device_unmount(void);
1654

1755
const struct region_device *mvpd_device_ro(void);
1856

57+
/* Reads #V of one of LRP records (mind that there is only one buffer) */
58+
const struct voltage_kwd *mvpd_get_voltage_data(int lrp);
59+
60+
/* Finds a specific keyword in MVPD partition and extracts it. *size is updated
61+
* to reflect needed or used space in the buffer. */
62+
bool mvpd_extract_keyword(const char *record_name, const char *kwd_name,
63+
uint8_t *buf, uint32_t *size);
64+
65+
/* Finds a specific ring in MVPD partition and extracts it */
1966
bool mvpd_extract_ring(const char *record_name, const char *kwd_name,
2067
uint8_t chiplet_id, uint16_t ring_id, uint8_t *buf,
2168
uint32_t buf_size);

src/include/cpu/power/powerbus.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#ifndef CPU_PPC64_POWERBUS_H
4+
#define CPU_PPC64_POWERBUS_H
5+
6+
#include <stdint.h>
7+
8+
enum FABRIC_CORE_FLOOR_RATIO
9+
{
10+
FABRIC_CORE_FLOOR_RATIO_RATIO_8_8 = 0x0,
11+
FABRIC_CORE_FLOOR_RATIO_RATIO_7_8 = 0x1,
12+
FABRIC_CORE_FLOOR_RATIO_RATIO_6_8 = 0x2,
13+
FABRIC_CORE_FLOOR_RATIO_RATIO_5_8 = 0x3,
14+
FABRIC_CORE_FLOOR_RATIO_RATIO_4_8 = 0x4,
15+
FABRIC_CORE_FLOOR_RATIO_RATIO_2_8 = 0x5,
16+
};
17+
18+
enum FABRIC_CORE_CEILING_RATIO
19+
{
20+
FABRIC_CORE_CEILING_RATIO_RATIO_8_8 = 0x0,
21+
FABRIC_CORE_CEILING_RATIO_RATIO_7_8 = 0x1,
22+
FABRIC_CORE_CEILING_RATIO_RATIO_6_8 = 0x2,
23+
FABRIC_CORE_CEILING_RATIO_RATIO_5_8 = 0x3,
24+
FABRIC_CORE_CEILING_RATIO_RATIO_4_8 = 0x4,
25+
FABRIC_CORE_CEILING_RATIO_RATIO_2_8 = 0x5,
26+
};
27+
28+
#define NUM_EPSILON_READ_TIERS 3
29+
#define NUM_EPSILON_WRITE_TIERS 2
30+
31+
/* Description of PowerBus configuration */
32+
struct powerbus_cfg
33+
{
34+
/* Data computed from #V of LRP0 in MVPD, is MHz */
35+
uint32_t freq_core_floor;
36+
uint32_t freq_core_ceiling;
37+
uint32_t fabric_freq;
38+
39+
/* Derived from data above */
40+
enum FABRIC_CORE_FLOOR_RATIO core_floor_ratio;
41+
enum FABRIC_CORE_CEILING_RATIO core_ceiling_ratio;
42+
43+
/* Derived from all data above */
44+
/* ATTR_PROC_EPS_READ_CYCLES_T* */
45+
uint32_t eps_r[NUM_EPSILON_READ_TIERS];
46+
/* ATTR_PROC_EPS_WRITE_CYCLES_T* */
47+
uint32_t eps_w[NUM_EPSILON_WRITE_TIERS];
48+
};
49+
50+
const struct powerbus_cfg *powerbus_cfg(void);
51+
52+
#endif // CPU_PPC64_POWERBUS_H

src/soc/ibm/power9/Makefile.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ bootblock-y += bootblock.c
66
bootblock-y += rom_media.c
77
romstage-y += rom_media.c
88
romstage-y += romstage.c
9+
romstage-y += mvpd.c
910
romstage-y += vpd.c
11+
romstage-y += powerbus.c
1012
romstage-y += istep_13_2.c
1113
romstage-y += istep_13_3.c
1214
romstage-y += istep_13_4.c
@@ -31,5 +33,6 @@ ramstage-y += mvpd.c
3133
ramstage-y += vpd.c
3234
ramstage-y += tor.c
3335
ramstage-y += rs4.c
36+
ramstage-y += powerbus.c
3437

3538
endif

src/soc/ibm/power9/istep_13_8.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
/* SPDX-License-Identifier: GPL-2.0-only */
22

33
#include <cpu/power/istep_13.h>
4+
#include <cpu/power/powerbus.h>
45
#include <cpu/power/vpd_data.h>
56
#include <console/console.h>
67

78
#include "istep_13_scom.h"
89

910
#define ATTR_PG 0xE000000000000000ull
10-
#define FREQ_PB_MHZ 1866
1111

1212
/*
1313
* This function was generated from initfiles. Some of the registers used here
@@ -22,6 +22,8 @@
2222
*/
2323
static void p9n_mca_scom(int mcs_i, int mca_i)
2424
{
25+
const struct powerbus_cfg *pb_cfg = powerbus_cfg();
26+
2527
chiplet_id_t id = mcs_ids[mcs_i];
2628
mca_data_t *mca = &mem_data.mcs[mcs_i].mca[mca_i];
2729
const int mca_mul = 0x10;
@@ -108,10 +110,15 @@ static void p9n_mca_scom(int mcs_i, int mca_i)
108110
[32-39] = (ATTR_PROC_EPS_READ_CYCLES_T2 + 6) / 4 // REMOTE_NODAL_EPSILON
109111
[40-47] = (ATTR_PROC_EPS_READ_CYCLES_T2 + 6) / 4 // VECTOR_GROUP_EPSILON
110112
*/
113+
#define F(X) (((X) + 6) / 4)
111114
scom_and_or_for_chiplet(nest, 0x05010826 + mca_i * mca_mul, ~PPC_BITMASK(0,47),
112-
PPC_SHIFT(1, 7) /* FIXME: fill the rest with non-hardcoded values*/
113-
| PPC_SHIFT(4, 15) | PPC_SHIFT(4, 23) | PPC_SHIFT(4, 31)
114-
| PPC_SHIFT(0x19, 39) | PPC_SHIFT(0x19, 47));
115+
PPC_SHIFT(1, 7)
116+
| PPC_SHIFT(F(pb_cfg->eps_r[0]), 15)
117+
| PPC_SHIFT(F(pb_cfg->eps_r[1]), 23)
118+
| PPC_SHIFT(F(pb_cfg->eps_r[1]), 31)
119+
| PPC_SHIFT(F(pb_cfg->eps_r[2]), 39)
120+
| PPC_SHIFT(F(pb_cfg->eps_r[2]), 47));
121+
#undef F
115122
//~ static const uint32_t EPSILON_R_T0_LE[] = { 7, 7, 8, 8, 10, 22 }; // T0, T1
116123
//~ static const uint32_t EPSILON_R_T2_LE[] = { 67, 69, 71, 74, 79, 103 }; // T2
117124

@@ -468,9 +475,10 @@ static void p9n_mca_scom(int mcs_i, int mca_i)
468475
/*
469476
* From Hostboot:
470477
* l_def_mn_freq_ratio = 1000 * ATTR_MSS_FREQ / ATTR_FREQ_PB_MHZ;
471-
* ATTR_MSS_FREQ is in MT/s (sigh), ATTR_FREQ_PB_MHZ is 1866 MHz (from talos.xml).
478+
* ATTR_MSS_FREQ is in MT/s (sigh).
472479
*/
473-
uint64_t mn_freq_ratio = 1000 * mem_data.speed / FREQ_PB_MHZ;
480+
uint32_t pb_freq = pb_cfg->fabric_freq;
481+
uint64_t mn_freq_ratio = 1000 * mem_data.speed / pb_freq;
474482
uint64_t val_to_data = mn_freq_ratio < 915 ? 3 :
475483
mn_freq_ratio < 1150 ? 4 :
476484
mn_freq_ratio < 1300 ? 5 : 6;

src/soc/ibm/power9/mvpd.c

Lines changed: 104 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <cpu/power/mvpd.h>
44

5+
#include <assert.h>
56
#include <commonlib/region.h>
67
#include <console/console.h>
78
#include <cpu/power/vpd.h>
@@ -91,57 +92,133 @@ static struct ring_hdr *find_ring(uint8_t chiplet_id, uint16_t ring_id,
9192
return NULL;
9293
}
9394

94-
/* Finds a specific ring in MVPD partition and extracts it */
95-
bool mvpd_extract_ring(const char *record_name, const char *kwd_name,
96-
uint8_t chiplet_id, uint16_t ring_id, uint8_t *buf,
97-
uint32_t buf_size)
95+
static const uint8_t *mvpd_get_keyword(const char *record_name,
96+
const char *kwd_name,
97+
size_t *kwd_size, void **mmaped_data)
9898
{
99-
const struct region_device *mvpd_device;
99+
const struct region_device *mvpd_device = mvpd_device_ro();
100100

101101
uint8_t mvpd_buf[MVPD_TOC_SIZE];
102102
struct mvpd_toc_entry *mvpd_toc = (struct mvpd_toc_entry *)mvpd_buf;
103103

104-
struct mvpd_toc_entry *cp00 = NULL;
105-
uint16_t cp00_offset = 0;
106-
const uint8_t *cp00_data = NULL;
107-
uint16_t cp00_size = 0;
104+
struct mvpd_toc_entry *toc_entry = NULL;
105+
uint16_t record_offset = 0;
106+
uint8_t *record_data = NULL;
107+
uint16_t record_size = 0;
108108

109-
const uint8_t *rings = NULL;
110-
size_t rings_size = 0;
111-
112-
struct ring_hdr *ring = NULL;
113-
uint32_t ring_size = 0;
114-
115-
mvpd_device_init();
116-
mvpd_device = mvpd_device_ro();
109+
const uint8_t *kwd = NULL;
117110

118111
/* Copy all TOC at once */
119112
if (rdev_readat(mvpd_device, mvpd_buf, 0,
120113
sizeof(mvpd_buf)) != sizeof(mvpd_buf))
121114
die("Failed to read MVPD TOC!\n");
122115

123-
cp00 = find_record(mvpd_toc, record_name);
124-
if (cp00 == NULL)
116+
toc_entry = find_record(mvpd_toc, record_name);
117+
if (toc_entry == NULL)
125118
die("Failed to find %s MVPD record!\n", record_name);
126-
cp00_offset = le16toh(cp00->offset);
119+
record_offset = le16toh(toc_entry->offset);
127120

128121
/* Read size of the record */
129-
if (rdev_readat(mvpd_device, &cp00_size, cp00_offset,
130-
sizeof(cp00_size)) != sizeof(cp00_size))
122+
if (rdev_readat(mvpd_device, &record_size, record_offset,
123+
sizeof(record_size)) != sizeof(record_size))
131124
die("Failed to read size of %s!\n", record_name);
132125

133-
cp00_data = rdev_mmap(mvpd_device, cp00_offset, cp00_size);
134-
if (!cp00_data)
126+
record_data = rdev_mmap(mvpd_device, record_offset, record_size);
127+
if (!record_data)
135128
die("Failed to map %s record!\n", record_name);
136129

137-
rings = vpd_find_kwd(cp00_data, record_name, kwd_name, &rings_size);
130+
kwd = vpd_find_kwd(record_data, record_name, kwd_name, kwd_size);
131+
if (kwd == NULL)
132+
die("Failed to find %s keyword in %s!\n", kwd_name,
133+
record_name);
134+
135+
*mmaped_data = record_data;
136+
return kwd;
137+
}
138+
139+
bool mvpd_extract_keyword(const char *record_name, const char *kwd_name,
140+
uint8_t *buf, uint32_t *size)
141+
{
142+
void *mmaped_data = NULL;
143+
144+
const uint8_t *kwd = NULL;
145+
size_t kwd_size = 0;
146+
bool copied_data = false;
147+
148+
mvpd_device_init();
149+
150+
kwd = mvpd_get_keyword(record_name, kwd_name, &kwd_size, &mmaped_data);
151+
if (kwd == NULL)
152+
die("Failed to find %s keyword in %s!\n", kwd_name,
153+
record_name);
154+
155+
if (*size >= kwd_size) {
156+
memcpy(buf, kwd, kwd_size);
157+
copied_data = true;
158+
}
159+
160+
*size = kwd_size;
161+
162+
if (rdev_munmap(mvpd_device_ro(), mmaped_data))
163+
die("Failed to unmap %s record!\n", record_name);
164+
165+
return copied_data;
166+
}
167+
168+
const struct voltage_kwd *mvpd_get_voltage_data(int lrp)
169+
{
170+
static int inited_lrp = -1;
171+
static uint8_t buf[sizeof(struct voltage_kwd)];
172+
173+
char record_name[] = { 'L', 'R', 'P', '0' + lrp };
174+
uint32_t buf_size = sizeof(buf);
175+
struct voltage_kwd *voltage = (void *)buf;
176+
177+
assert(lrp >= 0 && lrp < 6);
178+
if (inited_lrp == lrp)
179+
return voltage;
180+
181+
inited_lrp = -1;
182+
183+
if (!mvpd_extract_keyword(record_name, "#V", buf, &buf_size)) {
184+
printk(BIOS_ERR, "Failed to read LRP0 record from MVPD\n");
185+
return NULL;
186+
}
187+
188+
if (voltage->version != VOLTAGE_DATA_VERSION) {
189+
printk(BIOS_ERR, "Only version %d of voltage data is supported, got: %d\n",
190+
VOLTAGE_DATA_VERSION, voltage->version);
191+
return NULL;
192+
}
193+
194+
inited_lrp = lrp;
195+
return voltage;
196+
}
197+
198+
/* Finds a specific ring in MVPD partition and extracts it */
199+
bool mvpd_extract_ring(const char *record_name, const char *kwd_name,
200+
uint8_t chiplet_id, uint16_t ring_id, uint8_t *buf,
201+
uint32_t buf_size)
202+
{
203+
void *mmaped_data = NULL;
204+
205+
const uint8_t *rings = NULL;
206+
size_t rings_size = 0;
207+
208+
struct ring_hdr *ring = NULL;
209+
uint32_t ring_size = 0;
210+
211+
mvpd_device_init();
212+
213+
rings = mvpd_get_keyword(record_name, kwd_name, &rings_size,
214+
&mmaped_data);
138215
if (rings == NULL)
139216
die("Failed to find %s keyword in %s!\n", kwd_name,
140217
record_name);
141218

142219
ring = find_ring(chiplet_id, ring_id, rings, rings_size);
143220
if (ring == NULL) {
144-
if (rdev_munmap(mvpd_device, (void *)cp00_data))
221+
if (rdev_munmap(mvpd_device_ro(), mmaped_data))
145222
die("Failed to unmap %s record!\n", record_name);
146223

147224
return false;
@@ -151,7 +228,7 @@ bool mvpd_extract_ring(const char *record_name, const char *kwd_name,
151228
if (buf_size >= ring_size)
152229
memcpy(buf, ring, ring_size);
153230

154-
if (rdev_munmap(mvpd_device, (void *)cp00_data))
231+
if (rdev_munmap(mvpd_device_ro(), mmaped_data))
155232
die("Failed to unmap %s record!\n", record_name);
156233

157234
return (buf_size >= ring_size);

0 commit comments

Comments
 (0)