aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/pau.c75
-rw-r--r--hw/phys-map.c59
-rw-r--r--include/pau-regs.h26
-rw-r--r--include/pau.h79
-rw-r--r--include/phys-map.h4
5 files changed, 235 insertions, 8 deletions
diff --git a/hw/pau.c b/hw/pau.c
index 63b69d3..5d4b157 100644
--- a/hw/pau.c
+++ b/hw/pau.c
@@ -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,