Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/include/cpu/power/istep8.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef SOC_ISTEP8_H
#define SOC_ISTEP8_H

enum FABRIC_ASYNC_MODE
{
FABRIC_ASYNC_PERFORMANCE_MODE = 0x0,
FABRIC_ASYNC_SAFE_MODE = 0x1,
};

enum FABRIC_CORE_FLOOR_RATIO
{
FABRIC_CORE_FLOOR_RATIO_RATIO_8_8 = 0x0,
FABRIC_CORE_FLOOR_RATIO_RATIO_7_8 = 0x1,
FABRIC_CORE_FLOOR_RATIO_RATIO_6_8 = 0x2,
FABRIC_CORE_FLOOR_RATIO_RATIO_5_8 = 0x3,
FABRIC_CORE_FLOOR_RATIO_RATIO_4_8 = 0x4,
FABRIC_CORE_FLOOR_RATIO_RATIO_2_8 = 0x5,
};

enum FABRIC_CORE_CEILING_RATIO
{
FABRIC_CORE_CEILING_RATIO_RATIO_8_8 = 0x0,
FABRIC_CORE_CEILING_RATIO_RATIO_7_8 = 0x1,
FABRIC_CORE_CEILING_RATIO_RATIO_6_8 = 0x2,
FABRIC_CORE_CEILING_RATIO_RATIO_5_8 = 0x3,
FABRIC_CORE_CEILING_RATIO_RATIO_4_8 = 0x4,
FABRIC_CORE_CEILING_RATIO_RATIO_2_8 = 0x5,
};

#define EPSILON_MIN_VALUE 0x1;
#define EPSILON_MAX_VALUE 0xFFFFFFFF;

#define NUM_EPSILON_READ_TIERS 3;
#define NUM_EPSILON_WRITE_TIERS 2;

#define CHIP_IS_NODE 0x01
#define CHIP_IS_GROUP 0x02

/* From src/import/chips/p9/procedures/xml/attribute_info/nest_attributes.xml */
#define EPS_TYPE_LE 0x01
#define EPS_TYPE_HE 0x02
#define EPS_TYPE_HE_F8 0x03

#endif
3 changes: 3 additions & 0 deletions src/soc/ibm/power9/Makefile.inc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ ifeq ($(CONFIG_CPU_IBM_POWER9),y)

bootblock-y += bootblock.c
postcar-y += exit_car.S
romstage-y += romstage.c
romstage-y += istep_8_6.c
romstage-y += istep_13_2.c
romstage-y += istep_13_3.c
romstage-y += istep_13_4.c
Expand All @@ -20,6 +22,7 @@ romstage-y += istep_14_5.c
romstage-y += i2c.c
romstage-y += ccs.c


ramstage-y += chip.c
ramstage-y += timer.c

Expand Down
280 changes: 280 additions & 0 deletions src/soc/ibm/power9/istep_8_6.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stdint.h>
#include <console/console.h>
#include <soc/istep8.h>

/* From src/import/chips/p9/procedures/hwp/nest/p9_fbc_eff_config.C */
/* LE epsilon (2 chips per-group) */
static const uint32_t EPSILON_R_T0_LE[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T1_LE[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T2_LE[] = { 67, 69, 71, 74, 79, 103 };
static const uint32_t EPSILON_W_T0_LE[] = { 0, 0, 0, 0, 0, 5 };
static const uint32_t EPSILON_W_T1_LE[] = { 15, 16, 17, 19, 21, 33 };

/* HE epsilon (4 chips per-group) */
static const uint32_t EPSILON_R_T0_HE[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T1_HE[] = { 92, 94, 96, 99, 104, 128 };
static const uint32_t EPSILON_R_T2_HE[] = { 209, 210, 213, 216, 221, 245 };
static const uint32_t EPSILON_W_T0_HE[] = { 28, 29, 30, 32, 34, 46 };
static const uint32_t EPSILON_W_T1_HE[] = { 117, 118, 119, 121, 123, 135 };

/* HE epsilon (flat 4 Zeppelin) */
static const uint32_t EPSILON_R_T0_F4[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T1_F4[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T2_F4[] = { 83, 84, 87, 90, 95, 119 };
static const uint32_t EPSILON_W_T0_F4[] = { 0, 0, 0, 0, 0, 5 };
static const uint32_t EPSILON_W_T1_F4[] = { 18, 19, 20, 22, 24, 36 };

/* HE epsilon (flat 8 configuration) */
static const uint32_t EPSILON_R_T0_F8[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T1_F8[] = { 7, 7, 8, 8, 10, 22 };
static const uint32_t EPSILON_R_T2_F8[] = { 148, 149, 152, 155, 160, 184 };
static const uint32_t EPSILON_W_T0_F8[] = { 0, 0, 0, 0, 0, 5 };
static const uint32_t EPSILON_W_T1_F8[] = { 76, 77, 78, 80, 82, 94 };


/* Keep them global and later we can use function to retrieve the values set here */

uint32_t eps_r[NUM_EPSILON_READ_TIERS];
uint32_t eps_w[NUM_EPSILON_WRITE_TIERS];
int8_t eps_guardband;
uint8_t core_floor_ratio;
uint8_t core_ceiling_ratio;
uint32_t freq_fbc;
uint32_t freq_core_ceiling;

static int p9_calculate_frequencies(uint8_t *floor_ratio, uint8_t *ceiling_ratio,
uint32_t *fbc_freq, uint32_t *freq_ceiling)
{
/* Default 4800 from src/usr/targeting/common/xmltohb/hb_customized_attrs.xml */
uint32_t freq_core_floor = 4800;
/* According to src/usr/targeting/common/xmltohb/attribute_types.xml
ATTR_FREQ_CORE_NOMINAL_MHZ maps to NOMINAL_FREQ_MHZ present in talos.xml */
uint32_t freq_core_nom = 4800;
uint8_t async_safe_mode = FABRIC_ASYNC_PERFORMANCE_MODE;
*freq_ceiling = 4800;
Comment on lines +51 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/3mdeb/openpower-coreboot-docs/blob/main/logs/scom_dumps/istep_6_12_host_voltage_config.log#L40 and surrounding lines. Obviously the default values are not the same as actual.


/* breakpoint ratio: core floor 4.0, pb 2.0 (cache floor :: pb = 8/8) */
if ((freq_core_floor) >= (2 * (*fbc_freq))) {
*floor_ratio = FABRIC_CORE_FLOOR_RATIO_RATIO_8_8;
}
/* breakpoint ratio: core floor 3.5, pb 2.0 (cache floor :: pb = 7/8) */
else if ((4 * freq_core_floor) >= (7 * (*fbc_freq))) {
*floor_ratio = FABRIC_CORE_FLOOR_RATIO_RATIO_7_8;
}
/* breakpoint ratio: core floor 3.0, pb 2.0 (cache floor :: pb = 6/8) */
else if ((2 * freq_core_floor) >= (3 * (*fbc_freq))) {
*floor_ratio = FABRIC_CORE_FLOOR_RATIO_RATIO_6_8;
}
/* breakpoint ratio: core floor 2.5, pb 2.0 (cache floor :: pb = 5/8) */
else if ((4 * freq_core_floor) >= (5 * (*fbc_freq))) {
*floor_ratio = FABRIC_CORE_FLOOR_RATIO_RATIO_5_8;
}
/* breakpoint ratio: core floor 2.0, pb 2.0 (cache floor :: pb = 4/8) */
else if (freq_core_floor >= (*fbc_freq)) {
*floor_ratio = FABRIC_CORE_FLOOR_RATIO_RATIO_4_8;
}
/* breakpoint ratio: core floor 1.0, pb 2.0 (cache floor :: pb = 2/8) */
else if ((2 * freq_core_floor) >= (*fbc_freq)) {
*floor_ratio = FABRIC_CORE_FLOOR_RATIO_RATIO_2_8;
}
else {
printk (BIOS_ERR, "Unsupported core ceiling/PB frequency ratio = (%d/%d)",
freq_core_floor, *fbc_freq);
return -1;
}

/* breakpoint ratio: core ceiling 4.0, pb 2.0 (cache ceiling :: pb = 8/8) */
if (*freq_ceiling >= (2 * (*fbc_freq))) {
*ceiling_ratio = FABRIC_CORE_CEILING_RATIO_RATIO_8_8;
}
/* breakpoint ratio: core ceiling 3.5, pb 2.0 (cache ceiling :: pb = 7/8) */
else if ((4 * (*freq_ceiling)) >= (7 * (*fbc_freq))) {
*ceiling_ratio = FABRIC_CORE_CEILING_RATIO_RATIO_7_8;
}
/* breakpoint ratio: core ceiling 3.0, pb 2.0 (cache ceiling :: pb = 6/8) */
else if ((2 * (*freq_ceiling)) >= (3 * (*fbc_freq))) {
*ceiling_ratio = FABRIC_CORE_CEILING_RATIO_RATIO_6_8;
}
/* breakpoint ratio: core ceiling 2.5, pb 2.0 (cache ceiling :: pb = 5/8) */
else if ((4 * (*freq_ceiling)) >= (5 * (*fbc_freq))) {
*ceiling_ratio = FABRIC_CORE_CEILING_RATIO_RATIO_5_8;
}
/* breakpoint ratio: core ceiling 2.0, pb 2.0 (cache ceiling :: pb = 4/8) */
else if ((*freq_ceiling) >= (*fbc_freq)) {
*ceiling_ratio = FABRIC_CORE_CEILING_RATIO_RATIO_4_8;
}
/* breakpoint ratio: core ceiling 1.0, pb 2.0 (cache ceiling :: pb = 2/8) */
else if ((2 * (*freq_ceiling)) >= (*fbc_freq)) {
*ceiling_ratio = FABRIC_CORE_CEILING_RATIO_RATIO_2_8;
}
else {
printk (BIOS_ERR, "Unsupported core ceiling/PB frequency ratio = (%d/%d)",
*freq_ceiling, *fbc_freq);
return -1;
}

return 0;
}

static void config_guardband_epsilon(const uint8_t gb_percentage, uint32_t *target_value)
{
uint32_t delta = (*target_value * gb_percentage) / 100;
delta += ((*target_value * gb_percentage) % 100) ? 1 : 0;

printk(BIOS_DEBUG, "%s\n", __func__);

/* Apply guardband */
if (gb_percentage >= 0)
{
/* Clamp to maximum value if necessary */
if (delta > (EPSILON_MAX_VALUE - target_value)) {
printk(BIOS_DEBUG, "Guardband application generated out-of-range target value,"
" clamping to maximum value!\n");
*target_value = EPSILON_MAX_VALUE;
} else {
*target_value += delta;
}
}
else
{
/* Clamp to minimum value if necessary */
if (delta >= *target_value) {
printk(BIOS_DEBUG, "Guardband application generated out-of-range target value,"
" clamping to minimum value!\n");
*target_value = EPSILON_MIN_VALUE;
} else {
*target_value -= delta;
}
}

}

static void dump_epsilons(void)
{
uint32_t i;

for (i = 0; i < NUM_EPSILON_READ_TIERS; i++)
{
printk(BIOS_DEBUG, " R_T[%d] = %d\n", i, eps_r[i]);
}

for (i = 0; i < NUM_EPSILON_WRITE_TIERS; i++)
{
printk(BIOS_DEBUG, " W_T[%d] = %d\n", i, eps_w[i]);
}
}

static int p9_calculate_epsilons(uint8_t *floor_ratio, uint8_t *ceiling_ratio,
uint32_t *fbc_freq, uint32_t *freq_ceiling)
{
uint8_t eps_table_type = EPS_TYPE_LE; /* ATTR_PROC_EPS_TABLE_TYPE from talos.xml */
uint32_t i;

/* Processor SMP Fabric broadcast scope configuration.
* CHIP_IS_NODE = MODE1 = default
* CHIP_IS_GROUP = MODE2
*/
uint8_t pump_mode = CHIP_IS_GROUP; /* ATTR_PROC_FABRIC_PUMP_MODE MODE2 from talos.xml */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be read from here: https://github.com/open-power/hostboot/blob/master/src/include/usr/initservice/mboxRegs.H#L163
Value from talos.xml is written by SBE, but it may change for different platforms or even different versions of SBE.


switch(eps_table_type)
{
case EPS_TYPE_HE:
if (pump_mode == CHIP_IS_NODE) {
eps_r[0] = EPSILON_R_T0_HE[*floor_ratio];
eps_r[1] = EPSILON_R_T1_HE[*floor_ratio];
eps_r[2] = EPSILON_R_T2_HE[*floor_ratio];

eps_w[0] = EPSILON_W_T0_HE[*floor_ratio];
eps_w[1] = EPSILON_W_T1_HE[*floor_ratio];
} else {
eps_r[0] = EPSILON_R_T0_F4[*floor_ratio];
eps_r[1] = EPSILON_R_T1_F4[*floor_ratio];
eps_r[2] = EPSILON_R_T2_F4[*floor_ratio];

eps_w[0] = EPSILON_W_T0_F4[*floor_ratio];
eps_w[1] = EPSILON_W_T1_F4[*floor_ratio];
}

break;
case EPS_TYPE_HE_F8:
eps_r[0] = EPSILON_R_T0_F8[*floor_ratio];

if (pump_mode == CHIP_IS_NODE)
eps_r[1] = EPSILON_R_T1_F8[*floor_ratio];
else
eps_r[1] = EPSILON_R_T0_F8[*floor_ratio];

eps_r[2] = EPSILON_R_T2_F8[*floor_ratio];

eps_w[0] = EPSILON_W_T0_F8[*floor_ratio];
eps_w[1] = EPSILON_W_T1_F8[*floor_ratio];
break;
case EPS_TYPE_LE:
eps_r[0] = EPSILON_R_T0_LE[*floor_ratio];

if (pump_mode == CHIP_IS_NODE)
eps_r[1] = EPSILON_R_T1_LE[*floor_ratio];
else
eps_r[1] = EPSILON_R_T0_LE[*floor_ratio];

eps_r[2] = EPSILON_R_T2_LE[*floor_ratio];

eps_w[0] = EPSILON_W_T0_LE[*floor_ratio];
eps_w[1] = EPSILON_W_T1_LE[*floor_ratio];
break;
default:
printk(BIOS_WARNING, "Invalid epsilon table type 0x%.8X", eps_table_type);
break;
}

/* dump base epsilon values */
printk(BIOS_DEBUG, "Base epsilon values read from table:\n");
dump_eplisons();

eps_guardband = 20;

/* scale base epsilon values if core is running 2x nest frequency */
if (*ceiling_ratio == FABRIC_CORE_CEILING_RATIO_RATIO_8_8)
{
printk(BIOS_DEBUG, "Scaling based on ceiling frequency");
uint8_t scale_percentage = 100 * (*freq_ceiling) / (2 * (*fbc_freq));
scale_percentage -= 100;

/* scale/apply guardband read epsilons */
for (i = 0; i < NUM_EPSILON_READ_TIERS; i++)
config_guardband_epsilon(scale_percentage, &eps_r[i]);

/* Scale write epsilons */
for (i = 0; i < NUM_EPSILON_WRITE_TIERS; i++)
config_guardband_epsilon(scale_percentage, &eps_w[i]);
}

printk(BIOS_DEBUG, "Scaled epsilon values based on %s%d percent guardband:\n",
(eps_guardband >= 0) ? ("+") : ("-"), eps_guardband);
dump_eplisons();

/*
* check relationship of epsilon counters:
* read tier values are strictly increasing
* write tier values are strictly increaing
*/
if ((eps_r[0] > eps_r[1]) || (eps_r[1] > eps_r[2]) || (eps_w[0] > eps_w[1]))
printk(BIOS_WARNING, "Invalid relationship between base epsilon values\n");
}

void configure_powerbus_link (void)
{

if (!p9_calculate_frequencies(&core_floor_ratio, &core_ceiling_ratio,
&freq_fbc, &freq_core_ceiling)) {
Comment on lines +270 to +271

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

freq_fbc is uninitialized here, it is later compared in p9_calculate_frequencies() and never written to.

die("Incorrect core or PowerBus frequency");
}

p9_calculate_epsilons(&core_floor_ratio, &core_ceiling_ratio,
&freq_fbc, &freq_core_ceiling);

/* Do we need to create variables for the fabric link activity and
disable them as in p9_fbc_eff_config_reset_attrs? */
}
1 change: 1 addition & 0 deletions src/soc/ibm/power9/romstage.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

asmlinkage void car_stage_entry(void)
{

}