summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2013-03-11 06:08:08 +0000
committerSimon Glass <sjg@chromium.org>2013-03-19 08:45:37 -0700
commitbb8215f437a7c948eec82a6abe754c226978bd6d (patch)
tree8e03252d3317225986dee7d9e58ee4dd32123d9f
parent5e6fb69778fa41e685add00b73ed5f22c7a96166 (diff)
downloadtalos-obmc-uboot-bb8215f437a7c948eec82a6abe754c226978bd6d.tar.gz
talos-obmc-uboot-bb8215f437a7c948eec82a6abe754c226978bd6d.zip
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.c46
-rw-r--r--include/fdtdec.h1
-rw-r--r--include/spi_flash.h1
-rw-r--r--lib/fdtdec.c1
4 files changed, 48 insertions, 1 deletions
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index b82011d0fd..111185af17 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 5ca84a0c72..3b363be036 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 030d49cb71..3b6a44edce 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 cffba94bf6..c95c2c28fa 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)
OpenPOWER on IntegriCloud