From bc79906cffb48dad96aa28c4ff3aa9a98b36de09 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Oct 2021 00:32:32 +0300 Subject: [PATCH 01/16] Start with PCI initialization Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/Makefile.inc | 1 + src/soc/ibm/power9/chip.c | 3 + src/soc/ibm/power9/pci.c | 243 ++++++++++++++++++++++++++++++++ src/soc/ibm/power9/pci.h | 8 ++ 4 files changed, 255 insertions(+) create mode 100644 src/soc/ibm/power9/pci.c create mode 100644 src/soc/ibm/power9/pci.h diff --git a/src/soc/ibm/power9/Makefile.inc b/src/soc/ibm/power9/Makefile.inc index 09160bc6ea0..962f6b59aab 100644 --- a/src/soc/ibm/power9/Makefile.inc +++ b/src/soc/ibm/power9/Makefile.inc @@ -39,6 +39,7 @@ ramstage-y += tor.c ramstage-y += rs4.c ramstage-y += powerbus.c ramstage-y += pstates.c +ramstage-y += pci.c ramstage-y += xive.c ramstage-y += int_vectors.S ramstage-y += i2c.c diff --git a/src/soc/ibm/power9/chip.c b/src/soc/ibm/power9/chip.c index eb0c89dc16b..6772cfabb14 100644 --- a/src/soc/ibm/power9/chip.c +++ b/src/soc/ibm/power9/chip.c @@ -14,6 +14,7 @@ #include "istep_13_scom.h" #include "chip.h" #include "homer.h" +#include "pci.h" /* * These are various definitions of the page sizes and segment sizes supported @@ -520,6 +521,8 @@ static void enable_soc_dev(struct device *dev) rng_init(); istep_18_11(); istep_18_12(); + + pci_init(); } /* diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/pci.c new file mode 100644 index 00000000000..ab4d604c7f8 --- /dev/null +++ b/src/soc/ibm/power9/pci.c @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "pci.h" + +#include +#include +#include +#include + +#define MAX_PEC_PER_PROC 3 +#define MAX_PHB_PER_PROC 6 + +#define MAX_LANE_GROUPS_PER_PEC 4 + +/* Enum indicating lane width (units = "number of lanes") */ +enum lane_width { + LANE_WIDTH_NC = 0, + LANE_WIDTH_4X = 4, + LANE_WIDTH_8X = 8, + LANE_WIDTH_16X = 16 +}; + +enum lane_mask { + LANE_MASK_X16 = 0xFFFF, + LANE_MASK_X8_GRP0 = 0xFF00, + LANE_MASK_X8_GRP1 = 0x00FF, + LANE_MASK_X4_GRP0 = 0x00F0, + LANE_MASK_X4_GRP1 = 0x000F, +}; + +/* Enumeration of PHB to PCI MAC mappings */ +enum phb_to_mac { + PHB_X16_MAC_MAP = 0x0000, + PHB_X8_X8_MAC_MAP = 0x0050, + PHB_X8_X4_X4_MAC_MAP = 0x0090, +}; + +/* Enum giving bitmask values for enabled PHBs */ +enum phb_active_mask { + PHB_MASK_NA = 0x00, // Sentinel mask (loop terminations) + PHB0_MASK = 0x80, // PHB0 enabled + PHB1_MASK = 0x40, // PHB1 enabled + PHB2_MASK = 0x20, // PHB2 enabled + PHB3_MASK = 0x10, // PHB3 enabled + PHB4_MASK = 0x08, // PHB4 enabled + PHB5_MASK = 0x04, // PHB5 enabled +}; + +/* + * Struct for each row in PCIE IOP configuration table. + * Used by code to compute the IOP config and PHBs active mask. + */ +struct lane_config_row { + /* + * Grouping of lanes under one IOP. + * Value signifies width of each PCIE lane set (0, 4, 8, or 16). + */ + // enum lane_width + uint8_t lane_set[MAX_LANE_GROUPS_PER_PEC]; + + /* IOP config value from PCIE IOP configuration table */ + uint8_t lane_config; + + /* + * PHB active mask (see phb_active_mask enum) + * PHB0 = 0x80 + * PHB1 = 0x40 + * PHB2 = 0x20 + * PHB3 = 0x10 + * PHB4 = 0x08 + * PHB5 = 0x04 + */ + // enum phb_active_mask + uint8_t phb_active; + + // enum phb_to_mac + uint16_t phb_to_pcie_mac; +}; + +/* + * Currently there are three PEC config tables for procs with 48 usable PCIE + * lanes. In general, the code accumulates the current configuration of + * the PECs from the MRW and other dynamic information(such as bifurcation) + * then matches that config to one of the rows in the table. Once a match + * is discovered, the PEC config value is pulled from the matching row and + * set in the attributes. + * + * Each PEC can control up to 16 lanes: + * - PEC0 can give 16 lanes to PHB0 + * - PEC1 can split 16 lanes between PHB1 & PHB2 + * - PEC2 can split 16 lanes between PHB3, PHB4 & PHB5 + */ +static const struct lane_config_row pec0_lane_cfg[] = { + { + { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB_MASK_NA, + PHB_X16_MAC_MAP + }, + { + { LANE_WIDTH_16X, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB0_MASK, + PHB_X16_MAC_MAP + }, +}; +static const struct lane_config_row pec1_lane_cfg[] = { + { + { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB_MASK_NA, + PHB_X8_X8_MAC_MAP + }, + { + { LANE_WIDTH_8X, LANE_WIDTH_NC, LANE_WIDTH_8X, LANE_WIDTH_NC }, + 0x00, + PHB1_MASK | PHB2_MASK, + PHB_X8_X8_MAC_MAP + }, + { + { LANE_WIDTH_8X, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB1_MASK, + PHB_X8_X8_MAC_MAP + }, + { + { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_8X, LANE_WIDTH_NC }, + 0x00, + PHB2_MASK, + PHB_X8_X8_MAC_MAP + }, +}; +static const struct lane_config_row pec2_lane_cfg[] = { + { + { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB_MASK_NA, + PHB_X16_MAC_MAP + }, + { + { LANE_WIDTH_16X, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB3_MASK, + PHB_X16_MAC_MAP + }, + { + { LANE_WIDTH_8X, LANE_WIDTH_NC, LANE_WIDTH_8X, LANE_WIDTH_NC }, + 0x10, + PHB3_MASK | PHB4_MASK, + PHB_X8_X8_MAC_MAP + }, + { + { LANE_WIDTH_8X, LANE_WIDTH_NC, LANE_WIDTH_4X, LANE_WIDTH_4X }, + 0x20, + PHB3_MASK | PHB4_MASK | PHB5_MASK, + PHB_X8_X4_X4_MAC_MAP + }, +}; + +static const struct lane_config_row *pec_lane_cfgs[] = { + pec0_lane_cfg, + pec1_lane_cfg, + pec2_lane_cfg +}; +static const size_t pec_lane_cfg_sizes[] = { + ARRAY_SIZE(pec0_lane_cfg), + ARRAY_SIZE(pec1_lane_cfg), + ARRAY_SIZE(pec2_lane_cfg) +}; + +// TODO: find (possibly dynamic) source of these values +// enum lane_width +static uint16_t lane_masks[MAX_PEC_PER_PROC][MAX_LANE_GROUPS_PER_PEC] = { + { LANE_MASK_X16, 0x0, 0x0, 0x0 }, + { LANE_MASK_X8_GRP0, 0x0, LANE_MASK_X8_GRP1, 0x0 }, + { LANE_MASK_X8_GRP0, 0x0, LANE_MASK_X4_GRP0, LANE_MASK_X4_GRP1 }, +}; + +static enum lane_width lane_mask_to_width(uint16_t mask) +{ + enum lane_width width = LANE_WIDTH_NC; + + if (mask == LANE_MASK_X16) + width = LANE_WIDTH_16X; + else if (mask == LANE_MASK_X8_GRP0 || mask == LANE_MASK_X8_GRP1) + width = LANE_WIDTH_8X; + else if (mask == LANE_MASK_X4_GRP0 || mask == LANE_MASK_X4_GRP1) + width = LANE_WIDTH_4X; + else + die("Invalid value for lane mask: 0x%04x\n", mask); + + return width; +} + +void pci_init(void) +{ + uint8_t pec; + + uint8_t phb_active_mask = 0; + + const struct lane_config_row *pec_cfgs[3] = { NULL }; + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + uint8_t i; + uint8_t lane_group; + + // enum lane_width + uint16_t lane_mask[MAX_LANE_GROUPS_PER_PEC]; + memcpy(&lane_mask, &lane_masks[pec], sizeof(lane_mask)); + + struct lane_config_row config = { + { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB_MASK_NA, + PHB_X16_MAC_MAP, + }; + + /* Transform effective config to match lane config table format */ + for (lane_group = 0; lane_group < MAX_LANE_GROUPS_PER_PEC; ++lane_group) + config.lane_set[lane_group] = lane_mask_to_width(lane_mask[lane_group]); + + for (i = 0; i < pec_lane_cfg_sizes[pec]; ++i) { + if (memcmp(pec_lane_cfgs[pec][i].lane_set, &config.lane_set, + sizeof(config.lane_set)) == 0) + break; + } + + if (i == pec_lane_cfg_sizes[pec]) + die("Failed to find PCIE IOP configuration for PEC%d\n", pec); + + phb_active_mask |= pec_lane_cfgs[pec][i].phb_active; + + pec_cfgs[pec] = &pec_lane_cfgs[pec][i]; + + // PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_lane_cfgs[pec][i].lane_config + // PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 + // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_lane_cfgs[pec][i].phb_to_pcie_mac + } + + // foreach PEC[ATTR_PROC_PCIE_IOVALID_ENABLE] := mask of functional PHBs + + // ATTR_PROC_PCIE_PHB_ACTIVE := phb_active_mask +} diff --git a/src/soc/ibm/power9/pci.h b/src/soc/ibm/power9/pci.h new file mode 100644 index 00000000000..ff67298d1e6 --- /dev/null +++ b/src/soc/ibm/power9/pci.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_IBM_POWER9_HOMER_H +#define __SOC_IBM_POWER9_HOMER_H + +void pci_init(void); + +#endif /* __SOC_IBM_POWER9_HOMER_H */ From e5fe391ce47bbe442d53c0ac8b3cf5b42023baac Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 10 Oct 2021 00:33:00 +0300 Subject: [PATCH 02/16] Phase 1 of initialization Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/pci.c | 360 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 356 insertions(+), 4 deletions(-) diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/pci.c index ab4d604c7f8..d8643d2fd2a 100644 --- a/src/soc/ibm/power9/pci.c +++ b/src/soc/ibm/power9/pci.c @@ -4,14 +4,18 @@ #include #include +#include #include #include +#include #define MAX_PEC_PER_PROC 3 #define MAX_PHB_PER_PROC 6 #define MAX_LANE_GROUPS_PER_PEC 4 +#define NUM_PCIE_LANES 16 + /* Enum indicating lane width (units = "number of lanes") */ enum lane_width { LANE_WIDTH_NC = 0, @@ -46,6 +50,13 @@ enum phb_active_mask { PHB5_MASK = 0x04, // PHB5 enabled }; +/* Bit position of the PHB with the largest number a given PEC can use */ +enum pec_phb_shift { + PEC0_PHB_SHIFT = 7, // PHB0 only + PEC1_PHB_SHIFT = 5, // PHB1 - PHB2 + PEC2_PHB_SHIFT = 2, // PHB3 - PHB5 +}; + /* * Struct for each row in PCIE IOP configuration table. * Used by code to compute the IOP config and PHBs active mask. @@ -176,6 +187,44 @@ static uint16_t lane_masks[MAX_PEC_PER_PROC][MAX_LANE_GROUPS_PER_PEC] = { { LANE_MASK_X8_GRP0, 0x0, LANE_MASK_X4_GRP0, LANE_MASK_X4_GRP1 }, }; +static const uint64_t RX_VGA_CTRL3_REGISTER[NUM_PCIE_LANES] = { + 0x8000008D0D010C3F, + 0x800000CD0D010C3F, + 0x8000018D0D010C3F, + 0x800001CD0D010C3F, + 0x8000028D0D010C3F, + 0x800002CD0D010C3F, + 0x8000038D0D010C3F, + 0x800003CD0D010C3F, + 0x8000088D0D010C3F, + 0x800008CD0D010C3F, + 0x8000098D0D010C3F, + 0x800009CD0D010C3F, + 0x80000A8D0D010C3F, + 0x80000ACD0D010C3F, + 0x80000B8D0D010C3F, + 0x80000BCD0D010C3F, +}; + +static const uint64_t RX_LOFF_CNTL_REGISTER[NUM_PCIE_LANES] = { + 0x800000A60D010C3F, + 0x800000E60D010C3F, + 0x800001A60D010C3F, + 0x800001E60D010C3F, + 0x800002A60D010C3F, + 0x800002E60D010C3F, + 0x800003A60D010C3F, + 0x800003E60D010C3F, + 0x800008A60D010C3F, + 0x800008E60D010C3F, + 0x800009A60D010C3F, + 0x800009E60D010C3F, + 0x80000AA60D010C3F, + 0x80000AE60D010C3F, + 0x80000BA60D010C3F, + 0x80000BE60D010C3F, +}; + static enum lane_width lane_mask_to_width(uint16_t mask) { enum lane_width width = LANE_WIDTH_NC; @@ -192,13 +241,91 @@ static enum lane_width lane_mask_to_width(uint16_t mask) return width; } +static uint64_t pec_val(int pec_id, uint8_t in, + uint32_t pec0_s, uint32_t pec0_c, + uint32_t pec1_s, uint32_t pec1_c, + uint32_t pec2_s, uint32_t pec2_c) +{ + uint64_t out = 0; + + switch (pec_id) { + case 0: + out = PPC_SHIFT(in & ((1 << pec0_c) - 1), pec0_s); + break; + case 1: + out = PPC_SHIFT(in & ((1 << pec1_c) - 1), pec1_s); + break; + case 2: + out = PPC_SHIFT(in & ((1 << pec2_c) - 1), pec2_s); + break; + default: + die("Unknown PEC ID: %d\n", pec_id); + } + + return out; +} + void pci_init(void) { + enum { + NUM_PCS_CONFIG = 4, + + PEC_CPLT_CONF1_OR = 0x0D000019, + PEC_CPLT_CTRL0_OR = 0x0D000010, + PEC_CPLT_CONF1_CLEAR = 0x0D000029, + + PEC_PCS_RX_CONFIG_MODE_REG = 0x800004800D010C3F, + PEC_PCS_RX_CDR_GAIN_REG = 0x800004B30D010C3F, + PEC_PCS_RX_SIGDET_CONTROL_REG = 0x800004A70D010C3F, + + PCI_IOP_FIR_ACTION0_REG = 0x0000000000000000ULL, + PCI_IOP_FIR_ACTION1_REG = 0xE000000000000000ULL, + PCI_IOP_FIR_MASK_REG = 0x1FFFFFFFF8000000ULL, + + PEC_FIR_ACTION0_REG = 0x0D010C06, + PEC_FIR_ACTION1_REG = 0x0D010C07, + PEC_FIR_MASK_REG = 0x0D010C03, + + PEC0_IOP_CONFIG_START_BIT = 13, + PEC1_IOP_CONFIG_START_BIT = 14, + PEC2_IOP_CONFIG_START_BIT = 10, + PEC0_IOP_BIT_COUNT = 1, + PEC1_IOP_BIT_COUNT = 2, + PEC2_IOP_BIT_COUNT = 3, + PEC0_IOP_SWAP_START_BIT = 12, + PEC1_IOP_SWAP_START_BIT = 12, + PEC2_IOP_SWAP_START_BIT = 7, + PEC0_IOP_IOVALID_ENABLE_START_BIT = 4, + PEC1_IOP_IOVALID_ENABLE_START_BIT = 4, + PEC2_IOP_IOVALID_ENABLE_START_BIT = 4, + PEC_IOP_IOVALID_ENABLE_STACK0_BIT = 4, + PEC_IOP_IOVALID_ENABLE_STACK1_BIT = 5, + PEC_IOP_IOVALID_ENABLE_STACK2_BIT = 6, + PEC_IOP_REFCLOCK_ENABLE_START_BIT = 32, + PEC_IOP_PMA_RESET_START_BIT = 29, + PEC_IOP_PIPE_RESET_START_BIT = 28, + + PEC_PCS_PCLCK_CNTL_PLLA_REG = 0x8000050F0D010C3F, + PEC_PCS_PCLCK_CNTL_PLLB_REG = 0x8000054F0D010C3F, + PEC_PCS_TX_DCLCK_ROTATOR_REG = 0x800004450D010C3F, + PEC_PCS_TX_PCIE_REC_DETECT_CNTL1_REG = 0x8000046C0D010C3F, + PEC_PCS_TX_PCIE_REC_DETECT_CNTL2_REG = 0x8000046D0D010C3F, + PEC_PCS_TX_POWER_SEQ_ENABLE_REG = 0x800004700D010C3F, + + PEC_SCOM0X0B_EDMOD = 52, + + PEC_PCS_RX_VGA_CONTROL1_REG = 0x8000048B0D010C3F, + PEC_PCS_RX_VGA_CONTROL2_REG = 0x8000048C0D010C3F, + PEC_PCS_SYS_CONTROL_REG = 0x80000C000D010C3F, + }; + uint8_t pec; uint8_t phb_active_mask = 0; - const struct lane_config_row *pec_cfgs[3] = { NULL }; + const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; + + uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { uint8_t i; @@ -232,12 +359,237 @@ void pci_init(void) pec_cfgs[pec] = &pec_lane_cfgs[pec][i]; - // PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_lane_cfgs[pec][i].lane_config + // PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_cfgs[pec]->lane_config // PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 - // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_lane_cfgs[pec][i].phb_to_pcie_mac + // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac } - // foreach PEC[ATTR_PROC_PCIE_IOVALID_ENABLE] := mask of functional PHBs + /* Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot */ + iovalid_enable[0] = pec_cfgs[0]->phb_active >> PEC0_PHB_SHIFT; + iovalid_enable[1] = pec_cfgs[1]->phb_active >> PEC1_PHB_SHIFT; + iovalid_enable[2] = pec_cfgs[2]->phb_active >> PEC2_PHB_SHIFT; // ATTR_PROC_PCIE_PHB_ACTIVE := phb_active_mask + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + long time; + uint8_t i; + uint64_t val; + uint8_t proc_pcie_iop_swap; + + chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + + /* Phase1 init step 1 (get VPD, no operation here) */ + + /* Phase1 init step 2a */ + val = pec_val(pec, pec_cfgs[pec]->lane_config, + PEC0_IOP_CONFIG_START_BIT, PEC0_IOP_BIT_COUNT * 2, + PEC1_IOP_CONFIG_START_BIT, PEC1_IOP_BIT_COUNT * 2, + PEC2_IOP_CONFIG_START_BIT, PEC2_IOP_BIT_COUNT * 2); + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_OR, val); + + /* Phase1 init step 2b */ + + /* ATTR_PROC_PCIE_IOP_SWAP, from talos.xml */ + proc_pcie_iop_swap = 0; + + val = pec_val(pec, proc_pcie_iop_swap, + PEC0_IOP_SWAP_START_BIT, PEC0_IOP_BIT_COUNT, + PEC1_IOP_SWAP_START_BIT, PEC1_IOP_BIT_COUNT, + PEC2_IOP_SWAP_START_BIT, PEC2_IOP_BIT_COUNT); + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_OR, val); + + /* Phase1 init step 3a */ + + val = pec_val(pec, iovalid_enable[pec], + PEC0_IOP_IOVALID_ENABLE_START_BIT, PEC0_IOP_BIT_COUNT, + PEC1_IOP_IOVALID_ENABLE_START_BIT, PEC1_IOP_BIT_COUNT, + PEC2_IOP_IOVALID_ENABLE_START_BIT, PEC2_IOP_BIT_COUNT); + + /* Set IOVALID for base PHB if PHB2, or PHB4, or PHB5 are set (SW417485) */ + if ((val & PPC_BIT(PEC_IOP_IOVALID_ENABLE_STACK1_BIT)) || + (val & PPC_BIT(PEC_IOP_IOVALID_ENABLE_STACK2_BIT))) { + val |= PPC_BIT(PEC_IOP_IOVALID_ENABLE_STACK0_BIT); + val |= PPC_BIT(PEC_IOP_IOVALID_ENABLE_STACK1_BIT); + } + + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_OR, val); + + /* Phase1 init step 3b (enable clock) */ + /* XXX: assume all PECs are enabled (due to hard-coded lanes), + * ATTR_PROC_PCIE_REFCLOCK_ENABLE */ + write_scom_for_chiplet(chiplet, PEC_CPLT_CTRL0_OR, + PPC_BIT(PEC_IOP_REFCLOCK_ENABLE_START_BIT)); + + /* Phase1 init step 4 (PMA reset) */ + + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, + PPC_BIT(PEC_IOP_PMA_RESET_START_BIT)); + (void)wait_us(1, false); /* at least 400ns */ + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_OR, + PPC_BIT(PEC_IOP_PMA_RESET_START_BIT)); + (void)wait_us(1, false); /* at least 400ns */ + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, + PPC_BIT(PEC_IOP_PMA_RESET_START_BIT)); + + /* + * Poll for PRTREADY status on PLLA and PLLB: + * PEC_IOP_PLLA_VCO_COURSE_CAL_REGISTER1 = 0x800005010D010C3F + * PEC_IOP_PLLB_VCO_COURSE_CAL_REGISTER1 = 0x800005410D010C3F + * PEC_IOP_HSS_PORT_READY_START_BIT = 58 + */ + time = wait_us(40, + (read_scom_for_chiplet(chiplet, 0x800005010D010C3F) & PPC_BIT(58)) || + (read_scom_for_chiplet(chiplet, 0x800005410D010C3F) & PPC_BIT(58))); + if (!time) + die("IOP HSS Port Ready status is not set!"); + + /* Phase1 init step 5 (Set IOP FIR action0) */ + write_scom_for_chiplet(chiplet, PEC_FIR_ACTION0_REG, PCI_IOP_FIR_ACTION0_REG); + + /* Phase1 init step 6 (Set IOP FIR action1) */ + write_scom_for_chiplet(chiplet, PEC_FIR_ACTION1_REG, PCI_IOP_FIR_ACTION1_REG); + + /* Phase1 init step 7 (Set IOP FIR mask) */ + write_scom_for_chiplet(chiplet, PEC_FIR_MASK_REG, PCI_IOP_FIR_MASK_REG); + + /* Phase1 init step 8-11 (Config 0 - 3) */ + + /* ATTR_PROC_PCIE_PCS_RX_CDR_GAIN, from talos.xml */ + uint8_t pcs_cdr_gain[] = { 0x56, 0x47, 0x47, 0x47 }; + /* ATTR_PROC_PCIE_PCS_RX_INIT_GAIN, all zeroes by default */ + uint8_t pcs_init_gain = 0; + /* ATTR_PROC_PCIE_PCS_RX_PK_INIT, all zeroes by default */ + uint8_t pcs_pk_init = 0; + /* ATTR_PROC_PCIE_PCS_RX_SIGDET_LVL, defaults and talos.xml */ + uint8_t pcs_sigdet_lvl = 0x0B; + + uint32_t pcs_config_mode[NUM_PCS_CONFIG] = { 0xA006, 0xA805, 0xB071, 0xB870 }; + + for (i = 0; i < NUM_PCS_CONFIG; ++i) { + uint8_t lane; + + /* RX Config Mode */ + write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, + PPC_SHIFT(pcs_config_mode[i], 48)); + + /* RX CDR GAIN */ + scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_CDR_GAIN_REG, + ~PPC_BITMASK(56, 63), + PPC_SHIFT(pcs_cdr_gain[i], 56)); + + for (lane = 0; lane < NUM_PCIE_LANES; ++lane) { + /* RX INITGAIN */ + scom_and_or_for_chiplet(chiplet, RX_VGA_CTRL3_REGISTER[lane], + ~PPC_BITMASK(48, 52), + PPC_SHIFT(pcs_init_gain, 48)); + + /* RX PKINIT */ + scom_and_or_for_chiplet(chiplet, RX_LOFF_CNTL_REGISTER[lane], + ~PPC_BITMASK(58, 63), + PPC_SHIFT(pcs_pk_init, 58)); + } + + /* RX SIGDET LVL */ + scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_SIGDET_CONTROL_REG, + ~PPC_BITMASK(59, 63), + PPC_SHIFT(pcs_sigdet_lvl, 59)); + } + + /* + * Phase1 init step 12 (RX Rot Cntl CDR Lookahead Disabled,SSC Disabled) + * + * Skipping update of PEC_PCS_RX_ROT_CNTL_REG, because all these attributes are zero + * for Nimbus and there is nothing to update: + * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_LOOKAHEAD + * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_SSC + * - ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL + * - ATTR_PROC_PCIE_PCS_RX_ROT_RST_FW + */ + + /* Phase1 init step 13 (RX Config Mode Enable External Config Control) */ + write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, PPC_SHIFT(0x8600, 48)); + + /* Phase1 init step 14 (PCLCK Control Register - PLLA) */ + /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLA = 0xF8 */ + scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLA_REG, + ~PPC_BITMASK(56, 63), + PPC_SHIFT(0xf8, 56)); + + /* Phase1 init step 15 (PCLCK Control Register - PLLB) */ + /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLB = 0xF8 */ + scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLB_REG, + ~PPC_BITMASK(56, 63), + PPC_SHIFT(0xf8, 56)); + + /* Phase1 init step 16 (TX DCLCK Rotator Override) */ + /* ATTR_PROC_PCIE_PCS_TX_DCLCK_ROT = 0x0022 */ + write_scom_for_chiplet(chiplet, PEC_PCS_TX_DCLCK_ROTATOR_REG, + PPC_SHIFT(0x0022, 48)); + + /* Phase1 init step 17 (TX PCIe Receiver Detect Control Register 1) */ + /* ATTR_PROC_PCIE_PCS_TX_PCIE_RECV_DETECT_CNTL_REG1 = 0xAA7A */ + write_scom_for_chiplet(chiplet, PEC_PCS_TX_PCIE_REC_DETECT_CNTL1_REG, + PPC_SHIFT(0xaa7a, 48)); + + /* Phase1 init step 18 (TX PCIe Receiver Detect Control Register 2) */ + /* ATTR_PROC_PCIE_PCS_TX_PCIE_RECV_DETECT_CNTL_REG2 = 0x2000 */ + write_scom_for_chiplet(chiplet, PEC_PCS_TX_PCIE_REC_DETECT_CNTL2_REG, + PPC_SHIFT(0x2000, 48)); + + /* Phase1 init step 19 (TX Power Sequence Enable) */ + /* ATTR_PROC_PCIE_PCS_TX_POWER_SEQ_ENABLE = 0xFF */ + scom_and_or_for_chiplet(chiplet, PEC_PCS_TX_POWER_SEQ_ENABLE_REG, + ~PPC_BITMASK(56, 62), + PPC_SHIFT(0xff, 56)); + + /* Phase1 init step 20 (RX VGA Control Register 1) */ + + /* ATTR_PROC_PCIE_PCS_RX_VGA_CNTL_REG1 = 0 */ + val = PPC_SHIFT(0, 48); + + /* Becase ATTR_CHIP_EC_FEATURE_HW414759 = 1 */ + val |= PPC_BIT(PEC_SCOM0X0B_EDMOD); + val |= PPC_BIT(PEC_SCOM0X0B_EDMOD + 1); + + write_scom_for_chiplet(chiplet, PEC_PCS_RX_VGA_CONTROL1_REG, val); + + /* Phase1 init step 21 (RX VGA Control Register 2) */ + /* ATTR_PROC_PCIE_PCS_RX_VGA_CNTL_REG2 = 0 */ + write_scom_for_chiplet(chiplet, PEC_PCS_RX_VGA_CONTROL2_REG, + PPC_SHIFT(0, 48)); + + /* Phase1 init step 22 (RX DFE Func Control Register 1) */ + /* ATTR_PROC_PCIE_PCS_RX_DFE_FDDC = 0, so not updating PEC_IOP_RX_DFE_FUNC_REGISTER1 */ + + /* Phase1 init step 23 (PCS System Control) */ + /* ATTR_PROC_PCIE_PCS_SYSTEM_CNTL computed above */ + scom_and_or_for_chiplet(chiplet, PEC_PCS_SYS_CONTROL_REG, + ~PPC_BITMASK(55, 63), + PPC_SHIFT(pec_cfgs[pec]->phb_to_pcie_mac, 55)); + + /* + * All values in ATTR_PROC_PCIE_PCS_M_CNTL seem to be 0, which + * makes the next four steps no-op. Hostboot has bugs here in + * that it updates PEC_PCS_M1_CONTROL_REG 4 times instead of + * updating 4 different registers (M1-M4), but no-op conceals this. + */ + + /* Phase1 init step 24 (PCS M1 Control) */ + /* Phase1 init step 25 (PCS M2 Control) */ + /* Phase1 init step 26 (PCS M3 Control) */ + /* Phase1 init step 27 (PCS M4 Control) */ + + /* Delay a minimum of 200ns to allow prior SCOM programming to take effect */ + (void)wait_us(1, false); + + // Phase1 init step 28 + write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, + PPC_BIT(PEC_IOP_PIPE_RESET_START_BIT)); + + /* + * Delay a minimum of 300ns for reset to complete. + * Inherent delay before deasserting PCS PIPE Reset is enough here. + */ + } } From 63f8408f164c1b645919ad250de6d70fb9eb5052 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 11 Oct 2021 00:27:18 +0300 Subject: [PATCH 03/16] Reorganize code a bit Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/pci.c | 104 +++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/pci.c index d8643d2fd2a..4917ef1ebbf 100644 --- a/src/soc/ibm/power9/pci.c +++ b/src/soc/ibm/power9/pci.c @@ -15,6 +15,7 @@ #define MAX_LANE_GROUPS_PER_PEC 4 #define NUM_PCIE_LANES 16 +#define NUM_PCS_CONFIG 4 /* Enum indicating lane width (units = "number of lanes") */ enum lane_width { @@ -241,6 +242,51 @@ static enum lane_width lane_mask_to_width(uint16_t mask) return width; } +static void determine_lane_configs(const struct lane_config_row **pec_cfgs) +{ + uint8_t pec = 0; + uint8_t phb_active_mask = 0; + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + uint8_t i; + uint8_t lane_group; + + // enum lane_width + uint16_t lane_mask[MAX_LANE_GROUPS_PER_PEC]; + memcpy(&lane_mask, &lane_masks[pec], sizeof(lane_mask)); + + struct lane_config_row config = { + { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, + 0x00, + PHB_MASK_NA, + PHB_X16_MAC_MAP, + }; + + /* Transform effective config to match lane config table format */ + for (lane_group = 0; lane_group < MAX_LANE_GROUPS_PER_PEC; ++lane_group) + config.lane_set[lane_group] = lane_mask_to_width(lane_mask[lane_group]); + + for (i = 0; i < pec_lane_cfg_sizes[pec]; ++i) { + if (memcmp(pec_lane_cfgs[pec][i].lane_set, &config.lane_set, + sizeof(config.lane_set)) == 0) + break; + } + + if (i == pec_lane_cfg_sizes[pec]) + die("Failed to find PCIE IOP configuration for PEC%d\n", pec); + + phb_active_mask |= pec_lane_cfgs[pec][i].phb_active; + + pec_cfgs[pec] = &pec_lane_cfgs[pec][i]; + + // PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_cfgs[pec]->lane_config + // PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 + // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac + } + + // ATTR_PROC_PCIE_PHB_ACTIVE := phb_active_mask +} + static uint64_t pec_val(int pec_id, uint8_t in, uint32_t pec0_s, uint32_t pec0_c, uint32_t pec1_s, uint32_t pec1_c, @@ -265,11 +311,9 @@ static uint64_t pec_val(int pec_id, uint8_t in, return out; } -void pci_init(void) +static void phase1(const struct lane_config_row **pec_cfgs) { enum { - NUM_PCS_CONFIG = 4, - PEC_CPLT_CONF1_OR = 0x0D000019, PEC_CPLT_CTRL0_OR = 0x0D000010, PEC_CPLT_CONF1_CLEAR = 0x0D000029, @@ -319,58 +363,14 @@ void pci_init(void) PEC_PCS_SYS_CONTROL_REG = 0x80000C000D010C3F, }; - uint8_t pec; - - uint8_t phb_active_mask = 0; - - const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; - + uint8_t pec = 0; uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; - for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { - uint8_t i; - uint8_t lane_group; - - // enum lane_width - uint16_t lane_mask[MAX_LANE_GROUPS_PER_PEC]; - memcpy(&lane_mask, &lane_masks[pec], sizeof(lane_mask)); - - struct lane_config_row config = { - { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, - 0x00, - PHB_MASK_NA, - PHB_X16_MAC_MAP, - }; - - /* Transform effective config to match lane config table format */ - for (lane_group = 0; lane_group < MAX_LANE_GROUPS_PER_PEC; ++lane_group) - config.lane_set[lane_group] = lane_mask_to_width(lane_mask[lane_group]); - - for (i = 0; i < pec_lane_cfg_sizes[pec]; ++i) { - if (memcmp(pec_lane_cfgs[pec][i].lane_set, &config.lane_set, - sizeof(config.lane_set)) == 0) - break; - } - - if (i == pec_lane_cfg_sizes[pec]) - die("Failed to find PCIE IOP configuration for PEC%d\n", pec); - - phb_active_mask |= pec_lane_cfgs[pec][i].phb_active; - - pec_cfgs[pec] = &pec_lane_cfgs[pec][i]; - - // PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_cfgs[pec]->lane_config - // PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 - // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac - } - /* Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot */ iovalid_enable[0] = pec_cfgs[0]->phb_active >> PEC0_PHB_SHIFT; iovalid_enable[1] = pec_cfgs[1]->phb_active >> PEC1_PHB_SHIFT; iovalid_enable[2] = pec_cfgs[2]->phb_active >> PEC2_PHB_SHIFT; - // ATTR_PROC_PCIE_PHB_ACTIVE := phb_active_mask - for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { long time; uint8_t i; @@ -593,3 +593,11 @@ void pci_init(void) */ } } + +void pci_init(void) +{ + const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; + + determine_lane_configs(pec_cfgs); + phase1(pec_cfgs); +} From a0c453b90a5eaf5282360aa65d3fd48699646b8f Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 11 Oct 2021 00:56:22 +0300 Subject: [PATCH 04/16] Enable RI/DI for PCIe Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/pci.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/pci.c index 4917ef1ebbf..1fffb28c394 100644 --- a/src/soc/ibm/power9/pci.c +++ b/src/soc/ibm/power9/pci.c @@ -594,10 +594,35 @@ static void phase1(const struct lane_config_row **pec_cfgs) } } +static void enable_ridi(void) +{ + enum { + PERV_NET_CTRL0 = 0x000F0040, + PERV_NET_CTRL0_WOR = 0x000F0042, + }; + + uint8_t pec = 0; + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + + /* Getting NET_CTRL0 register value and checking its CHIPLET_ENABLE bit */ + if (read_scom_for_chiplet(chiplet, PERV_NET_CTRL0) & PPC_BIT(0)) { + /* Enable Recievers, Drivers DI1 & DI2 */ + uint64_t val = 0; + val |= PPC_BIT(19); // NET_CTRL0.RI_N = 1 + val |= PPC_BIT(20); // NET_CTRL0.DI1_N = 1 + val |= PPC_BIT(21); // NET_CTRL0.DI2_N = 1 + write_scom_for_chiplet(chiplet, PERV_NET_CTRL0_WOR, val); + } + } +} + void pci_init(void) { const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; determine_lane_configs(pec_cfgs); phase1(pec_cfgs); + enable_ridi(); } From 4cdcab735281247421e6b9495899a01849983e66 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Mon, 11 Oct 2021 01:17:49 +0300 Subject: [PATCH 05/16] First half of Phase2 (PEC init) Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/pci.c | 199 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 14 deletions(-) diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/pci.c index 1fffb28c394..664b63e41ce 100644 --- a/src/soc/ibm/power9/pci.c +++ b/src/soc/ibm/power9/pci.c @@ -311,7 +311,8 @@ static uint64_t pec_val(int pec_id, uint8_t in, return out; } -static void phase1(const struct lane_config_row **pec_cfgs) +static void phase1(const struct lane_config_row **pec_cfgs, + const uint8_t *iovalid_enable) { enum { PEC_CPLT_CONF1_OR = 0x0D000019, @@ -364,12 +365,6 @@ static void phase1(const struct lane_config_row **pec_cfgs) }; uint8_t pec = 0; - uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; - - /* Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot */ - iovalid_enable[0] = pec_cfgs[0]->phb_active >> PEC0_PHB_SHIFT; - iovalid_enable[1] = pec_cfgs[1]->phb_active >> PEC1_PHB_SHIFT; - iovalid_enable[2] = pec_cfgs[2]->phb_active >> PEC2_PHB_SHIFT; for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { long time; @@ -476,7 +471,7 @@ static void phase1(const struct lane_config_row **pec_cfgs) /* RX CDR GAIN */ scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_CDR_GAIN_REG, ~PPC_BITMASK(56, 63), - PPC_SHIFT(pcs_cdr_gain[i], 56)); + PPC_SHIFT(pcs_cdr_gain[i], 63)); for (lane = 0; lane < NUM_PCIE_LANES; ++lane) { /* RX INITGAIN */ @@ -487,13 +482,13 @@ static void phase1(const struct lane_config_row **pec_cfgs) /* RX PKINIT */ scom_and_or_for_chiplet(chiplet, RX_LOFF_CNTL_REGISTER[lane], ~PPC_BITMASK(58, 63), - PPC_SHIFT(pcs_pk_init, 58)); + PPC_SHIFT(pcs_pk_init, 63)); } /* RX SIGDET LVL */ scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_SIGDET_CONTROL_REG, ~PPC_BITMASK(59, 63), - PPC_SHIFT(pcs_sigdet_lvl, 59)); + PPC_SHIFT(pcs_sigdet_lvl, 63)); } /* @@ -514,13 +509,13 @@ static void phase1(const struct lane_config_row **pec_cfgs) /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLA = 0xF8 */ scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLA_REG, ~PPC_BITMASK(56, 63), - PPC_SHIFT(0xf8, 56)); + PPC_SHIFT(0xf8, 63)); /* Phase1 init step 15 (PCLCK Control Register - PLLB) */ /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLB = 0xF8 */ scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLB_REG, ~PPC_BITMASK(56, 63), - PPC_SHIFT(0xf8, 56)); + PPC_SHIFT(0xf8, 63)); /* Phase1 init step 16 (TX DCLCK Rotator Override) */ /* ATTR_PROC_PCIE_PCS_TX_DCLCK_ROT = 0x0022 */ @@ -566,7 +561,7 @@ static void phase1(const struct lane_config_row **pec_cfgs) /* ATTR_PROC_PCIE_PCS_SYSTEM_CNTL computed above */ scom_and_or_for_chiplet(chiplet, PEC_PCS_SYS_CONTROL_REG, ~PPC_BITMASK(55, 63), - PPC_SHIFT(pec_cfgs[pec]->phb_to_pcie_mac, 55)); + PPC_SHIFT(pec_cfgs[pec]->phb_to_pcie_mac, 63)); /* * All values in ATTR_PROC_PCIE_PCS_M_CNTL seem to be 0, which @@ -618,11 +613,187 @@ static void enable_ridi(void) } } +static void init_pecs(const uint8_t *iovalid_enable) +{ + enum { + P9N2_PEC_ADDREXTMASK_REG = 0x4010C05, + PEC_PBCQHWCFG_REG = 0x4010C00, + PEC_NESTTRC_REG = 0x4010C03, + PEC_PBAIBHWCFG_REG = 0xD010800, + + /* powerbus.c has these too */ + MBOX_SCRATCH_REG1 = 0x00050038, + MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = (1 << 23), + }; + + uint8_t dd = get_dd(); + + uint8_t pec = 0; + + uint64_t scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); + + /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ + bool node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + uint64_t val = 0; + chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + + /* + * ATTR_FABRIC_ADDR_EXTENSION_GROUP_ID = 0 + * ATTR_FABRIC_ADDR_EXTENSION_CHIP_ID = 0 + */ + scom_and_or_for_chiplet(chiplet, P9N2_PEC_ADDREXTMASK_REG, + ~PPC_BITMASK(0, 6), + PPC_SHIFT(0, 6)); + + /* + * Phase2 init step 1 + * NestBase+0x00 + * Set bits 00:03 = 0b0001 Set hang poll scale + * Set bits 04:07 = 0b0001 Set data scale + * Set bits 08:11 = 0b0001 Set hang pe scale + * Set bit 22 = 0b1 Disable out­of­order store behavior + * Set bit 33 = 0b1 Enable Channel Tag streaming behavior + * Set bits 34:35 = 0b11 Set P9 Style cache-inject behavior + * Set bits 46:48 = 0b011 Set P9 Style cache-inject rate, 1/16 cycles + * Set bit 60 = 0b1 only if PEC is bifurcated or trifurcated. + * if HW423589_option1, set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope + */ + + val = read_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG); + /* Set hang poll scale */ + val &= ~PPC_BITMASK(0, 3); + val |= PPC_SHIFT(1, 3); + /* Set data scale */ + val &= ~PPC_BITMASK(4, 7); + val |= PPC_SHIFT(1, 7); + /* Set hang pe scale */ + val &= ~PPC_BITMASK(8, 11); + val |= PPC_SHIFT(1, 11); + /* Disable out­of­order store behavior */ + val |= PPC_BIT(22); + /* Enable Channel Tag streaming behavior */ + val |= PPC_BIT(33); + + /* Set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope */ + val |= PPC_BIT(41); // PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG + val |= PPC_BIT(42); // PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP + val |= PPC_BIT(43); // PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG + val |= PPC_BIT(44); // PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP + val |= PPC_BIT(54); // PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG + val |= PPC_BIT(51); // PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP + val |= PPC_BIT(56); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP + val |= PPC_BIT(59); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG + + /* Disable P9 Style cache injects if chip is node */ + if (!node_pump_mode) { + /* + * ATTR_PROC_PCIE_CACHE_INJ_MODE + * Attribute to control the cache inject mode. + * + * DISABLE_CI = 0x0 - Disable cache inject completely. (Reset value default) + * P7_STYLE_CI = 0x1 - Use cache inject design from Power7. + * PCITLP_STYLE_CI = 0x2 - Use PCI TLP Hint bits in packet to perform the cache inject. + * P9_STYLE_CI = 0x3 - Initial attempt as cache inject. Power9 style. (Attribute default) + * + * Different cache inject modes will affect DMA write performance. The attribute default was + * selected based on various workloads and was to be the most optimal settings for Power9. + * fapi2::ATTR_PROC_PCIE_CACHE_INJ_MODE = 3 by default + */ + val &= ~PPC_BITMASK(34, 36); + val |= PPC_SHIFT(0x3, 36); + + if (dd == 0x21 || dd == 0x22 || dd == 0x23) { + /* + * ATTR_PROC_PCIE_CACHE_INJ_THROTTLE + * Attribute to control the cache inject throttling when cache inject is enable. + * + * DISABLE = 0x0 - Disable cache inject throttling. (Reset value default) + * 16_CYCLES = 0x1 - Perform 1 cache inject every 16 clock cycles. + * 32_CYCLES = 0x3 - Perform 1 cache inject every 32 clock cycles. (Attribute default) + * 64_CYCLES = 0x7 - Perform 1 cache inject every 32 clock cycles. + * + * Different throttle rates will affect DMA write performance. The attribute default + * settings were optimal settings found across various workloads. + */ + val &= ~PPC_BITMASK(46, 48); + val |= PPC_SHIFT(0x3, 48); + } + } + + if (pec == 1 || (pec == 2 && iovalid_enable[pec] != 0x4)) + val |= PPC_BIT(60); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION + + write_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG, val); + + /* + * Phase2 init step 2 + * NestBase + 0x01 + * N/A Modify Drop Priority Control Register (DrPriCtl) + */ + + /* + * Phase2 init step 3 + * NestBase + 0x03 + * Set bits 00:03 = 0b1001 Enable trace, and select + * inbound operations with addr information + */ + scom_and_or_for_chiplet(chiplet, PEC_NESTTRC_REG, + ~PPC_BITMASK(0, 3), + PPC_SHIFT(9, 3)); + + /* + * Phase2 init step 4 + * NestBase+0x05 + * N/A For use of atomics/asb_notify + */ + + /* + * Phase2 init step 5 + * NestBase+0x06 + * N/A To override scope prediction + */ + + /* + * Phase2 init step 6 + * PCIBase +0x00 + * Set bits 30 = 0b1 Enable Trace + */ + val = 0; + val |= PPC_BIT(0x1E); // PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN + val |= PPC_SHIFT(7, 0x2A); // PEC_AIB_HWCFG_OSBM_HOL_BLK_CNT + write_scom_for_chiplet(chiplet, PEC_PBAIBHWCFG_REG, val); + } +} + +static void init_phbs(const uint8_t *iovalid_enable) +{ + // TODO: write code +} + +static void phase2(const uint8_t *iovalid_enable) +{ + init_pecs(iovalid_enable); + init_phbs(iovalid_enable); +} + void pci_init(void) { const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; + uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; determine_lane_configs(pec_cfgs); - phase1(pec_cfgs); + + /* + * Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot. + * LSB is the PHB with the highest number for the given PEC. + */ + iovalid_enable[0] = pec_cfgs[0]->phb_active >> PEC0_PHB_SHIFT; + iovalid_enable[1] = pec_cfgs[1]->phb_active >> PEC1_PHB_SHIFT; + iovalid_enable[2] = pec_cfgs[2]->phb_active >> PEC2_PHB_SHIFT; + + phase1(pec_cfgs, iovalid_enable); enable_ridi(); + phase2(iovalid_enable); } From 66980e89bb6903184705d3b01e6f71f0256592ea Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 14 Oct 2021 00:27:30 +0300 Subject: [PATCH 06/16] Second half of Phase2 (PHB init) Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/pci.c | 301 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 292 insertions(+), 9 deletions(-) diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/pci.c index 664b63e41ce..8f067eb4e7b 100644 --- a/src/soc/ibm/power9/pci.c +++ b/src/soc/ibm/power9/pci.c @@ -242,7 +242,7 @@ static enum lane_width lane_mask_to_width(uint16_t mask) return width; } -static void determine_lane_configs(const struct lane_config_row **pec_cfgs) +static uint8_t determine_lane_configs(const struct lane_config_row **pec_cfgs) { uint8_t pec = 0; uint8_t phb_active_mask = 0; @@ -284,7 +284,7 @@ static void determine_lane_configs(const struct lane_config_row **pec_cfgs) // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac } - // ATTR_PROC_PCIE_PHB_ACTIVE := phb_active_mask + return phb_active_mask; } static uint64_t pec_val(int pec_id, uint8_t in, @@ -465,27 +465,32 @@ static void phase1(const struct lane_config_row **pec_cfgs, uint8_t lane; /* RX Config Mode */ + // write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, PPC_SHIFT(pcs_config_mode[i], 48)); /* RX CDR GAIN */ + // scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_CDR_GAIN_REG, ~PPC_BITMASK(56, 63), PPC_SHIFT(pcs_cdr_gain[i], 63)); for (lane = 0; lane < NUM_PCIE_LANES; ++lane) { /* RX INITGAIN */ + // scom_and_or_for_chiplet(chiplet, RX_VGA_CTRL3_REGISTER[lane], ~PPC_BITMASK(48, 52), PPC_SHIFT(pcs_init_gain, 48)); /* RX PKINIT */ + // scom_and_or_for_chiplet(chiplet, RX_LOFF_CNTL_REGISTER[lane], ~PPC_BITMASK(58, 63), PPC_SHIFT(pcs_pk_init, 63)); } /* RX SIGDET LVL */ + // scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_SIGDET_CONTROL_REG, ~PPC_BITMASK(59, 63), PPC_SHIFT(pcs_sigdet_lvl, 63)); @@ -503,7 +508,9 @@ static void phase1(const struct lane_config_row **pec_cfgs, */ /* Phase1 init step 13 (RX Config Mode Enable External Config Control) */ - write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, PPC_SHIFT(0x8600, 48)); + // verify this and other shifts below + write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, + PPC_SHIFT(0x8600, 48)); /* Phase1 init step 14 (PCLCK Control Register - PLLA) */ /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLA = 0xF8 */ @@ -767,15 +774,291 @@ static void init_pecs(const uint8_t *iovalid_enable) } } -static void init_phbs(const uint8_t *iovalid_enable) +static uint64_t phb_addr(uint8_t phb, uint64_t addr) { - // TODO: write code + chiplet_id_t chiplet; + uint8_t sat_id = (addr >> 6) & 0xF; + + if (phb == 0) { + chiplet = PCI0_CHIPLET_ID; + sat_id = (sat_id < 4 ? 1 : 4); + } else { + chiplet = PCI0_CHIPLET_ID + (phb / 3) + 1; + sat_id = (sat_id < 4 ? 1 : 4) + + ((phb % 2) ? 0 : 1) + + (2 * (phb / 5)); + } + + addr &= ~PPC_BITMASK(34, 39); + addr |= PPC_SHIFT(chiplet & 0x3F, 39); + + addr &= ~PPC_BITMASK(54, 57); + addr |= PPC_SHIFT(sat_id & 0xF, 57); + + return addr; +} + +static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) +{ + enum { + PHB_CERR_RPT0_REG = 0x4010C4A, + PHB_CERR_RPT1_REG = 0x4010C4B, + PHB_NFIR_REG = 0x4010C40, + PHB_NFIRWOF_REG = 0x4010C48, + + PHB_NFIRACTION0_REG = 0x4010C46, + PCI_NFIR_ACTION0_REG = 0x5B0F81E000000000, + + PHB_NFIRACTION1_REG = 0x4010C47, + PCI_NFIR_ACTION1_REG = 0x7F0F81E000000000, + + PHB_NFIRMASK_REG = 0x4010C43, + PCI_NFIR_MASK_REG = 0x30001C00000000, + + PHB_PE_DFREEZE_REG = 0x4010C55, + PHB_PBAIB_CERR_RPT_REG = 0xD01084B, + PHB_PFIR_REG = 0xD010840, + PHB_PFIRWOF_REG = 0xD010848, + + PHB_PFIRACTION0_REG = 0xD010846, + PCI_PFIR_ACTION0_REG = 0xB000000000000000, + + PHB_PFIRACTION1_REG = 0xD010847, + PCI_PFIR_ACTION1_REG = 0xB000000000000000, + + PHB_PFIRMASK_REG = 0xD010843, + PCI_PFIR_MASK_REG = 0xE00000000000000, + + P9_PCIE_CONFIG_BAR_SHIFT = 8, + + PHB_MMIOBAR0_REG = 0x4010C4E, + PHB_MMIOBAR0_MASK_REG = 0x4010C4F, + PHB_MMIOBAR1_REG = 0x4010C50, + PHB_MMIOBAR1_MASK_REG = 0x04010C51, + PHB_PHBBAR_REG = 0x4010C52, + PHB_BARE_REG = 0x4010C54, + + PHB_PHBRESET_REG = 0xD01084A, + PHB_ACT0_REG = 0xD01090E, + PHB_ACTION1_REG = 0xD01090F, + PHB_MASK_REG = 0xD01090B, + }; + + /* ATTR_PROC_PCIE_MMIO_BAR0_BASE_ADDR_OFFSET */ + uint64_t mmio_bar0_offsets[MAX_PHB_PER_PROC] = { 0 }; + /* ATTR_PROC_PCIE_MMIO_BAR1_BASE_ADDR_OFFSET */ + uint64_t mmio_bar1_offsets[MAX_PHB_PER_PROC] = { 0 }; + /* ATTR_PROC_PCIE_REGISTER_BAR_BASE_ADDR_OFFSET */ + uint64_t register_bar_offsets[MAX_PHB_PER_PROC] = { 0 }; + /* ATTR_PROC_PCIE_BAR_SIZE */ + uint64_t bar_sizes[3] = { 0 }; + + /* Determine base address of chip MMIO range */ + uint64_t base_addr_mmio = 0; + base_addr_mmio |= PPC_SHIFT(0, 12); // 5 bits, ATTR_PROC_FABRIC_SYSTEM_ID + base_addr_mmio |= PPC_SHIFT(0, 18); // 4 bits, ATTR_PROC_EFF_FABRIC_GROUP_ID + base_addr_mmio |= PPC_SHIFT(0, 21); // 3 bits, ATTR_PROC_EFF_FABRIC_CHIP_ID + base_addr_mmio |= PPC_SHIFT(3, 14); // 2 bits, FABRIC_ADDR_MSEL, + // nm = 0b00/01, m = 0b10, mmio = 0b11 + + uint8_t phb = 0; + for (phb = 0; phb < MAX_PHB_PER_PROC; ++phb) { + /* BAR enable attribute (ATTR_PROC_PCIE_BAR_ENABLE) */ + uint8_t l_bar_enables[3] = { 0 }; + + uint64_t val = 0; + uint64_t mmio0_bar = base_addr_mmio; + uint64_t mmio1_bar = base_addr_mmio; + uint64_t register_bar = base_addr_mmio; + + if (!(phb_active_mask & (PHB0_MASK >> phb))) + continue; + + /* + * Phase2 init step 12_a (yes, out of order) + * NestBase + StackBase + 0xA + * 0xFFFFFFFF_FFFFFFFF + * Clear any spurious cerr_rpt0 bits (cerr_rpt0) + */ + write_scom(phb_addr(phb, PHB_CERR_RPT0_REG), PPC_BITMASK(0, 63)); + + /* + * Phase2 init step 12_b (yes, out of order) + * NestBase + StackBase + 0xB + * 0xFFFFFFFF_FFFFFFFF + * Clear any spurious cerr_rpt1 bits (cerr_rpt1) + */ + write_scom(phb_addr(phb, PHB_CERR_RPT1_REG), PPC_BITMASK(0, 63)); + + /* + * Phase2 init step 7_c + * NestBase + StackBase + 0x0 + * 0x00000000_00000000 + * Clear any spurious FIR + * bits (NFIR)NFIR + */ + write_scom(phb_addr(phb, PHB_NFIR_REG), 0); + + /* + * Phase2 init step 8 + * NestBase + StackBase + 0x8 + * 0x00000000_00000000 + * Clear any spurious WOF bits (NFIRWOF) + */ + write_scom(phb_addr(phb, PHB_NFIRWOF_REG), 0); + + /* + * Phase2 init step 9 + * NestBase + StackBase + 0x6 + * Set the per FIR Bit Action 0 register + */ + write_scom(phb_addr(phb, PHB_NFIRACTION0_REG), PCI_NFIR_ACTION0_REG); + + /* + * Phase2 init step 10 + * NestBase + StackBase + 0x7 + * Set the per FIR Bit Action 1 register + */ + write_scom(phb_addr(phb, PHB_NFIRACTION1_REG), PCI_NFIR_ACTION1_REG); + + /* + * Phase2 init step 11 + * NestBase + StackBase + 0x3 + * Set FIR Mask Bits to allow errors (NFIRMask) + */ + write_scom(phb_addr(phb, PHB_NFIRMASK_REG), PCI_NFIR_MASK_REG); + + /* + * Phase2 init step 12 + * NestBase + StackBase + 0x15 + * 0x00000000_00000000 + * Set Data Freeze Type Register for SUE handling (DFREEZE) + */ + write_scom(phb_addr(phb, PHB_PE_DFREEZE_REG), 0); + + /* + * Phase2 init step 13_a + * PCIBase + StackBase + 0xB + * 0x00000000_00000000 + * Clear any spurious pbaib_cerr_rpt bits + */ + write_scom(phb_addr(phb, PHB_PBAIB_CERR_RPT_REG), 0); + + /* + * Phase2 init step 13_b + * PCIBase + StackBase + 0x0 + * 0x00000000_00000000 + * Clear any spurious FIR + * bits (PFIR)PFIR + */ + write_scom(phb_addr(phb, PHB_PFIR_REG), 0); + + /* + * Phase2 init step 14 + * PCIBase + StackBase + 0x8 + * 0x00000000_00000000 + * Clear any spurious WOF bits (PFIRWOF) + */ + write_scom(phb_addr(phb, PHB_PFIRWOF_REG), 0); + + /* + * Phase2 init step 15 + * PCIBase + StackBase + 0x6 + * Set the per FIR Bit Action 0 register + */ + write_scom(phb_addr(phb, PHB_PFIRACTION0_REG), PCI_PFIR_ACTION0_REG); + + /* + * Phase2 init step 16 + * PCIBase + StackBase + 0x7 + * Set the per FIR Bit Action 1 register + */ + write_scom(phb_addr(phb, PHB_PFIRACTION1_REG), PCI_PFIR_ACTION1_REG); + + /* + * Phase2 init step 17 + * PCIBase + StackBase + 0x3 + * Set FIR Mask Bits to allow errors (PFIRMask) + */ + write_scom(phb_addr(phb, PHB_PFIRMASK_REG), PCI_PFIR_MASK_REG); + + /* + * Phase2 init step 18 + * NestBase + StackBase + 0xE + * Set MMIO Base Address Register 0 (MMIOBAR0) + */ + mmio0_bar += mmio_bar0_offsets[phb]; + mmio0_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; + write_scom(phb_addr(phb, PHB_MMIOBAR0_REG), mmio0_bar); + + /* + * Phase2 init step 19 + * NestBase + StackBase + 0xF + * Set MMIO BASE Address Register Mask 0 (MMIOBAR0_MASK) + */ + write_scom(phb_addr(phb, PHB_MMIOBAR0_MASK_REG), bar_sizes[0]); + + /* + * Phase2 init step 20 + * NestBase + StackBase + 0x10 + * Set MMIO Base + * Address Register 1 (MMIOBAR1) + */ + mmio1_bar += mmio_bar1_offsets[phb]; + mmio1_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; + write_scom(phb_addr(phb, PHB_MMIOBAR1_REG), mmio1_bar); + + /* + * Phase2 init step 21 + * NestBase + StackBase + 0x11 + * Set MMIO Base Address Register Mask 1 (MMIOBAR1_MASK) + */ + write_scom(phb_addr(phb, PHB_MMIOBAR1_MASK_REG), bar_sizes[1]); + + /* + * Phase2 init step 22 + * NestBase + StackBase + 0x12 + * Set PHB Register Base address Register (PHBBAR) + */ + register_bar += register_bar_offsets[phb]; + register_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; + write_scom(phb_addr(phb, PHB_PHBBAR_REG), register_bar); + + /* + * Phase2 init step 23 + * NestBase + StackBase + 0x14 + * Set Base address Enable Register (BARE) + */ + + val = 0; + + if (l_bar_enables[0]) + val |= PPC_BIT(0); // PHB_BARE_REG_PE_MMIO_BAR0_EN, bit 0 for BAR0 + if (l_bar_enables[1]) + val |= PPC_BIT(1); // PHB_BARE_REG_PE_MMIO_BAR1_EN, bit 1 for BAR1 + if (l_bar_enables[2]) + val |= PPC_BIT(1); // PHB_BARE_REG_PE_PHB_BAR_EN, bit 2 for PHB + + write_scom(phb_addr(phb, PHB_BARE_REG), val); + + /* + * Phase2 init step 24 + * PCIBase + StackBase +0x0A + * 0x00000000_00000000 + * Remove ETU/AIB bus from reset (PHBReset) + */ + write_scom(phb_addr(phb, PHB_PHBRESET_REG), 0); + /* Configure ETU FIR (all masked) */ + write_scom(phb_addr(phb, PHB_ACT0_REG), 0); + write_scom(phb_addr(phb, PHB_ACTION1_REG), 0); + write_scom(phb_addr(phb, PHB_MASK_REG), PPC_BITMASK(0, 63)); + } } -static void phase2(const uint8_t *iovalid_enable) +static void phase2(uint8_t phb_active_mask, const uint8_t *iovalid_enable) { init_pecs(iovalid_enable); - init_phbs(iovalid_enable); + init_phbs(phb_active_mask, iovalid_enable); } void pci_init(void) @@ -783,7 +1066,7 @@ void pci_init(void) const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; - determine_lane_configs(pec_cfgs); + uint8_t phb_active_mask = determine_lane_configs(pec_cfgs); /* * Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot. @@ -795,5 +1078,5 @@ void pci_init(void) phase1(pec_cfgs, iovalid_enable); enable_ridi(); - phase2(iovalid_enable); + phase2(phb_active_mask, iovalid_enable); } From f67f7dedf417bfac49b7ded5961465dfe6cf6850 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 14 Oct 2021 01:02:26 +0300 Subject: [PATCH 07/16] Reorganize code into isteps in romstage Signed-off-by: Sergii Dmytruk --- src/include/cpu/power/istep_10.h | 11 + src/include/cpu/power/istep_14.h | 41 +- src/soc/ibm/power9/Makefile.inc | 3 +- src/soc/ibm/power9/chip.c | 4 - src/soc/ibm/power9/{pci.c => istep_10_10.c} | 494 +------------------- src/soc/ibm/power9/istep_10_12.c | 43 ++ src/soc/ibm/power9/istep_14_2.c | 11 + src/soc/ibm/power9/istep_14_3.c | 478 +++++++++++++++++-- src/soc/ibm/power9/pci.h | 14 + src/soc/ibm/power9/romstage.c | 12 +- 10 files changed, 558 insertions(+), 553 deletions(-) create mode 100644 src/include/cpu/power/istep_10.h rename src/soc/ibm/power9/{pci.c => istep_10_10.c} (55%) create mode 100644 src/soc/ibm/power9/istep_10_12.c diff --git a/src/include/cpu/power/istep_10.h b/src/include/cpu/power/istep_10.h new file mode 100644 index 00000000000..9166076ea7f --- /dev/null +++ b/src/include/cpu/power/istep_10.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef CPU_PPC64_ISTEP10_H +#define CPU_PPC64_ISTEP10_H + +#include + +void istep_10_10(uint8_t *phb_active_mask, uint8_t *iovalid_enable); +void istep_10_12(void); + +#endif /* CPU_PPC64_ISTEP10_H */ diff --git a/src/include/cpu/power/istep_14.h b/src/include/cpu/power/istep_14.h index 4f24e436598..6b35e05a8ff 100644 --- a/src/include/cpu/power/istep_14.h +++ b/src/include/cpu/power/istep_14.h @@ -1,38 +1,11 @@ -#ifndef ISTEP_14_H -#define ISTEP_14_H +/* SPDX-License-Identifier: GPL-2.0-only */ -#include +#ifndef CPU_PPC64_ISTEP14_H +#define CPU_PPC64_ISTEP14_H -#define PEC_PBCQHWCFG_REG (0x4010C00) -#define PEC_NESTTRC_REG (0x4010C03) -#define P9N2_PEC_ADDREXTMASK_REG (0x4010C05) -#define MCS_MCMODE0 (0x5010811) -#define MCS_MCSYNC (0x5010815) -#define MCA_MBA_FARB3Q (0x7010916) -#define PEC_PBAIBHWCFG_REG (0xD010800) - -#define MCS_MCSYNC_SYNC_GO_CH0 (16) -#define SUPER_SYNC_BIT (14) -#define MBA_REFRESH_SYNC_BIT (8) -#define MCS_MCMODE0_DISABLE_MC_SYNC (27) -#define MCS_MCMODE0_DISABLE_MC_PAIR_SYNC (28) -#define PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN (30) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_OOO_MODE (0x16) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP (42) -#define PEC_PBCQHWCFG_REG_PE_CHANNEL_STREAMING_EN (33) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG (41) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG (43) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP (44) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP (51) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG (54) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP (56) -#define PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG (59) - -#define PEC_PER_PROC (3) -static const chiplet_id_t pec_ids[PEC_PER_PROC] = { - PCI0_CHIPLET_ID, PCI1_CHIPLET_ID, PCI2_CHIPLET_ID, -}; +#include void istep_14_2(void); -void istep_14_3(void); -#endif +void istep_14_3(uint8_t phb_active_mask, const uint8_t *iovalid_enable); + +#endif /* CPU_PPC64_ISTEP14_H */ diff --git a/src/soc/ibm/power9/Makefile.inc b/src/soc/ibm/power9/Makefile.inc index 962f6b59aab..a3c2317b12e 100644 --- a/src/soc/ibm/power9/Makefile.inc +++ b/src/soc/ibm/power9/Makefile.inc @@ -9,6 +9,8 @@ romstage-y += romstage.c romstage-y += mvpd.c romstage-y += vpd.c romstage-y += powerbus.c +romstage-y += istep_10_10.c +romstage-y += istep_10_12.c romstage-y += istep_10_13.c romstage-y += istep_13_2.c romstage-y += istep_13_3.c @@ -39,7 +41,6 @@ ramstage-y += tor.c ramstage-y += rs4.c ramstage-y += powerbus.c ramstage-y += pstates.c -ramstage-y += pci.c ramstage-y += xive.c ramstage-y += int_vectors.S ramstage-y += i2c.c diff --git a/src/soc/ibm/power9/chip.c b/src/soc/ibm/power9/chip.c index 6772cfabb14..94e3bf7aa24 100644 --- a/src/soc/ibm/power9/chip.c +++ b/src/soc/ibm/power9/chip.c @@ -13,8 +13,6 @@ #include "homer.h" #include "istep_13_scom.h" #include "chip.h" -#include "homer.h" -#include "pci.h" /* * These are various definitions of the page sizes and segment sizes supported @@ -521,8 +519,6 @@ static void enable_soc_dev(struct device *dev) rng_init(); istep_18_11(); istep_18_12(); - - pci_init(); } /* diff --git a/src/soc/ibm/power9/pci.c b/src/soc/ibm/power9/istep_10_10.c similarity index 55% rename from src/soc/ibm/power9/pci.c rename to src/soc/ibm/power9/istep_10_10.c index 8f067eb4e7b..5b9046bfca3 100644 --- a/src/soc/ibm/power9/pci.c +++ b/src/soc/ibm/power9/istep_10_10.c @@ -1,16 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#include "pci.h" +#include -#include #include #include #include #include #include -#define MAX_PEC_PER_PROC 3 -#define MAX_PHB_PER_PROC 6 +#include "pci.h" #define MAX_LANE_GROUPS_PER_PEC 4 @@ -40,17 +38,6 @@ enum phb_to_mac { PHB_X8_X4_X4_MAC_MAP = 0x0090, }; -/* Enum giving bitmask values for enabled PHBs */ -enum phb_active_mask { - PHB_MASK_NA = 0x00, // Sentinel mask (loop terminations) - PHB0_MASK = 0x80, // PHB0 enabled - PHB1_MASK = 0x40, // PHB1 enabled - PHB2_MASK = 0x20, // PHB2 enabled - PHB3_MASK = 0x10, // PHB3 enabled - PHB4_MASK = 0x08, // PHB4 enabled - PHB5_MASK = 0x04, // PHB5 enabled -}; - /* Bit position of the PHB with the largest number a given PEC can use */ enum pec_phb_shift { PEC0_PHB_SHIFT = 7, // PHB0 only @@ -596,477 +583,14 @@ static void phase1(const struct lane_config_row **pec_cfgs, } } -static void enable_ridi(void) -{ - enum { - PERV_NET_CTRL0 = 0x000F0040, - PERV_NET_CTRL0_WOR = 0x000F0042, - }; - - uint8_t pec = 0; - - for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { - chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; - - /* Getting NET_CTRL0 register value and checking its CHIPLET_ENABLE bit */ - if (read_scom_for_chiplet(chiplet, PERV_NET_CTRL0) & PPC_BIT(0)) { - /* Enable Recievers, Drivers DI1 & DI2 */ - uint64_t val = 0; - val |= PPC_BIT(19); // NET_CTRL0.RI_N = 1 - val |= PPC_BIT(20); // NET_CTRL0.DI1_N = 1 - val |= PPC_BIT(21); // NET_CTRL0.DI2_N = 1 - write_scom_for_chiplet(chiplet, PERV_NET_CTRL0_WOR, val); - } - } -} - -static void init_pecs(const uint8_t *iovalid_enable) -{ - enum { - P9N2_PEC_ADDREXTMASK_REG = 0x4010C05, - PEC_PBCQHWCFG_REG = 0x4010C00, - PEC_NESTTRC_REG = 0x4010C03, - PEC_PBAIBHWCFG_REG = 0xD010800, - - /* powerbus.c has these too */ - MBOX_SCRATCH_REG1 = 0x00050038, - MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = (1 << 23), - }; - - uint8_t dd = get_dd(); - - uint8_t pec = 0; - - uint64_t scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); - - /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ - bool node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); - - for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { - uint64_t val = 0; - chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; - - /* - * ATTR_FABRIC_ADDR_EXTENSION_GROUP_ID = 0 - * ATTR_FABRIC_ADDR_EXTENSION_CHIP_ID = 0 - */ - scom_and_or_for_chiplet(chiplet, P9N2_PEC_ADDREXTMASK_REG, - ~PPC_BITMASK(0, 6), - PPC_SHIFT(0, 6)); - - /* - * Phase2 init step 1 - * NestBase+0x00 - * Set bits 00:03 = 0b0001 Set hang poll scale - * Set bits 04:07 = 0b0001 Set data scale - * Set bits 08:11 = 0b0001 Set hang pe scale - * Set bit 22 = 0b1 Disable out­of­order store behavior - * Set bit 33 = 0b1 Enable Channel Tag streaming behavior - * Set bits 34:35 = 0b11 Set P9 Style cache-inject behavior - * Set bits 46:48 = 0b011 Set P9 Style cache-inject rate, 1/16 cycles - * Set bit 60 = 0b1 only if PEC is bifurcated or trifurcated. - * if HW423589_option1, set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope - */ - - val = read_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG); - /* Set hang poll scale */ - val &= ~PPC_BITMASK(0, 3); - val |= PPC_SHIFT(1, 3); - /* Set data scale */ - val &= ~PPC_BITMASK(4, 7); - val |= PPC_SHIFT(1, 7); - /* Set hang pe scale */ - val &= ~PPC_BITMASK(8, 11); - val |= PPC_SHIFT(1, 11); - /* Disable out­of­order store behavior */ - val |= PPC_BIT(22); - /* Enable Channel Tag streaming behavior */ - val |= PPC_BIT(33); - - /* Set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope */ - val |= PPC_BIT(41); // PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG - val |= PPC_BIT(42); // PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP - val |= PPC_BIT(43); // PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG - val |= PPC_BIT(44); // PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP - val |= PPC_BIT(54); // PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG - val |= PPC_BIT(51); // PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP - val |= PPC_BIT(56); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP - val |= PPC_BIT(59); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG - - /* Disable P9 Style cache injects if chip is node */ - if (!node_pump_mode) { - /* - * ATTR_PROC_PCIE_CACHE_INJ_MODE - * Attribute to control the cache inject mode. - * - * DISABLE_CI = 0x0 - Disable cache inject completely. (Reset value default) - * P7_STYLE_CI = 0x1 - Use cache inject design from Power7. - * PCITLP_STYLE_CI = 0x2 - Use PCI TLP Hint bits in packet to perform the cache inject. - * P9_STYLE_CI = 0x3 - Initial attempt as cache inject. Power9 style. (Attribute default) - * - * Different cache inject modes will affect DMA write performance. The attribute default was - * selected based on various workloads and was to be the most optimal settings for Power9. - * fapi2::ATTR_PROC_PCIE_CACHE_INJ_MODE = 3 by default - */ - val &= ~PPC_BITMASK(34, 36); - val |= PPC_SHIFT(0x3, 36); - - if (dd == 0x21 || dd == 0x22 || dd == 0x23) { - /* - * ATTR_PROC_PCIE_CACHE_INJ_THROTTLE - * Attribute to control the cache inject throttling when cache inject is enable. - * - * DISABLE = 0x0 - Disable cache inject throttling. (Reset value default) - * 16_CYCLES = 0x1 - Perform 1 cache inject every 16 clock cycles. - * 32_CYCLES = 0x3 - Perform 1 cache inject every 32 clock cycles. (Attribute default) - * 64_CYCLES = 0x7 - Perform 1 cache inject every 32 clock cycles. - * - * Different throttle rates will affect DMA write performance. The attribute default - * settings were optimal settings found across various workloads. - */ - val &= ~PPC_BITMASK(46, 48); - val |= PPC_SHIFT(0x3, 48); - } - } - - if (pec == 1 || (pec == 2 && iovalid_enable[pec] != 0x4)) - val |= PPC_BIT(60); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION - - write_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG, val); - - /* - * Phase2 init step 2 - * NestBase + 0x01 - * N/A Modify Drop Priority Control Register (DrPriCtl) - */ - - /* - * Phase2 init step 3 - * NestBase + 0x03 - * Set bits 00:03 = 0b1001 Enable trace, and select - * inbound operations with addr information - */ - scom_and_or_for_chiplet(chiplet, PEC_NESTTRC_REG, - ~PPC_BITMASK(0, 3), - PPC_SHIFT(9, 3)); - - /* - * Phase2 init step 4 - * NestBase+0x05 - * N/A For use of atomics/asb_notify - */ - - /* - * Phase2 init step 5 - * NestBase+0x06 - * N/A To override scope prediction - */ - - /* - * Phase2 init step 6 - * PCIBase +0x00 - * Set bits 30 = 0b1 Enable Trace - */ - val = 0; - val |= PPC_BIT(0x1E); // PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN - val |= PPC_SHIFT(7, 0x2A); // PEC_AIB_HWCFG_OSBM_HOL_BLK_CNT - write_scom_for_chiplet(chiplet, PEC_PBAIBHWCFG_REG, val); - } -} - -static uint64_t phb_addr(uint8_t phb, uint64_t addr) -{ - chiplet_id_t chiplet; - uint8_t sat_id = (addr >> 6) & 0xF; - - if (phb == 0) { - chiplet = PCI0_CHIPLET_ID; - sat_id = (sat_id < 4 ? 1 : 4); - } else { - chiplet = PCI0_CHIPLET_ID + (phb / 3) + 1; - sat_id = (sat_id < 4 ? 1 : 4) - + ((phb % 2) ? 0 : 1) - + (2 * (phb / 5)); - } - - addr &= ~PPC_BITMASK(34, 39); - addr |= PPC_SHIFT(chiplet & 0x3F, 39); - - addr &= ~PPC_BITMASK(54, 57); - addr |= PPC_SHIFT(sat_id & 0xF, 57); - - return addr; -} - -static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) -{ - enum { - PHB_CERR_RPT0_REG = 0x4010C4A, - PHB_CERR_RPT1_REG = 0x4010C4B, - PHB_NFIR_REG = 0x4010C40, - PHB_NFIRWOF_REG = 0x4010C48, - - PHB_NFIRACTION0_REG = 0x4010C46, - PCI_NFIR_ACTION0_REG = 0x5B0F81E000000000, - - PHB_NFIRACTION1_REG = 0x4010C47, - PCI_NFIR_ACTION1_REG = 0x7F0F81E000000000, - - PHB_NFIRMASK_REG = 0x4010C43, - PCI_NFIR_MASK_REG = 0x30001C00000000, - - PHB_PE_DFREEZE_REG = 0x4010C55, - PHB_PBAIB_CERR_RPT_REG = 0xD01084B, - PHB_PFIR_REG = 0xD010840, - PHB_PFIRWOF_REG = 0xD010848, - - PHB_PFIRACTION0_REG = 0xD010846, - PCI_PFIR_ACTION0_REG = 0xB000000000000000, - - PHB_PFIRACTION1_REG = 0xD010847, - PCI_PFIR_ACTION1_REG = 0xB000000000000000, - - PHB_PFIRMASK_REG = 0xD010843, - PCI_PFIR_MASK_REG = 0xE00000000000000, - - P9_PCIE_CONFIG_BAR_SHIFT = 8, - - PHB_MMIOBAR0_REG = 0x4010C4E, - PHB_MMIOBAR0_MASK_REG = 0x4010C4F, - PHB_MMIOBAR1_REG = 0x4010C50, - PHB_MMIOBAR1_MASK_REG = 0x04010C51, - PHB_PHBBAR_REG = 0x4010C52, - PHB_BARE_REG = 0x4010C54, - - PHB_PHBRESET_REG = 0xD01084A, - PHB_ACT0_REG = 0xD01090E, - PHB_ACTION1_REG = 0xD01090F, - PHB_MASK_REG = 0xD01090B, - }; - - /* ATTR_PROC_PCIE_MMIO_BAR0_BASE_ADDR_OFFSET */ - uint64_t mmio_bar0_offsets[MAX_PHB_PER_PROC] = { 0 }; - /* ATTR_PROC_PCIE_MMIO_BAR1_BASE_ADDR_OFFSET */ - uint64_t mmio_bar1_offsets[MAX_PHB_PER_PROC] = { 0 }; - /* ATTR_PROC_PCIE_REGISTER_BAR_BASE_ADDR_OFFSET */ - uint64_t register_bar_offsets[MAX_PHB_PER_PROC] = { 0 }; - /* ATTR_PROC_PCIE_BAR_SIZE */ - uint64_t bar_sizes[3] = { 0 }; - - /* Determine base address of chip MMIO range */ - uint64_t base_addr_mmio = 0; - base_addr_mmio |= PPC_SHIFT(0, 12); // 5 bits, ATTR_PROC_FABRIC_SYSTEM_ID - base_addr_mmio |= PPC_SHIFT(0, 18); // 4 bits, ATTR_PROC_EFF_FABRIC_GROUP_ID - base_addr_mmio |= PPC_SHIFT(0, 21); // 3 bits, ATTR_PROC_EFF_FABRIC_CHIP_ID - base_addr_mmio |= PPC_SHIFT(3, 14); // 2 bits, FABRIC_ADDR_MSEL, - // nm = 0b00/01, m = 0b10, mmio = 0b11 - - uint8_t phb = 0; - for (phb = 0; phb < MAX_PHB_PER_PROC; ++phb) { - /* BAR enable attribute (ATTR_PROC_PCIE_BAR_ENABLE) */ - uint8_t l_bar_enables[3] = { 0 }; - - uint64_t val = 0; - uint64_t mmio0_bar = base_addr_mmio; - uint64_t mmio1_bar = base_addr_mmio; - uint64_t register_bar = base_addr_mmio; - - if (!(phb_active_mask & (PHB0_MASK >> phb))) - continue; - - /* - * Phase2 init step 12_a (yes, out of order) - * NestBase + StackBase + 0xA - * 0xFFFFFFFF_FFFFFFFF - * Clear any spurious cerr_rpt0 bits (cerr_rpt0) - */ - write_scom(phb_addr(phb, PHB_CERR_RPT0_REG), PPC_BITMASK(0, 63)); - - /* - * Phase2 init step 12_b (yes, out of order) - * NestBase + StackBase + 0xB - * 0xFFFFFFFF_FFFFFFFF - * Clear any spurious cerr_rpt1 bits (cerr_rpt1) - */ - write_scom(phb_addr(phb, PHB_CERR_RPT1_REG), PPC_BITMASK(0, 63)); - - /* - * Phase2 init step 7_c - * NestBase + StackBase + 0x0 - * 0x00000000_00000000 - * Clear any spurious FIR - * bits (NFIR)NFIR - */ - write_scom(phb_addr(phb, PHB_NFIR_REG), 0); - - /* - * Phase2 init step 8 - * NestBase + StackBase + 0x8 - * 0x00000000_00000000 - * Clear any spurious WOF bits (NFIRWOF) - */ - write_scom(phb_addr(phb, PHB_NFIRWOF_REG), 0); - - /* - * Phase2 init step 9 - * NestBase + StackBase + 0x6 - * Set the per FIR Bit Action 0 register - */ - write_scom(phb_addr(phb, PHB_NFIRACTION0_REG), PCI_NFIR_ACTION0_REG); - - /* - * Phase2 init step 10 - * NestBase + StackBase + 0x7 - * Set the per FIR Bit Action 1 register - */ - write_scom(phb_addr(phb, PHB_NFIRACTION1_REG), PCI_NFIR_ACTION1_REG); - - /* - * Phase2 init step 11 - * NestBase + StackBase + 0x3 - * Set FIR Mask Bits to allow errors (NFIRMask) - */ - write_scom(phb_addr(phb, PHB_NFIRMASK_REG), PCI_NFIR_MASK_REG); - - /* - * Phase2 init step 12 - * NestBase + StackBase + 0x15 - * 0x00000000_00000000 - * Set Data Freeze Type Register for SUE handling (DFREEZE) - */ - write_scom(phb_addr(phb, PHB_PE_DFREEZE_REG), 0); - - /* - * Phase2 init step 13_a - * PCIBase + StackBase + 0xB - * 0x00000000_00000000 - * Clear any spurious pbaib_cerr_rpt bits - */ - write_scom(phb_addr(phb, PHB_PBAIB_CERR_RPT_REG), 0); - - /* - * Phase2 init step 13_b - * PCIBase + StackBase + 0x0 - * 0x00000000_00000000 - * Clear any spurious FIR - * bits (PFIR)PFIR - */ - write_scom(phb_addr(phb, PHB_PFIR_REG), 0); - - /* - * Phase2 init step 14 - * PCIBase + StackBase + 0x8 - * 0x00000000_00000000 - * Clear any spurious WOF bits (PFIRWOF) - */ - write_scom(phb_addr(phb, PHB_PFIRWOF_REG), 0); - - /* - * Phase2 init step 15 - * PCIBase + StackBase + 0x6 - * Set the per FIR Bit Action 0 register - */ - write_scom(phb_addr(phb, PHB_PFIRACTION0_REG), PCI_PFIR_ACTION0_REG); - - /* - * Phase2 init step 16 - * PCIBase + StackBase + 0x7 - * Set the per FIR Bit Action 1 register - */ - write_scom(phb_addr(phb, PHB_PFIRACTION1_REG), PCI_PFIR_ACTION1_REG); - - /* - * Phase2 init step 17 - * PCIBase + StackBase + 0x3 - * Set FIR Mask Bits to allow errors (PFIRMask) - */ - write_scom(phb_addr(phb, PHB_PFIRMASK_REG), PCI_PFIR_MASK_REG); - - /* - * Phase2 init step 18 - * NestBase + StackBase + 0xE - * Set MMIO Base Address Register 0 (MMIOBAR0) - */ - mmio0_bar += mmio_bar0_offsets[phb]; - mmio0_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; - write_scom(phb_addr(phb, PHB_MMIOBAR0_REG), mmio0_bar); - - /* - * Phase2 init step 19 - * NestBase + StackBase + 0xF - * Set MMIO BASE Address Register Mask 0 (MMIOBAR0_MASK) - */ - write_scom(phb_addr(phb, PHB_MMIOBAR0_MASK_REG), bar_sizes[0]); - - /* - * Phase2 init step 20 - * NestBase + StackBase + 0x10 - * Set MMIO Base - * Address Register 1 (MMIOBAR1) - */ - mmio1_bar += mmio_bar1_offsets[phb]; - mmio1_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; - write_scom(phb_addr(phb, PHB_MMIOBAR1_REG), mmio1_bar); - - /* - * Phase2 init step 21 - * NestBase + StackBase + 0x11 - * Set MMIO Base Address Register Mask 1 (MMIOBAR1_MASK) - */ - write_scom(phb_addr(phb, PHB_MMIOBAR1_MASK_REG), bar_sizes[1]); - - /* - * Phase2 init step 22 - * NestBase + StackBase + 0x12 - * Set PHB Register Base address Register (PHBBAR) - */ - register_bar += register_bar_offsets[phb]; - register_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; - write_scom(phb_addr(phb, PHB_PHBBAR_REG), register_bar); - - /* - * Phase2 init step 23 - * NestBase + StackBase + 0x14 - * Set Base address Enable Register (BARE) - */ - - val = 0; - - if (l_bar_enables[0]) - val |= PPC_BIT(0); // PHB_BARE_REG_PE_MMIO_BAR0_EN, bit 0 for BAR0 - if (l_bar_enables[1]) - val |= PPC_BIT(1); // PHB_BARE_REG_PE_MMIO_BAR1_EN, bit 1 for BAR1 - if (l_bar_enables[2]) - val |= PPC_BIT(1); // PHB_BARE_REG_PE_PHB_BAR_EN, bit 2 for PHB - - write_scom(phb_addr(phb, PHB_BARE_REG), val); - - /* - * Phase2 init step 24 - * PCIBase + StackBase +0x0A - * 0x00000000_00000000 - * Remove ETU/AIB bus from reset (PHBReset) - */ - write_scom(phb_addr(phb, PHB_PHBRESET_REG), 0); - /* Configure ETU FIR (all masked) */ - write_scom(phb_addr(phb, PHB_ACT0_REG), 0); - write_scom(phb_addr(phb, PHB_ACTION1_REG), 0); - write_scom(phb_addr(phb, PHB_MASK_REG), PPC_BITMASK(0, 63)); - } -} - -static void phase2(uint8_t phb_active_mask, const uint8_t *iovalid_enable) -{ - init_pecs(iovalid_enable); - init_phbs(phb_active_mask, iovalid_enable); -} - -void pci_init(void) +void istep_10_10(uint8_t *phb_active_mask, uint8_t *iovalid_enable) { const struct lane_config_row *pec_cfgs[MAX_PEC_PER_PROC] = { NULL }; - uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; - uint8_t phb_active_mask = determine_lane_configs(pec_cfgs); + printk(BIOS_EMERG, "starting istep 10.10\n"); + report_istep(10,10); + + *phb_active_mask = determine_lane_configs(pec_cfgs); /* * Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot. @@ -1077,6 +601,6 @@ void pci_init(void) iovalid_enable[2] = pec_cfgs[2]->phb_active >> PEC2_PHB_SHIFT; phase1(pec_cfgs, iovalid_enable); - enable_ridi(); - phase2(phb_active_mask, iovalid_enable); + + printk(BIOS_EMERG, "ending istep 10.10\n"); } diff --git a/src/soc/ibm/power9/istep_10_12.c b/src/soc/ibm/power9/istep_10_12.c new file mode 100644 index 00000000000..1c2a56059be --- /dev/null +++ b/src/soc/ibm/power9/istep_10_12.c @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +#include +#include + +#include "pci.h" + +/* PCIe only at the moment, should also do other buses */ +static void enable_ridi(void) +{ + enum { + PERV_NET_CTRL0 = 0x000F0040, + PERV_NET_CTRL0_WOR = 0x000F0042, + }; + + uint8_t pec = 0; + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + + /* Getting NET_CTRL0 register value and checking its CHIPLET_ENABLE bit */ + if (read_scom_for_chiplet(chiplet, PERV_NET_CTRL0) & PPC_BIT(0)) { + /* Enable Recievers, Drivers DI1 & DI2 */ + uint64_t val = 0; + val |= PPC_BIT(19); // NET_CTRL0.RI_N = 1 + val |= PPC_BIT(20); // NET_CTRL0.DI1_N = 1 + val |= PPC_BIT(21); // NET_CTRL0.DI2_N = 1 + write_scom_for_chiplet(chiplet, PERV_NET_CTRL0_WOR, val); + } + } +} + +void istep_10_12(void) +{ + printk(BIOS_EMERG, "starting istep 10.12\n"); + report_istep(10,12); + + enable_ridi(); + + printk(BIOS_EMERG, "ending istep 10.12\n"); +} diff --git a/src/soc/ibm/power9/istep_14_2.c b/src/soc/ibm/power9/istep_14_2.c index dde1760fb77..1343b30b1df 100644 --- a/src/soc/ibm/power9/istep_14_2.c +++ b/src/soc/ibm/power9/istep_14_2.c @@ -2,6 +2,17 @@ #include #include +#include + +#define MCS_MCMODE0 (0x5010811) +#define MCS_MCSYNC (0x5010815) +#define MCA_MBA_FARB3Q (0x7010916) + +#define MCS_MCSYNC_SYNC_GO_CH0 (16) +#define SUPER_SYNC_BIT (14) +#define MBA_REFRESH_SYNC_BIT (8) +#define MCS_MCMODE0_DISABLE_MC_SYNC (27) +#define MCS_MCMODE0_DISABLE_MC_PAIR_SYNC (28) static void thermalInit(void) { diff --git a/src/soc/ibm/power9/istep_14_3.c b/src/soc/ibm/power9/istep_14_3.c index 4a345c6c8aa..c8fc124eaff 100644 --- a/src/soc/ibm/power9/istep_14_3.c +++ b/src/soc/ibm/power9/istep_14_3.c @@ -2,37 +2,461 @@ #include -static void p9_pcie_config(void) +#include + +#include "pci.h" + +static void init_pecs(const uint8_t *iovalid_enable) { - for(size_t PECIndex = 0; PECIndex < PEC_PER_PROC; ++PECIndex) - { - scom_and_for_chiplet( - N2_CHIPLET_ID, P9N2_PEC_ADDREXTMASK_REG + 0x400 * PECIndex, - ~PPC_BITMASK(0, 6)); - scom_or_for_chiplet( - N2_CHIPLET_ID, PEC_PBCQHWCFG_REG + 0x400 * PECIndex, - PPC_BIT(3) | PPC_BIT(7) | PPC_BIT(11) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_OOO_MODE) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_CHANNEL_STREAMING_EN) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP) - | PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG)); - scom_or_for_chiplet( - N2_CHIPLET_ID, PEC_NESTTRC_REG + 0x400 * PECIndex, - PPC_BIT(0) | PPC_BIT(3)); - write_scom_for_chiplet( - pec_ids[PECIndex], PEC_PBAIBHWCFG_REG, - 0xe00000 | PPC_BIT(PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN)); + enum { + P9N2_PEC_ADDREXTMASK_REG = 0x4010C05, + PEC_PBCQHWCFG_REG = 0x4010C00, + PEC_NESTTRC_REG = 0x4010C03, + PEC_PBAIBHWCFG_REG = 0xD010800, + + /* powerbus.c has these too */ + MBOX_SCRATCH_REG1 = 0x00050038, + MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = (1 << 23), + + PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN = 30, + PEC_PBCQHWCFG_REG_PE_DISABLE_OOO_MODE = 0x16, + PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP = 42, + PEC_PBCQHWCFG_REG_PE_CHANNEL_STREAMING_EN = 33, + PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG = 41, + PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG = 43, + PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP = 44, + PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP = 51, + PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG = 54, + PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP = 56, + PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG = 59, + }; + + uint8_t dd = get_dd(); + + uint8_t pec = 0; + + uint64_t scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); + + /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ + bool node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); + + for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { + uint64_t val = 0; + chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + + /* + * ATTR_FABRIC_ADDR_EXTENSION_GROUP_ID = 0 + * ATTR_FABRIC_ADDR_EXTENSION_CHIP_ID = 0 + */ + scom_and_or_for_chiplet(chiplet, P9N2_PEC_ADDREXTMASK_REG, + ~PPC_BITMASK(0, 6), + PPC_SHIFT(0, 6)); + + /* + * Phase2 init step 1 + * NestBase+0x00 + * Set bits 00:03 = 0b0001 Set hang poll scale + * Set bits 04:07 = 0b0001 Set data scale + * Set bits 08:11 = 0b0001 Set hang pe scale + * Set bit 22 = 0b1 Disable out­of­order store behavior + * Set bit 33 = 0b1 Enable Channel Tag streaming behavior + * Set bits 34:35 = 0b11 Set P9 Style cache-inject behavior + * Set bits 46:48 = 0b011 Set P9 Style cache-inject rate, 1/16 cycles + * Set bit 60 = 0b1 only if PEC is bifurcated or trifurcated. + * if HW423589_option1, set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope + */ + + val = read_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG); + /* Set hang poll scale */ + val &= ~PPC_BITMASK(0, 3); + val |= PPC_SHIFT(1, 3); + /* Set data scale */ + val &= ~PPC_BITMASK(4, 7); + val |= PPC_SHIFT(1, 7); + /* Set hang pe scale */ + val &= ~PPC_BITMASK(8, 11); + val |= PPC_SHIFT(1, 11); + /* Disable out­of­order store behavior */ + val |= PPC_BIT(22); + /* Enable Channel Tag streaming behavior */ + val |= PPC_BIT(33); + + /* Set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope */ + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP); + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG); + + /* Disable P9 Style cache injects if chip is node */ + if (!node_pump_mode) { + /* + * ATTR_PROC_PCIE_CACHE_INJ_MODE + * Attribute to control the cache inject mode. + * + * DISABLE_CI = 0x0 - Disable cache inject completely. (Reset value default) + * P7_STYLE_CI = 0x1 - Use cache inject design from Power7. + * PCITLP_STYLE_CI = 0x2 - Use PCI TLP Hint bits in packet to perform the cache inject. + * P9_STYLE_CI = 0x3 - Initial attempt as cache inject. Power9 style. (Attribute default) + * + * Different cache inject modes will affect DMA write performance. The attribute default was + * selected based on various workloads and was to be the most optimal settings for Power9. + * fapi2::ATTR_PROC_PCIE_CACHE_INJ_MODE = 3 by default + */ + val &= ~PPC_BITMASK(34, 36); + val |= PPC_SHIFT(0x3, 36); + + if (dd == 0x21 || dd == 0x22 || dd == 0x23) { + /* + * ATTR_PROC_PCIE_CACHE_INJ_THROTTLE + * Attribute to control the cache inject throttling when cache inject is enable. + * + * DISABLE = 0x0 - Disable cache inject throttling. (Reset value default) + * 16_CYCLES = 0x1 - Perform 1 cache inject every 16 clock cycles. + * 32_CYCLES = 0x3 - Perform 1 cache inject every 32 clock cycles. (Attribute default) + * 64_CYCLES = 0x7 - Perform 1 cache inject every 32 clock cycles. + * + * Different throttle rates will affect DMA write performance. The attribute default + * settings were optimal settings found across various workloads. + */ + val &= ~PPC_BITMASK(46, 48); + val |= PPC_SHIFT(0x3, 48); + } + } + + if (pec == 1 || (pec == 2 && iovalid_enable[pec] != 0x4)) + val |= PPC_BIT(60); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION + + write_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG, val); + + /* + * Phase2 init step 2 + * NestBase + 0x01 + * N/A Modify Drop Priority Control Register (DrPriCtl) + */ + + /* + * Phase2 init step 3 + * NestBase + 0x03 + * Set bits 00:03 = 0b1001 Enable trace, and select + * inbound operations with addr information + */ + scom_and_or_for_chiplet(chiplet, PEC_NESTTRC_REG, + ~PPC_BITMASK(0, 3), + PPC_SHIFT(9, 3)); + + /* + * Phase2 init step 4 + * NestBase+0x05 + * N/A For use of atomics/asb_notify + */ + + /* + * Phase2 init step 5 + * NestBase+0x06 + * N/A To override scope prediction + */ + + /* + * Phase2 init step 6 + * PCIBase +0x00 + * Set bits 30 = 0b1 Enable Trace + */ + val = 0; + val |= PPC_BIT(0x1E); // PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN + val |= PPC_SHIFT(7, 0x2A); // PEC_AIB_HWCFG_OSBM_HOL_BLK_CNT + write_scom_for_chiplet(chiplet, PEC_PBAIBHWCFG_REG, val); + } +} + +static uint64_t phb_addr(uint8_t phb, uint64_t addr) +{ + chiplet_id_t chiplet; + uint8_t sat_id = (addr >> 6) & 0xF; + + if (phb == 0) { + chiplet = PCI0_CHIPLET_ID; + sat_id = (sat_id < 4 ? 1 : 4); + } else { + chiplet = PCI0_CHIPLET_ID + (phb / 3) + 1; + sat_id = (sat_id < 4 ? 1 : 4) + + ((phb % 2) ? 0 : 1) + + (2 * (phb / 5)); + } + + addr &= ~PPC_BITMASK(34, 39); + addr |= PPC_SHIFT(chiplet & 0x3F, 39); + + addr &= ~PPC_BITMASK(54, 57); + addr |= PPC_SHIFT(sat_id & 0xF, 57); + + return addr; +} + +static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) +{ + enum { + PHB_CERR_RPT0_REG = 0x4010C4A, + PHB_CERR_RPT1_REG = 0x4010C4B, + PHB_NFIR_REG = 0x4010C40, + PHB_NFIRWOF_REG = 0x4010C48, + + PHB_NFIRACTION0_REG = 0x4010C46, + PCI_NFIR_ACTION0_REG = 0x5B0F81E000000000, + + PHB_NFIRACTION1_REG = 0x4010C47, + PCI_NFIR_ACTION1_REG = 0x7F0F81E000000000, + + PHB_NFIRMASK_REG = 0x4010C43, + PCI_NFIR_MASK_REG = 0x30001C00000000, + + PHB_PE_DFREEZE_REG = 0x4010C55, + PHB_PBAIB_CERR_RPT_REG = 0xD01084B, + PHB_PFIR_REG = 0xD010840, + PHB_PFIRWOF_REG = 0xD010848, + + PHB_PFIRACTION0_REG = 0xD010846, + PCI_PFIR_ACTION0_REG = 0xB000000000000000, + + PHB_PFIRACTION1_REG = 0xD010847, + PCI_PFIR_ACTION1_REG = 0xB000000000000000, + + PHB_PFIRMASK_REG = 0xD010843, + PCI_PFIR_MASK_REG = 0xE00000000000000, + + P9_PCIE_CONFIG_BAR_SHIFT = 8, + + PHB_MMIOBAR0_REG = 0x4010C4E, + PHB_MMIOBAR0_MASK_REG = 0x4010C4F, + PHB_MMIOBAR1_REG = 0x4010C50, + PHB_MMIOBAR1_MASK_REG = 0x04010C51, + PHB_PHBBAR_REG = 0x4010C52, + PHB_BARE_REG = 0x4010C54, + + PHB_PHBRESET_REG = 0xD01084A, + PHB_ACT0_REG = 0xD01090E, + PHB_ACTION1_REG = 0xD01090F, + PHB_MASK_REG = 0xD01090B, + }; + + /* ATTR_PROC_PCIE_MMIO_BAR0_BASE_ADDR_OFFSET */ + uint64_t mmio_bar0_offsets[MAX_PHB_PER_PROC] = { 0 }; + /* ATTR_PROC_PCIE_MMIO_BAR1_BASE_ADDR_OFFSET */ + uint64_t mmio_bar1_offsets[MAX_PHB_PER_PROC] = { 0 }; + /* ATTR_PROC_PCIE_REGISTER_BAR_BASE_ADDR_OFFSET */ + uint64_t register_bar_offsets[MAX_PHB_PER_PROC] = { 0 }; + /* ATTR_PROC_PCIE_BAR_SIZE */ + uint64_t bar_sizes[3] = { 0 }; + + /* Determine base address of chip MMIO range */ + uint64_t base_addr_mmio = 0; + base_addr_mmio |= PPC_SHIFT(0, 12); // 5 bits, ATTR_PROC_FABRIC_SYSTEM_ID + base_addr_mmio |= PPC_SHIFT(0, 18); // 4 bits, ATTR_PROC_EFF_FABRIC_GROUP_ID + base_addr_mmio |= PPC_SHIFT(0, 21); // 3 bits, ATTR_PROC_EFF_FABRIC_CHIP_ID + base_addr_mmio |= PPC_SHIFT(3, 14); // 2 bits, FABRIC_ADDR_MSEL, + // nm = 0b00/01, m = 0b10, mmio = 0b11 + + uint8_t phb = 0; + for (phb = 0; phb < MAX_PHB_PER_PROC; ++phb) { + /* BAR enable attribute (ATTR_PROC_PCIE_BAR_ENABLE) */ + uint8_t l_bar_enables[3] = { 0 }; + + uint64_t val = 0; + uint64_t mmio0_bar = base_addr_mmio; + uint64_t mmio1_bar = base_addr_mmio; + uint64_t register_bar = base_addr_mmio; + + if (!(phb_active_mask & (PHB0_MASK >> phb))) + continue; + + /* + * Phase2 init step 12_a (yes, out of order) + * NestBase + StackBase + 0xA + * 0xFFFFFFFF_FFFFFFFF + * Clear any spurious cerr_rpt0 bits (cerr_rpt0) + */ + write_scom(phb_addr(phb, PHB_CERR_RPT0_REG), PPC_BITMASK(0, 63)); + + /* + * Phase2 init step 12_b (yes, out of order) + * NestBase + StackBase + 0xB + * 0xFFFFFFFF_FFFFFFFF + * Clear any spurious cerr_rpt1 bits (cerr_rpt1) + */ + write_scom(phb_addr(phb, PHB_CERR_RPT1_REG), PPC_BITMASK(0, 63)); + + /* + * Phase2 init step 7_c + * NestBase + StackBase + 0x0 + * 0x00000000_00000000 + * Clear any spurious FIR + * bits (NFIR)NFIR + */ + write_scom(phb_addr(phb, PHB_NFIR_REG), 0); + + /* + * Phase2 init step 8 + * NestBase + StackBase + 0x8 + * 0x00000000_00000000 + * Clear any spurious WOF bits (NFIRWOF) + */ + write_scom(phb_addr(phb, PHB_NFIRWOF_REG), 0); + + /* + * Phase2 init step 9 + * NestBase + StackBase + 0x6 + * Set the per FIR Bit Action 0 register + */ + write_scom(phb_addr(phb, PHB_NFIRACTION0_REG), PCI_NFIR_ACTION0_REG); + + /* + * Phase2 init step 10 + * NestBase + StackBase + 0x7 + * Set the per FIR Bit Action 1 register + */ + write_scom(phb_addr(phb, PHB_NFIRACTION1_REG), PCI_NFIR_ACTION1_REG); + + /* + * Phase2 init step 11 + * NestBase + StackBase + 0x3 + * Set FIR Mask Bits to allow errors (NFIRMask) + */ + write_scom(phb_addr(phb, PHB_NFIRMASK_REG), PCI_NFIR_MASK_REG); + + /* + * Phase2 init step 12 + * NestBase + StackBase + 0x15 + * 0x00000000_00000000 + * Set Data Freeze Type Register for SUE handling (DFREEZE) + */ + write_scom(phb_addr(phb, PHB_PE_DFREEZE_REG), 0); + + /* + * Phase2 init step 13_a + * PCIBase + StackBase + 0xB + * 0x00000000_00000000 + * Clear any spurious pbaib_cerr_rpt bits + */ + write_scom(phb_addr(phb, PHB_PBAIB_CERR_RPT_REG), 0); + + /* + * Phase2 init step 13_b + * PCIBase + StackBase + 0x0 + * 0x00000000_00000000 + * Clear any spurious FIR + * bits (PFIR)PFIR + */ + write_scom(phb_addr(phb, PHB_PFIR_REG), 0); + + /* + * Phase2 init step 14 + * PCIBase + StackBase + 0x8 + * 0x00000000_00000000 + * Clear any spurious WOF bits (PFIRWOF) + */ + write_scom(phb_addr(phb, PHB_PFIRWOF_REG), 0); + + /* + * Phase2 init step 15 + * PCIBase + StackBase + 0x6 + * Set the per FIR Bit Action 0 register + */ + write_scom(phb_addr(phb, PHB_PFIRACTION0_REG), PCI_PFIR_ACTION0_REG); + + /* + * Phase2 init step 16 + * PCIBase + StackBase + 0x7 + * Set the per FIR Bit Action 1 register + */ + write_scom(phb_addr(phb, PHB_PFIRACTION1_REG), PCI_PFIR_ACTION1_REG); + + /* + * Phase2 init step 17 + * PCIBase + StackBase + 0x3 + * Set FIR Mask Bits to allow errors (PFIRMask) + */ + write_scom(phb_addr(phb, PHB_PFIRMASK_REG), PCI_PFIR_MASK_REG); + + /* + * Phase2 init step 18 + * NestBase + StackBase + 0xE + * Set MMIO Base Address Register 0 (MMIOBAR0) + */ + mmio0_bar += mmio_bar0_offsets[phb]; + mmio0_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; + write_scom(phb_addr(phb, PHB_MMIOBAR0_REG), mmio0_bar); + + /* + * Phase2 init step 19 + * NestBase + StackBase + 0xF + * Set MMIO BASE Address Register Mask 0 (MMIOBAR0_MASK) + */ + write_scom(phb_addr(phb, PHB_MMIOBAR0_MASK_REG), bar_sizes[0]); + + /* + * Phase2 init step 20 + * NestBase + StackBase + 0x10 + * Set MMIO Base + * Address Register 1 (MMIOBAR1) + */ + mmio1_bar += mmio_bar1_offsets[phb]; + mmio1_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; + write_scom(phb_addr(phb, PHB_MMIOBAR1_REG), mmio1_bar); + + /* + * Phase2 init step 21 + * NestBase + StackBase + 0x11 + * Set MMIO Base Address Register Mask 1 (MMIOBAR1_MASK) + */ + write_scom(phb_addr(phb, PHB_MMIOBAR1_MASK_REG), bar_sizes[1]); + + /* + * Phase2 init step 22 + * NestBase + StackBase + 0x12 + * Set PHB Register Base address Register (PHBBAR) + */ + register_bar += register_bar_offsets[phb]; + register_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; + write_scom(phb_addr(phb, PHB_PHBBAR_REG), register_bar); + + /* + * Phase2 init step 23 + * NestBase + StackBase + 0x14 + * Set Base address Enable Register (BARE) + */ + + val = 0; + + if (l_bar_enables[0]) + val |= PPC_BIT(0); // PHB_BARE_REG_PE_MMIO_BAR0_EN, bit 0 for BAR0 + if (l_bar_enables[1]) + val |= PPC_BIT(1); // PHB_BARE_REG_PE_MMIO_BAR1_EN, bit 1 for BAR1 + if (l_bar_enables[2]) + val |= PPC_BIT(1); // PHB_BARE_REG_PE_PHB_BAR_EN, bit 2 for PHB + + write_scom(phb_addr(phb, PHB_BARE_REG), val); + + /* + * Phase2 init step 24 + * PCIBase + StackBase +0x0A + * 0x00000000_00000000 + * Remove ETU/AIB bus from reset (PHBReset) + */ + write_scom(phb_addr(phb, PHB_PHBRESET_REG), 0); + /* Configure ETU FIR (all masked) */ + write_scom(phb_addr(phb, PHB_ACT0_REG), 0); + write_scom(phb_addr(phb, PHB_ACTION1_REG), 0); + write_scom(phb_addr(phb, PHB_MASK_REG), PPC_BITMASK(0, 63)); } } -void istep_14_3(void) +void istep_14_3(uint8_t phb_active_mask, const uint8_t *iovalid_enable) { report_istep(14, 3); - p9_pcie_config(); + + init_pecs(iovalid_enable); + init_phbs(phb_active_mask, iovalid_enable); } diff --git a/src/soc/ibm/power9/pci.h b/src/soc/ibm/power9/pci.h index ff67298d1e6..1f3012a85f3 100644 --- a/src/soc/ibm/power9/pci.h +++ b/src/soc/ibm/power9/pci.h @@ -3,6 +3,20 @@ #ifndef __SOC_IBM_POWER9_HOMER_H #define __SOC_IBM_POWER9_HOMER_H +#define MAX_PEC_PER_PROC 3 +#define MAX_PHB_PER_PROC 6 + +/* Enum giving bitmask values for enabled PHBs */ +enum phb_active_mask { + PHB_MASK_NA = 0x00, // Sentinel mask (loop terminations) + PHB0_MASK = 0x80, // PHB0 enabled + PHB1_MASK = 0x40, // PHB1 enabled + PHB2_MASK = 0x20, // PHB2 enabled + PHB3_MASK = 0x10, // PHB3 enabled + PHB4_MASK = 0x08, // PHB4 enabled + PHB5_MASK = 0x04, // PHB5 enabled +}; + void pci_init(void); #endif /* __SOC_IBM_POWER9_HOMER_H */ diff --git a/src/soc/ibm/power9/romstage.c b/src/soc/ibm/power9/romstage.c index c9741b76e1a..cc686e41ea1 100644 --- a/src/soc/ibm/power9/romstage.c +++ b/src/soc/ibm/power9/romstage.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -11,6 +12,8 @@ #include #include +#include "pci.h" + mcbist_data_t mem_data; static void dump_mca_data(mca_data_t *mca) @@ -334,6 +337,9 @@ void istep_10_13(void); void main(void) { + uint8_t phb_active_mask = 0; + uint8_t iovalid_enable[MAX_PEC_PER_PROC] = { 0 }; + timestamp_add_now(TS_START_ROMSTAGE); console_init(); @@ -347,6 +353,9 @@ void main(void) vpd_pnor_main(); prepare_dimm_data(); + istep_10_10(&phb_active_mask, iovalid_enable); + istep_10_12(); + report_istep(13,1); // no-op istep_13_2(); istep_13_3(); @@ -363,8 +372,7 @@ void main(void) istep_14_1(); istep_14_2(); - /* istep_14_3 doesn't work, probably due to missing SCOM init, skip for now. */ - // istep_14_3(); + istep_14_3(phb_active_mask, iovalid_enable); report_istep(14,4); // no-op istep_14_5(); From 48545ed9afb5a081ec42a6c159a783e8125e009e Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Fri, 15 Oct 2021 01:03:47 +0300 Subject: [PATCH 08/16] Remove bad check for dying Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_10_10.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/soc/ibm/power9/istep_10_10.c b/src/soc/ibm/power9/istep_10_10.c index 5b9046bfca3..f0507d93ad4 100644 --- a/src/soc/ibm/power9/istep_10_10.c +++ b/src/soc/ibm/power9/istep_10_10.c @@ -223,8 +223,6 @@ static enum lane_width lane_mask_to_width(uint16_t mask) width = LANE_WIDTH_8X; else if (mask == LANE_MASK_X4_GRP0 || mask == LANE_MASK_X4_GRP1) width = LANE_WIDTH_4X; - else - die("Invalid value for lane mask: 0x%04x\n", mask); return width; } From 86c7ea5e2f3550e4a9fd5879730daf7b9efd4529 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Fri, 15 Oct 2021 01:11:09 +0300 Subject: [PATCH 09/16] Small code improvements Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_14_3.c | 38 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/soc/ibm/power9/istep_14_3.c b/src/soc/ibm/power9/istep_14_3.c index c8fc124eaff..1280d5bf237 100644 --- a/src/soc/ibm/power9/istep_14_3.c +++ b/src/soc/ibm/power9/istep_14_3.c @@ -2,6 +2,7 @@ #include +#include #include #include "pci.h" @@ -18,24 +19,24 @@ static void init_pecs(const uint8_t *iovalid_enable) MBOX_SCRATCH_REG1 = 0x00050038, MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = (1 << 23), - PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN = 30, - PEC_PBCQHWCFG_REG_PE_DISABLE_OOO_MODE = 0x16, - PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP = 42, - PEC_PBCQHWCFG_REG_PE_CHANNEL_STREAMING_EN = 33, - PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG = 41, - PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG = 43, - PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP = 44, - PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP = 51, - PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG = 54, - PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP = 56, - PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG = 59, + PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN = 30, + PEC_PBCQHWCFG_REG_PE_DISABLE_OOO_MODE = 0x16, + PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP = 42, + PEC_PBCQHWCFG_REG_PE_CHANNEL_STREAMING_EN = 33, + PEC_PBCQHWCFG_REG_PE_DISABLE_WR_VG = 41, + PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_VG = 43, + PEC_PBCQHWCFG_REG_PE_DISABLE_INTWR_SCOPE_GROUP = 44, + PEC_PBCQHWCFG_REG_PE_DISABLE_RD_SCOPE_GROUP = 51, + PEC_PBCQHWCFG_REG_PE_DISABLE_RD_VG = 54, + PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_SCOPE_GROUP = 56, + PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_VG = 59, }; - uint8_t dd = get_dd(); - + uint64_t scratch_reg6 = 0; uint8_t pec = 0; + uint8_t dd = get_dd(); - uint64_t scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); + scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ bool node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); @@ -44,6 +45,8 @@ static void init_pecs(const uint8_t *iovalid_enable) uint64_t val = 0; chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + printk(BIOS_EMERG, "Initializing PEC%d...\n", pec); + /* * ATTR_FABRIC_ADDR_EXTENSION_GROUP_ID = 0 * ATTR_FABRIC_ADDR_EXTENSION_CHIP_ID = 0 @@ -272,6 +275,8 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) if (!(phb_active_mask & (PHB0_MASK >> phb))) continue; + printk(BIOS_EMERG, "Initializing PHB%d...\n", phb); + /* * Phase2 init step 12_a (yes, out of order) * NestBase + StackBase + 0xA @@ -455,8 +460,11 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) void istep_14_3(uint8_t phb_active_mask, const uint8_t *iovalid_enable) { - report_istep(14, 3); + printk(BIOS_EMERG, "starting istep 14.3\n"); + report_istep(14,3); init_pecs(iovalid_enable); init_phbs(phb_active_mask, iovalid_enable); + + printk(BIOS_EMERG, "ending istep 14.3\n"); } From 951aa9648f415f072f199499fc3958795f635c1a Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sat, 16 Oct 2021 00:44:55 +0300 Subject: [PATCH 10/16] Fixes for istep 10.10 Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_10_10.c | 131 +++++++++++++++++-------------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/src/soc/ibm/power9/istep_10_10.c b/src/soc/ibm/power9/istep_10_10.c index f0507d93ad4..f46d0d7e3e4 100644 --- a/src/soc/ibm/power9/istep_10_10.c +++ b/src/soc/ibm/power9/istep_10_10.c @@ -54,8 +54,7 @@ struct lane_config_row { * Grouping of lanes under one IOP. * Value signifies width of each PCIE lane set (0, 4, 8, or 16). */ - // enum lane_width - uint8_t lane_set[MAX_LANE_GROUPS_PER_PEC]; + uint8_t lane_set[MAX_LANE_GROUPS_PER_PEC]; // enum lane_width /* IOP config value from PCIE IOP configuration table */ uint8_t lane_config; @@ -69,11 +68,9 @@ struct lane_config_row { * PHB4 = 0x08 * PHB5 = 0x04 */ - // enum phb_active_mask - uint8_t phb_active; + uint8_t phb_active; // enum phb_active_mask - // enum phb_to_mac - uint16_t phb_to_pcie_mac; + uint16_t phb_to_pcie_mac; // enum phb_to_mac }; /* @@ -167,8 +164,15 @@ static const size_t pec_lane_cfg_sizes[] = { ARRAY_SIZE(pec2_lane_cfg) }; -// TODO: find (possibly dynamic) source of these values -// enum lane_width +/* + * This probably comes from parsing PEC_PCIE_HX_KEYWORD_DATA in Hostboot, its + * description: + * This attribute holds the contents of the HX keyword read by the FSP + * from a PCIe card. + * genHwsvMrwXml.pl has some defaults but with a different value for PEC2. + * Defaults differ among processors. + * enum lane_width + */ static uint16_t lane_masks[MAX_PEC_PER_PROC][MAX_LANE_GROUPS_PER_PEC] = { { LANE_MASK_X16, 0x0, 0x0, 0x0 }, { LANE_MASK_X8_GRP0, 0x0, LANE_MASK_X8_GRP1, 0x0 }, @@ -236,8 +240,7 @@ static uint8_t determine_lane_configs(const struct lane_config_row **pec_cfgs) uint8_t i; uint8_t lane_group; - // enum lane_width - uint16_t lane_mask[MAX_LANE_GROUPS_PER_PEC]; + uint16_t lane_mask[MAX_LANE_GROUPS_PER_PEC]; // enum lane_width memcpy(&lane_mask, &lane_masks[pec], sizeof(lane_mask)); struct lane_config_row config = { @@ -264,9 +267,13 @@ static uint8_t determine_lane_configs(const struct lane_config_row **pec_cfgs) pec_cfgs[pec] = &pec_lane_cfgs[pec][i]; - // PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_cfgs[pec]->lane_config - // PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 - // PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac + /* + * In the rest of PCIe-related code the following PEC attributes have these + * values: + * - PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_cfgs[pec]->lane_config + * - PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 + * - PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac + */ } return phb_active_mask; @@ -281,13 +288,13 @@ static uint64_t pec_val(int pec_id, uint8_t in, switch (pec_id) { case 0: - out = PPC_SHIFT(in & ((1 << pec0_c) - 1), pec0_s); + out = PPC_SHIFT(in & ((1 << pec0_c) - 1), pec0_s + pec0_c - 1); break; case 1: - out = PPC_SHIFT(in & ((1 << pec1_c) - 1), pec1_s); + out = PPC_SHIFT(in & ((1 << pec1_c) - 1), pec1_s + pec1_c - 1); break; case 2: - out = PPC_SHIFT(in & ((1 << pec2_c) - 1), pec2_s); + out = PPC_SHIFT(in & ((1 << pec2_c) - 1), pec2_s + pec2_c - 1); break; default: die("Unknown PEC ID: %d\n", pec_id); @@ -304,6 +311,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, PEC_CPLT_CTRL0_OR = 0x0D000010, PEC_CPLT_CONF1_CLEAR = 0x0D000029, + PEC_PCS_RX_ROT_CNTL_REG = 0x800004820D010C3F, PEC_PCS_RX_CONFIG_MODE_REG = 0x800004800D010C3F, PEC_PCS_RX_CDR_GAIN_REG = 0x800004B30D010C3F, PEC_PCS_RX_SIGDET_CONTROL_REG = 0x800004A70D010C3F, @@ -346,7 +354,13 @@ static void phase1(const struct lane_config_row **pec_cfgs, PEC_PCS_RX_VGA_CONTROL1_REG = 0x8000048B0D010C3F, PEC_PCS_RX_VGA_CONTROL2_REG = 0x8000048C0D010C3F, + PEC_IOP_RX_DFE_FUNC_REGISTER1 = 0x8000049F0D010C3F, PEC_PCS_SYS_CONTROL_REG = 0x80000C000D010C3F, + + PEC_PCS_M1_CONTROL_REG = 0x80000C010D010C3F, + PEC_PCS_M2_CONTROL_REG = 0x80000C020D010C3F, + PEC_PCS_M3_CONTROL_REG = 0x80000C030D010C3F, + PEC_PCS_M4_CONTROL_REG = 0x80000C040D010C3F, }; uint8_t pec = 0; @@ -370,8 +384,11 @@ static void phase1(const struct lane_config_row **pec_cfgs, /* Phase1 init step 2b */ - /* ATTR_PROC_PCIE_IOP_SWAP, from talos.xml */ - proc_pcie_iop_swap = 0; + /* + * FIXME: ATTR_PROC_PCIE_IOP_SWAP, might be computed by processPec() in + * processMrw.pl and stored somewhere, this is based on logs... + */ + proc_pcie_iop_swap = (pec == 0); val = pec_val(pec, proc_pcie_iop_swap, PEC0_IOP_SWAP_START_BIT, PEC0_IOP_BIT_COUNT, @@ -450,127 +467,119 @@ static void phase1(const struct lane_config_row **pec_cfgs, uint8_t lane; /* RX Config Mode */ - // write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, - PPC_SHIFT(pcs_config_mode[i], 48)); + pcs_config_mode[i]); /* RX CDR GAIN */ - // scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_CDR_GAIN_REG, ~PPC_BITMASK(56, 63), - PPC_SHIFT(pcs_cdr_gain[i], 63)); + pcs_cdr_gain[i]); for (lane = 0; lane < NUM_PCIE_LANES; ++lane) { /* RX INITGAIN */ - // scom_and_or_for_chiplet(chiplet, RX_VGA_CTRL3_REGISTER[lane], ~PPC_BITMASK(48, 52), - PPC_SHIFT(pcs_init_gain, 48)); + PPC_SHIFT(pcs_init_gain, 52)); /* RX PKINIT */ - // scom_and_or_for_chiplet(chiplet, RX_LOFF_CNTL_REGISTER[lane], ~PPC_BITMASK(58, 63), - PPC_SHIFT(pcs_pk_init, 63)); + pcs_pk_init); } /* RX SIGDET LVL */ - // scom_and_or_for_chiplet(chiplet, PEC_PCS_RX_SIGDET_CONTROL_REG, ~PPC_BITMASK(59, 63), - PPC_SHIFT(pcs_sigdet_lvl, 63)); + pcs_sigdet_lvl); } /* - * Phase1 init step 12 (RX Rot Cntl CDR Lookahead Disabled,SSC Disabled) + * Phase1 init step 12 (RX Rot Cntl CDR Lookahead Disabled, SSC Disabled) * - * Skipping update of PEC_PCS_RX_ROT_CNTL_REG, because all these attributes are zero - * for Nimbus and there is nothing to update: - * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_LOOKAHEAD - * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_SSC - * - ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL - * - ATTR_PROC_PCIE_PCS_RX_ROT_RST_FW + * All these attributes seem to be zero for Nimbus: + * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_LOOKAHEAD (55) + * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_SSC (63) + * - ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL (59) + * - ATTR_PROC_PCIE_PCS_RX_ROT_RST_FW (62) */ + scom_and_for_chiplet(chiplet, PEC_PCS_RX_ROT_CNTL_REG, + ~(PPC_BIT(55) | PPC_BIT(63) | PPC_BIT(59) | PPC_BIT(62))); /* Phase1 init step 13 (RX Config Mode Enable External Config Control) */ - // verify this and other shifts below - write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, - PPC_SHIFT(0x8600, 48)); + write_scom_for_chiplet(chiplet, PEC_PCS_RX_CONFIG_MODE_REG, 0x8600); /* Phase1 init step 14 (PCLCK Control Register - PLLA) */ /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLA = 0xF8 */ scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLA_REG, ~PPC_BITMASK(56, 63), - PPC_SHIFT(0xf8, 63)); + 0xf8); /* Phase1 init step 15 (PCLCK Control Register - PLLB) */ /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLB = 0xF8 */ scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLB_REG, ~PPC_BITMASK(56, 63), - PPC_SHIFT(0xf8, 63)); + 0xf8); /* Phase1 init step 16 (TX DCLCK Rotator Override) */ /* ATTR_PROC_PCIE_PCS_TX_DCLCK_ROT = 0x0022 */ - write_scom_for_chiplet(chiplet, PEC_PCS_TX_DCLCK_ROTATOR_REG, - PPC_SHIFT(0x0022, 48)); + write_scom_for_chiplet(chiplet, PEC_PCS_TX_DCLCK_ROTATOR_REG, 0x0022); /* Phase1 init step 17 (TX PCIe Receiver Detect Control Register 1) */ /* ATTR_PROC_PCIE_PCS_TX_PCIE_RECV_DETECT_CNTL_REG1 = 0xAA7A */ - write_scom_for_chiplet(chiplet, PEC_PCS_TX_PCIE_REC_DETECT_CNTL1_REG, - PPC_SHIFT(0xaa7a, 48)); + write_scom_for_chiplet(chiplet, PEC_PCS_TX_PCIE_REC_DETECT_CNTL1_REG, 0xaa7a); /* Phase1 init step 18 (TX PCIe Receiver Detect Control Register 2) */ /* ATTR_PROC_PCIE_PCS_TX_PCIE_RECV_DETECT_CNTL_REG2 = 0x2000 */ - write_scom_for_chiplet(chiplet, PEC_PCS_TX_PCIE_REC_DETECT_CNTL2_REG, - PPC_SHIFT(0x2000, 48)); + write_scom_for_chiplet(chiplet, PEC_PCS_TX_PCIE_REC_DETECT_CNTL2_REG, 0x2000); /* Phase1 init step 19 (TX Power Sequence Enable) */ - /* ATTR_PROC_PCIE_PCS_TX_POWER_SEQ_ENABLE = 0xFF */ + /* ATTR_PROC_PCIE_PCS_TX_POWER_SEQ_ENABLE = 0xFF, but field is 7 bits */ scom_and_or_for_chiplet(chiplet, PEC_PCS_TX_POWER_SEQ_ENABLE_REG, ~PPC_BITMASK(56, 62), - PPC_SHIFT(0xff, 56)); + PPC_SHIFT(0x7f, 62)); /* Phase1 init step 20 (RX VGA Control Register 1) */ /* ATTR_PROC_PCIE_PCS_RX_VGA_CNTL_REG1 = 0 */ - val = PPC_SHIFT(0, 48); + val = 0; - /* Becase ATTR_CHIP_EC_FEATURE_HW414759 = 1 */ - val |= PPC_BIT(PEC_SCOM0X0B_EDMOD); - val |= PPC_BIT(PEC_SCOM0X0B_EDMOD + 1); + /* ATTR_CHIP_EC_FEATURE_HW414759 = 0, so not setting PEC_SCOM0X0B_EDMOD */ write_scom_for_chiplet(chiplet, PEC_PCS_RX_VGA_CONTROL1_REG, val); /* Phase1 init step 21 (RX VGA Control Register 2) */ /* ATTR_PROC_PCIE_PCS_RX_VGA_CNTL_REG2 = 0 */ - write_scom_for_chiplet(chiplet, PEC_PCS_RX_VGA_CONTROL2_REG, - PPC_SHIFT(0, 48)); + write_scom_for_chiplet(chiplet, PEC_PCS_RX_VGA_CONTROL2_REG, 0); /* Phase1 init step 22 (RX DFE Func Control Register 1) */ - /* ATTR_PROC_PCIE_PCS_RX_DFE_FDDC = 0, so not updating PEC_IOP_RX_DFE_FUNC_REGISTER1 */ + /* ATTR_PROC_PCIE_PCS_RX_DFE_FDDC = 1 */ + scom_or_for_chiplet(chiplet, PEC_IOP_RX_DFE_FUNC_REGISTER1, PPC_BIT(50)); /* Phase1 init step 23 (PCS System Control) */ /* ATTR_PROC_PCIE_PCS_SYSTEM_CNTL computed above */ scom_and_or_for_chiplet(chiplet, PEC_PCS_SYS_CONTROL_REG, ~PPC_BITMASK(55, 63), - PPC_SHIFT(pec_cfgs[pec]->phb_to_pcie_mac, 63)); + pec_cfgs[pec]->phb_to_pcie_mac); /* - * All values in ATTR_PROC_PCIE_PCS_M_CNTL seem to be 0, which - * makes the next four steps no-op. Hostboot has bugs here in - * that it updates PEC_PCS_M1_CONTROL_REG 4 times instead of - * updating 4 different registers (M1-M4), but no-op conceals this. + * All values in ATTR_PROC_PCIE_PCS_M_CNTL seem to be 0. + * Hostboot has bugs here in that it updates PEC_PCS_M1_CONTROL_REG + * 4 times instead of updating 4 different registers (M1-M4). */ /* Phase1 init step 24 (PCS M1 Control) */ + scom_and_for_chiplet(chiplet, PEC_PCS_M1_CONTROL_REG, ~PPC_BITMASK(55, 63)); /* Phase1 init step 25 (PCS M2 Control) */ + scom_and_for_chiplet(chiplet, PEC_PCS_M2_CONTROL_REG, ~PPC_BITMASK(55, 63)); /* Phase1 init step 26 (PCS M3 Control) */ + scom_and_for_chiplet(chiplet, PEC_PCS_M3_CONTROL_REG, ~PPC_BITMASK(55, 63)); /* Phase1 init step 27 (PCS M4 Control) */ + scom_and_for_chiplet(chiplet, PEC_PCS_M4_CONTROL_REG, ~PPC_BITMASK(55, 63)); /* Delay a minimum of 200ns to allow prior SCOM programming to take effect */ (void)wait_us(1, false); - // Phase1 init step 28 + /* Phase1 init step 28 */ write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, PPC_BIT(PEC_IOP_PIPE_RESET_START_BIT)); From 5766d92c3d4e8d52c1951fccec5bc82142a698d2 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sat, 16 Oct 2021 18:43:28 +0300 Subject: [PATCH 11/16] Non-functional code improvements Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_10_10.c | 93 +++++++++++++------------------- src/soc/ibm/power9/istep_14_3.c | 19 +++---- 2 files changed, 48 insertions(+), 64 deletions(-) diff --git a/src/soc/ibm/power9/istep_10_10.c b/src/soc/ibm/power9/istep_10_10.c index f46d0d7e3e4..9e01dd979fa 100644 --- a/src/soc/ibm/power9/istep_10_10.c +++ b/src/soc/ibm/power9/istep_10_10.c @@ -38,7 +38,10 @@ enum phb_to_mac { PHB_X8_X4_X4_MAC_MAP = 0x0090, }; -/* Bit position of the PHB with the largest number a given PEC can use */ +/* + * Bit position of the PHB with the largest number a given PEC can use + * (see enum phb_active_mask for bit values). + */ enum pec_phb_shift { PEC0_PHB_SHIFT = 7, // PHB0 only PEC1_PHB_SHIFT = 5, // PHB1 - PHB2 @@ -59,16 +62,8 @@ struct lane_config_row { /* IOP config value from PCIE IOP configuration table */ uint8_t lane_config; - /* - * PHB active mask (see phb_active_mask enum) - * PHB0 = 0x80 - * PHB1 = 0x40 - * PHB2 = 0x20 - * PHB3 = 0x10 - * PHB4 = 0x08 - * PHB5 = 0x04 - */ - uint8_t phb_active; // enum phb_active_mask + /* PHB active mask (see phb_active_mask enum) */ + uint8_t phb_active; uint16_t phb_to_pcie_mac; // enum phb_to_mac }; @@ -76,10 +71,10 @@ struct lane_config_row { /* * Currently there are three PEC config tables for procs with 48 usable PCIE * lanes. In general, the code accumulates the current configuration of - * the PECs from the MRW and other dynamic information(such as bifurcation) - * then matches that config to one of the rows in the table. Once a match - * is discovered, the PEC config value is pulled from the matching row and - * set in the attributes. + * the PECs from the MRW and other dynamic information (such as bifurcation) + * then matches that config to one of the rows in the table. Once a match + * is discovered, the PEC config value is pulled from the matching row for + * future use. * * Each PEC can control up to 16 lanes: * - PEC0 can give 16 lanes to PHB0 @@ -165,13 +160,8 @@ static const size_t pec_lane_cfg_sizes[] = { }; /* - * This probably comes from parsing PEC_PCIE_HX_KEYWORD_DATA in Hostboot, its - * description: - * This attribute holds the contents of the HX keyword read by the FSP - * from a PCIe card. - * genHwsvMrwXml.pl has some defaults but with a different value for PEC2. - * Defaults differ among processors. - * enum lane_width + * PEC_PCIE_LANE_MASK_NON_BIFURCATED in processed talos.xml for the first + * processor chip. Values correspond to lane_width enumeration. */ static uint16_t lane_masks[MAX_PEC_PER_PROC][MAX_LANE_GROUPS_PER_PEC] = { { LANE_MASK_X16, 0x0, 0x0, 0x0 }, @@ -231,18 +221,17 @@ static enum lane_width lane_mask_to_width(uint16_t mask) return width; } -static uint8_t determine_lane_configs(const struct lane_config_row **pec_cfgs) +static void determine_lane_configs(uint8_t *phb_active_mask, + const struct lane_config_row **pec_cfgs) { uint8_t pec = 0; - uint8_t phb_active_mask = 0; + + *phb_active_mask = 0; for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { uint8_t i; uint8_t lane_group; - uint16_t lane_mask[MAX_LANE_GROUPS_PER_PEC]; // enum lane_width - memcpy(&lane_mask, &lane_masks[pec], sizeof(lane_mask)); - struct lane_config_row config = { { LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC, LANE_WIDTH_NC }, 0x00, @@ -252,7 +241,7 @@ static uint8_t determine_lane_configs(const struct lane_config_row **pec_cfgs) /* Transform effective config to match lane config table format */ for (lane_group = 0; lane_group < MAX_LANE_GROUPS_PER_PEC; ++lane_group) - config.lane_set[lane_group] = lane_mask_to_width(lane_mask[lane_group]); + config.lane_set[lane_group] = lane_mask_to_width(lane_masks[pec][lane_group]); for (i = 0; i < pec_lane_cfg_sizes[pec]; ++i) { if (memcmp(pec_lane_cfgs[pec][i].lane_set, &config.lane_set, @@ -263,20 +252,18 @@ static uint8_t determine_lane_configs(const struct lane_config_row **pec_cfgs) if (i == pec_lane_cfg_sizes[pec]) die("Failed to find PCIE IOP configuration for PEC%d\n", pec); - phb_active_mask |= pec_lane_cfgs[pec][i].phb_active; + *phb_active_mask |= pec_lane_cfgs[pec][i].phb_active; pec_cfgs[pec] = &pec_lane_cfgs[pec][i]; /* - * In the rest of PCIe-related code the following PEC attributes have these + * In the rest of the PCIe-related code the following PEC attributes have these * values: * - PEC[ATTR_PROC_PCIE_IOP_CONFIG] := pec_cfgs[pec]->lane_config * - PEC[ATTR_PROC_PCIE_REFCLOCK_ENABLE] := 1 * - PEC[ATTR_PROC_PCIE_PCS_SYSTEM_CNTL] := pec_cfgs[pec]->phb_to_pcie_mac */ } - - return phb_active_mask; } static uint64_t pec_val(int pec_id, uint8_t in, @@ -373,6 +360,17 @@ static void phase1(const struct lane_config_row **pec_cfgs, chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; + /* ATTR_PROC_PCIE_PCS_RX_CDR_GAIN, from talos.xml */ + uint8_t pcs_cdr_gain[] = { 0x56, 0x47, 0x47, 0x47 }; + /* ATTR_PROC_PCIE_PCS_RX_INIT_GAIN, all zeroes by default */ + uint8_t pcs_init_gain = 0; + /* ATTR_PROC_PCIE_PCS_RX_PK_INIT, all zeroes by default */ + uint8_t pcs_pk_init = 0; + /* ATTR_PROC_PCIE_PCS_RX_SIGDET_LVL, defaults and talos.xml */ + uint8_t pcs_sigdet_lvl = 0x0B; + + uint32_t pcs_config_mode[NUM_PCS_CONFIG] = { 0xA006, 0xA805, 0xB071, 0xB870 }; + /* Phase1 init step 1 (get VPD, no operation here) */ /* Phase1 init step 2a */ @@ -384,10 +382,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, /* Phase1 init step 2b */ - /* - * FIXME: ATTR_PROC_PCIE_IOP_SWAP, might be computed by processPec() in - * processMrw.pl and stored somewhere, this is based on logs... - */ + /* ATTR_PROC_PCIE_IOP_SWAP from processed talos.xml for first proc */ proc_pcie_iop_swap = (pec == 0); val = pec_val(pec, proc_pcie_iop_swap, @@ -413,8 +408,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_OR, val); /* Phase1 init step 3b (enable clock) */ - /* XXX: assume all PECs are enabled (due to hard-coded lanes), - * ATTR_PROC_PCIE_REFCLOCK_ENABLE */ + /* ATTR_PROC_PCIE_REFCLOCK_ENABLE, all PECs are enabled. */ write_scom_for_chiplet(chiplet, PEC_CPLT_CTRL0_OR, PPC_BIT(PEC_IOP_REFCLOCK_ENABLE_START_BIT)); @@ -452,17 +446,6 @@ static void phase1(const struct lane_config_row **pec_cfgs, /* Phase1 init step 8-11 (Config 0 - 3) */ - /* ATTR_PROC_PCIE_PCS_RX_CDR_GAIN, from talos.xml */ - uint8_t pcs_cdr_gain[] = { 0x56, 0x47, 0x47, 0x47 }; - /* ATTR_PROC_PCIE_PCS_RX_INIT_GAIN, all zeroes by default */ - uint8_t pcs_init_gain = 0; - /* ATTR_PROC_PCIE_PCS_RX_PK_INIT, all zeroes by default */ - uint8_t pcs_pk_init = 0; - /* ATTR_PROC_PCIE_PCS_RX_SIGDET_LVL, defaults and talos.xml */ - uint8_t pcs_sigdet_lvl = 0x0B; - - uint32_t pcs_config_mode[NUM_PCS_CONFIG] = { 0xA006, 0xA805, 0xB071, 0xB870 }; - for (i = 0; i < NUM_PCS_CONFIG; ++i) { uint8_t lane; @@ -496,7 +479,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, /* * Phase1 init step 12 (RX Rot Cntl CDR Lookahead Disabled, SSC Disabled) * - * All these attributes seem to be zero for Nimbus: + * All these attributes are zero for Nimbus: * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_LOOKAHEAD (55) * - ATTR_PROC_PCIE_PCS_RX_ROT_CDR_SSC (63) * - ATTR_PROC_PCIE_PCS_RX_ROT_EXTEL (59) @@ -512,13 +495,13 @@ static void phase1(const struct lane_config_row **pec_cfgs, /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLA = 0xF8 */ scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLA_REG, ~PPC_BITMASK(56, 63), - 0xf8); + 0xF8); /* Phase1 init step 15 (PCLCK Control Register - PLLB) */ /* ATTR_PROC_PCIE_PCS_PCLCK_CNTL_PLLB = 0xF8 */ scom_and_or_for_chiplet(chiplet, PEC_PCS_PCLCK_CNTL_PLLB_REG, ~PPC_BITMASK(56, 63), - 0xf8); + 0xF8); /* Phase1 init step 16 (TX DCLCK Rotator Override) */ /* ATTR_PROC_PCIE_PCS_TX_DCLCK_ROT = 0x0022 */ @@ -536,7 +519,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, /* ATTR_PROC_PCIE_PCS_TX_POWER_SEQ_ENABLE = 0xFF, but field is 7 bits */ scom_and_or_for_chiplet(chiplet, PEC_PCS_TX_POWER_SEQ_ENABLE_REG, ~PPC_BITMASK(56, 62), - PPC_SHIFT(0x7f, 62)); + PPC_SHIFT(0x7F, 62)); /* Phase1 init step 20 (RX VGA Control Register 1) */ @@ -562,7 +545,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, pec_cfgs[pec]->phb_to_pcie_mac); /* - * All values in ATTR_PROC_PCIE_PCS_M_CNTL seem to be 0. + * All values in ATTR_PROC_PCIE_PCS_M_CNTL are 0. * Hostboot has bugs here in that it updates PEC_PCS_M1_CONTROL_REG * 4 times instead of updating 4 different registers (M1-M4). */ @@ -597,7 +580,7 @@ void istep_10_10(uint8_t *phb_active_mask, uint8_t *iovalid_enable) printk(BIOS_EMERG, "starting istep 10.10\n"); report_istep(10,10); - *phb_active_mask = determine_lane_configs(pec_cfgs); + determine_lane_configs(phb_active_mask, pec_cfgs); /* * Mask of functional PHBs for each PEC, ATTR_PROC_PCIE_IOVALID_ENABLE in Hostboot. diff --git a/src/soc/ibm/power9/istep_14_3.c b/src/soc/ibm/power9/istep_14_3.c index 1280d5bf237..600de47756c 100644 --- a/src/soc/ibm/power9/istep_14_3.c +++ b/src/soc/ibm/power9/istep_14_3.c @@ -34,12 +34,13 @@ static void init_pecs(const uint8_t *iovalid_enable) uint64_t scratch_reg6 = 0; uint8_t pec = 0; + bool node_pump_mode = false; uint8_t dd = get_dd(); scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ - bool node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); + node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { uint64_t val = 0; @@ -57,7 +58,7 @@ static void init_pecs(const uint8_t *iovalid_enable) /* * Phase2 init step 1 - * NestBase+0x00 + * NestBase + 0x00 * Set bits 00:03 = 0b0001 Set hang poll scale * Set bits 04:07 = 0b0001 Set data scale * Set bits 08:11 = 0b0001 Set hang pe scale @@ -153,13 +154,13 @@ static void init_pecs(const uint8_t *iovalid_enable) /* * Phase2 init step 4 - * NestBase+0x05 + * NestBase + 0x05 * N/A For use of atomics/asb_notify */ /* * Phase2 init step 5 - * NestBase+0x06 + * NestBase + 0x06 * N/A To override scope prediction */ @@ -265,7 +266,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) uint8_t phb = 0; for (phb = 0; phb < MAX_PHB_PER_PROC; ++phb) { /* BAR enable attribute (ATTR_PROC_PCIE_BAR_ENABLE) */ - uint8_t l_bar_enables[3] = { 0 }; + uint8_t bar_enables[3] = { 0 }; uint64_t val = 0; uint64_t mmio0_bar = base_addr_mmio; @@ -435,12 +436,12 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) val = 0; - if (l_bar_enables[0]) + if (bar_enables[0]) val |= PPC_BIT(0); // PHB_BARE_REG_PE_MMIO_BAR0_EN, bit 0 for BAR0 - if (l_bar_enables[1]) + if (bar_enables[1]) val |= PPC_BIT(1); // PHB_BARE_REG_PE_MMIO_BAR1_EN, bit 1 for BAR1 - if (l_bar_enables[2]) - val |= PPC_BIT(1); // PHB_BARE_REG_PE_PHB_BAR_EN, bit 2 for PHB + if (bar_enables[2]) + val |= PPC_BIT(2); // PHB_BARE_REG_PE_PHB_BAR_EN, bit 2 for PHB write_scom(phb_addr(phb, PHB_BARE_REG), val); From 544a0200605e8015c6055c7033fa4b3c54fb1df8 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Sun, 17 Oct 2021 00:32:46 +0300 Subject: [PATCH 12/16] Use udelay() where appropriate Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_10_10.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/soc/ibm/power9/istep_10_10.c b/src/soc/ibm/power9/istep_10_10.c index 9e01dd979fa..893d33009e6 100644 --- a/src/soc/ibm/power9/istep_10_10.c +++ b/src/soc/ibm/power9/istep_10_10.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -416,10 +417,10 @@ static void phase1(const struct lane_config_row **pec_cfgs, write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, PPC_BIT(PEC_IOP_PMA_RESET_START_BIT)); - (void)wait_us(1, false); /* at least 400ns */ + udelay(1); /* at least 400ns */ write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_OR, PPC_BIT(PEC_IOP_PMA_RESET_START_BIT)); - (void)wait_us(1, false); /* at least 400ns */ + udelay(1); /* at least 400ns */ write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, PPC_BIT(PEC_IOP_PMA_RESET_START_BIT)); @@ -560,7 +561,7 @@ static void phase1(const struct lane_config_row **pec_cfgs, scom_and_for_chiplet(chiplet, PEC_PCS_M4_CONTROL_REG, ~PPC_BITMASK(55, 63)); /* Delay a minimum of 200ns to allow prior SCOM programming to take effect */ - (void)wait_us(1, false); + udelay(1); /* Phase1 init step 28 */ write_scom_for_chiplet(chiplet, PEC_CPLT_CONF1_CLEAR, From 2d03fc51bd2f59dee51bb4857488f132961f18ba Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 21 Oct 2021 00:34:22 +0300 Subject: [PATCH 13/16] Fixes for istep 14.3 * Small changes for consistency. * Access some registers through a nest chiplet ID. * Fix a bug in PEC initialization (ATTR_PROC_PCIE_CACHE_INJ_MODE). Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_14_3.c | 109 ++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/src/soc/ibm/power9/istep_14_3.c b/src/soc/ibm/power9/istep_14_3.c index 600de47756c..7915af7dd1a 100644 --- a/src/soc/ibm/power9/istep_14_3.c +++ b/src/soc/ibm/power9/istep_14_3.c @@ -7,6 +7,11 @@ #include "pci.h" +static uint64_t pec_addr(uint8_t pec, uint64_t addr) +{ + return addr + pec*0x400; +} + static void init_pecs(const uint8_t *iovalid_enable) { enum { @@ -19,7 +24,9 @@ static void init_pecs(const uint8_t *iovalid_enable) MBOX_SCRATCH_REG1 = 0x00050038, MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = (1 << 23), + PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION = 60, PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN = 30, + PEC_AIB_HWCFG_OSBM_HOL_BLK_CNT = 42, PEC_PBCQHWCFG_REG_PE_DISABLE_OOO_MODE = 0x16, PEC_PBCQHWCFG_REG_PE_DISABLE_WR_SCOPE_GROUP = 42, PEC_PBCQHWCFG_REG_PE_CHANNEL_STREAMING_EN = 33, @@ -44,7 +51,6 @@ static void init_pecs(const uint8_t *iovalid_enable) for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { uint64_t val = 0; - chiplet_id_t chiplet = PCI0_CHIPLET_ID + pec; printk(BIOS_EMERG, "Initializing PEC%d...\n", pec); @@ -52,7 +58,7 @@ static void init_pecs(const uint8_t *iovalid_enable) * ATTR_FABRIC_ADDR_EXTENSION_GROUP_ID = 0 * ATTR_FABRIC_ADDR_EXTENSION_CHIP_ID = 0 */ - scom_and_or_for_chiplet(chiplet, P9N2_PEC_ADDREXTMASK_REG, + scom_and_or_for_chiplet(N2_CHIPLET_ID, pec_addr(pec, P9N2_PEC_ADDREXTMASK_REG), ~PPC_BITMASK(0, 6), PPC_SHIFT(0, 6)); @@ -70,7 +76,7 @@ static void init_pecs(const uint8_t *iovalid_enable) * if HW423589_option1, set Disable Group Scope (r/w) and Use Vg(sys) at Vg scope */ - val = read_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG); + val = read_scom_for_chiplet(N2_CHIPLET_ID, pec_addr(pec, PEC_PBCQHWCFG_REG)); /* Set hang poll scale */ val &= ~PPC_BITMASK(0, 3); val |= PPC_SHIFT(1, 3); @@ -110,8 +116,8 @@ static void init_pecs(const uint8_t *iovalid_enable) * selected based on various workloads and was to be the most optimal settings for Power9. * fapi2::ATTR_PROC_PCIE_CACHE_INJ_MODE = 3 by default */ - val &= ~PPC_BITMASK(34, 36); - val |= PPC_SHIFT(0x3, 36); + val &= ~PPC_BITMASK(34, 35); + val |= PPC_SHIFT(0x3, 35); if (dd == 0x21 || dd == 0x22 || dd == 0x23) { /* @@ -132,9 +138,9 @@ static void init_pecs(const uint8_t *iovalid_enable) } if (pec == 1 || (pec == 2 && iovalid_enable[pec] != 0x4)) - val |= PPC_BIT(60); // PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION + val |= PPC_BIT(PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION); - write_scom_for_chiplet(chiplet, PEC_PBCQHWCFG_REG, val); + write_scom_for_chiplet(N2_CHIPLET_ID, pec_addr(pec, PEC_PBCQHWCFG_REG), val); /* * Phase2 init step 2 @@ -148,7 +154,7 @@ static void init_pecs(const uint8_t *iovalid_enable) * Set bits 00:03 = 0b1001 Enable trace, and select * inbound operations with addr information */ - scom_and_or_for_chiplet(chiplet, PEC_NESTTRC_REG, + scom_and_or_for_chiplet(N2_CHIPLET_ID, pec_addr(pec, PEC_NESTTRC_REG), ~PPC_BITMASK(0, 3), PPC_SHIFT(9, 3)); @@ -170,13 +176,14 @@ static void init_pecs(const uint8_t *iovalid_enable) * Set bits 30 = 0b1 Enable Trace */ val = 0; - val |= PPC_BIT(0x1E); // PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN - val |= PPC_SHIFT(7, 0x2A); // PEC_AIB_HWCFG_OSBM_HOL_BLK_CNT - write_scom_for_chiplet(chiplet, PEC_PBAIBHWCFG_REG, val); + val |= PPC_BIT(PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN); + val |= PPC_SHIFT(7, PEC_AIB_HWCFG_OSBM_HOL_BLK_CNT); + write_scom_for_chiplet(PCI0_CHIPLET_ID + pec, PEC_PBAIBHWCFG_REG, val); } } -static uint64_t phb_addr(uint8_t phb, uint64_t addr) +/* See src/import/chips/p9/common/scominfo/p9_scominfo.C in Hostboot */ +static void phb_write(uint8_t phb, uint64_t addr, uint64_t data) { chiplet_id_t chiplet; uint8_t sat_id = (addr >> 6) & 0xF; @@ -191,13 +198,37 @@ static uint64_t phb_addr(uint8_t phb, uint64_t addr) + (2 * (phb / 5)); } - addr &= ~PPC_BITMASK(34, 39); - addr |= PPC_SHIFT(chiplet & 0x3F, 39); + addr &= ~PPC_BITMASK(54, 57); + addr |= PPC_SHIFT(sat_id & 0xF, 57); + + write_scom_for_chiplet(chiplet, addr, data); +} + +/* See src/import/chips/p9/common/scominfo/p9_scominfo.C in Hostboot */ +static void phb_nest_write(uint8_t phb, uint64_t addr, uint64_t data) +{ + enum { N2_PCIS0_0_RING_ID = 0x3 }; + + uint8_t ring; + uint8_t sat_id = (addr >> 6) & 0xF; + + if (phb == 0) { + ring = (N2_PCIS0_0_RING_ID & 0xF); + sat_id = (sat_id < 4 ? 1 : 4); + } else { + ring = ((N2_PCIS0_0_RING_ID + (phb / 3) + 1) & 0xF); + sat_id = (sat_id < 4 ? 1 : 4) + + (phb % 2 ? 0 : 1) + + (2 * (phb / 5)); + } + + addr &= ~PPC_BITMASK(50, 53); + addr |= PPC_SHIFT(ring & 0xF, 53); addr &= ~PPC_BITMASK(54, 57); addr |= PPC_SHIFT(sat_id & 0xF, 57); - return addr; + write_scom_for_chiplet(N2_CHIPLET_ID, addr, data); } static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) @@ -284,7 +315,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0xFFFFFFFF_FFFFFFFF * Clear any spurious cerr_rpt0 bits (cerr_rpt0) */ - write_scom(phb_addr(phb, PHB_CERR_RPT0_REG), PPC_BITMASK(0, 63)); + phb_nest_write(phb, PHB_CERR_RPT0_REG, PPC_BITMASK(0, 63)); /* * Phase2 init step 12_b (yes, out of order) @@ -292,7 +323,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0xFFFFFFFF_FFFFFFFF * Clear any spurious cerr_rpt1 bits (cerr_rpt1) */ - write_scom(phb_addr(phb, PHB_CERR_RPT1_REG), PPC_BITMASK(0, 63)); + phb_nest_write(phb, PHB_CERR_RPT1_REG, PPC_BITMASK(0, 63)); /* * Phase2 init step 7_c @@ -301,7 +332,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * Clear any spurious FIR * bits (NFIR)NFIR */ - write_scom(phb_addr(phb, PHB_NFIR_REG), 0); + phb_nest_write(phb, PHB_NFIR_REG, 0); /* * Phase2 init step 8 @@ -309,28 +340,28 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0x00000000_00000000 * Clear any spurious WOF bits (NFIRWOF) */ - write_scom(phb_addr(phb, PHB_NFIRWOF_REG), 0); + phb_nest_write(phb, PHB_NFIRWOF_REG, 0); /* * Phase2 init step 9 * NestBase + StackBase + 0x6 * Set the per FIR Bit Action 0 register */ - write_scom(phb_addr(phb, PHB_NFIRACTION0_REG), PCI_NFIR_ACTION0_REG); + phb_nest_write(phb, PHB_NFIRACTION0_REG, PCI_NFIR_ACTION0_REG); /* * Phase2 init step 10 * NestBase + StackBase + 0x7 * Set the per FIR Bit Action 1 register */ - write_scom(phb_addr(phb, PHB_NFIRACTION1_REG), PCI_NFIR_ACTION1_REG); + phb_nest_write(phb, PHB_NFIRACTION1_REG, PCI_NFIR_ACTION1_REG); /* * Phase2 init step 11 * NestBase + StackBase + 0x3 * Set FIR Mask Bits to allow errors (NFIRMask) */ - write_scom(phb_addr(phb, PHB_NFIRMASK_REG), PCI_NFIR_MASK_REG); + phb_nest_write(phb, PHB_NFIRMASK_REG, PCI_NFIR_MASK_REG); /* * Phase2 init step 12 @@ -338,7 +369,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0x00000000_00000000 * Set Data Freeze Type Register for SUE handling (DFREEZE) */ - write_scom(phb_addr(phb, PHB_PE_DFREEZE_REG), 0); + phb_nest_write(phb, PHB_PE_DFREEZE_REG, 0); /* * Phase2 init step 13_a @@ -346,7 +377,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0x00000000_00000000 * Clear any spurious pbaib_cerr_rpt bits */ - write_scom(phb_addr(phb, PHB_PBAIB_CERR_RPT_REG), 0); + phb_write(phb, PHB_PBAIB_CERR_RPT_REG, 0); /* * Phase2 init step 13_b @@ -355,7 +386,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * Clear any spurious FIR * bits (PFIR)PFIR */ - write_scom(phb_addr(phb, PHB_PFIR_REG), 0); + phb_write(phb, PHB_PFIR_REG, 0); /* * Phase2 init step 14 @@ -363,28 +394,28 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0x00000000_00000000 * Clear any spurious WOF bits (PFIRWOF) */ - write_scom(phb_addr(phb, PHB_PFIRWOF_REG), 0); + phb_write(phb, PHB_PFIRWOF_REG, 0); /* * Phase2 init step 15 * PCIBase + StackBase + 0x6 * Set the per FIR Bit Action 0 register */ - write_scom(phb_addr(phb, PHB_PFIRACTION0_REG), PCI_PFIR_ACTION0_REG); + phb_write(phb, PHB_PFIRACTION0_REG, PCI_PFIR_ACTION0_REG); /* * Phase2 init step 16 * PCIBase + StackBase + 0x7 * Set the per FIR Bit Action 1 register */ - write_scom(phb_addr(phb, PHB_PFIRACTION1_REG), PCI_PFIR_ACTION1_REG); + phb_write(phb, PHB_PFIRACTION1_REG, PCI_PFIR_ACTION1_REG); /* * Phase2 init step 17 * PCIBase + StackBase + 0x3 * Set FIR Mask Bits to allow errors (PFIRMask) */ - write_scom(phb_addr(phb, PHB_PFIRMASK_REG), PCI_PFIR_MASK_REG); + phb_write(phb, PHB_PFIRMASK_REG, PCI_PFIR_MASK_REG); /* * Phase2 init step 18 @@ -393,14 +424,14 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) */ mmio0_bar += mmio_bar0_offsets[phb]; mmio0_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; - write_scom(phb_addr(phb, PHB_MMIOBAR0_REG), mmio0_bar); + phb_nest_write(phb, PHB_MMIOBAR0_REG, mmio0_bar); /* * Phase2 init step 19 * NestBase + StackBase + 0xF * Set MMIO BASE Address Register Mask 0 (MMIOBAR0_MASK) */ - write_scom(phb_addr(phb, PHB_MMIOBAR0_MASK_REG), bar_sizes[0]); + phb_nest_write(phb, PHB_MMIOBAR0_MASK_REG, bar_sizes[0]); /* * Phase2 init step 20 @@ -410,14 +441,14 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) */ mmio1_bar += mmio_bar1_offsets[phb]; mmio1_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; - write_scom(phb_addr(phb, PHB_MMIOBAR1_REG), mmio1_bar); + phb_nest_write(phb, PHB_MMIOBAR1_REG, mmio1_bar); /* * Phase2 init step 21 * NestBase + StackBase + 0x11 * Set MMIO Base Address Register Mask 1 (MMIOBAR1_MASK) */ - write_scom(phb_addr(phb, PHB_MMIOBAR1_MASK_REG), bar_sizes[1]); + phb_nest_write(phb, PHB_MMIOBAR1_MASK_REG, bar_sizes[1]); /* * Phase2 init step 22 @@ -426,7 +457,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) */ register_bar += register_bar_offsets[phb]; register_bar <<= P9_PCIE_CONFIG_BAR_SHIFT; - write_scom(phb_addr(phb, PHB_PHBBAR_REG), register_bar); + phb_nest_write(phb, PHB_PHBBAR_REG, register_bar); /* * Phase2 init step 23 @@ -443,7 +474,7 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) if (bar_enables[2]) val |= PPC_BIT(2); // PHB_BARE_REG_PE_PHB_BAR_EN, bit 2 for PHB - write_scom(phb_addr(phb, PHB_BARE_REG), val); + phb_nest_write(phb, PHB_BARE_REG, val); /* * Phase2 init step 24 @@ -451,11 +482,11 @@ static void init_phbs(uint8_t phb_active_mask, const uint8_t *iovalid_enable) * 0x00000000_00000000 * Remove ETU/AIB bus from reset (PHBReset) */ - write_scom(phb_addr(phb, PHB_PHBRESET_REG), 0); + phb_write(phb, PHB_PHBRESET_REG, 0); /* Configure ETU FIR (all masked) */ - write_scom(phb_addr(phb, PHB_ACT0_REG), 0); - write_scom(phb_addr(phb, PHB_ACTION1_REG), 0); - write_scom(phb_addr(phb, PHB_MASK_REG), PPC_BITMASK(0, 63)); + phb_write(phb, PHB_ACT0_REG, 0); + phb_write(phb, PHB_ACTION1_REG, 0); + phb_write(phb, PHB_MASK_REG, PPC_BITMASK(0, 63)); } } From 2a2e5b28c8a58714ee9a9b82fdf981476281ad72 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 21 Oct 2021 20:00:29 +0300 Subject: [PATCH 14/16] Fix value of MBOX_SCRATCH_REG6_GROUP_PUMP_MODE Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_14_3.c | 4 ++-- src/soc/ibm/power9/powerbus.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/soc/ibm/power9/istep_14_3.c b/src/soc/ibm/power9/istep_14_3.c index 7915af7dd1a..58eb6afc109 100644 --- a/src/soc/ibm/power9/istep_14_3.c +++ b/src/soc/ibm/power9/istep_14_3.c @@ -22,7 +22,7 @@ static void init_pecs(const uint8_t *iovalid_enable) /* powerbus.c has these too */ MBOX_SCRATCH_REG1 = 0x00050038, - MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = (1 << 23), + MBOX_SCRATCH_REG6_GROUP_PUMP_MODE = 23, PEC_PBCQHWCFG_REG_PE_DISABLE_TCE_ARBITRATION = 60, PEC_PBAIBHWCFG_REG_PE_PCIE_CLK_TRACE_EN = 30, @@ -47,7 +47,7 @@ static void init_pecs(const uint8_t *iovalid_enable) scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ - node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); + node_pump_mode = !(scratch_reg6 & PPC_BIT(MBOX_SCRATCH_REG6_GROUP_PUMP_MODE)); for (pec = 0; pec < MAX_PEC_PER_PROC; ++pec) { uint64_t val = 0; diff --git a/src/soc/ibm/power9/powerbus.c b/src/soc/ibm/power9/powerbus.c index 96a2cf23d1d..6c3ebd861a5 100644 --- a/src/soc/ibm/power9/powerbus.c +++ b/src/soc/ibm/power9/powerbus.c @@ -10,7 +10,7 @@ #define EPSILON_MAX_VALUE 0xFFFFFFFF #define MBOX_SCRATCH_REG1 0x00050038 -#define MBOX_SCRATCH_REG6_GROUP_PUMP_MODE (1 << 23) +#define MBOX_SCRATCH_REG6_GROUP_PUMP_MODE 23 #define EPS_GUARDBAND 20 @@ -167,7 +167,7 @@ static void calculate_epsilons(struct powerbus_cfg *cfg) uint64_t scratch_reg6 = read_scom(MBOX_SCRATCH_REG1 + 5); /* ATTR_PROC_FABRIC_PUMP_MODE, it's either node or group pump mode */ - bool node_pump_mode = !(scratch_reg6 & MBOX_SCRATCH_REG6_GROUP_PUMP_MODE); + bool node_pump_mode = !(scratch_reg6 & PPC_BIT(MBOX_SCRATCH_REG6_GROUP_PUMP_MODE)); /* Assuming that ATTR_PROC_EPS_TABLE_TYPE = EPS_TYPE_LE in talos.xml is always correct */ From 0c6ccde8d62e282eafe9ccdd139610ebc2edf589 Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 21 Oct 2021 20:02:31 +0300 Subject: [PATCH 15/16] Remove non-breaking spaces in istep_14_3.c Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/istep_14_3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/soc/ibm/power9/istep_14_3.c b/src/soc/ibm/power9/istep_14_3.c index 58eb6afc109..37dc83f21af 100644 --- a/src/soc/ibm/power9/istep_14_3.c +++ b/src/soc/ibm/power9/istep_14_3.c @@ -68,7 +68,7 @@ static void init_pecs(const uint8_t *iovalid_enable) * Set bits 00:03 = 0b0001 Set hang poll scale * Set bits 04:07 = 0b0001 Set data scale * Set bits 08:11 = 0b0001 Set hang pe scale - * Set bit 22 = 0b1 Disable out­of­order store behavior + * Set bit 22 = 0b1 Disable out of order store behavior * Set bit 33 = 0b1 Enable Channel Tag streaming behavior * Set bits 34:35 = 0b11 Set P9 Style cache-inject behavior * Set bits 46:48 = 0b011 Set P9 Style cache-inject rate, 1/16 cycles @@ -86,7 +86,7 @@ static void init_pecs(const uint8_t *iovalid_enable) /* Set hang pe scale */ val &= ~PPC_BITMASK(8, 11); val |= PPC_SHIFT(1, 11); - /* Disable out­of­order store behavior */ + /* Disable out of order store behavior */ val |= PPC_BIT(22); /* Enable Channel Tag streaming behavior */ val |= PPC_BIT(33); From 16ed2474d09e04c00a6ce95186eed2894d4a634e Mon Sep 17 00:00:00 2001 From: Sergii Dmytruk Date: Thu, 21 Oct 2021 20:03:05 +0300 Subject: [PATCH 16/16] Invoke istep_10_* earlier in romstage Change-Id: I229f3b40d1f8b115eaa1d9d9b9e813a43ee807ae Signed-off-by: Sergii Dmytruk --- src/soc/ibm/power9/romstage.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/soc/ibm/power9/romstage.c b/src/soc/ibm/power9/romstage.c index cc686e41ea1..0f1ca30623e 100644 --- a/src/soc/ibm/power9/romstage.c +++ b/src/soc/ibm/power9/romstage.c @@ -346,6 +346,8 @@ void main(void) init_timer(); + istep_10_10(&phb_active_mask, iovalid_enable); + istep_10_12(); istep_10_13(); timestamp_add_now(TS_BEFORE_INITRAM); @@ -353,9 +355,6 @@ void main(void) vpd_pnor_main(); prepare_dimm_data(); - istep_10_10(&phb_active_mask, iovalid_enable); - istep_10_12(); - report_istep(13,1); // no-op istep_13_2(); istep_13_3();