summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chipset_enable.c218
-rw-r--r--flash.h9
-rw-r--r--ichspi.c213
3 files changed, 234 insertions, 206 deletions
diff --git a/chipset_enable.c b/chipset_enable.c
index dc0e55f52..bb18b4d65 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -417,69 +417,15 @@ static int enable_flash_poulsbo(struct pci_dev *dev, const char *name)
static int enable_flash_vt8237s_spi(struct pci_dev *dev, const char *name)
{
- uint32_t mmio_base;
-
/* Do we really need no write enable? */
- mmio_base = (pci_read_long(dev, 0xbc)) << 8;
- msg_pdbg("MMIO base at = 0x%x\n", mmio_base);
- ich_spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);
-
- msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n",
- mmio_readw(ich_spibar + 0x6c));
-
- /* Not sure if it speaks all these bus protocols. */
- buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
- spi_controller = SPI_CONTROLLER_VIA;
- ich_init_opcodes();
-
- return 0;
-}
-
-#define ICH_BMWAG(x) ((x >> 24) & 0xff)
-#define ICH_BMRAG(x) ((x >> 16) & 0xff)
-#define ICH_BRWA(x) ((x >> 8) & 0xff)
-#define ICH_BRRA(x) ((x >> 0) & 0xff)
-
-#define ICH_FREG_BASE(x) ((x >> 0) & 0x1fff)
-#define ICH_FREG_LIMIT(x) ((x >> 16) & 0x1fff)
-
-static void do_ich9_spi_frap(uint32_t frap, int i)
-{
- const char *access_names[4] = {
- "locked", "read-only", "write-only", "read-write"
- };
- const char *region_names[5] = {
- "Flash Descriptor", "BIOS", "Management Engine",
- "Gigabit Ethernet", "Platform Data"
- };
- uint32_t base, limit;
- int rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) |
- (((ICH_BRRA(frap) >> i) & 1) << 0);
- int offset = 0x54 + i * 4;
- uint32_t freg = mmio_readl(ich_spibar + offset);
-
- msg_pdbg("0x%02X: 0x%08x (FREG%i: %s)\n",
- offset, freg, i, region_names[i]);
-
- base = ICH_FREG_BASE(freg);
- limit = ICH_FREG_LIMIT(freg);
- if (base == 0x1fff && limit == 0) {
- /* this FREG is disabled */
- msg_pdbg("%s region is unused.\n", region_names[i]);
- return;
- }
-
- msg_pdbg("0x%08x-0x%08x is %s\n",
- (base << 12), (limit << 12) | 0x0fff,
- access_names[rwperms]);
+ return via_init_spi(dev);
}
static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
int ich_generation)
{
- int ret, i;
- uint8_t old, new, bbs, buc;
- uint16_t spibar_offset, tmp2;
+ int ret;
+ uint8_t bbs, buc;
uint32_t tmp, gcs;
void *rcrb;
//TODO: These names are incorrect for EP80579. For that, the solution would look like the commented line
@@ -512,152 +458,22 @@ static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
* on ICH7 when the southbridge is strapped to LPC
*/
- if (ich_generation == 7 && bbs == ICH_STRAP_LPC) {
- buses_supported = CHIP_BUSTYPE_FWH;
- /* No further SPI initialization required */
- return ret;
- }
-
- switch (ich_generation) {
- case 7:
- buses_supported = CHIP_BUSTYPE_SPI;
- spi_controller = SPI_CONTROLLER_ICH7;
- spibar_offset = 0x3020;
- break;
- case 8:
- buses_supported = CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
- spi_controller = SPI_CONTROLLER_ICH9;
- spibar_offset = 0x3020;
- break;
- case 9:
- case 10:
- default: /* Future version might behave the same */
- buses_supported = CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
- spi_controller = SPI_CONTROLLER_ICH9;
- spibar_offset = 0x3800;
- break;
- }
-
- /* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */
- msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", tmp, spibar_offset);
-
- /* Assign Virtual Address */
- ich_spibar = rcrb + spibar_offset;
-
- switch (spi_controller) {
- case SPI_CONTROLLER_ICH7:
- msg_pdbg("0x00: 0x%04x (SPIS)\n",
- mmio_readw(ich_spibar + 0));
- msg_pdbg("0x02: 0x%04x (SPIC)\n",
- mmio_readw(ich_spibar + 2));
- msg_pdbg("0x04: 0x%08x (SPIA)\n",
- mmio_readl(ich_spibar + 4));
- for (i = 0; i < 8; i++) {
- int offs;
- offs = 8 + (i * 8);
- msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
- mmio_readl(ich_spibar + offs), i);
- msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
- mmio_readl(ich_spibar + offs + 4), i);
- }
- ichspi_bbar = mmio_readl(ich_spibar + 0x50);
- msg_pdbg("0x50: 0x%08x (BBAR)\n",
- ichspi_bbar);
- msg_pdbg("0x54: 0x%04x (PREOP)\n",
- mmio_readw(ich_spibar + 0x54));
- msg_pdbg("0x56: 0x%04x (OPTYPE)\n",
- mmio_readw(ich_spibar + 0x56));
- msg_pdbg("0x58: 0x%08x (OPMENU)\n",
- mmio_readl(ich_spibar + 0x58));
- msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n",
- mmio_readl(ich_spibar + 0x5c));
- for (i = 0; i < 4; i++) {
- int offs;
- offs = 0x60 + (i * 4);
- msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,
- mmio_readl(ich_spibar + offs), i);
- }
- msg_pdbg("\n");
- if (mmio_readw(ich_spibar) & (1 << 15)) {
- msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
- ichspi_lock = 1;
- }
- ich_init_opcodes();
- break;
- case SPI_CONTROLLER_ICH9:
- tmp2 = mmio_readw(ich_spibar + 4);
- msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2);
- msg_pdbg("FLOCKDN %i, ", (tmp2 >> 15 & 1));
- msg_pdbg("FDV %i, ", (tmp2 >> 14) & 1);
- msg_pdbg("FDOPSS %i, ", (tmp2 >> 13) & 1);
- msg_pdbg("SCIP %i, ", (tmp2 >> 5) & 1);
- msg_pdbg("BERASE %i, ", (tmp2 >> 3) & 3);
- msg_pdbg("AEL %i, ", (tmp2 >> 2) & 1);
- msg_pdbg("FCERR %i, ", (tmp2 >> 1) & 1);
- msg_pdbg("FDONE %i\n", (tmp2 >> 0) & 1);
-
- tmp = mmio_readl(ich_spibar + 0x50);
- msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);
- msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp));
- msg_pdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp));
- msg_pdbg("BRWA 0x%02x, ", ICH_BRWA(tmp));
- msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));
-
- /* print out the FREGx registers along with FRAP access bits */
- for(i = 0; i < 5; i++)
- do_ich9_spi_frap(tmp, i);
-
- msg_pdbg("0x74: 0x%08x (PR0)\n",
- mmio_readl(ich_spibar + 0x74));
- msg_pdbg("0x78: 0x%08x (PR1)\n",
- mmio_readl(ich_spibar + 0x78));
- msg_pdbg("0x7C: 0x%08x (PR2)\n",
- mmio_readl(ich_spibar + 0x7C));
- msg_pdbg("0x80: 0x%08x (PR3)\n",
- mmio_readl(ich_spibar + 0x80));
- msg_pdbg("0x84: 0x%08x (PR4)\n",
- mmio_readl(ich_spibar + 0x84));
- msg_pdbg("0x90: 0x%08x (SSFS, SSFC)\n",
- mmio_readl(ich_spibar + 0x90));
- msg_pdbg("0x94: 0x%04x (PREOP)\n",
- mmio_readw(ich_spibar + 0x94));
- msg_pdbg("0x96: 0x%04x (OPTYPE)\n",
- mmio_readw(ich_spibar + 0x96));
- msg_pdbg("0x98: 0x%08x (OPMENU)\n",
- mmio_readl(ich_spibar + 0x98));
- msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",
- mmio_readl(ich_spibar + 0x9C));
- ichspi_bbar = mmio_readl(ich_spibar + 0xA0);
- msg_pdbg("0xA0: 0x%08x (BBAR)\n",
- ichspi_bbar);
- msg_pdbg("0xB0: 0x%08x (FDOC)\n",
- mmio_readl(ich_spibar + 0xB0));
- if (tmp2 & (1 << 15)) {
- msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
- ichspi_lock = 1;
+ buses_supported = CHIP_BUSTYPE_FWH;
+ if (ich_generation == 7) {
+ if(bbs == ICH_STRAP_LPC) {
+ /* No further SPI initialization required */
+ return ret;
}
- ich_init_opcodes();
- break;
- default:
- /* Nothing */
- break;
+ else
+ /* Disable LPC/FWH if strapped to PCI or SPI */
+ buses_supported = 0;
}
- old = pci_read_byte(dev, 0xdc);
- msg_pdbg("SPI Read Configuration: ");
- new = (old >> 2) & 0x3;
- switch (new) {
- case 0:
- case 1:
- case 2:
- msg_pdbg("prefetching %sabled, caching %sabled, ",
- (new & 0x2) ? "en" : "dis",
- (new & 0x1) ? "dis" : "en");
- break;
- default:
- msg_pdbg("invalid prefetching/caching settings, ");
- break;
- }
+ /* this adds CHIP_BUSTYPE_SPI */
+ if (ich_init_spi(dev, tmp, rcrb, ich_generation) != 0) {
+ if (!ret)
+ ret = ERROR_NONFATAL;
+ }
return ret;
}
@@ -1546,6 +1362,8 @@ int chipset_flash_enable(void)
msg_pinfo("FAILED!\n");
else if(ret == 0)
msg_pinfo("OK.\n");
+ else if(ret == ERROR_NONFATAL)
+ msg_pinfo("PROBLEMS, continuing anyway\n");
}
msg_pinfo("This chipset supports the following protocols: %s.\n",
diff --git a/flash.h b/flash.h
index ca3f6f547..1cf333aca 100644
--- a/flash.h
+++ b/flash.h
@@ -607,6 +607,9 @@ int doit(struct flashchip *flash, int force, char *filename, int read_it, int wr
#define OK 0
#define NT 1 /* Not tested */
+/* Something happened that shouldn't happen, but we can go on */
+#define ERROR_NONFATAL 0x100
+
/* cli_output.c */
/* Let gcc and clang check for correct printf-style format strings. */
int print(int type, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
@@ -694,10 +697,10 @@ 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;
-extern void *ich_spibar;
-int ich_init_opcodes(void);
+int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
+ int ich_generation);
+int via_init_spi(struct pci_dev *dev);
int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
int ich_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
diff --git a/ichspi.c b/ichspi.c
index d6f9118e1..88e993d45 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -101,11 +101,11 @@
#define ICH7_REG_OPMENU 0x58 /* 64 Bits */
/* ICH SPI configuration lock-down. May be set during chipset enabling. */
-int ichspi_lock = 0;
+static int ichspi_lock = 0;
uint32_t ichspi_bbar = 0;
-void *ich_spibar = NULL;
+static void *ich_spibar = NULL;
typedef struct _OPCODE {
uint8_t opcode; //This commands spi opcode
@@ -364,7 +364,7 @@ void ich_set_bbar(uint32_t minaddr)
*
* It should be called before ICH sends any spi command.
*/
-int ich_init_opcodes(void)
+static int ich_init_opcodes(void)
{
int rc = 0;
OPCODES *curopcodes_done;
@@ -863,4 +863,211 @@ int ich_spi_send_multicommand(struct spi_command *cmds)
return ret;
}
+#define ICH_BMWAG(x) ((x >> 24) & 0xff)
+#define ICH_BMRAG(x) ((x >> 16) & 0xff)
+#define ICH_BRWA(x) ((x >> 8) & 0xff)
+#define ICH_BRRA(x) ((x >> 0) & 0xff)
+
+#define ICH_FREG_BASE(x) ((x >> 0) & 0x1fff)
+#define ICH_FREG_LIMIT(x) ((x >> 16) & 0x1fff)
+
+static void do_ich9_spi_frap(uint32_t frap, int i)
+{
+ const char *access_names[4] = {
+ "locked", "read-only", "write-only", "read-write"
+ };
+ const char *region_names[5] = {
+ "Flash Descriptor", "BIOS", "Management Engine",
+ "Gigabit Ethernet", "Platform Data"
+ };
+ uint32_t base, limit;
+ int rwperms = (((ICH_BRWA(frap) >> i) & 1) << 1) |
+ (((ICH_BRRA(frap) >> i) & 1) << 0);
+ int offset = 0x54 + i * 4;
+ uint32_t freg = mmio_readl(ich_spibar + offset);
+
+ msg_pdbg("0x%02X: 0x%08x (FREG%i: %s)\n",
+ offset, freg, i, region_names[i]);
+
+ base = ICH_FREG_BASE(freg);
+ limit = ICH_FREG_LIMIT(freg);
+ if (base == 0x1fff && limit == 0) {
+ /* this FREG is disabled */
+ msg_pdbg("%s region is unused.\n", region_names[i]);
+ return;
+ }
+
+ msg_pdbg("0x%08x-0x%08x is %s\n",
+ (base << 12), (limit << 12) | 0x0fff,
+ access_names[rwperms]);
+}
+
+int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
+ int ich_generation)
+{
+ int i;
+ uint8_t old, new;
+ uint16_t spibar_offset, tmp2;
+ uint32_t tmp;
+
+ buses_supported |= CHIP_BUSTYPE_SPI;
+ switch (ich_generation) {
+ case 7:
+ spi_controller = SPI_CONTROLLER_ICH7;
+ spibar_offset = 0x3020;
+ break;
+ case 8:
+ spi_controller = SPI_CONTROLLER_ICH9;
+ spibar_offset = 0x3020;
+ break;
+ case 9:
+ case 10:
+ default: /* Future version might behave the same */
+ spi_controller = SPI_CONTROLLER_ICH9;
+ spibar_offset = 0x3800;
+ break;
+ }
+
+ /* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */
+ msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", base, spibar_offset);
+
+ /* Assign Virtual Address */
+ ich_spibar = rcrb + spibar_offset;
+
+ switch (spi_controller) {
+ case SPI_CONTROLLER_ICH7:
+ msg_pdbg("0x00: 0x%04x (SPIS)\n",
+ mmio_readw(ich_spibar + 0));
+ msg_pdbg("0x02: 0x%04x (SPIC)\n",
+ mmio_readw(ich_spibar + 2));
+ msg_pdbg("0x04: 0x%08x (SPIA)\n",
+ mmio_readl(ich_spibar + 4));
+ for (i = 0; i < 8; i++) {
+ int offs;
+ offs = 8 + (i * 8);
+ msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
+ mmio_readl(ich_spibar + offs), i);
+ msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
+ mmio_readl(ich_spibar + offs + 4), i);
+ }
+ ichspi_bbar = mmio_readl(ich_spibar + 0x50);
+ msg_pdbg("0x50: 0x%08x (BBAR)\n",
+ ichspi_bbar);
+ msg_pdbg("0x54: 0x%04x (PREOP)\n",
+ mmio_readw(ich_spibar + 0x54));
+ msg_pdbg("0x56: 0x%04x (OPTYPE)\n",
+ mmio_readw(ich_spibar + 0x56));
+ msg_pdbg("0x58: 0x%08x (OPMENU)\n",
+ mmio_readl(ich_spibar + 0x58));
+ msg_pdbg("0x5c: 0x%08x (OPMENU+4)\n",
+ mmio_readl(ich_spibar + 0x5c));
+ for (i = 0; i < 4; i++) {
+ int offs;
+ offs = 0x60 + (i * 4);
+ msg_pdbg("0x%02x: 0x%08x (PBR%d)\n", offs,
+ mmio_readl(ich_spibar + offs), i);
+ }
+ msg_pdbg("\n");
+ if (mmio_readw(ich_spibar) & (1 << 15)) {
+ msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
+ ichspi_lock = 1;
+ }
+ ich_init_opcodes();
+ break;
+ case SPI_CONTROLLER_ICH9:
+ tmp2 = mmio_readw(ich_spibar + 4);
+ msg_pdbg("0x04: 0x%04x (HSFS)\n", tmp2);
+ msg_pdbg("FLOCKDN %i, ", (tmp2 >> 15 & 1));
+ msg_pdbg("FDV %i, ", (tmp2 >> 14) & 1);
+ msg_pdbg("FDOPSS %i, ", (tmp2 >> 13) & 1);
+ msg_pdbg("SCIP %i, ", (tmp2 >> 5) & 1);
+ msg_pdbg("BERASE %i, ", (tmp2 >> 3) & 3);
+ msg_pdbg("AEL %i, ", (tmp2 >> 2) & 1);
+ msg_pdbg("FCERR %i, ", (tmp2 >> 1) & 1);
+ msg_pdbg("FDONE %i\n", (tmp2 >> 0) & 1);
+
+ tmp = mmio_readl(ich_spibar + 0x50);
+ msg_pdbg("0x50: 0x%08x (FRAP)\n", tmp);
+ msg_pdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp));
+ msg_pdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp));
+ msg_pdbg("BRWA 0x%02x, ", ICH_BRWA(tmp));
+ msg_pdbg("BRRA 0x%02x\n", ICH_BRRA(tmp));
+
+ /* print out the FREGx registers along with FRAP access bits */
+ for(i = 0; i < 5; i++)
+ do_ich9_spi_frap(tmp, i);
+
+ msg_pdbg("0x74: 0x%08x (PR0)\n",
+ mmio_readl(ich_spibar + 0x74));
+ msg_pdbg("0x78: 0x%08x (PR1)\n",
+ mmio_readl(ich_spibar + 0x78));
+ msg_pdbg("0x7C: 0x%08x (PR2)\n",
+ mmio_readl(ich_spibar + 0x7C));
+ msg_pdbg("0x80: 0x%08x (PR3)\n",
+ mmio_readl(ich_spibar + 0x80));
+ msg_pdbg("0x84: 0x%08x (PR4)\n",
+ mmio_readl(ich_spibar + 0x84));
+ msg_pdbg("0x90: 0x%08x (SSFS, SSFC)\n",
+ mmio_readl(ich_spibar + 0x90));
+ msg_pdbg("0x94: 0x%04x (PREOP)\n",
+ mmio_readw(ich_spibar + 0x94));
+ msg_pdbg("0x96: 0x%04x (OPTYPE)\n",
+ mmio_readw(ich_spibar + 0x96));
+ msg_pdbg("0x98: 0x%08x (OPMENU)\n",
+ mmio_readl(ich_spibar + 0x98));
+ msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n",
+ mmio_readl(ich_spibar + 0x9C));
+ ichspi_bbar = mmio_readl(ich_spibar + 0xA0);
+ msg_pdbg("0xA0: 0x%08x (BBAR)\n",
+ ichspi_bbar);
+ msg_pdbg("0xB0: 0x%08x (FDOC)\n",
+ mmio_readl(ich_spibar + 0xB0));
+ if (tmp2 & (1 << 15)) {
+ msg_pinfo("WARNING: SPI Configuration Lockdown activated.\n");
+ ichspi_lock = 1;
+ }
+ ich_init_opcodes();
+ break;
+ default:
+ /* Nothing */
+ break;
+ }
+
+ old = pci_read_byte(dev, 0xdc);
+ msg_pdbg("SPI Read Configuration: ");
+ new = (old >> 2) & 0x3;
+ switch (new) {
+ case 0:
+ case 1:
+ case 2:
+ msg_pdbg("prefetching %sabled, caching %sabled, ",
+ (new & 0x2) ? "en" : "dis",
+ (new & 0x1) ? "dis" : "en");
+ break;
+ default:
+ msg_pdbg("invalid prefetching/caching settings, ");
+ break;
+ }
+ return 0;
+}
+
+int via_init_spi(struct pci_dev *dev)
+{
+ uint32_t mmio_base;
+
+ mmio_base = (pci_read_long(dev, 0xbc)) << 8;
+ msg_pdbg("MMIO base at = 0x%x\n", mmio_base);
+ ich_spibar = physmap("VT8237S MMIO registers", mmio_base, 0x70);
+
+ msg_pdbg("0x6c: 0x%04x (CLOCK/DEBUG)\n",
+ mmio_readw(ich_spibar + 0x6c));
+
+ /* Not sure if it speaks all these bus protocols. */
+ buses_supported = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH | CHIP_BUSTYPE_SPI;
+ spi_controller = SPI_CONTROLLER_VIA;
+ ich_init_opcodes();
+
+ return 0;
+}
+
#endif