summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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)
{