summaryrefslogtreecommitdiff
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
parent282c8322791800ee0d732fdaa5eb2cd8f7effd58 (diff)
downloadcoreboot-c28984d9ea08e7d995ef9fc8064c10ec0c0d9d77.tar.xz
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>
-rw-r--r--src/cpu/amd/pi/spi.c12
-rw-r--r--src/drivers/intel/fsp1_0/fastboot_cache.c8
-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
-rw-r--r--src/include/spi-generic.h5
-rw-r--r--src/include/spi_flash.h66
-rw-r--r--src/northbridge/amd/agesa/oem_s3.c12
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/s3utils.c13
-rw-r--r--src/northbridge/intel/common/mrc_cache.c7
-rw-r--r--src/soc/imgtec/pistachio/spi.c2
-rw-r--r--src/soc/intel/apollolake/spi.c22
-rw-r--r--src/soc/intel/baytrail/spi.c2
-rw-r--r--src/soc/intel/braswell/spi.c2
-rw-r--r--src/soc/intel/common/nvm.c7
-rw-r--r--src/soc/intel/fsp_baytrail/nvm.c4
-rw-r--r--src/soc/intel/fsp_baytrail/spi.c2
-rw-r--r--src/soc/intel/skylake/flash_controller.c23
-rw-r--r--src/soc/intel/skylake/include/soc/flash_controller.h13
-rw-r--r--src/soc/intel/skylake/romstage/spi.c1
-rw-r--r--src/soc/mediatek/mt8173/flash_controller.c17
-rw-r--r--src/soc/qualcomm/ipq40xx/include/soc/spi.h2
-rw-r--r--src/soc/qualcomm/ipq40xx/spi.c1
-rw-r--r--src/soc/qualcomm/ipq806x/include/soc/spi.h2
-rw-r--r--src/soc/qualcomm/ipq806x/spi.c1
-rw-r--r--src/soc/rockchip/common/spi.c27
-rw-r--r--src/soc/samsung/exynos5420/spi.c7
-rw-r--r--src/southbridge/amd/agesa/hudson/Kconfig1
-rw-r--r--src/southbridge/amd/agesa/hudson/spi.c43
-rw-r--r--src/southbridge/amd/cimx/sb800/Kconfig1
-rw-r--r--src/southbridge/amd/cimx/sb800/spi.c46
-rw-r--r--src/southbridge/intel/common/spi.c18
45 files changed, 406 insertions, 332 deletions
diff --git a/src/cpu/amd/pi/spi.c b/src/cpu/amd/pi/spi.c
index f5718057d1..71b5d95444 100644
--- a/src/cpu/amd/pi/spi.c
+++ b/src/cpu/amd/pi/spi.c
@@ -31,15 +31,13 @@ void spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
return;
}
- flash->spi->rw = SPI_WRITE_FLAG;
- spi_claim_bus(flash->spi);
+ spi_flash_volatile_group_begin(flash);
- flash->erase(flash, pos, size);
- flash->write(flash, pos, sizeof(len), &len);
- flash->write(flash, pos + sizeof(len), len, buf);
+ spi_flash_erase(flash, pos, size);
+ spi_flash_write(flash, pos, sizeof(len), &len);
+ spi_flash_write(flash, pos + sizeof(len), len, buf);
- flash->spi->rw = SPI_WRITE_FLAG;
- spi_release_bus(flash->spi);
+ spi_flash_volatile_group_end(flash);
return;
}
diff --git a/src/drivers/intel/fsp1_0/fastboot_cache.c b/src/drivers/intel/fsp1_0/fastboot_cache.c
index 68150f9379..b57f382b27 100644
--- a/src/drivers/intel/fsp1_0/fastboot_cache.c
+++ b/src/drivers/intel/fsp1_0/fastboot_cache.c
@@ -209,16 +209,16 @@ void update_mrc_cache(void *unused)
"Need to erase the MRC cache region of %d bytes at %p\n",
cache_size, cache_base);
- flash->erase(flash, to_flash_offset(cache_base), cache_size);
+ spi_flash_erase(flash, to_flash_offset(cache_base), cache_size);
/* we will start at the beginning again */
cache = cache_base;
}
- /* 4. write mrc data with flash->write() */
+ /* 4. write mrc data with spi_flash_write() */
printk(BIOS_DEBUG, "Write MRC cache update to flash at %p\n",
cache);
- flash->write(flash, to_flash_offset(cache),
- current->mrc_data_size + sizeof(*current), current);
+ spi_flash_write(flash, to_flash_offset(cache),
+ current->mrc_data_size + sizeof(*current), current);
}
#endif /* !defined(__PRE_RAM__) */
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;
diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h
index 9097f48c13..ee02394096 100644
--- a/src/include/spi-generic.h
+++ b/src/include/spi-generic.h
@@ -24,9 +24,6 @@
#define SPI_OPCODE_WREN 0x06
#define SPI_OPCODE_FAST_READ 0x0b
-#define SPI_READ_FLAG 0x01
-#define SPI_WRITE_FLAG 0x02
-
/*-----------------------------------------------------------------------
* Representation of a SPI slave, i.e. what we're communicating with.
*
@@ -34,7 +31,6 @@
*
* bus: ID of the bus that the slave is attached to.
* cs: ID of the chip select connected to the slave.
- * rw: Read or Write flag
* max_transfer_size: maximum amount of bytes which can be sent in a single
* read or write transaction, usually this is a controller
* property, kept in the slave structure for convenience. Zero in
@@ -43,7 +39,6 @@
struct spi_slave {
unsigned int bus;
unsigned int cs;
- unsigned int rw;
unsigned int max_transfer_size;
int force_programmer_specific;
struct spi_flash * (*programmer_specific_probe) (struct spi_slave *spi);
diff --git a/src/include/spi_flash.h b/src/include/spi_flash.h
index 52de184302..5cb68299e9 100644
--- a/src/include/spi_flash.h
+++ b/src/include/spi_flash.h
@@ -17,35 +17,63 @@
#include <stdint.h>
#include <stddef.h>
-#include <console/console.h>
-#include <spi-generic.h>
#include <boot/coreboot_tables.h>
struct spi_flash {
struct spi_slave *spi;
-
- const char *name;
-
- u32 size;
-
- u32 sector_size;
-
- u8 erase_cmd;
-
- u8 status_cmd;
-
- /* All callbacks return 0 on success and != 0 on error. */
- int (*read)(struct spi_flash *flash, u32 offset,
+ const char *name;
+ u32 size;
+ u32 sector_size;
+ u8 erase_cmd;
+ u8 status_cmd;
+ /*
+ * Internal functions are expected to be called ONLY by spi flash
+ * driver. External components should only use the public API calls
+ * spi_flash_{read,write,erase,status,volatile_group_begin,
+ * volatile_group_end}.
+ */
+ int (*internal_read)(const struct spi_flash *flash, u32 offset,
size_t len, void *buf);
- int (*write)(struct spi_flash *flash, u32 offset,
+ int (*internal_write)(const struct spi_flash *flash, u32 offset,
size_t len, const void *buf);
- int (*erase)(struct spi_flash *flash, u32 offset,
+ int (*internal_erase)(const struct spi_flash *flash, u32 offset,
size_t len);
- int (*status)(struct spi_flash *flash, u8 *reg);
+ int (*internal_status)(const struct spi_flash *flash, u8 *reg);
};
+void lb_spi_flash(struct lb_header *header);
+
+/* SPI Flash Driver Public API */
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs);
-void lb_spi_flash(struct lb_header *header);
+/* All the following functions return 0 on success and non-zero on error. */
+int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len,
+ void *buf);
+int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len,
+ const void *buf);
+int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len);
+int spi_flash_status(const struct spi_flash *flash, u8 *reg);
+/*
+ * Some SPI controllers require exclusive access to SPI flash when volatile
+ * operations like erase or write are being performed. In such cases,
+ * volatile_group_begin will gain exclusive access to SPI flash if not already
+ * acquired and volatile_group_end will end exclusive access if this was the
+ * last request in the group. spi_flash_{write,erase} operations call
+ * volatile_group_begin at the start of function and volatile_group_end after
+ * erase/write operation is performed. These functions can also be used by any
+ * components that wish to club multiple volatile operations into a single
+ * group.
+ */
+int spi_flash_volatile_group_begin(const struct spi_flash *flash);
+int spi_flash_volatile_group_end(const struct spi_flash *flash);
+
+/*
+ * These are callbacks for marking the start and end of volatile group as
+ * handled by the chipset. Not every chipset requires this special handling. So,
+ * these functions are expected to be implemented in Kconfig option for volatile
+ * group is enabled (SPI_FLASH_HAS_VOLATILE_GROUP).
+ */
+int chipset_volatile_group_begin(const struct spi_flash *flash);
+int chipset_volatile_group_end(const struct spi_flash *flash);
#endif /* _SPI_FLASH_H_ */
diff --git a/src/northbridge/amd/agesa/oem_s3.c b/src/northbridge/amd/agesa/oem_s3.c
index fcf8ada4c5..c7d23ff346 100644
--- a/src/northbridge/amd/agesa/oem_s3.c
+++ b/src/northbridge/amd/agesa/oem_s3.c
@@ -97,15 +97,13 @@ static int spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
if (!flash)
return -1;
- flash->spi->rw = SPI_WRITE_FLAG;
- spi_claim_bus(flash->spi);
+ spi_flash_volatile_group_begin(flash);
- flash->erase(flash, pos, size);
- flash->write(flash, pos, sizeof(len), &len);
- flash->write(flash, pos + sizeof(len), len, buf);
+ spi_flash_erase(flash, pos, size);
+ spi_flash_write(flash, pos, sizeof(len), &len);
+ spi_flash_write(flash, pos + sizeof(len), len, buf);
- flash->spi->rw = SPI_WRITE_FLAG;
- spi_release_bus(flash->spi);
+ spi_flash_volatile_group_end(flash);
return 0;
#else
return -1;
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
index 97cadcb828..d3fc53b12f 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/s3utils.c
@@ -1140,20 +1140,17 @@ int8_t save_mct_information_to_nvram(void)
return -1;
}
- /* Set up SPI flash access */
- flash->spi->rw = SPI_WRITE_FLAG;
- spi_claim_bus(flash->spi);
+ spi_flash_volatile_group_begin(flash);
/* Erase and write data structure */
- flash->erase(flash, s3nv_offset, CONFIG_S3_DATA_SIZE);
- flash->write(flash, s3nv_offset, sizeof(struct amd_s3_persistent_data), persistent_data);
+ spi_flash_erase(flash, s3nv_offset, CONFIG_S3_DATA_SIZE);
+ spi_flash_write(flash, s3nv_offset,
+ sizeof(struct amd_s3_persistent_data), persistent_data);
/* Deallocate temporary data structures */
free(persistent_data);
- /* Tear down SPI flash access */
- flash->spi->rw = SPI_WRITE_FLAG;
- spi_release_bus(flash->spi);
+ spi_flash_volatile_group_end(flash);
/* Allow training bypass if DIMM configuration is unchanged on next boot */
nvram = 1;
diff --git a/src/northbridge/intel/common/mrc_cache.c b/src/northbridge/intel/common/mrc_cache.c
index 4c3ee5d43c..a15812311b 100644
--- a/src/northbridge/intel/common/mrc_cache.c
+++ b/src/northbridge/intel/common/mrc_cache.c
@@ -212,7 +212,8 @@ static void update_mrc_cache(void *unused)
"Need to erase the MRC cache region of %d bytes at %p\n",
cache_size, cache_base);
- flash->erase(flash, to_flash_offset(flash, cache_base), cache_size);
+ spi_flash_erase(flash, to_flash_offset(flash, cache_base),
+ cache_size);
/* we will start at the beginning again */
cache = cache_base;
@@ -220,8 +221,8 @@ static void update_mrc_cache(void *unused)
// 4. write mrc data with flash->write()
printk(BIOS_DEBUG, "Finally: write MRC cache update to flash at %p\n",
cache);
- ret = flash->write(flash, to_flash_offset(flash, cache),
- current->mrc_data_size + sizeof(*current), current);
+ ret = spi_flash_write(flash, to_flash_offset(flash, cache),
+ current->mrc_data_size + sizeof(*current), current);
if (ret)
printk(BIOS_WARNING, "Writing the MRC cache failed with ret %d\n",
diff --git a/src/soc/imgtec/pistachio/spi.c b/src/soc/imgtec/pistachio/spi.c
index f38607cf5b..87dd66fd59 100644
--- a/src/soc/imgtec/pistachio/spi.c
+++ b/src/soc/imgtec/pistachio/spi.c
@@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/
+#include <console/console.h>
#include <soc/cpu.h>
#include <soc/spi.h>
#include <spi_flash.h>
@@ -444,7 +445,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
img_slave->base = base;
slave->bus = bus;
slave->cs = cs;
- slave->rw = SPI_READ_FLAG | SPI_WRITE_FLAG;
slave->max_transfer_size = IMGTEC_SPI_MAX_TRANSFER_SIZE;
device_parameters->bitrate = 64;
diff --git a/src/soc/intel/apollolake/spi.c b/src/soc/intel/apollolake/spi.c
index d60176a9aa..018572cfab 100644
--- a/src/soc/intel/apollolake/spi.c
+++ b/src/soc/intel/apollolake/spi.c
@@ -19,12 +19,14 @@
#include <arch/early_variables.h>
#include <arch/io.h>
+#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <soc/intel/common/spi.h>
#include <soc/pci_devs.h>
#include <soc/spi.h>
#include <spi_flash.h>
+#include <spi-generic.h>
#include <stdlib.h>
#include <string.h>
@@ -224,7 +226,8 @@ void spi_release_bus(struct spi_slave *slave)
/* No magic needed here. */
}
-static int nuclear_spi_erase(struct spi_flash *flash, uint32_t offset, size_t len)
+static int nuclear_spi_erase(const struct spi_flash *flash, uint32_t offset,
+ size_t len)
{
int ret;
size_t erase_size;
@@ -274,7 +277,8 @@ static size_t get_xfer_len(uint32_t addr, size_t len)
return xfer_len;
}
-static int nuclear_spi_read(struct spi_flash *flash, uint32_t addr, size_t len, void *buf)
+static int nuclear_spi_read(const struct spi_flash *flash, uint32_t addr,
+ size_t len, void *buf)
{
int ret;
size_t xfer_len;
@@ -300,8 +304,8 @@ static int nuclear_spi_read(struct spi_flash *flash, uint32_t addr, size_t len,
return SUCCESS;
}
-static int nuclear_spi_write(struct spi_flash *flash,
- uint32_t addr, size_t len, const void *buf)
+static int nuclear_spi_write(const struct spi_flash *flash, uint32_t addr,
+ size_t len, const void *buf)
{
int ret;
size_t xfer_len;
@@ -326,7 +330,7 @@ static int nuclear_spi_write(struct spi_flash *flash,
return SUCCESS;
}
-static int nuclear_spi_status(struct spi_flash *flash, uint8_t *reg)
+static int nuclear_spi_status(const struct spi_flash *flash, uint8_t *reg)
{
int ret;
BOILERPLATE_CREATE_CTX(ctx);
@@ -379,10 +383,10 @@ static struct spi_flash *nuclear_flash_probe(struct spi_slave *spi)
* flash->status_cmd = ???
*/
- flash->write = nuclear_spi_write;
- flash->erase = nuclear_spi_erase;
- flash->read = nuclear_spi_read;
- flash->status = nuclear_spi_status;
+ flash->internal_write = nuclear_spi_write;
+ flash->internal_erase = nuclear_spi_erase;
+ flash->internal_read = nuclear_spi_read;
+ flash->internal_status = nuclear_spi_status;
return flash;
}
diff --git a/src/soc/intel/baytrail/spi.c b/src/soc/intel/baytrail/spi.c
index ffe619866f..d651350cd5 100644
--- a/src/soc/intel/baytrail/spi.c
+++ b/src/soc/intel/baytrail/spi.c
@@ -21,7 +21,7 @@
#include <arch/io.h>
#include <console/console.h>
#include <device/pci_ids.h>
-#include <spi_flash.h>
+#include <spi-generic.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
diff --git a/src/soc/intel/braswell/spi.c b/src/soc/intel/braswell/spi.c
index 01fe773dea..97ca2e56ef 100644
--- a/src/soc/intel/braswell/spi.c
+++ b/src/soc/intel/braswell/spi.c
@@ -22,7 +22,7 @@
#include <rules.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
-#include <spi_flash.h>
+#include <spi-generic.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/soc/intel/common/nvm.c b/src/soc/intel/common/nvm.c
index 6b86faf2e8..e44fb940b7 100644
--- a/src/soc/intel/common/nvm.c
+++ b/src/soc/intel/common/nvm.c
@@ -81,7 +81,7 @@ int nvm_erase(void *start, size_t size)
{
if (nvm_init() < 0)
return -1;
- return flash->erase(flash, nvm_mmio_to_flash_offset(start), size);
+ return spi_flash_erase(flash, nvm_mmio_to_flash_offset(start), size);
}
/* Write data to NVM. Returns 0 on success < 0 on error. */
@@ -89,7 +89,8 @@ int nvm_write(void *start, const void *data, size_t size)
{
if (nvm_init() < 0)
return -1;
- return flash->write(flash, nvm_mmio_to_flash_offset(start), size, data);
+ return spi_flash_write(flash, nvm_mmio_to_flash_offset(start), size,
+ data);
}
/* Read flash status register to determine if write protect is active */
@@ -107,7 +108,7 @@ int nvm_is_write_protected(void)
wp_gpio = get_write_protect_state();
/* Read Status Register 1 */
- if (flash->status(flash, &sr1) < 0) {
+ if (spi_flash_status(flash, &sr1) < 0) {
printk(BIOS_ERR,
"Failed to read SPI status register 1\n");
return -1;
diff --git a/src/soc/intel/fsp_baytrail/nvm.c b/src/soc/intel/fsp_baytrail/nvm.c
index ed0d12165b..6f2fdbbd6a 100644
--- a/src/soc/intel/fsp_baytrail/nvm.c
+++ b/src/soc/intel/fsp_baytrail/nvm.c
@@ -67,7 +67,7 @@ int nvm_erase(void *start, size_t size)
{
if (nvm_init() < 0)
return -1;
- flash->erase(flash, to_flash_offset(start), size);
+ spi_flash_erase(flash, to_flash_offset(start), size);
return 0;
}
@@ -76,6 +76,6 @@ int nvm_write(void *start, const void *data, size_t size)
{
if (nvm_init() < 0)
return -1;
- flash->write(flash, to_flash_offset(start), size, data);
+ spi_flash_write(flash, to_flash_offset(start), size, data);
return 0;
}
diff --git a/src/soc/intel/fsp_baytrail/spi.c b/src/soc/intel/fsp_baytrail/spi.c
index 374e7f6a44..b021175961 100644
--- a/src/soc/intel/fsp_baytrail/spi.c
+++ b/src/soc/intel/fsp_baytrail/spi.c
@@ -22,7 +22,7 @@
#include <arch/io.h>
#include <console/console.h>
#include <device/pci_ids.h>
-#include <spi_flash.h>
+#include <spi-generic.h>
#include <soc/lpc.h>
#include <soc/pci_devs.h>
diff --git a/src/soc/intel/skylake/flash_controller.c b/src/soc/intel/skylake/flash_controller.c
index 56c7c69527..5a715a4011 100644
--- a/src/soc/intel/skylake/flash_controller.c
+++ b/src/soc/intel/skylake/flash_controller.c
@@ -18,12 +18,12 @@
#include <stdlib.h>
#include <string.h>
#include <bootstate.h>
-#include <spi_flash.h>
#include <timer.h>
#include <soc/flash_controller.h>
#include <soc/intel/common/spi.h>
#include <soc/pci_devs.h>
#include <soc/spi.h>
+#include <spi-generic.h>
static inline uint16_t spi_read_hsfs(pch_spi_regs * const regs)
{
@@ -181,7 +181,7 @@ void spi_release_bus(struct spi_slave *slave)
/* Handled by PCH automatically. */
}
-int pch_hwseq_erase(struct spi_flash *flash, u32 offset, size_t len)
+int pch_hwseq_erase(const struct spi_flash *flash, u32 offset, size_t len)
{
u32 start, end, erase_size;
int ret = 0;
@@ -192,8 +192,6 @@ int pch_hwseq_erase(struct spi_flash *flash, u32 offset, size_t len)
return -1;
}
- flash->spi->rw = SPI_WRITE_FLAG;
-
start = offset;
end = start + len;
@@ -231,7 +229,8 @@ static void pch_read_data(uint8_t *data, int len)
}
}
-int pch_hwseq_read(struct spi_flash *flash, u32 addr, size_t len, void *buf)
+int pch_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len,
+ void *buf)
{
uint8_t block_len;
@@ -292,8 +291,8 @@ static void pch_fill_data(const uint8_t *data, int len)
writel_(temp32, (uint8_t *)spi_bar->fdata + (i - (i % 4)));
}
-int pch_hwseq_write(struct spi_flash *flash,
- u32 addr, size_t len, const void *buf)
+int pch_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len,
+ const void *buf)
{
uint8_t block_len;
uint32_t start = addr;
@@ -330,7 +329,7 @@ int pch_hwseq_write(struct spi_flash *flash,
return 0;
}
-int pch_hwseq_read_status(struct spi_flash *flash, u8 *reg)
+int pch_hwseq_read_status(const struct spi_flash *flash, u8 *reg)
{
size_t block_len = SPI_READ_STATUS_LENGTH;
const int timeout_ms = 6;
@@ -358,10 +357,10 @@ static struct spi_flash *spi_flash_hwseq_probe(struct spi_slave *spi)
flash->spi = spi;
flash->name = "Opaque HW-sequencing";
- flash->write = pch_hwseq_write;
- flash->erase = pch_hwseq_erase;
- flash->read = pch_hwseq_read;
- flash->status = pch_hwseq_read_status;
+ flash->internal_write = pch_hwseq_write;
+ flash->internal_erase = pch_hwseq_erase;
+ flash->internal_read = pch_hwseq_read;
+ flash->internal_status = pch_hwseq_read_status;
/* The hardware sequencing supports 4KiB or 64KiB erase. Use 4KiB. */
flash->sector_size = 4*KiB;
diff --git a/src/soc/intel/skylake/include/soc/flash_controller.h b/src/soc/intel/skylake/include/soc/flash_controller.h
index 49d60b0cd4..00500670fe 100644
--- a/src/soc/intel/skylake/include/soc/flash_controller.h
+++ b/src/soc/intel/skylake/include/soc/flash_controller.h
@@ -21,13 +21,12 @@
#include <console/console.h>
#include <spi_flash.h>
-int pch_hwseq_erase(struct spi_flash *flash, u32 offset, size_t len);
-int pch_hwseq_write(struct spi_flash *flash,
- u32 addr, size_t len, const void *buf);
-
-int pch_hwseq_read(struct spi_flash *flash,
- u32 addr, size_t len, void *buf);
-int pch_hwseq_read_status(struct spi_flash *flash, u8 *reg);
+int pch_hwseq_erase(const struct spi_flash *flash, u32 offset, size_t len);
+int pch_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len,
+ const void *buf);
+int pch_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len,
+ void *buf);
+int pch_hwseq_read_status(const struct spi_flash *flash, u8 *reg);
#if IS_ENABLED(CONFIG_DEBUG_SPI_FLASH)
diff --git a/src/soc/intel/skylake/romstage/spi.c b/src/soc/intel/skylake/romstage/spi.c
index db69cbeab7..16224046d7 100644
--- a/src/soc/intel/skylake/romstage/spi.c
+++ b/src/soc/intel/skylake/romstage/spi.c
@@ -16,6 +16,7 @@
#include <soc/flash_controller.h>
#include <soc/romstage.h>
+#include <spi-generic.h>
/*
* Minimal set of commands to read WPSR from SPI.
diff --git a/src/soc/mediatek/mt8173/flash_controller.c b/src/soc/mediatek/mt8173/flash_controller.c
index 5d73f3aba2..dc64d4083c 100644
--- a/src/soc/mediatek/mt8173/flash_controller.c
+++ b/src/soc/mediatek/mt8173/flash_controller.c
@@ -157,7 +157,8 @@ static int pio_read(u32 addr, u8 *buf, u32 len)
return 0;
}
-static int nor_read(struct spi_flash *flash, u32 addr, size_t len, void *buf)
+static int nor_read(const struct spi_flash *flash, u32 addr, size_t len,
+ void *buf)
{
u32 next;
@@ -195,8 +196,8 @@ static int nor_read(struct spi_flash *flash, u32 addr, size_t len, void *buf)
return 0;
}
-static int nor_write(struct spi_flash *flash, u32 addr, size_t len,
- const void *buf)
+static int nor_write(const struct spi_flash *flash, u32 addr, size_t len,
+ const void *buf)
{
const u8 *buffer = (const u8 *)buf;
@@ -214,7 +215,7 @@ static int nor_write(struct spi_flash *flash, u32 addr, size_t len,
return 0;
}
-static int nor_erase(struct spi_flash *flash, u32 offset, size_t len)
+static int nor_erase(const struct spi_flash *flash, u32 offset, size_t len)
{
int sector_start = offset;
int sector_num = (u32)len / flash->sector_size;
@@ -242,10 +243,10 @@ struct spi_flash *mt8173_nor_flash_probe(struct spi_slave *spi)
write32(&mt8173_nor->wrprot, SFLASH_COMMAND_ENABLE);
flash.spi = spi;
flash.name = "mt8173 flash controller";
- flash.write = nor_write;
- flash.erase = nor_erase;
- flash.read = nor_read;
- flash.status = 0;
+ flash.internal_write = nor_write;
+ flash.internal_erase = nor_erase;
+ flash.internal_read = nor_read;
+ flash.internal_status = 0;
flash.sector_size = 0x1000;
flash.erase_cmd = SECTOR_ERASE_CMD;
flash.size = CONFIG_ROM_SIZE;
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/spi.h b/src/soc/qualcomm/ipq40xx/include/soc/spi.h
index 014b333667..1fd6a571ca 100644
--- a/src/soc/qualcomm/ipq40xx/include/soc/spi.h
+++ b/src/soc/qualcomm/ipq40xx/include/soc/spi.h
@@ -32,9 +32,9 @@
#ifndef _IPQ40XX_SPI_H_
#define _IPQ40XX_SPI_H_
-#include <spi_flash.h>
#include <soc/iomap.h>
#include <soc/qup.h>
+#include <spi-generic.h>
#define BLSP0_QUP_REG_BASE ((void *)0x78b5000u)
#define BLSP1_QUP_REG_BASE ((void *)0x78b6000u)
diff --git a/src/soc/qualcomm/ipq40xx/spi.c b/src/soc/qualcomm/ipq40xx/spi.c
index 8d39f77ae4..dcd00c0065 100644
--- a/src/soc/qualcomm/ipq40xx/spi.c
+++ b/src/soc/qualcomm/ipq40xx/spi.c
@@ -28,6 +28,7 @@
*/
#include <arch/io.h>
+#include <console/console.h>
#include <delay.h>
#include <gpio.h>
#include <soc/iomap.h>
diff --git a/src/soc/qualcomm/ipq806x/include/soc/spi.h b/src/soc/qualcomm/ipq806x/include/soc/spi.h
index 3e623463cc..4f6f055e61 100644
--- a/src/soc/qualcomm/ipq806x/include/soc/spi.h
+++ b/src/soc/qualcomm/ipq806x/include/soc/spi.h
@@ -6,7 +6,7 @@
#ifndef _IPQ806X_SPI_H_
#define _IPQ806X_SPI_H_
-#include <spi_flash.h>
+#include <spi-generic.h>
#include <soc/iomap.h>
#define QUP5_BASE ((uint32_t)GSBI_QUP5_BASE)
diff --git a/src/soc/qualcomm/ipq806x/spi.c b/src/soc/qualcomm/ipq806x/spi.c
index 4a353130e1..71a8c29085 100644
--- a/src/soc/qualcomm/ipq806x/spi.c
+++ b/src/soc/qualcomm/ipq806x/spi.c
@@ -3,6 +3,7 @@
*/
#include <arch/io.h>
+#include <console/console.h>
#include <delay.h>
#include <gpio.h>
#include <soc/iomap.h>
diff --git a/src/soc/rockchip/common/spi.c b/src/soc/rockchip/common/spi.c
index 57e9ca117e..3666de39d1 100644
--- a/src/soc/rockchip/common/spi.c
+++ b/src/soc/rockchip/common/spi.c
@@ -37,45 +37,30 @@ struct rockchip_spi_slave {
static struct rockchip_spi_slave rockchip_spi_slaves[] = {
{
- .slave = {
- .bus = 0,
- .rw = SPI_READ_FLAG | SPI_WRITE_FLAG,
- },
+ .slave = { .bus = 0, },
.regs = (void *)SPI0_BASE,
},
{
- .slave = {.bus = 1, .rw = SPI_READ_FLAG,},
+ .slave = { .bus = 1, },
.regs = (void *)SPI1_BASE,
},
{
- .slave = {
- .bus = 2,
- .rw = SPI_READ_FLAG | SPI_WRITE_FLAG,
- },
+ .slave = { .bus = 2, },
.regs = (void *)SPI2_BASE,
},
#ifdef SPI3_BASE
{
- .slave = {
- .bus = 3,
- .rw = SPI_READ_FLAG | SPI_WRITE_FLAG,
- },
+ .slave = { .bus = 3, },
.regs = (void *)SPI3_BASE,
},
#ifdef SPI4_BASE
{
- .slave = {
- .bus = 4,
- .rw = SPI_READ_FLAG | SPI_WRITE_FLAG,
- },
+ .slave = { .bus = 4, },
.regs = (void *)SPI4_BASE,
},
#ifdef SPI5_BASE
{
- .slave = {
- .bus = 5,
- .rw = SPI_READ_FLAG | SPI_WRITE_FLAG,
- },
+ .slave = { .bus = 5, },
.regs = (void *)SPI5_BASE,
},
#endif
diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c
index 589809d5af..fd31a2fdf7 100644
--- a/src/soc/samsung/exynos5420/spi.c
+++ b/src/soc/samsung/exynos5420/spi.c
@@ -19,7 +19,7 @@
#include <console/console.h>
#include <soc/cpu.h>
#include <soc/spi.h>
-#include <spi_flash.h>
+#include <spi-generic.h>
#include <stdlib.h>
#include <string.h>
#include <symbols.h>
@@ -48,13 +48,12 @@ static struct exynos_spi_slave exynos_spi_slaves[3] = {
},
// SPI 1
{
- .slave = { .bus = 1, .rw = SPI_READ_FLAG, },
+ .slave = { .bus = 1, },
.regs = (void *)EXYNOS5_SPI1_BASE,
},
// SPI 2
{
- .slave = { .bus = 2,
- .rw = SPI_READ_FLAG | SPI_WRITE_FLAG, },
+ .slave = { .bus = 2, },
.regs = (void *)EXYNOS5_SPI2_BASE,
},
};
diff --git a/src/southbridge/amd/agesa/hudson/Kconfig b/src/southbridge/amd/agesa/hudson/Kconfig
index fd79a3f034..eed83ae53f 100644
--- a/src/southbridge/amd/agesa/hudson/Kconfig
+++ b/src/southbridge/amd/agesa/hudson/Kconfig
@@ -64,6 +64,7 @@ config HUDSON_XHCI_FWM
config HUDSON_IMC_FWM
bool "Add imc firmware"
default y if USE_BLOBS
+ select SPI_FLASH_HAS_VOLATILE_GROUP if SPI_FLASH
help
Add Hudson 2/3/4 IMC Firmware to support the onboard fan control
diff --git a/src/southbridge/amd/agesa/hudson/spi.c b/src/southbridge/amd/agesa/hudson/spi.c
index 31160bdcd9..f1a82e9022 100644
--- a/src/southbridge/amd/agesa/hudson/spi.c
+++ b/src/southbridge/amd/agesa/hudson/spi.c
@@ -17,17 +17,14 @@
#include <string.h>
#include <arch/io.h>
#include <console/console.h>
+#include <spi_flash.h>
#include <spi-generic.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
-#if IS_ENABLED (CONFIG_HUDSON_IMC_FWM)
#include <Proc/Fch/FchPlatform.h>
-static int bus_claimed = 0;
-#endif
-
#define SPI_REG_OPCODE 0x0
#define SPI_REG_CNTRL01 0x1
#define SPI_REG_CNTRL02 0x2
@@ -149,32 +146,34 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
return 0;
}
+
int spi_claim_bus(struct spi_slave *slave)
{
-#if IS_ENABLED (CONFIG_HUDSON_IMC_FWM)
+ /* Nothing is required. */
+ return 0;
+}
- if (slave->rw == SPI_WRITE_FLAG) {
- bus_claimed++;
- if (bus_claimed == 1)
- ImcSleep(NULL);
- }
-#endif
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* Nothing is required. */
+}
+
+int chipset_volatile_group_begin(const struct spi_flash *flash)
+{
+ if (!IS_ENABLED (CONFIG_HUDSON_IMC_FWM))
+ return 0;
+ ImcSleep(NULL);
return 0;
}
-void spi_release_bus(struct spi_slave *slave)
+int chipset_volatile_group_end(const struct spi_flash *flash)
{
-#if IS_ENABLED (CONFIG_HUDSON_IMC_FWM)
-
- if (slave->rw == SPI_WRITE_FLAG) {
- bus_claimed--;
- if (bus_claimed <= 0) {
- bus_claimed = 0;
- ImcWakeup(NULL);
- }
- }
-#endif
+ if (!IS_ENABLED (CONFIG_HUDSON_IMC_FWM))
+ return 0;
+
+ ImcWakeup(NULL);
+ return 0;
}
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
diff --git a/src/southbridge/amd/cimx/sb800/Kconfig b/src/southbridge/amd/cimx/sb800/Kconfig
index a48b93a67c..07232f1a74 100644
--- a/src/southbridge/amd/cimx/sb800/Kconfig
+++ b/src/southbridge/amd/cimx/sb800/Kconfig
@@ -123,6 +123,7 @@ endif
config SB800_IMC_FWM
bool "Add IMC firmware"
default n
+ select SPI_FLASH_HAS_VOLATILE_GROUP if SPI_FLASH
help
Add SB800 / Hudson 1 IMC Firmware to support the onboard fan control.
diff --git a/src/southbridge/amd/cimx/sb800/spi.c b/src/southbridge/amd/cimx/sb800/spi.c
index f6898926e3..726d8e0129 100644
--- a/src/southbridge/amd/cimx/sb800/spi.c
+++ b/src/southbridge/amd/cimx/sb800/spi.c
@@ -17,18 +17,15 @@
#include <string.h>
#include <arch/io.h>
#include <console/console.h>
+#include <spi_flash.h>
#include <spi-generic.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
-#if IS_ENABLED (CONFIG_SB800_IMC_FWM)
#include "SBPLATFORM.h"
#include <vendorcode/amd/cimx/sb800/ECfan.h>
-static int bus_claimed = 0;
-#endif
-
#define AMD_SB_SPI_TX_LEN 8
static uintptr_t spibar;
@@ -114,8 +111,6 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
return 0;
}
-#if IS_ENABLED (CONFIG_SB800_IMC_FWM)
-
static void ImcSleep(void)
{
u8 cmd_val = 0x96; /* Kick off IMC Mailbox command 96 */
@@ -142,34 +137,35 @@ static void ImcWakeup(void)
WaitForEcLDN9MailboxCmdAck();
}
-#endif
int spi_claim_bus(struct spi_slave *slave)
{
-#if IS_ENABLED (CONFIG_SB800_IMC_FWM)
+ /* Nothing is required. */
+ return 0;
+}
- if (slave->rw == SPI_WRITE_FLAG) {
- bus_claimed++;
- if (bus_claimed == 1)
- ImcSleep();
- }
-#endif
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* Nothing is required. */
+ return;
+}
+
+int chipset_volatile_group_begin(const struct spi_flash *flash)
+{
+ if (!IS_ENABLED(CONFIG_SB800_IMC_FWM))
+ return 0;
+ ImcSleep();
return 0;
}
-void spi_release_bus(struct spi_slave *slave)
+int chipset_volatile_group_end(const struct spi_flash *flash)
{
-#if IS_ENABLED (CONFIG_SB800_IMC_FWM)
-
- if (slave->rw == SPI_WRITE_FLAG) {
- bus_claimed--;
- if (bus_claimed <= 0) {
- bus_claimed = 0;
- ImcWakeup();
- }
- }
-#endif
+ if (!IS_ENABLED(CONFIG_SB800_IMC_FWM))
+ return 0;
+
+ ImcWakeup();
+ return 0;
}
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c
index 1ab151b79e..e0414220c6 100644
--- a/src/southbridge/intel/common/spi.c
+++ b/src/southbridge/intel/common/spi.c
@@ -737,7 +737,8 @@ static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
}
-static int ich_hwseq_erase(struct spi_flash *flash, u32 offset, size_t len)
+static int ich_hwseq_erase(const struct spi_flash *flash, u32 offset,
+ size_t len)
{
u32 start, end, erase_size;
int ret;
@@ -750,7 +751,6 @@ static int ich_hwseq_erase(struct spi_flash *flash, u32 offset, size_t len)
return -1;
}
- flash->spi->rw = SPI_WRITE_FLAG;
ret = spi_claim_bus(flash->spi);
if (ret) {
printk(BIOS_ERR, "SF: Unable to claim SPI bus\n");
@@ -801,8 +801,8 @@ static void ich_read_data(uint8_t *data, int len)
}
}
-static int ich_hwseq_read(struct spi_flash *flash,
- u32 addr, size_t len, void *buf)
+static int ich_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len,
+ void *buf)
{
uint16_t hsfc;
uint16_t timeout = 100 * 60;
@@ -869,8 +869,8 @@ static void ich_fill_data(const uint8_t *data, int len)
writel_(temp32, cntlr.data + (i - (i % 4)));
}
-static int ich_hwseq_write(struct spi_flash *flash,
- u32 addr, size_t len, const void *buf)
+static int ich_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len,
+ const void *buf)
{
uint16_t hsfc;
uint16_t timeout = 100 * 60;
@@ -934,9 +934,9 @@ static struct spi_flash *spi_flash_hwseq(struct spi_slave *spi)
flash->spi = spi;
flash->name = "Opaque HW-sequencing";
- flash->write = ich_hwseq_write;
- flash->erase = ich_hwseq_erase;
- flash->read = ich_hwseq_read;
+ flash->internal_write = ich_hwseq_write;
+ flash->internal_erase = ich_hwseq_erase;
+ flash->internal_read = ich_hwseq_read;
ich_hwseq_set_addr (0);
switch ((cntlr.hsfs >> 3) & 3)
{