summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chipset_enable.c8
-rw-r--r--flash.h2
-rw-r--r--ichspi.c50
-rw-r--r--spi.c18
4 files changed, 71 insertions, 7 deletions
diff --git a/chipset_enable.c b/chipset_enable.c
index 76893a1..04b1a1c 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -36,8 +36,6 @@
#if defined(__i386__) || defined(__x86_64__)
-extern int ichspi_lock;
-
static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name)
{
uint8_t tmp;
@@ -515,8 +513,9 @@ static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
mmio_readl(spibar + offs + 4), i);
}
+ ichspi_bbar = mmio_readl(spibar + 0x50);
msg_pdbg("0x50: 0x%08x (BBAR)\n",
- mmio_readl(spibar + 0x50));
+ ichspi_bbar);
msg_pdbg("0x54: 0x%04x (PREOP)\n",
mmio_readw(spibar + 0x54));
msg_pdbg("0x56: 0x%04x (OPTYPE)\n",
@@ -587,8 +586,9 @@ static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
mmio_readl(spibar + 0x98));
msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",
mmio_readl(spibar + 0x9C));
+ ichspi_bbar = mmio_readl(spibar + 0xA0);
msg_pdbg("0xA0: 0x%08x (BBAR)\n",
- mmio_readl(spibar + 0xA0));
+ ichspi_bbar);
msg_pdbg("0xB0: 0x%08x (FDOC)\n",
mmio_readl(spibar + 0xB0));
if (tmp2 & (1 << 15)) {
diff --git a/flash.h b/flash.h
index a201af3..ec7dd8e 100644
--- a/flash.h
+++ b/flash.h
@@ -663,6 +663,8 @@ int default_spi_send_multicommand(struct spi_command *cmds);
uint32_t spi_get_valid_read_addr(void);
/* ichspi.c */
+extern int ichspi_lock;
+extern uint32_t ichspi_bbar;
int ich_init_opcodes(void);
int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
diff --git a/ichspi.c b/ichspi.c
index e9a3611..76a61d2 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -103,6 +103,8 @@
/* ICH SPI configuration lock-down. May be set during chipset enabling. */
int ichspi_lock = 0;
+uint32_t ichspi_bbar = 0;
+
typedef struct _OPCODE {
uint8_t opcode; //This commands spi opcode
uint8_t spi_type; //This commands spi type
@@ -327,6 +329,34 @@ int program_opcodes(OPCODES * op)
return 0;
}
+/*
+ * Try to set BBAR (BIOS Base Address Register), but read back the value in case
+ * it didn't stick.
+ */
+void ich_set_bbar(uint32_t minaddr)
+{
+ switch (spi_controller) {
+ case SPI_CONTROLLER_ICH7:
+ mmio_writel(minaddr, spibar + 0x50);
+ ichspi_bbar = mmio_readl(spibar + 0x50);
+ /* We don't have any option except complaining. */
+ if (ichspi_bbar != minaddr)
+ msg_perr("Setting BBAR failed!\n");
+ break;
+ case SPI_CONTROLLER_ICH9:
+ mmio_writel(minaddr, spibar + 0xA0);
+ ichspi_bbar = mmio_readl(spibar + 0xA0);
+ /* We don't have any option except complaining. */
+ if (ichspi_bbar != minaddr)
+ msg_perr("Setting BBAR failed!\n");
+ break;
+ default:
+ /* Not sure if BBAR actually exists on VIA. */
+ msg_pdbg("Setting BBAR is not implemented for VIA yet.\n");
+ break;
+ }
+}
+
/* This function generates OPCODES from or programs OPCODES to ICH according to
* the chipset's SPI configuration lock.
*
@@ -341,13 +371,18 @@ int ich_init_opcodes(void)
return 0;
if (ichspi_lock) {
- msg_pdbg("Generating OPCODES... ");
+ msg_pdbg("Reading OPCODES... ");
curopcodes_done = &O_EXISTING;
rc = generate_opcodes(curopcodes_done);
} else {
msg_pdbg("Programming OPCODES... ");
curopcodes_done = &O_ST_M25P;
rc = program_opcodes(curopcodes_done);
+ /* Technically not part of opcode init, but it allows opcodes
+ * to run without transaction errors by setting the lowest
+ * allowed address to zero.
+ */
+ ich_set_bbar(0);
}
if (rc) {
@@ -743,6 +778,19 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
addr = (writearr[1] << 16) |
(writearr[2] << 8) | (writearr[3] << 0);
+ switch (spi_controller) {
+ case SPI_CONTROLLER_ICH7:
+ case SPI_CONTROLLER_ICH9:
+ if (addr < ichspi_bbar) {
+ msg_perr("%s: Address 0x%06x below allowed "
+ "range 0x%06x-0xffffff\n", __func__,
+ addr, ichspi_bbar);
+ return SPI_INVALID_ADDRESS;
+ }
+ break;
+ default:
+ break;
+ }
}
/* translate read/write array/count */
diff --git a/spi.c b/spi.c
index 24696fb..0d501c0 100644
--- a/spi.c
+++ b/spi.c
@@ -207,8 +207,22 @@ int spi_chip_write_256(struct flashchip *flash, uint8_t *buf)
return spi_programmer[spi_controller].write_256(flash, buf);
}
+/*
+ * Get the lowest allowed address for read accesses. This often happens to
+ * be the lowest allowed address for all commands which take an address.
+ * This is a programmer limitation.
+ */
uint32_t spi_get_valid_read_addr(void)
{
- /* Need to return BBAR for ICH chipsets. */
- return 0;
+ switch (spi_controller) {
+#if INTERNAL_SUPPORT == 1
+#if defined(__i386__) || defined(__x86_64__)
+ case SPI_CONTROLLER_ICH7:
+ /* Return BBAR for ICH chipsets. */
+ return ichspi_bbar;
+#endif
+#endif
+ default:
+ return 0;
+ }
}
OpenPOWER on IntegriCloud