From 66c38f45e9fc079dc47c8865ee6a27da5e7cdc0f Mon Sep 17 00:00:00 2001 From: Christophe Lombard Date: Tue, 29 Aug 2023 11:23:18 +0200 Subject: hw: Move lpc firmware space helpers Add new lpc helpers for doing a bulk io to firmware space. Reviewed-by: Abhishek Singh Tomar Signed-off-by: Christophe Lombard Signed-off-by: Reza Arbab --- hw/lpc.c | 74 ++++++++++++++++++++++++++++++++++++++++ include/lpc.h | 6 ++++ libflash/ipmi-hiomap.c | 66 ++--------------------------------- libflash/mbox-flash.c | 64 ++-------------------------------- libflash/test/mbox-server.c | 68 ++++++++++++++++++++++++++++++++++++ libflash/test/test-ipmi-hiomap.c | 66 +++++++++++++++++++++++++++++++++++ 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) { -- cgit v1.1