[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