aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/spi')
-rw-r--r--src/drivers/spi/Kconfig7
-rw-r--r--src/drivers/spi/adesto.c24
-rw-r--r--src/drivers/spi/amic.c24
-rw-r--r--src/drivers/spi/atmel.c24
-rw-r--r--src/drivers/spi/boot_device_rw_nommap.c7
-rw-r--r--src/drivers/spi/cbfs_spi.c7
-rw-r--r--src/drivers/spi/eon.c17
-rw-r--r--src/drivers/spi/gigadevice.c21
-rw-r--r--src/drivers/spi/macronix.c22
-rw-r--r--src/drivers/spi/spansion.c20
-rw-r--r--src/drivers/spi/spi_flash.c105
-rw-r--r--src/drivers/spi/spi_flash_internal.h12
-rw-r--r--src/drivers/spi/spiconsole.c2
-rw-r--r--src/drivers/spi/sst.c42
-rw-r--r--src/drivers/spi/stmicro.c17
-rw-r--r--src/drivers/spi/winbond.c20
16 files changed, 220 insertions, 151 deletions
diff --git a/src/drivers/spi/Kconfig b/src/drivers/spi/Kconfig
index 4c2fd1f060..b55de58962 100644
--- a/src/drivers/spi/Kconfig
+++ b/src/drivers/spi/Kconfig
@@ -164,6 +164,13 @@ config SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B
output command (opcode 0x3b) where the opcode and address are sent
to the chip on MOSI and data is received on both MOSI and MISO.
+config SPI_FLASH_HAS_VOLATILE_GROUP
+ bool
+ default n
+ help
+ Allows chipset to group write/erase operations under a single volatile
+ group.
+
endif # SPI_FLASH
config HAVE_SPI_CONSOLE_SUPPORT
diff --git a/src/drivers/spi/adesto.c b/src/drivers/spi/adesto.c
index fdde90f697..91bb774e36 100644
--- a/src/drivers/spi/adesto.c
+++ b/src/drivers/spi/adesto.c
@@ -10,8 +10,10 @@
* Licensed under the GPL-2 or later.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -46,7 +48,7 @@ struct adesto_spi_flash {
};
static inline struct adesto_spi_flash *
-to_adesto_spi_flash(struct spi_flash *flash)
+to_adesto_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct adesto_spi_flash, flash);
}
@@ -78,8 +80,8 @@ static const struct adesto_spi_flash_params adesto_spi_flash_table[] = {
},
};
-static int adesto_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
+static int adesto_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
struct adesto_spi_flash *stm = to_adesto_spi_flash(flash);
unsigned long byte_addr;
@@ -92,13 +94,6 @@ static int adesto_write(struct spi_flash *flash,
page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
- ret = spi_claim_bus(flash->spi);
- if (ret) {
- printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
- return ret;
- }
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -141,7 +136,6 @@ static int adesto_write(struct spi_flash *flash,
ret = 0;
out:
- spi_release_bus(flash->spi);
return ret;
}
@@ -177,12 +171,12 @@ struct spi_flash *spi_flash_probe_adesto(struct spi_slave *spi, u8 *idcode)
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
- stm->flash.write = adesto_write;
- stm->flash.erase = spi_flash_cmd_erase;
+ stm->flash.internal_write = adesto_write;
+ stm->flash.internal_erase = spi_flash_cmd_erase;
#if CONFIG_SPI_FLASH_NO_FAST_READ
- stm->flash.read = spi_flash_cmd_read_slow;
+ stm->flash.internal_read = spi_flash_cmd_read_slow;
#else
- stm->flash.read = spi_flash_cmd_read_fast;
+ stm->flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
diff --git a/src/drivers/spi/amic.c b/src/drivers/spi/amic.c
index e5f6672002..4f3002c73b 100644
--- a/src/drivers/spi/amic.c
+++ b/src/drivers/spi/amic.c
@@ -8,8 +8,10 @@
* Licensed under the GPL-2 or later.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -44,7 +46,7 @@ struct amic_spi_flash {
};
static inline struct amic_spi_flash *
-to_amic_spi_flash(struct spi_flash *flash)
+to_amic_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct amic_spi_flash, flash);
}
@@ -60,8 +62,8 @@ static const struct amic_spi_flash_params amic_spi_flash_table[] = {
},
};
-static int amic_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
+static int amic_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
struct amic_spi_flash *amic = to_amic_spi_flash(flash);
unsigned long byte_addr;
@@ -74,13 +76,6 @@ static int amic_write(struct spi_flash *flash,
page_size = 1 << amic->params->l2_page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
- ret = spi_claim_bus(flash->spi);
- if (ret) {
- printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
- return ret;
- }
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -123,7 +118,6 @@ static int amic_write(struct spi_flash *flash,
ret = 0;
out:
- spi_release_bus(flash->spi);
return ret;
}
@@ -159,12 +153,12 @@ struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode)
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
- amic->flash.write = amic_write;
- amic->flash.erase = spi_flash_cmd_erase;
+ amic->flash.internal_write = amic_write;
+ amic->flash.internal_erase = spi_flash_cmd_erase;
#if CONFIG_SPI_FLASH_NO_FAST_READ
- amic->flash.read = spi_flash_cmd_read_slow;
+ amic->flash.internal_read = spi_flash_cmd_read_slow;
#else
- amic->flash.read = spi_flash_cmd_read_fast;
+ amic->flash.internal_read = spi_flash_cmd_read_fast;
#endif
amic->flash.sector_size = (1 << amic->params->l2_page_size) *
amic->params->pages_per_sector;
diff --git a/src/drivers/spi/atmel.c b/src/drivers/spi/atmel.c
index 0286e09cdc..e53889205d 100644
--- a/src/drivers/spi/atmel.c
+++ b/src/drivers/spi/atmel.c
@@ -6,8 +6,10 @@
* Licensed under the GPL-2 or later.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
/* M25Pxx-specific commands */
@@ -41,7 +43,7 @@ struct atmel_spi_flash {
};
static inline struct atmel_spi_flash *
-to_atmel_spi_flash(struct spi_flash *flash)
+to_atmel_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct atmel_spi_flash, flash);
}
@@ -105,8 +107,8 @@ static const struct atmel_spi_flash_params atmel_spi_flash_table[] = {
},
};
-static int atmel_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
+static int atmel_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
struct atmel_spi_flash *stm = to_atmel_spi_flash(flash);
unsigned long byte_addr;
@@ -119,13 +121,6 @@ static int atmel_write(struct spi_flash *flash,
page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
- ret = spi_claim_bus(flash->spi);
- if (ret) {
- printk(BIOS_WARNING, "SF: Unable to claim SPI bus\n");
- return ret;
- }
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -168,7 +163,6 @@ static int atmel_write(struct spi_flash *flash,
ret = 0;
out:
- spi_release_bus(flash->spi);
return ret;
}
@@ -204,12 +198,12 @@ struct spi_flash *spi_flash_probe_atmel(struct spi_slave *spi, u8 *idcode)
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
- stm->flash.write = atmel_write;
- stm->flash.erase = spi_flash_cmd_erase;
+ stm->flash.internal_write = atmel_write;
+ stm->flash.internal_erase = spi_flash_cmd_erase;
#if CONFIG_SPI_FLASH_NO_FAST_READ
- stm->flash.read = spi_flash_cmd_read_slow;
+ stm->flash.internal_read = spi_flash_cmd_read_slow;
#else
- stm->flash.read = spi_flash_cmd_read_fast;
+ stm->flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm->flash.sector_size = (1 << stm->params->l2_page_size) *
stm->params->pages_per_sector;
diff --git a/src/drivers/spi/boot_device_rw_nommap.c b/src/drivers/spi/boot_device_rw_nommap.c
index 32ded9c393..a52a7befd2 100644
--- a/src/drivers/spi/boot_device_rw_nommap.c
+++ b/src/drivers/spi/boot_device_rw_nommap.c
@@ -16,6 +16,7 @@
#include <arch/early_variables.h>
#include <boot_device.h>
#include <spi_flash.h>
+#include <spi-generic.h>
static struct spi_flash *sfg CAR_GLOBAL;
@@ -27,7 +28,7 @@ static ssize_t spi_readat(const struct region_device *rd, void *b,
if (sf == NULL)
return -1;
- if (sf->read(sf, offset, size, b))
+ if (spi_flash_read(sf, offset, size, b))
return -1;
return size;
@@ -41,7 +42,7 @@ static ssize_t spi_writeat(const struct region_device *rd, const void *b,
if (sf == NULL)
return -1;
- if (sf->write(sf, offset, size, b))
+ if (spi_flash_write(sf, offset, size, b))
return -1;
return size;
@@ -55,7 +56,7 @@ static ssize_t spi_eraseat(const struct region_device *rd,
if (sf == NULL)
return -1;
- if (sf->erase(sf, offset, size))
+ if (spi_flash_erase(sf, offset, size))
return -1;
return size;
diff --git a/src/drivers/spi/cbfs_spi.c b/src/drivers/spi/cbfs_spi.c
index 46e7346379..7aeec57cf6 100644
--- a/src/drivers/spi/cbfs_spi.c
+++ b/src/drivers/spi/cbfs_spi.c
@@ -20,6 +20,7 @@
*/
#include <boot_device.h>
+#include <console/console.h>
#include <spi_flash.h>
#include <symbols.h>
#include <cbmem.h>
@@ -46,7 +47,7 @@ static ssize_t spi_readat(const struct region_device *rd, void *b,
if (show)
stopwatch_init(&sw);
- if (spi_flash_info->read(spi_flash_info, offset, size, b))
+ if (spi_flash_read(spi_flash_info, offset, size, b))
return -1;
if (show) {
long usecs;
@@ -67,7 +68,7 @@ static ssize_t spi_readat(const struct region_device *rd, void *b,
static ssize_t spi_writeat(const struct region_device *rd, const void *b,
size_t offset, size_t size)
{
- if (spi_flash_info->write(spi_flash_info, offset, size, b))
+ if (spi_flash_write(spi_flash_info, offset, size, b))
return -1;
return size;
}
@@ -75,7 +76,7 @@ static ssize_t spi_writeat(const struct region_device *rd, const void *b,
static ssize_t spi_eraseat(const struct region_device *rd,
size_t offset, size_t size)
{
- if (spi_flash_info->erase(spi_flash_info, offset, size))
+ if (spi_flash_erase(spi_flash_info, offset, size))
return -1;
return size;
}
diff --git a/src/drivers/spi/eon.c b/src/drivers/spi/eon.c
index 923b0a5601..64307664de 100644
--- a/src/drivers/spi/eon.c
+++ b/src/drivers/spi/eon.c
@@ -6,8 +6,10 @@
* Licensed under the GPL-2 or later.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -43,7 +45,8 @@ struct eon_spi_flash {
const struct eon_spi_flash_params *params;
};
-static inline struct eon_spi_flash *to_eon_spi_flash(struct spi_flash *flash)
+static inline
+struct eon_spi_flash *to_eon_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct eon_spi_flash, flash);
}
@@ -75,7 +78,7 @@ static const struct eon_spi_flash_params eon_spi_flash_table[] = {
},
};
-static int eon_write(struct spi_flash *flash,
+static int eon_write(const struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
struct eon_spi_flash *eon = to_eon_spi_flash(flash);
@@ -89,8 +92,6 @@ static int eon_write(struct spi_flash *flash,
page_size = 1 << eon->params->page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -166,10 +167,10 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
eon->flash.spi = spi;
eon->flash.name = params->name;
- eon->flash.write = eon_write;
- eon->flash.erase = spi_flash_cmd_erase;
- eon->flash.status = spi_flash_cmd_status;
- eon->flash.read = spi_flash_cmd_read_fast;
+ eon->flash.internal_write = eon_write;
+ eon->flash.internal_erase = spi_flash_cmd_erase;
+ eon->flash.internal_status = spi_flash_cmd_status;
+ eon->flash.internal_read = spi_flash_cmd_read_fast;
eon->flash.sector_size = params->page_size * params->pages_per_sector;
eon->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors;
diff --git a/src/drivers/spi/gigadevice.c b/src/drivers/spi/gigadevice.c
index 780cc82b23..3146a97167 100644
--- a/src/drivers/spi/gigadevice.c
+++ b/src/drivers/spi/gigadevice.c
@@ -17,9 +17,10 @@
* GNU General Public License for more details.
*/
-
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -54,7 +55,7 @@ struct gigadevice_spi_flash {
};
static inline struct gigadevice_spi_flash *
-to_gigadevice_spi_flash(struct spi_flash *flash)
+to_gigadevice_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct gigadevice_spi_flash, flash);
}
@@ -118,8 +119,8 @@ static const struct gigadevice_spi_flash_params gigadevice_spi_flash_table[] = {
},
};
-static int gigadevice_write(struct spi_flash *flash, u32 offset,
- size_t len, const void *buf)
+static int gigadevice_write(const struct spi_flash *flash, u32 offset,
+ size_t len, const void *buf)
{
struct gigadevice_spi_flash *stm = to_gigadevice_spi_flash(flash);
unsigned long byte_addr;
@@ -132,8 +133,6 @@ static int gigadevice_write(struct spi_flash *flash, u32 offset,
page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -212,13 +211,13 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
- stm.flash.write = gigadevice_write;
- stm.flash.erase = spi_flash_cmd_erase;
- stm.flash.status = spi_flash_cmd_status;
+ stm.flash.internal_write = gigadevice_write;
+ stm.flash.internal_erase = spi_flash_cmd_erase;
+ stm.flash.internal_status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ
- stm.flash.read = spi_flash_cmd_read_slow;
+ stm.flash.internal_read = spi_flash_cmd_read_slow;
#else
- stm.flash.read = spi_flash_cmd_read_fast;
+ stm.flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm.flash.sector_size = (1 << stm.params->l2_page_size) *
stm.params->pages_per_sector;
diff --git a/src/drivers/spi/macronix.c b/src/drivers/spi/macronix.c
index 09cb80cb0e..799cc97c8b 100644
--- a/src/drivers/spi/macronix.c
+++ b/src/drivers/spi/macronix.c
@@ -21,8 +21,10 @@
* GNU General Public License for more details.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -56,8 +58,8 @@ struct macronix_spi_flash {
const struct macronix_spi_flash_params *params;
};
-static inline struct macronix_spi_flash *to_macronix_spi_flash(struct spi_flash
- *flash)
+static inline
+struct macronix_spi_flash *to_macronix_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct macronix_spi_flash, flash);
}
@@ -145,8 +147,8 @@ static const struct macronix_spi_flash_params macronix_spi_flash_table[] = {
},
};
-static int macronix_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
+static int macronix_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
struct macronix_spi_flash *mcx = to_macronix_spi_flash(flash);
unsigned long byte_addr;
@@ -159,8 +161,6 @@ static int macronix_write(struct spi_flash *flash,
page_size = mcx->params->page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -227,13 +227,13 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
mcx.flash.spi = spi;
mcx.flash.name = params->name;
- mcx.flash.write = macronix_write;
- mcx.flash.erase = spi_flash_cmd_erase;
- mcx.flash.status = spi_flash_cmd_status;
+ mcx.flash.internal_write = macronix_write;
+ mcx.flash.internal_erase = spi_flash_cmd_erase;
+ mcx.flash.internal_status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ
- mcx.flash.read = spi_flash_cmd_read_slow;
+ mcx.flash.internal_read = spi_flash_cmd_read_slow;
#else
- mcx.flash.read = spi_flash_cmd_read_fast;
+ mcx.flash.internal_read = spi_flash_cmd_read_fast;
#endif
mcx.flash.sector_size = params->page_size * params->pages_per_sector;
mcx.flash.size = mcx.flash.sector_size * params->sectors_per_block *
diff --git a/src/drivers/spi/spansion.c b/src/drivers/spi/spansion.c
index fc6cef99af..95b1bafe05 100644
--- a/src/drivers/spi/spansion.c
+++ b/src/drivers/spi/spansion.c
@@ -17,8 +17,10 @@
* GNU General Public License for more details.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -66,8 +68,8 @@ struct spansion_spi_flash {
const struct spansion_spi_flash_params *params;
};
-static inline struct spansion_spi_flash *to_spansion_spi_flash(struct spi_flash
- *flash)
+static inline
+struct spansion_spi_flash *to_spansion_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct spansion_spi_flash, flash);
}
@@ -198,8 +200,8 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = {
},
};
-static int spansion_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
+static int spansion_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
struct spansion_spi_flash *spsn = to_spansion_spi_flash(flash);
unsigned long page_addr;
@@ -214,8 +216,6 @@ static int spansion_write(struct spi_flash *flash,
page_addr = offset / page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
@@ -286,10 +286,10 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
spsn->flash.spi = spi;
spsn->flash.name = params->name;
- spsn->flash.write = spansion_write;
- spsn->flash.erase = spi_flash_cmd_erase;
- spsn->flash.read = spi_flash_cmd_read_slow;
- spsn->flash.status = spi_flash_cmd_status;
+ spsn->flash.internal_write = spansion_write;
+ spsn->flash.internal_erase = spi_flash_cmd_erase;
+ spsn->flash.internal_read = spi_flash_cmd_read_slow;
+ spsn->flash.internal_status = spi_flash_cmd_status;
spsn->flash.sector_size = params->page_size * params->pages_per_sector;
spsn->flash.size = spsn->flash.sector_size * params->nr_sectors;
spsn->flash.erase_cmd = CMD_S25FLXX_SE;
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index 60064208d2..7ca6822ba1 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -7,6 +7,8 @@
* Licensed under the GPL-2 or later.
*/
+#include <arch/early_variables.h>
+#include <assert.h>
#include <boot_device.h>
#include <cbfs.h>
#include <cpu/x86/smm.h>
@@ -142,8 +144,8 @@ static int spi_flash_cmd_read_array(struct spi_slave *spi, u8 *cmd,
return len != 0;
}
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
- size_t len, void *data)
+int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset,
+ size_t len, void *data)
{
u8 cmd[5];
@@ -154,8 +156,8 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
offset, len, data);
}
-int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset,
- size_t len, void *data)
+int spi_flash_cmd_read_slow(const struct spi_flash *flash, u32 offset,
+ size_t len, void *data)
{
u8 cmd[4];
@@ -164,7 +166,7 @@ int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset,
offset, len, data);
}
-int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
+int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout,
u8 cmd, u8 poll_bit)
{
struct spi_slave *spi = flash->spi;
@@ -189,13 +191,14 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
return -1;
}
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
+int spi_flash_cmd_wait_ready(const struct spi_flash *flash,
+ unsigned long timeout)
{
return spi_flash_cmd_poll_bit(flash, timeout,
CMD_READ_STATUS, STATUS_WIP);
}
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
+int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len)
{
u32 start, end, erase_size;
int ret;
@@ -207,8 +210,6 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
return -1;
}
- flash->spi->rw = SPI_WRITE_FLAG;
-
cmd[0] = flash->erase_cmd;
start = offset;
end = start + len;
@@ -240,7 +241,7 @@ out:
return ret;
}
-int spi_flash_cmd_status(struct spi_flash *flash, u8 *reg)
+int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg)
{
return spi_flash_cmd(flash->spi, flash->status_cmd, reg, sizeof(*reg));
}
@@ -312,6 +313,8 @@ static struct {
};
#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
+
+/* Public API implementations. */
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs)
{
struct spi_slave *spi;
@@ -325,8 +328,6 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs)
return NULL;
}
- spi->rw = SPI_READ_FLAG;
-
if (spi->force_programmer_specific && spi->programmer_specific_probe) {
flash = spi->programmer_specific_probe (spi);
if (!flash)
@@ -388,6 +389,86 @@ err_read_id:
return NULL;
}
+int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len,
+ void *buf)
+{
+ return flash->internal_read(flash, offset, len, buf);
+}
+
+int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
+{
+ int ret;
+
+ if (spi_flash_volatile_group_begin(flash))
+ return -1;
+
+ ret = flash->internal_write(flash, offset, len, buf);
+
+ if (spi_flash_volatile_group_end(flash))
+ return -1;
+
+ return ret;
+}
+
+int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len)
+{
+ int ret;
+
+ if (spi_flash_volatile_group_begin(flash))
+ return -1;
+
+ ret = flash->internal_erase(flash, offset, len);
+
+ if (spi_flash_volatile_group_end(flash))
+ return -1;
+
+ return ret;
+}
+
+int spi_flash_status(const struct spi_flash *flash, u8 *reg)
+{
+ return flash->internal_status(flash, reg);
+}
+
+static uint32_t volatile_group_count CAR_GLOBAL;
+
+int spi_flash_volatile_group_begin(const struct spi_flash *flash)
+{
+ uint32_t count;
+ int ret = 0;
+
+ if (!IS_ENABLED(CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP))
+ return ret;
+
+ count = car_get_var(volatile_group_count);
+ if (count == 0)
+ ret = chipset_volatile_group_begin(flash);
+
+ count++;
+ car_set_var(volatile_group_count, count);
+ return ret;
+}
+
+int spi_flash_volatile_group_end(const struct spi_flash *flash)
+{
+ uint32_t count;
+ int ret = 0;
+
+ if (!IS_ENABLED(CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP))
+ return ret;
+
+ count = car_get_var(volatile_group_count);
+ assert(count == 0);
+ count--;
+ car_set_var(volatile_group_count, count);
+
+ if (count == 0)
+ ret = chipset_volatile_group_end(flash);
+
+ return ret;
+}
+
void lb_spi_flash(struct lb_header *header)
{
struct lb_spi_flash *flash;
diff --git a/src/drivers/spi/spi_flash_internal.h b/src/drivers/spi/spi_flash_internal.h
index fec3dcc9cf..c75839357e 100644
--- a/src/drivers/spi/spi_flash_internal.h
+++ b/src/drivers/spi/spi_flash_internal.h
@@ -34,10 +34,10 @@
/* Send a single-byte command to the device and read the response */
int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len);
-int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
+int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset,
size_t len, void *data);
-int spi_flash_cmd_read_slow(struct spi_flash *flash, u32 offset,
+int spi_flash_cmd_read_slow(const struct spi_flash *flash, u32 offset,
size_t len, void *data);
/*
@@ -48,20 +48,20 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
const void *data, size_t data_len);
/* Send a command to the device and wait for some bit to clear itself. */
-int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
+int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout,
u8 cmd, u8 poll_bit);
/*
* Send the read status command to the device and wait for the wip
* (write-in-progress) bit to clear itself.
*/
-int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
+int spi_flash_cmd_wait_ready(const struct spi_flash *flash, unsigned long timeout);
/* Erase sectors. */
-int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
+int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len);
/* Read status register. */
-int spi_flash_cmd_status(struct spi_flash *flash, u8 *reg);
+int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg);
/* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
diff --git a/src/drivers/spi/spiconsole.c b/src/drivers/spi/spiconsole.c
index a2a1effc74..0831f2c896 100644
--- a/src/drivers/spi/spiconsole.c
+++ b/src/drivers/spi/spiconsole.c
@@ -54,7 +54,7 @@ void spiconsole_tx_byte(unsigned char c) {
if (c == '\n' || (sizeof(struct em100_msg_header) +
msg.header.msg_length == spi_crop_chunk(0,
MAX_MSG_LENGTH))) {
- struct spi_slave spi = {.rw = SPI_READ_FLAG};
+ struct spi_slave spi = { };
spi_xfer(&spi, &msg, sizeof(struct em100_msg_header) +
msg.header.msg_length, NULL, 0);
diff --git a/src/drivers/spi/sst.c b/src/drivers/spi/sst.c
index 87c1c5b38a..940d894396 100644
--- a/src/drivers/spi/sst.c
+++ b/src/drivers/spi/sst.c
@@ -12,8 +12,10 @@
* Licensed under the GPL-2 or later.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -40,7 +42,7 @@ struct sst_spi_flash_params {
u8 idcode1;
u16 nr_sectors;
const char *name;
- int (*write)(struct spi_flash *flash, u32 offset,
+ int (*write)(const struct spi_flash *flash, u32 offset,
size_t len, const void *buf);
};
@@ -49,10 +51,10 @@ struct sst_spi_flash {
const struct sst_spi_flash_params *params;
};
-static int
-sst_write_ai(struct spi_flash *flash, u32 offset, size_t len, const void *buf);
-static int
-sst_write_256(struct spi_flash *flash, u32 offset, size_t len, const void *buf);
+static int sst_write_ai(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf);
+static int sst_write_256(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf);
#define SST_SECTOR_SIZE (4 * 1024)
static const struct sst_spi_flash_params sst_spi_flash_table[] = {
@@ -105,7 +107,7 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = {
};
static int
-sst_enable_writing(struct spi_flash *flash)
+sst_enable_writing(const struct spi_flash *flash)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0);
if (ret)
@@ -114,7 +116,7 @@ sst_enable_writing(struct spi_flash *flash)
}
static int
-sst_enable_writing_status(struct spi_flash *flash)
+sst_enable_writing_status(const struct spi_flash *flash)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_EWSR, NULL, 0);
if (ret)
@@ -123,7 +125,7 @@ sst_enable_writing_status(struct spi_flash *flash)
}
static int
-sst_disable_writing(struct spi_flash *flash)
+sst_disable_writing(const struct spi_flash *flash)
{
int ret = spi_flash_cmd(flash->spi, CMD_SST_WRDI, NULL, 0);
if (ret)
@@ -132,7 +134,7 @@ sst_disable_writing(struct spi_flash *flash)
}
static int
-sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
+sst_byte_write(const struct spi_flash *flash, u32 offset, const void *buf)
{
int ret;
u8 cmd[4] = {
@@ -158,8 +160,8 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
}
-static int
-sst_write_256(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
+static int sst_write_256(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
size_t actual, chunk_len, cmd_len;
unsigned long byte_addr;
@@ -170,8 +172,6 @@ sst_write_256(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
page_size = 256;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
/* If the data is not word aligned, write out leading single byte */
actual = offset % 2;
if (actual) {
@@ -234,15 +234,13 @@ done:
return ret;
}
-static int
-sst_write_ai(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
+static int sst_write_ai(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
size_t actual, cmd_len;
int ret = 0;
u8 cmd[4];
- flash->spi->rw = SPI_WRITE_FLAG;
-
/* If the data is not word aligned, write out leading single byte */
actual = offset % 2;
if (actual) {
@@ -301,7 +299,7 @@ done:
static int
-sst_unlock(struct spi_flash *flash)
+sst_unlock(const struct spi_flash *flash)
{
int ret;
u8 cmd, status;
@@ -349,10 +347,10 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
stm->flash.spi = spi;
stm->flash.name = params->name;
- stm->flash.write = params->write;
- stm->flash.erase = spi_flash_cmd_erase;
- stm->flash.status = spi_flash_cmd_status;
- stm->flash.read = spi_flash_cmd_read_fast;
+ stm->flash.internal_write = params->write;
+ stm->flash.internal_erase = spi_flash_cmd_erase;
+ stm->flash.internal_status = spi_flash_cmd_status;
+ stm->flash.internal_read = spi_flash_cmd_read_fast;
stm->flash.sector_size = SST_SECTOR_SIZE;
stm->flash.size = stm->flash.sector_size * params->nr_sectors;
stm->flash.erase_cmd = CMD_SST_SE;
diff --git a/src/drivers/spi/stmicro.c b/src/drivers/spi/stmicro.c
index 6ab601c73f..56181628c6 100644
--- a/src/drivers/spi/stmicro.c
+++ b/src/drivers/spi/stmicro.c
@@ -19,8 +19,10 @@
* GNU General Public License for more details.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -69,8 +71,8 @@ struct stmicro_spi_flash {
const struct stmicro_spi_flash_params *params;
};
-static inline struct stmicro_spi_flash *to_stmicro_spi_flash(struct spi_flash
- *flash)
+static inline
+struct stmicro_spi_flash *to_stmicro_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct stmicro_spi_flash, flash);
}
@@ -174,7 +176,7 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = {
},
};
-static int stmicro_write(struct spi_flash *flash,
+static int stmicro_write(const struct spi_flash *flash,
u32 offset, size_t len, const void *buf)
{
struct stmicro_spi_flash *stm = to_stmicro_spi_flash(flash);
@@ -188,8 +190,6 @@ static int stmicro_write(struct spi_flash *flash,
page_size = stm->params->page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -232,7 +232,6 @@ static int stmicro_write(struct spi_flash *flash,
ret = 0;
out:
- spi_release_bus(flash->spi);
return ret;
}
@@ -272,9 +271,9 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode)
stm.flash.spi = spi;
stm.flash.name = params->name;
- stm.flash.write = stmicro_write;
- stm.flash.erase = spi_flash_cmd_erase;
- stm.flash.read = spi_flash_cmd_read_fast;
+ stm.flash.internal_write = stmicro_write;
+ stm.flash.internal_erase = spi_flash_cmd_erase;
+ stm.flash.internal_read = spi_flash_cmd_read_fast;
stm.flash.sector_size = params->page_size * params->pages_per_sector;
stm.flash.size = stm.flash.sector_size * params->nr_sectors;
stm.flash.erase_cmd = params->op_erase;
diff --git a/src/drivers/spi/winbond.c b/src/drivers/spi/winbond.c
index defb8a5786..c6af2acc64 100644
--- a/src/drivers/spi/winbond.c
+++ b/src/drivers/spi/winbond.c
@@ -4,8 +4,10 @@
* Licensed under the GPL-2 or later.
*/
+#include <console/console.h>
#include <stdlib.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include "spi_flash_internal.h"
@@ -40,7 +42,7 @@ struct winbond_spi_flash {
};
static inline struct winbond_spi_flash *
-to_winbond_spi_flash(struct spi_flash *flash)
+to_winbond_spi_flash(const struct spi_flash *flash)
{
return container_of(flash, struct winbond_spi_flash, flash);
}
@@ -136,8 +138,8 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = {
},
};
-static int winbond_write(struct spi_flash *flash,
- u32 offset, size_t len, const void *buf)
+static int winbond_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf)
{
struct winbond_spi_flash *stm = to_winbond_spi_flash(flash);
unsigned long byte_addr;
@@ -150,8 +152,6 @@ static int winbond_write(struct spi_flash *flash,
page_size = 1 << stm->params->l2_page_size;
byte_addr = offset % page_size;
- flash->spi->rw = SPI_WRITE_FLAG;
-
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
chunk_len = spi_crop_chunk(sizeof(cmd), chunk_len);
@@ -224,13 +224,13 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
/* Assuming power-of-two page size initially. */
page_size = 1 << params->l2_page_size;
- stm.flash.write = winbond_write;
- stm.flash.erase = spi_flash_cmd_erase;
- stm.flash.status = spi_flash_cmd_status;
+ stm.flash.internal_write = winbond_write;
+ stm.flash.internal_erase = spi_flash_cmd_erase;
+ stm.flash.internal_status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ
- stm.flash.read = spi_flash_cmd_read_slow;
+ stm.flash.internal_read = spi_flash_cmd_read_slow;
#else
- stm.flash.read = spi_flash_cmd_read_fast;
+ stm.flash.internal_read = spi_flash_cmd_read_fast;
#endif
stm.flash.sector_size = (1 << stm.params->l2_page_size) *
stm.params->pages_per_sector;