aboutsummaryrefslogtreecommitdiff
path: root/include/pau.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/pau.h')
-rw-r--r--include/pau.h79
1 files changed, 79 insertions, 0 deletions
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 */