summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>2013-09-15 14:17:39 +0000
committerStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>2013-09-15 14:17:39 +0000
commita6a0d2000a1197e90faaf8d9e7697c96f1deb934 (patch)
treeedbcfbcc9921b732f9c69f2d72e20e184ec2b4b4
parent949ccc8a7ed2a7ad075103e064ad92483ffa8720 (diff)
downloadast2050-flashrom-a6a0d2000a1197e90faaf8d9e7697c96f1deb934.zip
ast2050-flashrom-a6a0d2000a1197e90faaf8d9e7697c96f1deb934.tar.gz
sbxxx: Set SPI clock to 16.5 MHz and disable fast reads
Do not rely on broken firmware to set up the SPI configuration correctly. Some boards fail with flashrom because the firmware chose too high speeds for the alternate SPI mode which flashrom uses. Temporarily change the clock to the lowest common value of 16.5 MHz. Also, disable fast reads just to be safe. Corresponding to flashrom svn r1750. Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
-rw-r--r--sb600spi.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/sb600spi.c b/sb600spi.c
index 8f93d65..9523591 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -272,6 +272,62 @@ static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
return 0;
}
+struct spispeed {
+ const char *const name;
+ const uint8_t speed;
+};
+
+static const struct spispeed spispeeds[] = {
+ { "66 MHz", 0x00 },
+ { "33 MHz", 0x01 },
+ { "22 MHz", 0x02 },
+ { "16.5 MHz", 0x03 },
+};
+
+static int set_speed(struct pci_dev *dev, const struct spispeed *spispeed)
+{
+ bool success = false;
+ uint8_t speed = spispeed->speed;
+
+ msg_pdbg("Setting SPI clock to %s (0x%x).\n", spispeed->name, speed);
+ if (amd_gen != CHIPSET_YANGTZE) {
+ rmmio_writeb((mmio_readb(sb600_spibar + 0xd) & ~(0x3 << 4)) | (speed << 4), sb600_spibar + 0xd);
+ success = (speed == ((mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3));
+ }
+
+ if (!success) {
+ msg_perr("Setting SPI clock failed.\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int handle_speed(struct pci_dev *dev)
+{
+ uint32_t tmp;
+ int8_t spispeed_idx = 3; /* Default to 16.5 MHz */
+
+ /* 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 yangtze
+ * 18 rsvd <- fastReadEnable ? <- ? SpiReadMode[0]
+ * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
+ */
+ if (amd_gen != CHIPSET_YANGTZE) {
+ if (amd_gen >= CHIPSET_SB89XX && amd_gen <= CHIPSET_HUDSON234) {
+ bool fast_read = (mmio_readl(sb600_spibar + 0x00) >> 18) & 0x1;
+ msg_pdbg("Fast Reads are %sabled\n", fast_read ? "en" : "dis");
+ if (fast_read) {
+ msg_pdbg("Disabling them temporarily.\n");
+ rmmio_writel(mmio_readl(sb600_spibar + 0x00) & ~(0x1 << 18),
+ sb600_spibar + 0x00);
+ }
+ }
+ tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
+ msg_pdbg("NormSpeed is %s\n", spispeeds[tmp].name);
+ }
+ return set_speed(dev, &spispeeds[spispeed_idx]);
+}
+
static int sb600_handle_imc(struct pci_dev *dev, bool amd_imc_force)
{
/* Handle IMC everywhere but sb600 which does not have one. */
@@ -322,9 +378,6 @@ int sb600_probe_spi(struct pci_dev *dev)
uint32_t tmp;
uint8_t reg;
bool amd_imc_force = false;
- static const char *const speed_names[4] = {
- "66/reserved", "33", "22", "16.5"
- };
char *arg = extract_programmer_param("amd_imc_force");
if (arg && !strcmp(arg, "yes")) {
@@ -411,7 +464,7 @@ int sb600_probe_spi(struct pci_dev *dev)
* See the chipset support matrix for SPI Base_Addr above for an explanation of the symbols used.
* bit 6xx 7xx/SP5100 8xx 9xx hudson1 hudson2+ yangtze
* 17 rsvd <- <- ? <- ? <-
- * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]
+ * 18 rsvd <- fastReadEnable<1> ? <- ? SpiReadMode[0]<1>
* 19 SpiArbEnable <- <- ? <- ? <-
* 20 (FifoPtrClr) <- <- ? <- ? <-
* 21 (FifoPtrInc) <- <- ? <- ? IllegalAccess
@@ -420,8 +473,10 @@ int sb600_probe_spi(struct pci_dev *dev)
* 24:26 ArbWaitCount <- <- ? <- ? <-
* 27 SpiBridgeDisable <- <- ? <- ? rsvd
* 28 rsvd DropOneClkOnRd = SPIClkGate ? <- ? <-
- * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]
+ * 29:30 rsvd <- <- ? <- ? SpiReadMode[2:1]<1>
* 31 rsvd <- SpiBusy ? <- ? <-
+ *
+ * <1> see handle_speed
*/
tmp = mmio_readl(sb600_spibar + 0x00);
msg_pdbg("(0x%08" PRIx32 ") SpiArbEnable=%i", tmp, (tmp >> 19) & 0x1);
@@ -447,9 +502,6 @@ int sb600_probe_spi(struct pci_dev *dev)
return ERROR_NONFATAL;
}
- tmp = (mmio_readb(sb600_spibar + 0xd) >> 4) & 0x3;
- msg_pdbg("NormSpeed is %s MHz\n", speed_names[tmp]);
-
if (amd_gen >= CHIPSET_SB89XX) {
tmp = mmio_readb(sb600_spibar + 0x1D);
msg_pdbg("Using SPI_CS%d\n", tmp & 0x3);
@@ -494,6 +546,9 @@ int sb600_probe_spi(struct pci_dev *dev)
return 0;
}
+ if (handle_speed(dev) != 0)
+ return ERROR_FATAL;
+
if (sb600_handle_imc(dev, amd_imc_force) != 0)
return ERROR_FATAL;
OpenPOWER on IntegriCloud