Nico Huber has uploaded a new change for review. ( https://review.coreboot.org/18938 )
Change subject: fixup! flashrom: Add Skylake platform support ......................................................................
fixup! flashrom: Add Skylake platform support
ichspi: Abstract over swseq register offsets and consolidate init.
SSFS/C register offset is guessed.
Change-Id: I0ad46f7944d92d3381975c5e10af0918ec163782 Signed-off-by: Nico Huber nico.huber@secunet.com --- M ichspi.c 1 file changed, 64 insertions(+), 160 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/38/18938/1
diff --git a/ichspi.c b/ichspi.c index 3b7e5d8..413d97c 100644 --- a/ichspi.c +++ b/ichspi.c @@ -50,9 +50,10 @@
#define PCH100_REG_FPR0 0x84 /* 32 Bytes Protected Range 0 */
-#define PCH100_REG_PREOP_OPTYPE 0xA4 /* 32 Bits */ -#define PCH100_REG_OPMENU_LOWER 0xA8 /* 32 Bits */ -#define PCH100_REG_OPMENU_UPPER 0xAC /* 32 Bits */ +#define PCH100_REG_SSFSC 0xA0 /* 32 Bits Status (8) + Control (24) */ +#define PCH100_REG_PREOP 0xA4 /* 16 Bits */ +#define PCH100_REG_OPTYPE 0xA6 /* 16 Bits */ +#define PCH100_REG_OPMENU 0xA8 /* 64 Bits */
/* ICH9 controller register definition */ #define ICH9_REG_HSFS 0x04 /* 16 Bits Hardware Sequencing Flash Status */ @@ -392,6 +393,13 @@ pprint_reg(SSFC, SCF, reg_val, "\n"); }
+static struct { + size_t reg_ssfsc; + size_t reg_preop; + size_t reg_optype; + size_t reg_opmenu; +} swseq_data; + static uint8_t lookup_spi_type(uint8_t opcode) { int a; @@ -495,18 +503,12 @@ opmenu[0] = REGREAD32(ICH7_REG_OPMENU); opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4); break; - case CHIPSET_100_SERIES_SUNRISE_POINT: - preop = REGREAD16(PCH100_REG_PREOP_OPTYPE); - optype = REGREAD16(PCH100_REG_PREOP_OPTYPE + 2); - opmenu[0] = REGREAD32(PCH100_REG_OPMENU_LOWER); - opmenu[1] = REGREAD32(PCH100_REG_OPMENU_UPPER); - break; case CHIPSET_ICH8: default: /* Future version might behave the same */ - preop = REGREAD16(ICH9_REG_PREOP); - optype = REGREAD16(ICH9_REG_OPTYPE); - opmenu[0] = REGREAD32(ICH9_REG_OPMENU); - opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4); + preop = REGREAD16(swseq_data.reg_preop); + optype = REGREAD16(swseq_data.reg_optype); + opmenu[0] = REGREAD32(swseq_data.reg_opmenu); + opmenu[1] = REGREAD32(swseq_data.reg_opmenu + 4); break; }
@@ -582,32 +584,19 @@ mmio_writel(opmenu[0], ich_spibar + ICH7_REG_OPMENU); mmio_writel(opmenu[1], ich_spibar + ICH7_REG_OPMENU + 4); break; - case CHIPSET_100_SERIES_SUNRISE_POINT: - /* Register undo only for enable_undo=1, i.e. first call. */ - if (enable_undo) { - rmmio_valw(ich_spibar + PCH100_REG_PREOP_OPTYPE); - rmmio_valw(ich_spibar + PCH100_REG_PREOP_OPTYPE + 2); - rmmio_vall(ich_spibar + PCH100_REG_OPMENU_LOWER); - rmmio_vall(ich_spibar + PCH100_REG_OPMENU_UPPER); - } - mmio_writew(preop, ich_spibar + PCH100_REG_PREOP_OPTYPE); - mmio_writew(optype, ich_spibar + PCH100_REG_PREOP_OPTYPE + 2); - mmio_writel(opmenu[0], ich_spibar + PCH100_REG_OPMENU_LOWER); - mmio_writel(opmenu[1], ich_spibar + PCH100_REG_OPMENU_UPPER); - break; case CHIPSET_ICH8: default: /* Future version might behave the same */ /* Register undo only for enable_undo=1, i.e. first call. */ if (enable_undo) { - rmmio_valw(ich_spibar + ICH9_REG_PREOP); - rmmio_valw(ich_spibar + ICH9_REG_OPTYPE); - rmmio_vall(ich_spibar + ICH9_REG_OPMENU); - rmmio_vall(ich_spibar + ICH9_REG_OPMENU + 4); + rmmio_valw(ich_spibar + swseq_data.reg_preop); + rmmio_valw(ich_spibar + swseq_data.reg_optype); + rmmio_vall(ich_spibar + swseq_data.reg_opmenu); + rmmio_vall(ich_spibar + swseq_data.reg_opmenu + 4); } - mmio_writew(preop, ich_spibar + ICH9_REG_PREOP); - mmio_writew(optype, ich_spibar + ICH9_REG_OPTYPE); - mmio_writel(opmenu[0], ich_spibar + ICH9_REG_OPMENU); - mmio_writel(opmenu[1], ich_spibar + ICH9_REG_OPMENU + 4); + mmio_writew(preop, ich_spibar + swseq_data.reg_preop); + mmio_writew(optype, ich_spibar + swseq_data.reg_optype); + mmio_writel(opmenu[0], ich_spibar + swseq_data.reg_opmenu); + mmio_writel(opmenu[1], ich_spibar + swseq_data.reg_opmenu + 4); break; }
@@ -894,7 +883,7 @@ }
timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */ - while ((REGREAD8(ICH9_REG_SSFS) & SSFS_SCIP) && --timeout) { + while ((REGREAD8(swseq_data.reg_ssfsc) & SSFS_SCIP) && --timeout) { programmer_delay(10); } if (!timeout) { @@ -912,12 +901,12 @@ ich_fill_data(data, datalength, ICH9_REG_FDATA0);
/* Assemble SSFS + SSFC */ - temp32 = REGREAD32(ICH9_REG_SSFS); + temp32 = REGREAD32(swseq_data.reg_ssfsc); /* Keep reserved bits only */ temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK; /* Clear cycle done and cycle error status registers */ temp32 |= (SSFS_FDONE | SSFS_FCERR); - REGWRITE32(ICH9_REG_SSFS, temp32); + REGWRITE32(swseq_data.reg_ssfsc, temp32);
/* Use 20 MHz */ temp32 |= SSFC_SCF_20MHZ; @@ -971,21 +960,21 @@ temp32 |= SSFC_SCGO;
/* write it */ - REGWRITE32(ICH9_REG_SSFS, temp32); + REGWRITE32(swseq_data.reg_ssfsc, temp32);
/* Wait for Cycle Done Status or Flash Cycle Error. */ - while (((REGREAD32(ICH9_REG_SSFS) & (SSFS_FDONE | SSFS_FCERR)) == 0) && + while (((REGREAD32(swseq_data.reg_ssfsc) & (SSFS_FDONE | SSFS_FCERR)) == 0) && --timeout) { programmer_delay(10); } if (!timeout) { - msg_perr("timeout, ICH9_REG_SSFS=0x%08x\n", - REGREAD32(ICH9_REG_SSFS)); + msg_perr("timeout, REG_SSFS=0x%08x\n", + REGREAD32(swseq_data.reg_ssfsc)); return 1; }
/* FIXME make sure we do not needlessly cause transaction errors. */ - temp32 = REGREAD32(ICH9_REG_SSFS); + temp32 = REGREAD32(swseq_data.reg_ssfsc); if (temp32 & SSFS_FCERR) { msg_perr("Transaction error!\n"); prettyprint_ich9_reg_ssfs(temp32); @@ -993,7 +982,7 @@ /* keep reserved bits */ temp32 &= SSFS_RESERVED_MASK | SSFC_RESERVED_MASK; /* Clear the transaction error. */ - REGWRITE32(ICH9_REG_SSFS, temp32 | SSFS_FCERR); + REGWRITE32(swseq_data.reg_ssfsc, temp32 | SSFS_FCERR); return 1; }
@@ -1644,6 +1633,25 @@ ich_generation = ich_gen; ich_spibar = spibar;
+ /* Moving registers / bits */ + if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) { + swseq_data.reg_ssfsc = PCH100_REG_SSFSC; + swseq_data.reg_preop = PCH100_REG_PREOP; + swseq_data.reg_optype = PCH100_REG_OPTYPE; + swseq_data.reg_opmenu = PCH100_REG_OPMENU; + hwseq_data.addr_mask = PCH100_FADDR_FLA; + hwseq_data.only_4k = true; + hwseq_data.hsfc_fcycle = PCH100_HSFC_FCYCLE; + } else { + swseq_data.reg_ssfsc = ICH9_REG_SSFS; + swseq_data.reg_preop = ICH9_REG_PREOP; + swseq_data.reg_optype = ICH9_REG_OPTYPE; + swseq_data.reg_opmenu = ICH9_REG_OPMENU; + hwseq_data.addr_mask = ICH9_FADDR_FLA; + hwseq_data.only_4k = false; + hwseq_data.hsfc_fcycle = HSFC_FCYCLE; + } + switch (ich_generation) { case CHIPSET_ICH7: case CHIPSET_TUNNEL_CREEK: @@ -1679,112 +1687,8 @@ ich_set_bbar(0); register_spi_master(&spi_master_ich7); break; - case CHIPSET_100_SERIES_SUNRISE_POINT: - hwseq_data.addr_mask = PCH100_FADDR_FLA; - hwseq_data.only_4k = true; - hwseq_data.hsfc_fcycle = PCH100_HSFC_FCYCLE; - - arg = extract_programmer_param("ich_spi_mode"); - if (arg && !strcmp(arg, "hwseq")) { - ich_spi_mode = ich_hwseq; - msg_pspew("user selected hwseq\n"); - } else if (arg && !strcmp(arg, "swseq")) { - ich_spi_mode = ich_swseq; - msg_pspew("user selected swseq\n"); - } else if (arg && !strcmp(arg, "auto")) { - msg_pspew("user selected auto\n"); - ich_spi_mode = ich_auto; - } else if (arg && !strlen(arg)) { - msg_perr("Missing argument for ich_spi_mode.\n"); - free(arg); - return ERROR_FATAL; - } else if (arg) { - msg_perr("Unknown argument for ich_spi_mode: %s\n", - arg); - free(arg); - return ERROR_FATAL; - } - free(arg); - tmp = mmio_readl(ich_spibar + ICH9_REG_HSFS); - msg_pdbg("0x04: 0x%04x (HSFSC)\n", tmp); - if (tmp & HSFS_FLOCKDN) { - msg_perr("WARNING: SPI Configuration " - "Lockdown activated.\n"); - ichspi_lock = 1; - } - if (tmp & HSFS_FDV) - desc_valid = 1; - - if (!(tmp & HSFS_FDOPSS) && desc_valid) - msg_perr("The Flash Descriptor Security Override " - "Strap-Pin is set. Restrictions implied\n" - "by the FRAP and FREG registers are NOT in " - "effect. Please note that Protected\n" - "Range (PR) restrictions still apply.\n"); - ich_init_opcodes(); - - tmp = mmio_readl(ich_spibar + ICH9_REG_FADDR); - msg_pdbg("0x08: 0x%08x (FADDR)\n", tmp); - if (desc_valid) { - tmp = mmio_readl(ich_spibar + ICH9_REG_FRAP); - msg_cdbg("0x50: 0x%08x (FRAP)\n", tmp); - msg_cdbg("BMWAG 0x%02x, ", ICH_BMWAG(tmp)); - msg_cdbg("BMRAG 0x%02x, ", ICH_BMRAG(tmp)); - msg_cdbg("BRWA 0x%02x, ", ICH_BRWA(tmp)); - msg_cdbg("BRRA 0x%02x\n", ICH_BRRA(tmp)); - - /* Decode and print FREGx and FRAP registers */ - for (i = 0; i < 5; i++) - ich9_handle_frap(tmp, i); - } - /* try to disable PR locks before printing them */ - if (!ichspi_lock) - for (i = 0; i < 5; i++) - ich9_set_pr(i, 0, 0, ich_generation); - for (i = 0; i < 5; i++) - ich9_handle_pr(i, ich_generation); - if (desc_valid) { - if (read_ich_descriptors_via_fdo(ich_gen, ich_spibar, &desc) == ICH_RET_OK) - prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN, - &desc); - /* If the descriptor is valid and indicates multiple - * flash devices we need to use hwseq to be able to - * access the second flash device. - */ - if (ich_spi_mode == ich_auto && desc.content.NC != 0) { - msg_pinfo("Enabling hardware sequencing due to " - "multiple flash chips detected.\n"); - ich_spi_mode = ich_hwseq; - } - } - - if (ich_spi_mode == ich_auto && ichspi_lock && - ich_missing_opcodes()) { - msg_pinfo("Enabling hardware sequencing because " - "some important opcode is locked.\n"); - ich_spi_mode = ich_hwseq; - } - - if (ich_spi_mode == ich_hwseq) { - if (!desc_valid) { - msg_perr("Hardware sequencing was requested " - "but the flash descriptor is not " - "valid. Aborting.\n"); - return ERROR_FATAL; - } - hwseq_data.size_comp0 = getFCBA_component_density(ich_gen, &desc, 0); - hwseq_data.size_comp1 = getFCBA_component_density(ich_gen, &desc, 1); - register_opaque_master(&opaque_master_ich_hwseq); - } else { - register_spi_master(&spi_master_ich9); - } - break; case CHIPSET_ICH8: default: /* Future version might behave the same */ - hwseq_data.addr_mask = ICH9_FADDR_FLA; - hwseq_data.only_4k = false; - hwseq_data.hsfc_fcycle = HSFC_FCYCLE; - arg = extract_programmer_param("ich_spi_mode"); if (arg && !strcmp(arg, "hwseq")) { ich_spi_mode = ich_hwseq; @@ -1884,30 +1788,30 @@ msg_pinfo("Continuing with write support because the user forced us to!\n"); }
- tmp = mmio_readl(ich_spibar + ICH9_REG_SSFS); - msg_pdbg("0x90: 0x%02x (SSFS)\n", tmp & 0xff); + tmp = mmio_readl(ich_spibar + swseq_data.reg_ssfsc); + msg_pdbg("0x%zx: 0x%02x (SSFS)\n", swseq_data.reg_ssfsc, tmp & 0xff); prettyprint_ich9_reg_ssfs(tmp); if (tmp & SSFS_FCERR) { msg_pdbg("Clearing SSFS.FCERR\n"); - mmio_writeb(SSFS_FCERR, ich_spibar + ICH9_REG_SSFS); + mmio_writeb(SSFS_FCERR, ich_spibar + swseq_data.reg_ssfsc); } - msg_pdbg("0x91: 0x%06x (SSFC)\n", tmp >> 8); + msg_pdbg("0x%zx: 0x%06x (SSFC)\n", swseq_data.reg_ssfsc + 1, tmp >> 8); prettyprint_ich9_reg_ssfc(tmp);
- msg_pdbg("0x94: 0x%04x (PREOP)\n", - mmio_readw(ich_spibar + ICH9_REG_PREOP)); - msg_pdbg("0x96: 0x%04x (OPTYPE)\n", - mmio_readw(ich_spibar + ICH9_REG_OPTYPE)); - msg_pdbg("0x98: 0x%08x (OPMENU)\n", - mmio_readl(ich_spibar + ICH9_REG_OPMENU)); - msg_pdbg("0x9C: 0x%08x (OPMENU+4)\n", - mmio_readl(ich_spibar + ICH9_REG_OPMENU + 4)); + msg_pdbg("0x%zx: 0x%04x (PREOP)\n", + swseq_data.reg_preop, mmio_readw(ich_spibar + swseq_data.reg_preop)); + msg_pdbg("0x%zx: 0x%04x (OPTYPE)\n", + swseq_data.reg_optype, mmio_readw(ich_spibar + swseq_data.reg_optype)); + msg_pdbg("0x%zx: 0x%08x (OPMENU)\n", + swseq_data.reg_opmenu, mmio_readl(ich_spibar + swseq_data.reg_opmenu)); + msg_pdbg("0x%zx: 0x%08x (OPMENU+4)\n", + swseq_data.reg_opmenu + 4, mmio_readl(ich_spibar + swseq_data.reg_opmenu + 4)); if (ich_generation == CHIPSET_ICH8 && desc_valid) { tmp = mmio_readl(ich_spibar + ICH8_REG_VSCC); msg_pdbg("0xC1: 0x%08x (VSCC)\n", tmp); msg_pdbg("VSCC: "); prettyprint_ich_reg_vscc(tmp, MSG_DEBUG, true); - } else { + } else if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) { if (ich_generation != CHIPSET_BAYTRAIL && desc_valid) { ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR); msg_pdbg("0xA0: 0x%08x (BBAR)\n",