[Skiboot] [PATCH] memboot: Add a memboot flash backend
Alistair Popple
alistair at popple.id.au
Tue Feb 24 16:10:02 AEDT 2015
memboot uses bmc system memory instead of a real flash chip. This
patch adds a flash backend for bmc system memory to allow use of the
memboot tool (in external/memboot) to boot the system.
Signed-off-by: Alistair Popple <alistair at popple.id.au>
---
hw/ast-bmc/ast-io.c | 9 +++++
hw/ast-bmc/ast-sf-ctrl.c | 90 ++++++++++++++++++++++++++++++++++++++++++------
include/ast.h | 2 ++
libflash/libflash.c | 1 +
platforms/astbmc/pnor.c | 17 +++++++--
5 files changed, 106 insertions(+), 13 deletions(-)
diff --git a/hw/ast-bmc/ast-io.c b/hw/ast-bmc/ast-io.c
index 34b588d..bc27155 100644
--- a/hw/ast-bmc/ast-io.c
+++ b/hw/ast-bmc/ast-io.c
@@ -382,6 +382,15 @@ void ast_io_init(void)
ast_setup_sio_irq_polarity();
}
+bool ast_is_ahb_lpc_pnor(void)
+{
+ uint32_t hicr7;
+
+ /* Determine if the LPC->AHB bridge is pointing at PNOR or not */
+ hicr7 = bmc_sio_ahb_readl(LPC_HICR7);
+ return (hicr7 & 0xffff0000) == (PNOR_FLASH_BASE & 0xffff0000);
+}
+
void ast_setup_ibt(uint16_t io_base, uint8_t irq)
{
uint32_t v;
diff --git a/hw/ast-bmc/ast-sf-ctrl.c b/hw/ast-bmc/ast-sf-ctrl.c
index 06287a8..eee18e1 100644
--- a/hw/ast-bmc/ast-sf-ctrl.c
+++ b/hw/ast-bmc/ast-sf-ctrl.c
@@ -672,7 +672,7 @@ static int ast_sf_setup_micron(struct ast_sf_ctrl *ct, struct flash_info *info)
static int ast_sf_setup(struct spi_flash_ctrl *ctrl, uint32_t *tsize)
{
- struct ast_sf_ctrl *ct = container_of(ctrl, struct ast_sf_ctrl, ops);
+ struct ast_sf_ctrl *ct = container_of(ctrl, struct ast_sf_ctrl, ops);
struct flash_info *info = ctrl->finfo;
(void)tsize;
@@ -681,7 +681,7 @@ static int ast_sf_setup(struct spi_flash_ctrl *ctrl, uint32_t *tsize)
* Configure better timings and read mode for known
* flash chips
*/
- switch(info->id) {
+ switch(info->id) {
case 0xc22019: /* MX25L25635F */
case 0xc2201a: /* MX66L51235F */
return ast_sf_setup_macronix(ct, info);
@@ -787,11 +787,69 @@ static bool ast_sf_init_bmc(struct ast_sf_ctrl *ct)
return true;
}
+static int ast_mem_set4b(struct spi_flash_ctrl *ctrl __unused,
+ bool enable __unused)
+{
+ return 0;
+}
+
+static int ast_mem_setup(struct spi_flash_ctrl *ctrl __unused,
+ uint32_t *tsize __unused)
+{
+ return 0;
+}
+
+static int ast_mem_chipid(struct spi_flash_ctrl *ctrl __unused, uint8_t *id_buf,
+ uint32_t *id_size)
+{
+ if (*id_size < 3)
+ return -1;
+
+ id_buf[0] = 0xaa;
+ id_buf[1] = 0x55;
+ id_buf[2] = 0xaa;
+ *id_size = 3;
+ return 0;
+}
+
+static int ast_mem_write(struct spi_flash_ctrl *ctrl, uint32_t pos,
+ const void *buf, uint32_t len)
+{
+ struct ast_sf_ctrl *ct = container_of(ctrl, struct ast_sf_ctrl, ops);
+
+ /*
+ * This only works when the ahb is pointed at system memory.
+ */
+ return ast_copy_to_ahb(ct->flash + pos, buf, len);
+}
+
+static int ast_mem_erase(struct spi_flash_ctrl *ctrl, uint32_t addr, uint32_t size)
+{
+ struct ast_sf_ctrl *ct = container_of(ctrl, struct ast_sf_ctrl, ops);
+ uint32_t pos, len, end = addr + size;
+ uint64_t zero = 0;
+ int ret;
+
+ for (pos = addr; pos < end; pos += sizeof(zero)) {
+ if (pos + sizeof(zero) > end)
+ len = end - pos;
+ else
+ len = sizeof(zero);
+
+ ret = ast_copy_to_ahb(ct->flash + pos, &zero, len);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int ast_sf_open(uint8_t type, struct spi_flash_ctrl **ctrl)
{
struct ast_sf_ctrl *ct;
- if (type != AST_SF_TYPE_PNOR && type != AST_SF_TYPE_BMC)
+ if (type != AST_SF_TYPE_PNOR && type != AST_SF_TYPE_BMC
+ && type != AST_SF_TYPE_MEM)
return -EINVAL;
*ctrl = NULL;
@@ -802,18 +860,31 @@ int ast_sf_open(uint8_t type, struct spi_flash_ctrl **ctrl)
}
memset(ct, 0, sizeof(*ct));
ct->type = type;
- ct->ops.cmd_wr = ast_sf_cmd_wr;
- ct->ops.cmd_rd = ast_sf_cmd_rd;
- ct->ops.set_4b = ast_sf_set_4b;
- ct->ops.read = ast_sf_read;
- ct->ops.setup = ast_sf_setup;
+
+ if (type == AST_SF_TYPE_MEM) {
+ ct->ops.cmd_wr = NULL;
+ ct->ops.cmd_rd = NULL;
+ ct->ops.read = ast_sf_read;
+ ct->ops.set_4b = ast_mem_set4b;
+ ct->ops.write = ast_mem_write;
+ ct->ops.erase = ast_mem_erase;
+ ct->ops.setup = ast_mem_setup;
+ ct->ops.chip_id = ast_mem_chipid;
+ ct->flash = PNOR_FLASH_BASE;
+ } else {
+ ct->ops.cmd_wr = ast_sf_cmd_wr;
+ ct->ops.cmd_rd = ast_sf_cmd_rd;
+ ct->ops.set_4b = ast_sf_set_4b;
+ ct->ops.read = ast_sf_read;
+ ct->ops.setup = ast_sf_setup;
+ }
ast_get_ahb_freq();
if (type == AST_SF_TYPE_PNOR) {
if (!ast_sf_init_pnor(ct))
goto fail;
- } else {
+ } else if (type == AST_SF_TYPE_BMC) {
if (!ast_sf_init_bmc(ct))
goto fail;
}
@@ -843,4 +914,3 @@ void ast_sf_close(struct spi_flash_ctrl *ctrl)
/* Free the whole lot */
free(ct);
}
-
diff --git a/include/ast.h b/include/ast.h
index efc898d..58adb6c 100644
--- a/include/ast.h
+++ b/include/ast.h
@@ -72,6 +72,7 @@ int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len);
int ast_copy_from_ahb(void *dst, uint32_t reg, uint32_t len);
void ast_io_init(void);
+bool ast_is_ahb_lpc_pnor(void);
/* UART configuration */
@@ -90,6 +91,7 @@ void ast_setup_ibt(uint16_t io_base, uint8_t irq);
*/
#define AST_SF_TYPE_PNOR 0
#define AST_SF_TYPE_BMC 1
+#define AST_SF_TYPE_MEM 2
struct spi_flash_ctrl;
int ast_sf_open(uint8_t type, struct spi_flash_ctrl **ctrl);
diff --git a/libflash/libflash.c b/libflash/libflash.c
index 5badbff..9d07694 100644
--- a/libflash/libflash.c
+++ b/libflash/libflash.c
@@ -28,6 +28,7 @@ static const struct flash_info flash_info[] = {
FL_ERASE_BULK | FL_MICRON_BUGS,
"Micron N25Qx512Ax" },
{ 0x55aa55, 0x00100000, FL_ERASE_ALL | FL_CAN_4B, "TEST_FLASH" },
+ { 0xaa55aa, 0x02000000, FL_ERASE_ALL | FL_CAN_4B, "EMULATED_FLASH"},
};
struct flash_chip {
diff --git a/platforms/astbmc/pnor.c b/platforms/astbmc/pnor.c
index c64f41e..5b04b4e 100644
--- a/platforms/astbmc/pnor.c
+++ b/platforms/astbmc/pnor.c
@@ -30,8 +30,20 @@ int pnor_init(void)
struct flash_chip *pnor_chip;
int rc;
- /* Open controller and flash */
- rc = ast_sf_open(AST_SF_TYPE_PNOR, &pnor_ctrl);
+ /* Open controller and flash. If the LPC->AHB doesn't point to
+ * the PNOR flash base we assume we're booting from BMC system
+ * memory (or some other place that supports LPC FW reads &
+ * writes).
+ *
+ * FIXME: In future Hostboot should indicate this via the
+ * device-tree and we should just use that to detect if we're
+ * booting from memory or not. */
+ if (ast_is_ahb_lpc_pnor())
+ rc = ast_sf_open(AST_SF_TYPE_PNOR, &pnor_ctrl);
+ else {
+ printf("PLAT: Memboot detected\n");
+ rc = ast_sf_open(AST_SF_TYPE_MEM, &pnor_ctrl);
+ }
if (rc) {
prerror("PLAT: Failed to open PNOR flash controller\n");
goto fail;
@@ -54,4 +66,3 @@ int pnor_init(void)
return rc;
}
-
--
1.8.3.2
More information about the Skiboot
mailing list