Edward O'Callaghan has submitted this change. ( https://review.coreboot.org/c/flashrom/+/38833 )
Change subject: sb600spi: Add spireadmode ......................................................................
sb600spi: Add spireadmode
Added spireadmode for >= Bolton. Do not override speed or read mode for >= Bolton if parameter not specified. Minor cleanup of sb600spi.c code.
TEST=Manual: deploy on tremblye read flash using various parameters BUG=b:147665085,b:147666328 BRANCH=master
Change-Id: Id7fec7eb87ff811148217dc56a86dca3fef122ff Signed-off-by: Rob Barnes robbarnes@google.com Reviewed-on: https://review.coreboot.org/c/flashrom/+/38833 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Edward O'Callaghan quasisec@chromium.org Reviewed-by: Angel Pons th3fanbus@gmail.com --- M flashrom.8.tmpl M sb600spi.c 2 files changed, 99 insertions(+), 44 deletions(-)
Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Edward O'Callaghan: Looks good to me, approved
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl index aa5bcd4..fde98c0 100644 --- a/flashrom.8.tmpl +++ b/flashrom.8.tmpl @@ -497,11 +497,29 @@ .sp * SB6xx, SB7xx, SP5xxx: from 16.5 MHz up to and including 33 MHz .sp +-The default is to use 16.5 MHz and disable Fast Reads. +.sp * SB8xx, SB9xx, Hudson: from 16.5 MHz up to and including 66 MHz .sp +-The default is to use 16.5 MHz and disable Fast Reads. +.sp * Yangtze (with SPI 100 engine as found in Kabini and Tamesh): all of them .sp -The default is to use 16.5 MHz and disable Fast Reads. +-The default is to use the frequency that is currently configured. +.sp +An optional +.B spireadmode +parameter specifies the read mode of the SPI bus where applicable (Bolton or later). +Syntax is +.sp +.B " flashrom -p internal:spireadmode=mode" +.sp +where +.B mode +can be +.BR "'Normal\ (up\ to\ 33 MHz)'" ", " "'Normal\ (up\ to\ 66 MHz)'" ", " "'Dual\ IO\ (1-1-2)'" ", " "'Quad\ IO\ (1-1-4)'" ", " "'Dual\ IO\ (1-2-2)'" ", " "'Quad\ IO\ (1-4-4)'" ", or " "'Fast\ Read'" "." +.sp +The default is to use the read mode that is currently configured. .TP .B Intel chipsets .sp diff --git a/sb600spi.c b/sb600spi.c index cb5c4a4..a649253 100644 --- a/sb600spi.c +++ b/sb600spi.c @@ -347,23 +347,33 @@ const uint8_t speed; };
-static const struct spispeed spispeeds[] = { - { "66 MHz", 0x00 }, - { "33 MHz", 0x01 }, - { "22 MHz", 0x02 }, - { "16.5 MHz", 0x03 }, - { "100 MHz", 0x04 }, - { "Reserved", 0x05 }, - { "Reserved", 0x06 }, - { "800 kHz", 0x07 }, +static const char* spispeeds[] = { + "66 MHz", + "33 MHz", + "22 MHz", + "16.5 MHz", + "100 MHz", + "Reserved", + "Reserved", + "800 kHz", };
-static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed) +static const char* spireadmodes[] = { + "Normal (up to 33 MHz)", + "Reserved", + "Dual IO (1-1-2)", + "Quad IO (1-1-4)", + "Dual IO (1-2-2)", + "Quad IO (1-4-4)", + "Normal (up to 66 MHz)", + "Fast Read", +}; + +static int set_speed(struct pci_dev *dev, uint8_t speed) { bool success = false; - uint8_t speed = spispeed->speed;
- msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed); + msg_pdbg("Setting SPI clock to %s (%i)... ", spispeeds[speed], speed); if (amd_gen >= CHIPSET_YANGTZE) { rmmio_writew((speed << 12) | (speed << 8) | (speed << 4) | speed, sb600_spibar + 0x22); uint16_t tmp = mmio_readw(sb600_spibar + 0x22); @@ -375,33 +385,41 @@ }
if (!success) { - msg_perr("Setting SPI clock failed.\n"); + msg_perr("FAILED!\n"); return 1; } + msg_pdbg("succeeded.\n"); return 0; }
-static int set_mode(struct pci_dev *dev, uint8_t read_mode) +static int set_mode(struct pci_dev *dev, uint8_t mode) { + msg_pdbg("Setting SPI read mode to %s (%i)... ", spireadmodes[mode], mode); uint32_t tmp = mmio_readl(sb600_spibar + 0x00); tmp &= ~(0x6 << 28 | 0x1 << 18); /* Clear mode bits */ - tmp |= ((read_mode & 0x6) << 28) | ((read_mode & 0x1) << 18); + tmp |= ((mode & 0x6) << 28) | ((mode & 0x1) << 18); rmmio_writel(tmp, sb600_spibar + 0x00); - if (tmp != mmio_readl(sb600_spibar + 0x00)) + if (tmp != mmio_readl(sb600_spibar + 0x00)) { + msg_perr("FAILED!\n"); return 1; + } + msg_pdbg("succeeded.\n"); return 0; }
static int handle_speed(struct pci_dev *dev) { uint32_t tmp; - uint8_t spispeed_idx = 3; /* Default to 16.5 MHz */ + int16_t spispeed_idx = -1; + int16_t spireadmode_idx = -1; + char *spispeed; + char *spireadmode;
- char *spispeed = extract_programmer_param("spispeed"); + spispeed = extract_programmer_param("spispeed"); if (spispeed != NULL) { unsigned int i; for (i = 0; i < ARRAY_SIZE(spispeeds); i++) { - if (strcasecmp(spispeeds[i].name, spispeed) == 0) { + if (strcasecmp(spispeeds[i], spispeed) == 0) { spispeed_idx = i; break; } @@ -421,32 +439,44 @@ free(spispeed); }
+ spireadmode = extract_programmer_param("spireadmode"); + if (spireadmode != NULL) { + unsigned int i; + for (i = 0; i < ARRAY_SIZE(spireadmodes); i++) { + if (strcasecmp(spireadmodes[i], spireadmode) == 0) { + spireadmode_idx = i; + break; + } + } + if ((strcasecmp(spireadmode, "reserved") == 0) || + (i == ARRAY_SIZE(spireadmodes))) { + msg_perr("Error: Invalid spireadmode value: '%s'.\n", spireadmode); + free(spireadmode); + return 1; + } + if (amd_gen < CHIPSET_BOLTON) { + msg_perr("Warning: spireadmode not supported for this chipset."); + } + free(spireadmode); + } + /* See the chipset support matrix for SPI Base_Addr below for an explanation of the symbols used. * bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson234 bolton/yangtze * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0] * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1] */ if (amd_gen >= CHIPSET_BOLTON) { - static const char *spireadmodes[] = { - "Normal (up to 33 MHz)", /* 0 */ - "Reserved", /* 1 */ - "Dual IO (1-1-2)", /* 2 */ - "Quad IO (1-1-4)", /* 3 */ - "Dual IO (1-2-2)", /* 4 */ - "Quad IO (1-4-4)", /* 5 */ - "Normal (up to 66 MHz)", /* 6 */ - "Fast Read", /* 7 (Not defined in the Bolton datasheet.) */ - }; + tmp = mmio_readl(sb600_spibar + 0x00); uint8_t read_mode = ((tmp >> 28) & 0x6) | ((tmp >> 18) & 0x1); - msg_pdbg("SpiReadMode=%s (%i)\n", spireadmodes[read_mode], read_mode); - if (read_mode != 6) { - read_mode = 6; /* Default to "Normal (up to 66 MHz)" */ - if (set_mode(dev, read_mode) != 0) { - msg_perr("Setting read mode to "%s" failed.\n", spireadmodes[read_mode]); - return 1; - } - msg_pdbg("Setting read mode to "%s" succeeded.\n", spireadmodes[read_mode]); + msg_pdbg("SPI read mode is %s (%i)\n", + spireadmodes[read_mode], read_mode); + if (spireadmode_idx < 0) { + msg_perr("Warning: spireadmode not set, " + "leaving spireadmode unchanged."); + } + else if (set_mode(dev, spireadmode_idx) != 0) { + return 1; }
if (amd_gen >= CHIPSET_YANGTZE) { @@ -463,10 +493,10 @@ }
tmp = mmio_readw(sb600_spibar + 0x22); /* SPI 100 Speed Config */ - msg_pdbg("NormSpeedNew is %s\n", spispeeds[(tmp >> 12) & 0xf].name); - msg_pdbg("FastSpeedNew is %s\n", spispeeds[(tmp >> 8) & 0xf].name); - msg_pdbg("AltSpeedNew is %s\n", spispeeds[(tmp >> 4) & 0xf].name); - msg_pdbg("TpmSpeedNew is %s\n", spispeeds[(tmp >> 0) & 0xf].name); + msg_pdbg("NormSpeedNew is %s\n", spispeeds[(tmp >> 12) & 0xf]); + msg_pdbg("FastSpeedNew is %s\n", spispeeds[(tmp >> 8) & 0xf]); + msg_pdbg("AltSpeedNew is %s\n", spispeeds[(tmp >> 4) & 0xf]); + msg_pdbg("TpmSpeedNew is %s\n", spispeeds[(tmp >> 0) & 0xf]); } } else { if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) { @@ -479,9 +509,16 @@ } } tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3; - msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name); + msg_pdbg("NormSpeed is %s\n", spispeeds[tmp]); + if (spispeed_idx < 0) { + spispeed_idx = 3; /* Default to 16.5 MHz */ + } } - return set_speed(dev, &spispeeds[spispeed_idx]); + if (spispeed_idx < 0) { + msg_perr("Warning: spispeed not set, leaving spispeed unchanged."); + return 0; + } + return set_speed(dev, spispeed_idx); }
static int handle_imc(struct pci_dev *dev)