diff options
author | Simon Glass <sjg@chromium.org> | 2013-03-11 06:08:08 +0000 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2013-03-19 08:45:37 -0700 |
commit | bb8215f437a7c948eec82a6abe754c226978bd6d (patch) | |
tree | 8e03252d3317225986dee7d9e58ee4dd32123d9f | |
parent | 5e6fb69778fa41e685add00b73ed5f22c7a96166 (diff) | |
download | u-boot-imx-bb8215f437a7c948eec82a6abe754c226978bd6d.zip u-boot-imx-bb8215f437a7c948eec82a6abe754c226978bd6d.tar.gz u-boot-imx-bb8215f437a7c948eec82a6abe754c226978bd6d.tar.bz2 |
sf: Enable FDT-based configuration and memory mapping
Enable device tree control of SPI flash, and use this to implement
memory-mapped SPI flash, which is supported on Intel chips.
Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r-- | drivers/mtd/spi/spi_flash.c | 46 | ||||
-rw-r--r-- | include/fdtdec.h | 1 | ||||
-rw-r--r-- | include/spi_flash.h | 1 | ||||
-rw-r--r-- | lib/fdtdec.c | 1 |
4 files changed, 48 insertions, 1 deletions
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index b82011d..111185a 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -8,6 +8,7 @@ */ #include <common.h> +#include <fdtdec.h> #include <malloc.h> #include <spi.h> #include <spi_flash.h> @@ -15,6 +16,8 @@ #include "spi_flash_internal.h" +DECLARE_GLOBAL_DATA_PTR; + static void spi_flash_addr(u32 addr, u8 *cmd) { /* cmd[0] is actual command */ @@ -146,6 +149,10 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, { u8 cmd[5]; + /* Handle memory-mapped SPI */ + if (flash->memory_map) + memcpy(data, flash->memory_map + offset, len); + cmd[0] = CMD_READ_ARRAY_FAST; spi_flash_addr(offset, cmd); cmd[4] = 0x00; @@ -275,6 +282,34 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) return 0; } +#ifdef CONFIG_OF_CONTROL +int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) +{ + fdt_addr_t addr; + fdt_size_t size; + int node; + + /* If there is no node, do nothing */ + node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); + if (node < 0) + return 0; + + addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("%s: Cannot decode address\n", __func__); + return 0; + } + + if (flash->size != size) { + debug("%s: Memory map must cover entire device\n", __func__); + return -1; + } + flash->memory_map = (void *)addr; + + return 0; +} +#endif /* CONFIG_OF_CONTROL */ + /* * The following table holds all device probe functions * @@ -391,9 +426,18 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; } +#ifdef CONFIG_OF_CONTROL + if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { + debug("SF: FDT decode error\n"); + goto err_manufacturer_probe; + } +#endif printf("SF: Detected %s with page size ", flash->name); print_size(flash->sector_size, ", total "); - print_size(flash->size, "\n"); + print_size(flash->size, ""); + if (flash->memory_map) + printf(", mapped at %p", flash->memory_map); + puts("\n"); spi_release_bus(spi); diff --git a/include/fdtdec.h b/include/fdtdec.h index 5ca84a0..3b363be 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -86,6 +86,7 @@ enum fdt_compat_id { COMPAT_SAMSUNG_EXYNOS_EHCI, /* Exynos EHCI controller */ COMPAT_SAMSUNG_EXYNOS_USB_PHY, /* Exynos phy controller for usb2.0 */ COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ + COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ COMPAT_COUNT, }; diff --git a/include/spi_flash.h b/include/spi_flash.h index 030d49c..3b6a44e 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -39,6 +39,7 @@ struct spi_flash { /* Erase (sector) size */ u32 sector_size; + void *memory_map; /* Address of read-only SPI flash access */ int (*read)(struct spi_flash *flash, u32 offset, size_t len, void *buf); int (*write)(struct spi_flash *flash, u32 offset, diff --git a/lib/fdtdec.c b/lib/fdtdec.c index cffba94..c95c2c2 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -59,6 +59,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"), COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"), COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"), + COMPAT(GENERIC_SPI_FLASH, "spi-flash"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) |