diff options
-rw-r--r-- | hw/pau.c | 75 | ||||
-rw-r--r-- | hw/phys-map.c | 59 | ||||
-rw-r--r-- | include/pau-regs.h | 26 | ||||
-rw-r--r-- | include/pau.h | 79 | ||||
-rw-r--r-- | include/phys-map.h | 4 |
5 files changed, 235 insertions, 8 deletions
@@ -193,6 +193,80 @@ static void pau_device_detect_fixup(struct pau_dev *dev) dt_add_property_strings(dn, "ibm,pau-link-type", "unknown"); } +static void pau_opencapi_assign_bars(struct pau *pau) +{ + struct pau_dev *dev; + uint64_t addr, size, val; + + /* Global MMIO bar (per pau) + * 16M aligned address -> 0x1000000 (bit 24) + */ + phys_map_get(pau->chip_id, PAU_REGS, pau->index, &addr, &size); + val = SETFIELD(PAU_MMIO_BAR_ADDR, 0ull, addr >> 24); + val |= PAU_MMIO_BAR_ENABLE; + pau_write(pau, PAU_MMIO_BAR, val); + + PAUINF(pau, "MMIO base: 0x%016llx (%lldMB)\n", addr, size >> 20); + pau->regs[0] = addr; + pau->regs[1] = size; + + /* NTL bar (per device) + * 64K aligned address -> 0x10000 (bit 16) + */ + pau_for_each_dev(dev, pau) { + if (dev->type == PAU_DEV_TYPE_UNKNOWN) + continue; + + phys_map_get(pau->chip_id, PAU_OCAPI_MMIO, + pau_dev_index(dev, PAU_LINKS_OPENCAPI_PER_PAU), + &addr, &size); + + val = SETFIELD(PAU_NTL_BAR_ADDR, 0ull, addr >> 16); + val = SETFIELD(PAU_NTL_BAR_SIZE, val, ilog2(size >> 16)); + pau_write(pau, PAU_NTL_BAR(dev->index), val); + + val = SETFIELD(PAU_CTL_MISC_MMIOPA_CONFIG_BAR_ADDR, 0ull, addr >> 16); + val = SETFIELD(PAU_CTL_MISC_MMIOPA_CONFIG_BAR_SIZE, val, ilog2(size >> 16)); + pau_write(pau, PAU_CTL_MISC_MMIOPA_CONFIG(dev->index), val); + + dev->ntl_bar.addr = addr; + dev->ntl_bar.size = size; + } + + /* GENID bar (logically divided per device) + * 512K aligned address -> 0x80000 (bit 19) + */ + phys_map_get(pau->chip_id, PAU_GENID, pau->index, &addr, &size); + val = SETFIELD(PAU_GENID_BAR_ADDR, 0ull, addr >> 19); + pau_write(pau, PAU_GENID_BAR, val); + + pau_for_each_dev(dev, pau) { + if (dev->type == PAU_DEV_TYPE_UNKNOWN) + continue; + + dev->genid_bar.size = size; + /* +320K = Bricks 0-4 Config Addr/Data registers */ + dev->genid_bar.cfg = addr + 0x50000; + } +} + +static void pau_opencapi_init_hw(struct pau *pau) +{ + pau_opencapi_assign_bars(pau); +} + +static void pau_opencapi_init(struct pau *pau) +{ + if (!pau_next_dev(pau, NULL, PAU_DEV_TYPE_OPENCAPI)) + return; + + assert(platform.ocapi); + + pau_opencapi_init_hw(pau); + + disable_fast_reboot("OpenCAPI device enabled"); +} + static void pau_init(struct pau *pau) { struct pau_dev *dev; @@ -201,6 +275,7 @@ static void pau_init(struct pau *pau) pau_for_each_dev(dev, pau) pau_device_detect_fixup(dev); + pau_opencapi_init(pau); } void probe_pau(void) diff --git a/hw/phys-map.c b/hw/phys-map.c index d6ff99f..711d626 100644 --- a/hw/phys-map.c +++ b/hw/phys-map.c @@ -82,8 +82,51 @@ static const struct phys_map_entry phys_map_table_p10[] = { { VAS_HYP_WIN , 0, 0x00060302fe000000ull, 0x0000000002000000ull }, { VAS_USER_WIN , 0, 0x0006030300000000ull, 0x0000000100000000ull }, - /* TODO: MC, OCMB, PAU */ - { RESV , 8, 0x0006030400000000ull, 0x000000f800000000ull }, + /* TODO: MC, OCMB */ + { RESV , 8, 0x0006030400000000ull, 0x0000008400000000ull }, + { PAU_OCAPI_MMIO , 0, 0x0006038800000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 1, 0x0006039000000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 2, 0x0006039800000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 3, 0x000603a000000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 4, 0x000603a800000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 5, 0x000603b000000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 6, 0x000603b800000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 7, 0x000603c000000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 8, 0x000603c800000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO , 9, 0x000603d000000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO ,10, 0x000603d800000000ull, 0x0000000800000000ull }, + { PAU_OCAPI_MMIO ,11, 0x000603e000000000ull, 0x0000000800000000ull }, + { PAU_REGS , 0, 0x000603e800000000ull, 0x0000000001000000ull }, + { PAU_REGS , 1, 0x000603e801000000ull, 0x0000000001000000ull }, + { PAU_REGS , 2, 0x000603e802000000ull, 0x0000000001000000ull }, + { PAU_REGS , 3, 0x000603e803000000ull, 0x0000000001000000ull }, + { PAU_REGS , 4, 0x000603e804000000ull, 0x0000000001000000ull }, + { PAU_REGS , 5, 0x000603e805000000ull, 0x0000000001000000ull }, + { RESV , 9, 0x000603e806000000ull, 0x0000000000040000ull }, + { PAU_NTL , 0, 0x000603e806040000ull, 0x0000000000020000ull }, + { PAU_NTL , 1, 0x000603e806060000ull, 0x0000000000020000ull }, + { PAU_GENID , 0, 0x000603e806080000ull, 0x0000000000080000ull }, + { RESV ,10, 0x000603e806100000ull, 0x0000000000040000ull }, + { PAU_NTL , 2, 0x000603e806140000ull, 0x0000000000020000ull }, + { PAU_NTL , 3, 0x000603e806160000ull, 0x0000000000020000ull }, + { PAU_GENID , 1, 0x000603e806180000ull, 0x0000000000080000ull }, + { RESV ,11, 0x000603e806200000ull, 0x0000000000040000ull }, + { PAU_NTL , 4, 0x000603e806240000ull, 0x0000000000020000ull }, + { PAU_NTL , 5, 0x000603e806260000ull, 0x0000000000020000ull }, + { PAU_GENID , 2, 0x000603e806280000ull, 0x0000000000080000ull }, + { RESV ,12, 0x000603e806300000ull, 0x0000000000040000ull }, + { PAU_NTL , 6, 0x000603e806340000ull, 0x0000000000020000ull }, + { PAU_NTL , 7, 0x000603e806360000ull, 0x0000000000020000ull }, + { PAU_GENID , 3, 0x000603e806380000ull, 0x0000000000080000ull }, + { RESV ,13, 0x000603e806400000ull, 0x0000000000040000ull }, + { PAU_NTL , 8, 0x000603e806440000ull, 0x0000000000020000ull }, + { PAU_NTL , 9, 0x000603e806460000ull, 0x0000000000020000ull }, + { PAU_GENID , 4, 0x000603e806480000ull, 0x0000000000080000ull }, + { RESV ,14, 0x000603e806500000ull, 0x0000000000040000ull }, + { PAU_NTL ,10, 0x000603e806540000ull, 0x0000000000020000ull }, + { PAU_NTL ,11, 0x000603e806560000ull, 0x0000000000020000ull }, + { PAU_GENID , 5, 0x000603e806580000ull, 0x0000000000080000ull }, + { RESV ,15, 0x000603e806600000ull, 0x00000013F9A00000ull }, { XSCOM , 0, 0x000603fc00000000ull, 0x0000000400000000ull }, /* 4 TB offset */ @@ -96,10 +139,10 @@ static const struct phys_map_entry phys_map_table_p10[] = { { XIVE_END , 0, 0x0006060000000000ull, 0x0000020000000000ull }, /* 8 - 13 TB offset */ - { RESV , 9, 0x0006080000000000ull, 0x0000060000000000ull }, + { RESV ,16, 0x0006080000000000ull, 0x0000060000000000ull }, /* 14 TB offset */ - { RESV ,10, 0x00060e0000000000ull, 0x0000008000000000ull }, + { RESV ,17, 0x00060e0000000000ull, 0x0000008000000000ull }, { NULL_MAP, 0, 0, 0 }, }; @@ -130,10 +173,10 @@ static const struct phys_map_entry phys_map_table_nimbus[] = { * * We don't currently support >4TB ranges. */ - { OCAPI_MEM, 0, 0x0002000000000000ull, 0x0000040000000000ull }, - { OCAPI_MEM, 1, 0x0002800000000000ull, 0x0000040000000000ull }, - { OCAPI_MEM, 2, 0x0003000000000000ull, 0x0000040000000000ull }, - { OCAPI_MEM, 3, 0x0003800000000000ull, 0x0000040000000000ull }, + { OCAPI_MEM, 0, 0x0002000000000000ull, 0x0000040000000000ull }, + { OCAPI_MEM, 1, 0x0002800000000000ull, 0x0000040000000000ull }, + { OCAPI_MEM, 2, 0x0003000000000000ull, 0x0000040000000000ull }, + { OCAPI_MEM, 3, 0x0003800000000000ull, 0x0000040000000000ull }, /* 0 TB offset @ MMIO 0x0006000000000000ull */ { PHB4_64BIT_MMIO, 0, 0x0006000000000000ull, 0x0000004000000000ull }, diff --git a/include/pau-regs.h b/include/pau-regs.h index a35668f..afe6f95 100644 --- a/include/pau-regs.h +++ b/include/pau-regs.h @@ -26,5 +26,31 @@ #define PAU_REG_OFFSET(reg) ((reg) & 0xffff) #define PAU_BLOCK_CQ_SM(n) PAU_BLOCK(4, (n)) +#define PAU_BLOCK_CQ_CTL PAU_BLOCK(4, 4) + +/* + * CQ_SM block registers + * + * Definitions here use PAU_BLOCK_CQ_SM(0), but when pau_write() is given + * one of these, it will do corresponding writes to every CQ_SM block. + */ +#define PAU_MCP_MISC_CFG0 (PAU_BLOCK_CQ_SM(0) + 0x000) +#define PAU_MCP_MISC_CFG0_MA_MCRESP_OPT_WRP PPC_BIT(9) +#define PAU_MCP_MISC_CFG0_ENABLE_PBUS PPC_BIT(26) +#define PAU_SNP_MISC_CFG0 (PAU_BLOCK_CQ_SM(0) + 0x180) +#define PAU_SNP_MISC_CFG0_ENABLE_PBUS PPC_BIT(2) +#define PAU_NTL_BAR(brk) (PAU_BLOCK_CQ_SM(0) + 0x1b8 + (brk) * 8) +#define PAU_NTL_BAR_ADDR PPC_BITMASK(3, 35) +#define PAU_NTL_BAR_SIZE PPC_BITMASK(39, 43) +#define PAU_MMIO_BAR (PAU_BLOCK_CQ_SM(0) + 0x1e0) +#define PAU_MMIO_BAR_ENABLE PPC_BIT(0) +#define PAU_MMIO_BAR_ADDR PPC_BITMASK(3, 27) +#define PAU_GENID_BAR (PAU_BLOCK_CQ_SM(0) + 0x1e8) +#define PAU_GENID_BAR_ADDR PPC_BITMASK(3, 32) + +/* CQ_CTL block registers */ +#define PAU_CTL_MISC_MMIOPA_CONFIG(brk) (PAU_BLOCK_CQ_CTL + 0x098 + (brk) * 8) +#define PAU_CTL_MISC_MMIOPA_CONFIG_BAR_ADDR PPC_BITMASK(1, 35) +#define PAU_CTL_MISC_MMIOPA_CONFIG_BAR_SIZE PPC_BITMASK(39, 43) #endif /* __PAU_REGS_H */ diff --git a/include/pau.h b/include/pau.h index e946e0f..be8ed26 100644 --- a/include/pau.h +++ b/include/pau.h @@ -19,11 +19,21 @@ enum pau_dev_type { PAU_DEV_TYPE_ANY = INT_MAX }; +/* Used to expose a hardware BAR (or logical slice of it) outside skiboot */ +struct pau_bar { + uint64_t addr; + uint64_t size; + uint64_t cfg; +}; + struct pau_dev { enum pau_dev_type type; uint32_t index; struct dt_node *dn; + struct pau_bar ntl_bar; + struct pau_bar genid_bar; + /* Associated I2C information */ uint8_t i2c_bus_id; @@ -44,6 +54,7 @@ struct pau { /* Global MMIO window (all PAU regs) */ uint64_t regs[2]; + bool mmio_access; struct lock lock; @@ -94,4 +105,72 @@ static inline int pau_get_phb_index(unsigned int pau_index, return PAU_PHB_INDEX_BASE + pau_index * 2 + link_index; } +/* + * We use the indirect method because it uses the same addresses as + * the MMIO offsets (PAU RING) + */ +static inline void pau_scom_sel(struct pau *pau, uint64_t reg, + uint64_t size) +{ + uint64_t val; + + val = SETFIELD(PAU_MISC_DA_ADDR, 0ull, reg); + val = SETFIELD(PAU_MISC_DA_LEN, val, size); + xscom_write(pau->chip_id, + pau->xscom_base + PAU_MISC_SCOM_IND_SCOM_ADDR, + val); +} + +static inline void pau_scom_write(struct pau *pau, uint64_t reg, + uint64_t size, + uint64_t val) +{ + pau_scom_sel(pau, reg, size); + xscom_write(pau->chip_id, + pau->xscom_base + PAU_MISC_SCOM_IND_SCOM_DATA, + val); +} + +static inline uint64_t pau_scom_read(struct pau *pau, uint64_t reg, + uint64_t size) +{ + uint64_t val; + + pau_scom_sel(pau, reg, size); + xscom_read(pau->chip_id, + pau->xscom_base + PAU_MISC_SCOM_IND_SCOM_DATA, + &val); + + return val; +} + +static inline void pau_write(struct pau *pau, uint64_t reg, + uint64_t val) +{ + void *mmio = (void *)pau->regs[0]; + + if (pau->mmio_access) + out_be64(mmio + reg, val); + else + pau_scom_write(pau, reg, PAU_MISC_DA_LEN_8B, val); + + /* CQ_SM writes should be mirrored in all four blocks */ + if (PAU_REG_BLOCK(reg) != PAU_BLOCK_CQ_SM(0)) + return; + + for (uint32_t i = 1; i < 4; i++) + pau_write(pau, PAU_BLOCK_CQ_SM(i) + PAU_REG_OFFSET(reg), + val); +} + +static inline uint64_t pau_read(struct pau *pau, uint64_t reg) +{ + void *mmio = (void *)pau->regs[0]; + + if (pau->mmio_access) + return in_be64(mmio + reg); + + return pau_scom_read(pau, reg, PAU_MISC_DA_LEN_8B); +} + #endif /* __PAU_H */ diff --git a/include/phys-map.h b/include/phys-map.h index 1dd337a..a53bcd0 100644 --- a/include/phys-map.h +++ b/include/phys-map.h @@ -51,6 +51,10 @@ enum phys_map_type { XIVE_NVPG, XIVE_ESB, XIVE_END, + PAU_OCAPI_MMIO, + PAU_REGS, + PAU_GENID, + PAU_NTL, }; extern void phys_map_get(uint64_t gcid, enum phys_map_type type, |