diff options
author | Alistair Popple <alistair@popple.id.au> | 2015-03-20 14:59:15 +1100 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-03-26 11:12:18 +1100 |
commit | fc2906d321adf27db33918711b1055a8ea5b34f9 (patch) | |
tree | 609849d3bbc735d0643d9cb42fa5e2764ab8da88 /hw/ast-bmc | |
parent | 822403ea5dcc51a5c70c0ab061ef49adb17d82e4 (diff) | |
download | skiboot-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.c | 29 | ||||
-rw-r--r-- | hw/ast-bmc/ast-sf-ctrl.c | 90 |
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); } - |