aboutsummaryrefslogtreecommitdiff
path: root/hw/ast-bmc
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2015-03-20 14:59:15 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-03-26 11:12:18 +1100
commitfc2906d321adf27db33918711b1055a8ea5b34f9 (patch)
tree609849d3bbc735d0643d9cb42fa5e2764ab8da88 /hw/ast-bmc
parent822403ea5dcc51a5c70c0ab061ef49adb17d82e4 (diff)
downloadskiboot-fc2906d321adf27db33918711b1055a8ea5b34f9.zip
skiboot-fc2906d321adf27db33918711b1055a8ea5b34f9.tar.gz
skiboot-fc2906d321adf27db33918711b1055a8ea5b34f9.tar.bz2
memboot: Add a memboot flash backend
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@popple.id.au> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/ast-bmc')
-rw-r--r--hw/ast-bmc/ast-io.c29
-rw-r--r--hw/ast-bmc/ast-sf-ctrl.c90
2 files changed, 104 insertions, 15 deletions
diff --git a/hw/ast-bmc/ast-io.c b/hw/ast-bmc/ast-io.c
index 34b588d..08ce99d 100644
--- a/hw/ast-bmc/ast-io.c
+++ b/hw/ast-bmc/ast-io.c
@@ -58,7 +58,7 @@
* flash from IDSEL 0 as follow:
*
* ADRBASE=0x3000 HWMBASE=0x0e00 for 32MB
- * ADRMASK=0xfe00 HWNCARE=0x01ff
+ * ADRMASK=0xfe00 HWNCARE=0x01ff
*
* Which means mapping of LPC 0x0e000000..0x0fffffff onto
* AHB 0x30000000..0x31ffffff
@@ -83,14 +83,20 @@
* we'll only do that after the boot script/program on the BMC is
* updated to restore the bridge to a state compatible with the SBE
* expectations on boot.
- */
-
+ */
+
#include <skiboot.h>
#include <lpc.h>
#include <lock.h>
#include "ast.h"
+#define BMC_SIO_SCR28 0x28
+#define BOOT_FLAGS_VERSION 0x42
+
+#define BMC_SIO_SCR29 0x29
+#define BMC_SIO_SCR29_MEMBOOT 0x10
+
enum {
BMC_SIO_DEV_NONE = -1,
BMC_SIO_DEV_UART1 = 2,
@@ -197,7 +203,7 @@ static uint32_t bmc_sio_ahb_readl(uint32_t reg)
bmc_sio_ahb_prep(reg, 2);
- /* Trigger */
+ /* Trigger */
bmc_sio_inb(0xfe);
/* Read results */
@@ -241,7 +247,7 @@ int ast_copy_to_ahb(uint32_t reg, const void *src, uint32_t len)
if ((reg ^ (reg + len - 1)) >> 28)
return -EINVAL;
- /* SPI flash, use LPC->AHB bridge */
+ /* SPI flash, use LPC->AHB bridge */
if ((reg >> 28) == (PNOR_AHB_ADDR >> 28)) {
uint32_t chunk, off = reg - PNOR_AHB_ADDR + pnor_lpc_offset;
int64_t rc;
@@ -382,6 +388,19 @@ void ast_io_init(void)
ast_setup_sio_irq_polarity();
}
+bool ast_is_ahb_lpc_pnor(void)
+{
+ uint8_t boot_version;
+ uint8_t boot_flags;
+
+ boot_version = bmc_sio_inb(BMC_SIO_SCR28);
+ if (boot_version != BOOT_FLAGS_VERSION)
+ return true;
+
+ boot_flags = bmc_sio_inb(BMC_SIO_SCR29);
+ return !(boot_flags & BMC_SIO_SCR29_MEMBOOT);
+}
+
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);
}
-