aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/spi
diff options
context:
space:
mode:
authorFurquan Shaikh <furquan@chromium.org>2016-11-20 21:04:00 -0800
committerFurquan Shaikh <furquan@google.com>2016-11-22 17:32:09 +0100
commitc28984d9ea08e7d995ef9fc8064c10ec0c0d9d77 (patch)
treec113582c3d2d8fb8d54a4c9a53375340fcc302d5 /src/drivers/spi
parent282c8322791800ee0d732fdaa5eb2cd8f7effd58 (diff)
spi: Clean up SPI flash driver interface
RW flag was added to spi_slave structure to get around a requirement on some AMD flash controllers that need to group together all spi volatile operations (write/erase). This rw flag is not a property or attribute of the SPI slave or controller. Thus, instead of saving it in spi_slave structure, clean up the SPI flash driver interface. This allows chipsets/mainboards (that require volatile operations to be grouped) to indicate beginning and end of such grouped operations. New user APIs are added to allow users to perform probe, read, write, erase, volatile group begin and end operations. Callbacks defined in spi_flash structure are expected to be used only by the SPI flash driver. Any chipset that requires grouping of volatile operations can select the newly added Kconfig option SPI_FLASH_HAS_VOLATILE_GROUP and define callbacks for chipset_volatile_group_{begin,end}. spi_claim_bus/spi_release_bus calls have been removed from the SPI flash chip drivers which end up calling do_spi_flash_cmd since it already has required calls for claiming and releasing SPI bus before performing a read/write operation. BUG=None BRANCH=None TEST=Compiles successfully. Change-Id: Idfc052e82ec15b6c9fa874cee7a61bd06e923fbf Signed-off-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: https://review.coreboot.org/17462 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
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;