diff --git a/src/include/cpu/power/istep8.h b/src/include/cpu/power/istep8.h new file mode 100644 index 00000000000..09e94f7f29f --- /dev/null +++ b/src/include/cpu/power/istep8.h @@ -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 \ No newline at end of file diff --git a/src/soc/ibm/power9/Makefile.inc b/src/soc/ibm/power9/Makefile.inc index 2c8a363746c..6d60e535229 100644 --- a/src/soc/ibm/power9/Makefile.inc +++ b/src/soc/ibm/power9/Makefile.inc @@ -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 @@ -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 diff --git a/src/soc/ibm/power9/istep_8_6.c b/src/soc/ibm/power9/istep_8_6.c new file mode 100644 index 00000000000..5c45e7919ef --- /dev/null +++ b/src/soc/ibm/power9/istep_8_6.c @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +/* 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; + + /* 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 */ + + 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)) { + 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? */ +} diff --git a/src/soc/ibm/power9/romstage.c b/src/soc/ibm/power9/romstage.c index 91074b20125..2431869c811 100644 --- a/src/soc/ibm/power9/romstage.c +++ b/src/soc/ibm/power9/romstage.c @@ -4,4 +4,5 @@ asmlinkage void car_stage_entry(void) { + }