summaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/spi/atmel.c8
-rw-r--r--drivers/mtd/spi/eon.c8
-rw-r--r--drivers/mtd/spi/macronix.c8
-rw-r--r--drivers/mtd/spi/ramtron.c4
-rw-r--r--drivers/mtd/spi/spansion.c8
-rw-r--r--drivers/mtd/spi/spi_flash.c81
-rw-r--r--drivers/mtd/spi/sst.c8
-rw-r--r--drivers/mtd/spi/stmicro.c8
-rw-r--r--drivers/mtd/spi/winbond.c8
9 files changed, 86 insertions, 55 deletions
diff --git a/drivers/mtd/spi/atmel.c b/drivers/mtd/spi/atmel.c
index 006f6d5d04..6a92c4b774 100644
--- a/drivers/mtd/spi/atmel.c
+++ b/drivers/mtd/spi/atmel.c
@@ -480,15 +480,13 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- asf = malloc(sizeof(struct atmel_spi_flash));
+ asf = spi_flash_alloc(struct atmel_spi_flash, spi, params->name);
if (!asf) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
asf->params = params;
- asf->flash.spi = spi;
- asf->flash.name = params->name;
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
@@ -513,7 +511,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
asf->flash.erase = dataflash_erase_at45;
page_size += 1 << (params->l2_page_size - 5);
} else {
- asf->flash.read = spi_flash_cmd_read_fast;
asf->flash.write = dataflash_write_p2;
asf->flash.erase = dataflash_erase_p2;
}
@@ -524,9 +521,6 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
case DF_FAMILY_AT26F:
case DF_FAMILY_AT26DF:
- asf->flash.read = spi_flash_cmd_read_fast;
- asf->flash.write = spi_flash_cmd_write_multi;
- asf->flash.erase = spi_flash_cmd_erase;
asf->flash.page_size = page_size;
asf->flash.sector_size = 4096;
/* clear SPRL# bit for locked flash */
diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c
index 691ed4efc4..b16e7ab098 100644
--- a/drivers/mtd/spi/eon.c
+++ b/drivers/mtd/spi/eon.c
@@ -46,18 +46,12 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- flash = malloc(sizeof(*flash));
+ flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- flash->spi = spi;
- flash->name = params->name;
-
- flash->write = spi_flash_cmd_write_multi;
- flash->erase = spi_flash_cmd_erase;
- flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * 16 * 16;
flash->size = 256 * 16
diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c
index c97a39d499..036c30d3be 100644
--- a/drivers/mtd/spi/macronix.c
+++ b/drivers/mtd/spi/macronix.c
@@ -97,18 +97,12 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- flash = malloc(sizeof(*flash));
+ flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- flash->spi = spi;
- flash->name = params->name;
-
- flash->write = spi_flash_cmd_write_multi;
- flash->erase = spi_flash_cmd_erase;
- flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * 16 * 16;
flash->size = flash->sector_size * params->nr_blocks;
diff --git a/drivers/mtd/spi/ramtron.c b/drivers/mtd/spi/ramtron.c
index 0999781496..5299a6dbde 100644
--- a/drivers/mtd/spi/ramtron.c
+++ b/drivers/mtd/spi/ramtron.c
@@ -284,15 +284,13 @@ struct spi_flash *spi_fram_probe_ramtron(struct spi_slave *spi, u8 *idcode)
return NULL;
found:
- sn = malloc(sizeof(*sn));
+ sn = spi_flash_alloc(struct ramtron_spi_fram, spi, params->name);
if (!sn) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
sn->params = params;
- sn->flash.spi = spi;
- sn->flash.name = params->name;
sn->flash.write = ramtron_write;
sn->flash.read = ramtron_read;
diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index 9288672c84..bc558c4c96 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -128,18 +128,12 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- flash = malloc(sizeof(*flash));
+ flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- flash->spi = spi;
- flash->name = params->name;
-
- flash->write = spi_flash_cmd_write_multi;
- flash->erase = spi_flash_cmd_erase;
- flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * params->pages_per_sector;
flash->size = flash->sector_size * params->nr_sectors;
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 00aece9291..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 */
@@ -87,6 +90,9 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
+ if (flash->spi->max_write_size)
+ chunk_len = min(chunk_len, flash->spi->max_write_size);
+
cmd[1] = page_addr >> 8;
cmd[2] = page_addr;
cmd[3] = byte_addr;
@@ -111,8 +117,11 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
if (ret)
break;
- page_addr++;
- byte_addr = 0;
+ byte_addr += chunk_len;
+ if (byte_addr == page_size) {
+ page_addr++;
+ byte_addr = 0;
+ }
}
debug("SF: program %s %zu bytes @ %#x\n",
@@ -140,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;
@@ -269,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
*
@@ -385,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);
@@ -401,6 +451,31 @@ err_claim_bus:
return NULL;
}
+void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi,
+ const char *name)
+{
+ struct spi_flash *flash;
+ void *ptr;
+
+ ptr = malloc(size);
+ if (!ptr) {
+ debug("SF: Failed to allocate memory\n");
+ return NULL;
+ }
+ memset(ptr, '\0', size);
+ flash = (struct spi_flash *)(ptr + offset);
+
+ /* Set up some basic fields - caller will sort out sizes */
+ flash->spi = spi;
+ flash->name = name;
+
+ flash->read = spi_flash_cmd_read_fast;
+ flash->write = spi_flash_cmd_write_multi;
+ flash->erase = spi_flash_cmd_erase;
+
+ return flash;
+}
+
void spi_flash_free(struct spi_flash *flash)
{
spi_free_slave(flash->spi);
diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c
index ced4f2473f..95f5490c35 100644
--- a/drivers/mtd/spi/sst.c
+++ b/drivers/mtd/spi/sst.c
@@ -203,22 +203,16 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- stm = malloc(sizeof(*stm));
+ stm = spi_flash_alloc(struct sst_spi_flash, spi, params->name);
if (!stm) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
stm->params = params;
- stm->flash.spi = spi;
- stm->flash.name = params->name;
if (stm->params->flags & SST_FEAT_WP)
stm->flash.write = sst_write_wp;
- else
- stm->flash.write = spi_flash_cmd_write_multi;
- stm->flash.erase = spi_flash_cmd_erase;
- stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.page_size = 256;
stm->flash.sector_size = 4096;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c
index 8a193449d0..2a9972bd4e 100644
--- a/drivers/mtd/spi/stmicro.c
+++ b/drivers/mtd/spi/stmicro.c
@@ -176,18 +176,12 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
return NULL;
}
- flash = malloc(sizeof(*flash));
+ flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- flash->spi = spi;
- flash->name = params->name;
-
- flash->write = spi_flash_cmd_write_multi;
- flash->erase = spi_flash_cmd_erase;
- flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 256 * params->pages_per_sector;
flash->size = flash->sector_size * params->nr_sectors;
diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c
index 4418302169..05dc644926 100644
--- a/drivers/mtd/spi/winbond.c
+++ b/drivers/mtd/spi/winbond.c
@@ -92,18 +92,12 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
return NULL;
}
- flash = malloc(sizeof(*flash));
+ flash = spi_flash_alloc_base(spi, params->name);
if (!flash) {
debug("SF: Failed to allocate memory\n");
return NULL;
}
- flash->spi = spi;
- flash->name = params->name;
-
- flash->write = spi_flash_cmd_write_multi;
- flash->erase = spi_flash_cmd_erase;
- flash->read = spi_flash_cmd_read_fast;
flash->page_size = 256;
flash->sector_size = 4096;
flash->size = 4096 * 16 * params->nr_blocks;
OpenPOWER on IntegriCloud