aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Lombard <clombard@linux.ibm.com>2023-08-29 11:23:18 +0200
committerReza Arbab <arbab@linux.ibm.com>2023-09-12 14:22:11 -0500
commit66c38f45e9fc079dc47c8865ee6a27da5e7cdc0f (patch)
tree52e5a6c14e04422037c8b9c29cb015acc5220574
parent67064d0dbf8e6b825e94cc9a7bb9824a408fe9cd (diff)
downloadskiboot-66c38f45e9fc079dc47c8865ee6a27da5e7cdc0f.zip
skiboot-66c38f45e9fc079dc47c8865ee6a27da5e7cdc0f.tar.gz
skiboot-66c38f45e9fc079dc47c8865ee6a27da5e7cdc0f.tar.bz2
hw: Move lpc firmware space helpers
Add new lpc helpers for doing a bulk io to firmware space. Reviewed-by: Abhishek Singh Tomar <abhishek@linux.ibm.com> Signed-off-by: Christophe Lombard <clombard@linux.ibm.com> Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
-rw-r--r--hw/lpc.c74
-rw-r--r--include/lpc.h6
-rw-r--r--libflash/ipmi-hiomap.c66
-rw-r--r--libflash/mbox-flash.c64
-rw-r--r--libflash/test/mbox-server.c68
-rw-r--r--libflash/test/test-ipmi-hiomap.c66
6 files changed, 218 insertions, 126 deletions
diff --git a/hw/lpc.c b/hw/lpc.c
index bf3ab1f..caaacc4 100644
--- a/hw/lpc.c
+++ b/hw/lpc.c
@@ -667,6 +667,80 @@ int64_t lpc_probe_read(enum OpalLPCAddressType addr_type, uint32_t addr,
return __lpc_read_sanity(addr_type, addr, data, sz, true);
}
+int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len)
+{
+ int rc;
+
+ prlog(PR_TRACE, "Reading 0x%08x bytes at FW offset 0x%08x\n",
+ len, off);
+
+ while (len) {
+ uint32_t chunk;
+ uint32_t dat;
+
+ /* XXX: make this read until it's aligned */
+ if (len > 3 && !(off & 3)) {
+ rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
+ if (!rc) {
+ /*
+ * lpc_read swaps to CPU endian but it's not
+ * really a 32-bit value, so convert back.
+ */
+ *(__be32 *)buf = cpu_to_be32(dat);
+ }
+ chunk = 4;
+ } else {
+ rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
+ if (!rc)
+ *(uint8_t *)buf = dat;
+ chunk = 1;
+ }
+ if (rc) {
+ prlog(PR_ERR, "lpc_read failure %d to FW 0x%08x\n", rc, off);
+ return rc;
+ }
+ len -= chunk;
+ off += chunk;
+ buf += chunk;
+ }
+
+ return 0;
+}
+
+int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len)
+{
+ int rc;
+
+ prlog(PR_TRACE, "Writing 0x%08x bytes at FW offset 0x%08x\n",
+ len, off);
+
+ while (len) {
+ uint32_t chunk;
+
+ if (len > 3 && !(off & 3)) {
+ /* endian swap: see lpc_window_write */
+ uint32_t dat = be32_to_cpu(*(__be32 *)buf);
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
+ chunk = 4;
+ } else {
+ uint8_t dat = *(uint8_t *)buf;
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
+ chunk = 1;
+ }
+ if (rc) {
+ prlog(PR_ERR, "lpc_write failure %d to FW 0x%08x\n", rc, off);
+ return rc;
+ }
+ len -= chunk;
+ off += chunk;
+ buf += chunk;
+ }
+
+ return 0;
+}
+
/*
* The "OPAL" variant add the emulation of 2 and 4 byte accesses using
* byte accesses for IO and MEM space in order to be compatible with
diff --git a/include/lpc.h b/include/lpc.h
index b641aa4..ce9c33d 100644
--- a/include/lpc.h
+++ b/include/lpc.h
@@ -102,6 +102,12 @@ extern int64_t lpc_probe_write(enum OpalLPCAddressType addr_type, uint32_t addr,
extern int64_t lpc_probe_read(enum OpalLPCAddressType addr_type, uint32_t addr,
uint32_t *data, uint32_t sz);
+/*
+ * helpers for doing a bulk io to firmware space.
+ */
+extern int64_t lpc_fw_read(uint32_t addr, void *buf, uint32_t sz);
+extern int64_t lpc_fw_write(uint32_t addr, const void *buf, uint32_t sz);
+
/* Mark LPC bus as used by console */
extern void lpc_used_by_console(void);
diff --git a/libflash/ipmi-hiomap.c b/libflash/ipmi-hiomap.c
index 29355d6..93aaef4 100644
--- a/libflash/ipmi-hiomap.c
+++ b/libflash/ipmi-hiomap.c
@@ -555,45 +555,11 @@ static int lpc_window_read(struct ipmi_hiomap *ctx, uint32_t pos,
void *buf, uint32_t len)
{
uint32_t off = ctx->current.lpc_addr + (pos - ctx->current.cur_pos);
- int rc;
if ((ctx->current.lpc_addr + ctx->current.size) < (off + len))
return FLASH_ERR_PARM_ERROR;
- prlog(PR_TRACE, "Reading at 0x%08x for 0x%08x offset: 0x%08x\n",
- pos, len, off);
-
- while(len) {
- uint32_t chunk;
- uint32_t dat;
-
- /* XXX: make this read until it's aligned */
- if (len > 3 && !(off & 3)) {
- rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
- if (!rc) {
- /*
- * lpc_read swaps to CPU endian but it's not
- * really a 32-bit value, so convert back.
- */
- *(__be32 *)buf = cpu_to_be32(dat);
- }
- chunk = 4;
- } else {
- rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
- if (!rc)
- *(uint8_t *)buf = dat;
- chunk = 1;
- }
- if (rc) {
- prlog(PR_ERR, "lpc_read failure %d to FW 0x%08x\n", rc, off);
- return rc;
- }
- len -= chunk;
- off += chunk;
- buf += chunk;
- }
-
- return 0;
+ return lpc_fw_read(off, buf, len);
}
static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
@@ -601,7 +567,6 @@ static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
{
uint32_t off = ctx->current.lpc_addr + (pos - ctx->current.cur_pos);
enum lpc_window_state state;
- int rc;
lock(&ctx->lock);
state = ctx->window_state;
@@ -613,34 +578,7 @@ static int lpc_window_write(struct ipmi_hiomap *ctx, uint32_t pos,
if ((ctx->current.lpc_addr + ctx->current.size) < (off + len))
return FLASH_ERR_PARM_ERROR;
- prlog(PR_TRACE, "Writing at 0x%08x for 0x%08x offset: 0x%08x\n",
- pos, len, off);
-
- while(len) {
- uint32_t chunk;
-
- if (len > 3 && !(off & 3)) {
- /* endian swap: see lpc_window_read */
- uint32_t dat = be32_to_cpu(*(__be32 *)buf);
-
- rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
- chunk = 4;
- } else {
- uint8_t dat = *(uint8_t *)buf;
-
- rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
- chunk = 1;
- }
- if (rc) {
- prlog(PR_ERR, "lpc_write failure %d to FW 0x%08x\n", rc, off);
- return rc;
- }
- len -= chunk;
- off += chunk;
- buf += chunk;
- }
-
- return 0;
+ return lpc_fw_write(off, buf, len);
}
/* Best-effort asynchronous event handling by blocklevel callbacks */
diff --git a/libflash/mbox-flash.c b/libflash/mbox-flash.c
index 4c20f15..9e686c9 100644
--- a/libflash/mbox-flash.c
+++ b/libflash/mbox-flash.c
@@ -147,79 +147,19 @@ static int lpc_window_read(struct mbox_flash_data *mbox_flash, uint32_t pos,
void *buf, uint32_t len)
{
uint32_t off = mbox_flash->read.lpc_addr + (pos - mbox_flash->read.cur_pos);
- int rc;
prlog(PR_TRACE, "Reading at 0x%08x for 0x%08x offset: 0x%08x\n",
pos, len, off);
- while(len) {
- uint32_t chunk;
- uint32_t dat;
-
- /* XXX: make this read until it's aligned */
- if (len > 3 && !(off & 3)) {
- rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
- if (!rc) {
- /*
- * lpc_read swaps to CPU endian but it's not
- * really a 32-bit value, so convert back.
- */
- *(__be32 *)buf = cpu_to_be32(dat);
- }
- chunk = 4;
- } else {
- rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
- if (!rc)
- *(uint8_t *)buf = dat;
- chunk = 1;
- }
- if (rc) {
- prlog(PR_ERR, "lpc_read failure %d to FW 0x%08x\n", rc, off);
- return rc;
- }
- len -= chunk;
- off += chunk;
- buf += chunk;
- }
-
- return 0;
+ return lpc_fw_read(off, buf, len);
}
static int lpc_window_write(struct mbox_flash_data *mbox_flash, uint32_t pos,
const void *buf, uint32_t len)
{
uint32_t off = mbox_flash->write.lpc_addr + (pos - mbox_flash->write.cur_pos);
- int rc;
-
-
- prlog(PR_TRACE, "Writing at 0x%08x for 0x%08x offset: 0x%08x\n",
- pos, len, off);
-
- while(len) {
- uint32_t chunk;
-
- if (len > 3 && !(off & 3)) {
- /* endian swap: see lpc_window_read */
- uint32_t dat = be32_to_cpu(*(__be32 *)buf);
-
- rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
- chunk = 4;
- } else {
- uint8_t dat = *(uint8_t *)buf;
-
- rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
- chunk = 1;
- }
- if (rc) {
- prlog(PR_ERR, "lpc_write failure %d to FW 0x%08x\n", rc, off);
- return rc;
- }
- len -= chunk;
- off += chunk;
- buf += chunk;
- }
- return 0;
+ return lpc_fw_write(off, buf, len);
}
static uint64_t mbox_flash_mask(struct mbox_flash_data *mbox_flash)
diff --git a/libflash/test/mbox-server.c b/libflash/test/mbox-server.c
index 8a68cff..053be98 100644
--- a/libflash/test/mbox-server.c
+++ b/libflash/test/mbox-server.c
@@ -142,6 +142,74 @@ int64_t lpc_write(enum OpalLPCAddressType __unused addr_type, uint32_t addr,
return 0;
}
+int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len);
+int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len)
+{
+ int rc;
+
+ while (len) {
+ uint32_t chunk;
+ uint32_t dat;
+
+ /* XXX: make this read until it's aligned */
+ if (len > 3 && !(off & 3)) {
+ rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
+ if (!rc) {
+ /*
+ * lpc_read swaps to CPU endian but it's not
+ * really a 32-bit value, so convert back.
+ */
+ *(__be32 *)buf = cpu_to_be32(dat);
+ }
+ chunk = 4;
+ } else {
+ rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
+ if (!rc)
+ *(uint8_t *)buf = dat;
+ chunk = 1;
+ }
+ if (rc)
+ return rc;
+
+ len -= chunk;
+ off += chunk;
+ buf += chunk;
+ }
+
+ return 0;
+}
+
+int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len);
+int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len)
+{
+ int rc;
+
+ while (len) {
+ uint32_t chunk;
+
+ if (len > 3 && !(off & 3)) {
+ /* endian swap: see lpc_window_write */
+ uint32_t dat = be32_to_cpu(*(__be32 *)buf);
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
+ chunk = 4;
+ } else {
+ uint8_t dat = *(uint8_t *)buf;
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
+ chunk = 1;
+ }
+ if (rc)
+ return rc;
+
+ len -= chunk;
+ off += chunk;
+ buf += chunk;
+ }
+
+ return 0;
+}
+
int bmc_mbox_register_attn(mbox_attn_cb handler, void *drv_data)
{
mbox_data.attn = handler;
diff --git a/libflash/test/test-ipmi-hiomap.c b/libflash/test/test-ipmi-hiomap.c
index 6117e9d..b740a6f 100644
--- a/libflash/test/test-ipmi-hiomap.c
+++ b/libflash/test/test-ipmi-hiomap.c
@@ -223,6 +223,72 @@ int64_t lpc_read(enum OpalLPCAddressType addr_type __attribute__((unused)),
return 0;
}
+int64_t lpc_fw_read(uint32_t off, void *buf, uint32_t len)
+{
+ int rc;
+
+ while (len) {
+ uint32_t chunk;
+ uint32_t dat;
+
+ /* XXX: make this read until it's aligned */
+ if (len > 3 && !(off & 3)) {
+ rc = lpc_read(OPAL_LPC_FW, off, &dat, 4);
+ if (!rc) {
+ /*
+ * lpc_read swaps to CPU endian but it's not
+ * really a 32-bit value, so convert back.
+ */
+ *(__be32 *)buf = cpu_to_be32(dat);
+ }
+ chunk = 4;
+ } else {
+ rc = lpc_read(OPAL_LPC_FW, off, &dat, 1);
+ if (!rc)
+ *(uint8_t *)buf = dat;
+ chunk = 1;
+ }
+ if (rc)
+ return rc;
+
+ len -= chunk;
+ off += chunk;
+ buf += chunk;
+ }
+
+ return 0;
+}
+
+int64_t lpc_fw_write(uint32_t off, const void *buf, uint32_t len)
+{
+ int rc;
+
+ while (len) {
+ uint32_t chunk;
+
+ if (len > 3 && !(off & 3)) {
+ /* endian swap: see lpc_window_write */
+ uint32_t dat = be32_to_cpu(*(__be32 *)buf);
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 4);
+ chunk = 4;
+ } else {
+ uint8_t dat = *(uint8_t *)buf;
+
+ rc = lpc_write(OPAL_LPC_FW, off, dat, 1);
+ chunk = 1;
+ }
+ if (rc)
+ return rc;
+
+ len -= chunk;
+ off += chunk;
+ buf += chunk;
+ }
+
+ return 0;
+}
+
static bool lpc_read_success(const uint8_t *buf, size_t len)
{
if (len < 64) {