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 <s...@chromium.org>
---
 drivers/mtd/spi/spi_flash.c |   46 ++++++++++++++++++++++++++++++++++++++++++-
 include/fdtdec.h            |    1 +
 include/spi_flash.h         |    1 +
 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 570d3ac..bfd1dda 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -72,6 +72,7 @@ enum fdt_compat_id {
        COMPAT_NVIDIA_TEGRA20_NAND,     /* Tegra2 NAND controller */
        COMPAT_NVIDIA_TEGRA20_PWM,      /* Tegra 2 PWM controller */
        COMPAT_NVIDIA_TEGRA20_DC,       /* Tegra 2 Display controller */
+       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 d0bc848..55305b4 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -45,6 +45,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
        COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
        COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
+       COMPAT(GENERIC_SPI_FLASH, "spi-flash"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
-- 
1.7.7.3

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to