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 | olio-uboot-2014.01-bb8215f437a7c948eec82a6abe754c226978bd6d.tar.xz olio-uboot-2014.01-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.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 b82011d0f..111185af1 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 5ca84a0c7..3b363be03 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 030d49cb7..3b6a44edc 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 cffba94bf..c95c2c28f 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) |