Arthur Heymans has uploaded this change for review.

View Change

sb600spi.c: Move promontory code into a mmap_read=yes mode

The only reason promontory code is handled differently is because memory
mapped reads can be faster than manual SPI sequencing. This is not
hardware specific so move it to an option 'mmap_read=yes'.

Change-Id: I13eb5a646d3569170b3911ae7b3127cd3e6022aa
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
M flashrom.8.tmpl
M sb600spi.c
2 files changed, 69 insertions(+), 21 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/65/71565/1
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index 0eabee5..6e2b4eb 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -599,6 +599,15 @@
-The default is to use the frequency that is currently configured.
.sp
An optional
+.B mmap_read
+parameter allows to do memory mapped reads instead of through manual SPI sequencing.
+This allows the programmer to use faster modes which can be set with the
+.B spireadmode
+parameter. This mode is however limited to 16MiB flashchips or smaller as more does not get mapped.
+.sp
+.B " flashrom \-p internal:mmap_read=yes
+.sp
+An optional
.B spireadmode
parameter specifies the read mode of the SPI bus where applicable (Bolton or later).
Syntax is
diff --git a/sb600spi.c b/sb600spi.c
index 5b9ac45..3e1339c 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -572,9 +572,14 @@
return amd_imc_shutdown(dev);
}

-static int promontory_read_memmapped(struct flashctx *flash, uint8_t *buf,
+static int amd_read_memmapped(struct flashctx *flash, uint8_t *buf,
unsigned int start, unsigned int len)
{
+ if (flash->chip->total_size > (16 * MiB) / KiB) {
+ msg_perr("No more than 16 MiB can be memory mapped.\n"
+ "Try again without mmap_read=yes");
+ return -1;
+ }
struct sb600spi_data * data = (struct sb600spi_data *)flash->mst->spi.data;
if (!data->flash) {
map_flash(flash);
@@ -584,6 +589,34 @@
return 0;
}

+static int handle_mmap_read(const struct programmer_cfg *cfg,
+ struct spi_master *master)
+{
+ bool mmap_read = false;
+ char *param_value = extract_programmer_param_str(cfg, "mmap_read");
+ if (param_value && !strcmp(param_value, "yes")) {
+ mmap_read = true;
+ msg_pspew("mmap_read enabled.\n");
+ } else if (param_value && !strlen(param_value)) {
+ msg_perr("Missing argument for mmap_read.\n");
+ free(param_value);
+ return 1;
+ } else if (param_value) {
+ msg_perr("Unknown argument for mmap_read: \"%s\" (not \"yes\").\n", param_value);
+ free(param_value);
+ return 1;
+ }
+ free(param_value);
+
+ if (!mmap_read)
+ return 0;
+
+ master->max_data_read = MAX_DATA_READ_UNLIMITED;
+ master->read = amd_read_memmapped;
+
+ return 0;
+}
+
static int sb600spi_shutdown(void *data)
{
struct sb600spi_data *sb600_data = data;
@@ -595,7 +628,7 @@
return 0;
}

-static const struct spi_master spi_master_sb600 = {
+static struct spi_master spi_master_sb600 = {
.max_data_read = FIFO_SIZE_OLD,
.max_data_write = FIFO_SIZE_OLD - 3,
.command = sb600_spi_send_command,
@@ -608,7 +641,7 @@
.probe_opcode = default_spi_probe_opcode,
};

-static const struct spi_master spi_master_yangtze = {
+static struct spi_master spi_master_yangtze = {
.max_data_read = FIFO_SIZE_YANGTZE - 3, /* Apparently the big SPI 100 buffer is not a ring buffer. */
.max_data_write = FIFO_SIZE_YANGTZE - 3,
.command = spi100_spi_send_command,
@@ -621,19 +654,6 @@
.probe_opcode = default_spi_probe_opcode,
};

-static const struct spi_master spi_master_promontory = {
- .max_data_read = MAX_DATA_READ_UNLIMITED,
- .max_data_write = FIFO_SIZE_YANGTZE - 3,
- .command = spi100_spi_send_command,
- .multicommand = default_spi_send_multicommand,
- .map_flash_region = physmap,
- .unmap_flash_region = physunmap,
- .read = promontory_read_memmapped,
- .write_256 = default_spi_write_256,
- .shutdown = sb600spi_shutdown,
- .probe_opcode = default_spi_probe_opcode,
-};
-
int sb600_probe_spi(const struct programmer_cfg *cfg, struct pci_dev *dev)
{
struct pci_dev *smbus_dev;
@@ -809,13 +829,18 @@
data->flash = NULL;
data->spibar = sb600_spibar;

+ struct spi_master *master;
+
/* Starting with Yangtze the SPI controller got a different interface with a much bigger buffer. */
if (amd_gen < CHIPSET_YANGTZE)
- register_spi_master(&spi_master_sb600, data);
- else if (amd_gen == CHIPSET_YANGTZE)
- register_spi_master(&spi_master_yangtze, data);
- else
- register_spi_master(&spi_master_promontory, data);
+ master = &spi_master_sb600;
+ else if (amd_gen >= CHIPSET_YANGTZE)
+ master = &spi_master_yangtze;
+
+ if (handle_mmap_read(cfg, master))
+ return ERROR_FLASHROM_FATAL;
+
+ register_spi_master(master, data);

return 0;
}

To view, visit change 71565. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I13eb5a646d3569170b3911ae7b3127cd3e6022aa
Gerrit-Change-Number: 71565
Gerrit-PatchSet: 1
Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz>
Gerrit-MessageType: newchange