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