diff options
author | David Hendricks <dhendricks@fb.com> | 2017-08-08 20:02:22 -0700 |
---|---|---|
committer | David Hendricks <david.hendricks@gmail.com> | 2017-09-01 20:34:44 +0000 |
commit | a5216367d5640f07d58a6549fa6df86d91daff1a (patch) | |
tree | 72cb2a7ba167ed6d6e0509ad8292ea7283932e7a | |
parent | aa91d5c16858cb400cc61e8a759838f645e3f314 (diff) | |
download | flashrom-a5216367d5640f07d58a6549fa6df86d91daff1a.tar.gz flashrom-a5216367d5640f07d58a6549fa6df86d91daff1a.tar.bz2 flashrom-a5216367d5640f07d58a6549fa6df86d91daff1a.zip |
chipset_enable: Add support for C620-series Lewisburg PCH
This adds PCI IDs for C620-series PCHs and adds
CHIPSET_C620_SERIES_LEWISBURG as a new entry in the ich_chipset enum.
Lewisburg is very similar to Sunrise Point for Flashrom's purposes,
however one important difference is the way the "number of masters" is
interpreted from the flash descriptor (0-based vs. 1-based). There are
also new flash regions defined.
Change-Id: I96c89bc28bdfcd953229c17679f2c28f8b874d0b
Signed-off-by: David Hendricks <dhendricks@fb.com>
Reviewed-on: https://review.coreboot.org/20922
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r-- | chipset_enable.c | 29 | ||||
-rw-r--r-- | ich_descriptors.c | 86 | ||||
-rw-r--r-- | ichspi.c | 27 | ||||
-rw-r--r-- | programmer.h | 1 | ||||
-rw-r--r-- | util/ich_descriptors_tool/ich_descriptors_tool.c | 4 |
5 files changed, 119 insertions, 28 deletions
diff --git a/chipset_enable.c b/chipset_enable.c index 36e2838f4..a3b7f8dd6 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -601,6 +601,7 @@ static void enable_flash_ich_report_gcs(struct pci_dev *const dev, const enum ic top_swap = (gcs & 2) >> 1; break; case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: reg_name = "BIOS_SPI_BC"; gcs = pci_read_long(dev, 0xdc); bild = (gcs >> 7) & 1; @@ -658,6 +659,7 @@ static void enable_flash_ich_report_gcs(struct pci_dev *const dev, const enum ic case CHIPSET_8_SERIES_LYNX_POINT_LP: case CHIPSET_9_SERIES_WILDCAT_POINT_LP: case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: straps_names = straps_names_pch8_lp; break; case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet @@ -681,6 +683,7 @@ static void enable_flash_ich_report_gcs(struct pci_dev *const dev, const enum ic bbs = (gcs >> 10) & 0x1; break; case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: bbs = (gcs >> 6) & 0x1; break; default: @@ -830,9 +833,8 @@ static int enable_flash_pch100_shutdown(void *const pci_acc) return 0; } -static int enable_flash_pch100(struct pci_dev *const dev, const char *const name) +static int enable_flash_pch100_or_c620(struct pci_dev *const dev, const char *const name, const enum ich_chipset pch_generation) { - const enum ich_chipset pch_generation = CHIPSET_100_SERIES_SUNRISE_POINT; int ret = ERROR_FATAL; /* @@ -888,6 +890,16 @@ _freepci_ret: return ret; } +static int enable_flash_pch100(struct pci_dev *const dev, const char *const name) +{ + return enable_flash_pch100_or_c620(dev, name, CHIPSET_100_SERIES_SUNRISE_POINT); +} + +static int enable_flash_c620(struct pci_dev *const dev, const char *const name) +{ + return enable_flash_pch100_or_c620(dev, name, CHIPSET_C620_SERIES_LEWISBURG); +} + /* Silvermont architecture: Bay Trail(-T/-I), Avoton/Rangeley. * These have a distinctly different behavior compared to other Intel chipsets and hence are handled separately. * @@ -1915,6 +1927,19 @@ const struct penable chipset_enables[] = { {0x8086, 0xa153, NT, "Intel", "QM175", enable_flash_pch100}, {0x8086, 0xa154, NT, "Intel", "CM238", enable_flash_pch100}, {0x8086, 0xa155, NT, "Intel", "QMU185", enable_flash_pch100}, + {0x8086, 0xa1c1, NT, "Intel", "C621 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa1c2, NT, "Intel", "C622 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa1c3, NT, "Intel", "C624 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa1c4, NT, "Intel", "C625 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa1c5, NT, "Intel", "C626 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa1c6, NT, "Intel", "C627 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa1c7, NT, "Intel", "C628 Series Chipset (QS/PRQ)", enable_flash_c620}, + {0x8086, 0xa242, NT, "Intel", "C624 Series Chipset Supersku", enable_flash_c620}, + {0x8086, 0xa243, NT, "Intel", "C627 Series Chipset Supersku", enable_flash_c620}, + {0x8086, 0xa244, NT, "Intel", "C621 Series Chipset Supersku", enable_flash_c620}, + {0x8086, 0xa245, NT, "Intel", "C627 Series Chipset Supersku", enable_flash_c620}, + {0x8086, 0xa246, NT, "Intel", "C628 Series Chipset Supersku", enable_flash_c620}, + {0x8086, 0xa247, NT, "Intel", "C620 Series Chipset Supersku", enable_flash_c620}, #endif {0}, }; diff --git a/ich_descriptors.c b/ich_descriptors.c index 791615286..69fcd75d3 100644 --- a/ich_descriptors.c +++ b/ich_descriptors.c @@ -46,6 +46,8 @@ ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont) { switch (cs) { + case CHIPSET_C620_SERIES_LEWISBURG: + return 16; case CHIPSET_100_SERIES_SUNRISE_POINT: return 10; case CHIPSET_9_SERIES_WILDCAT_POINT_LP: @@ -67,10 +69,16 @@ ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_c ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_content *const cont) { - if (cont->NM < MAX_NUM_MASTERS) - return cont->NM + 1; - else - return -1; + switch (cs) { + case CHIPSET_C620_SERIES_LEWISBURG: + if (cont->NM <= MAX_NUM_MASTERS) + return cont->NM; + default: + if (cont->NM < MAX_NUM_MASTERS) + return cont->NM + 1; + } + + return -1; } void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl) @@ -98,6 +106,7 @@ void prettyprint_ich_chipset(enum ich_chipset cs) "5 series Ibex Peak", "6 series Cougar Point", "7 series Panther Point", "8 series Lynx Point", "Baytrail", "8 series Lynx Point LP", "8 series Wellsburg", "9 series Wildcat Point", "9 series Wildcat Point LP", "100 series Sunrise Point", + "C620 series Lewisburg", }; if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names)) cs = 0; @@ -187,7 +196,8 @@ static const char *pprint_density(enum ich_chipset cs, const struct ich_descript case CHIPSET_8_SERIES_WELLSBURG: case CHIPSET_9_SERIES_WILDCAT_POINT: case CHIPSET_9_SERIES_WILDCAT_POINT_LP: - case CHIPSET_100_SERIES_SUNRISE_POINT: { + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: { uint8_t size_enc; if (idx == 0) { size_enc = desc->component.dens_new.comp1_density; @@ -243,6 +253,7 @@ static const char *pprint_freq(enum ich_chipset cs, uint8_t value) case CHIPSET_9_SERIES_WILDCAT_POINT_LP: return freq_str[0][value]; case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: return freq_str[1][value]; case CHIPSET_ICH_UNKNOWN: default: @@ -256,7 +267,7 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ msg_pdbg2("=== Component Section ===\n"); msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP); msg_pdbg2("FLILL 0x%08x\n", desc->component.FLILL ); - if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) + if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1); msg_pdbg2("\n"); @@ -276,10 +287,10 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ if (cs > CHIPSET_6_SERIES_COUGAR_POINT) msg_pdbg2("Dual Output Fast Read Support: %sabled\n", desc->component.modes.dual_output ? "dis" : "en"); - if (desc->component.FLILL == 0 && - (cs != CHIPSET_100_SERIES_SUNRISE_POINT || desc->component.FLILL1 == 0)) { - msg_pdbg2("No forbidden opcodes.\n"); - } else { + + int has_forbidden_opcode = 0; + if (desc->component.FLILL != 0) { + has_forbidden_opcode = 1; msg_pdbg2("Invalid instruction 0: 0x%02x\n", desc->component.invalid_instr0); msg_pdbg2("Invalid instruction 1: 0x%02x\n", @@ -288,7 +299,10 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ desc->component.invalid_instr2); msg_pdbg2("Invalid instruction 3: 0x%02x\n", desc->component.invalid_instr3); - if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) { + } + if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) { + if (desc->component.FLILL1 != 0) { + has_forbidden_opcode = 1; msg_pdbg2("Invalid instruction 4: 0x%02x\n", desc->component.invalid_instr4); msg_pdbg2("Invalid instruction 5: 0x%02x\n", @@ -299,14 +313,17 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ desc->component.invalid_instr7); } } + if (!has_forbidden_opcode) + msg_pdbg2("No forbidden opcodes.\n"); + msg_pdbg2("\n"); } static void pprint_freg(const struct ich_desc_region *reg, uint32_t i) { static const char *const region_names[] = { - "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "unknown", "unknown", - "EC", "unknown", + "Descr.", "BIOS", "ME", "GbE", "Platf.", "unknown", "BIOS2", "unknown", + "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown" }; if (i >= ARRAY_SIZE(region_names)) { msg_pdbg2("%s: region index too high.\n", __func__); @@ -376,6 +393,32 @@ void prettyprint_ich_descriptor_master(const enum ich_chipset cs, const struct i desc->master.mstr[i].write & (1 << j) ? 'w' : ' '); msg_pdbg2("\n"); } + } else if (cs == CHIPSET_C620_SERIES_LEWISBURG) { + const char *const master_names[] = { + "BIOS", "ME", "GbE", "DE", "BMC", "IE", + }; + /* NM starts at 1 instead of 0 for LBG */ + if (nm > ARRAY_SIZE(master_names)) { + msg_pdbg2("%s: number of masters too high (%d).\n", __func__, + desc->content.NM); + return; + } + + msg_pdbg2("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", + " ", /* width of master name (4 chars minimum) */ + " FD ", " BIOS", " ME ", " GbE ", " Pltf", + " DE ", "BIOS2", " Reg7", " BMC ", " DE2 ", + " IE ", "10GbE", "OpROM", "Reg13", "Reg14", + "Reg15"); + for (i = 0; i < nm; i++) { + size_t j; + msg_pdbg2("%-4s", master_names[i]); + for (j = 0; j < 16; j++) + msg_pdbg2(" %c%c ", + desc->master.mstr[i].read & (1 << j) ? 'r' : ' ', + desc->master.mstr[i].write & (1 << j) ? 'w' : ' '); + msg_pdbg2("\n"); + } } else { const struct ich_desc_master *const mstr = &desc->master; msg_pdbg2(" Descr. BIOS ME GbE Platf.\n"); @@ -829,6 +872,8 @@ static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_con return CHIPSET_8_SERIES_LYNX_POINT; msg_pwarn("Peculiar firmware descriptor, assuming Wildcat Point compatibility.\n"); return CHIPSET_9_SERIES_WILDCAT_POINT; + } else if (content->NM == 6) { + return CHIPSET_C620_SERIES_LEWISBURG; } else { return CHIPSET_100_SERIES_SUNRISE_POINT; } @@ -846,14 +891,16 @@ static enum ich_chipset guess_ich_chipset(const struct ich_desc_content *const c const enum ich_chipset guess = guess_ich_chipset_from_content(content); if (component->modes.freq_read == 6) { - if (guess != CHIPSET_100_SERIES_SUNRISE_POINT) + if ((guess != CHIPSET_100_SERIES_SUNRISE_POINT) && (guess != CHIPSET_C620_SERIES_LEWISBURG)) { msg_pwarn("\nThe firmware descriptor has the read frequency set to 17MHz. However,\n" "it doesn't look like a Skylake/Sunrise Point compatible descriptor.\n" "Please report this message, the output of `ich_descriptors_tool` for\n" "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n"); - return CHIPSET_100_SERIES_SUNRISE_POINT; + return CHIPSET_100_SERIES_SUNRISE_POINT; + } + return guess; } else { - if (guess == CHIPSET_100_SERIES_SUNRISE_POINT) { + if (guess == CHIPSET_100_SERIES_SUNRISE_POINT || guess == CHIPSET_C620_SERIES_LEWISBURG) { msg_pwarn("\nThe firmware descriptor looks like a Skylake/Sunrise Point descriptor.\n" "However, the read frequency isn't set to 17MHz (the only valid value).\n" "Please report this message, the output of `ich_descriptors_tool` for\n" @@ -992,6 +1039,7 @@ int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors case CHIPSET_9_SERIES_WILDCAT_POINT: case CHIPSET_9_SERIES_WILDCAT_POINT_LP: case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: if (idx == 0) { size_enc = desc->component.dens_new.comp1_density; } else { @@ -1022,14 +1070,13 @@ static uint32_t read_descriptor_reg(enum ich_chipset cs, uint8_t section, uint16 uint32_t control = 0; control |= (section << FDOC_FDSS_OFF) & FDOC_FDSS; control |= (offset << FDOC_FDSI_OFF) & FDOC_FDSI; - if (cs == CHIPSET_100_SERIES_SUNRISE_POINT) { + if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) { mmio_le_writel(control, spibar + PCH100_REG_FDOC); return mmio_le_readl(spibar + PCH100_REG_FDOD); } else { mmio_le_writel(control, spibar + ICH9_REG_FDOC); return mmio_le_readl(spibar + ICH9_REG_FDOD); } - } int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_descriptors *desc) @@ -1113,7 +1160,8 @@ int read_ich_descriptors_via_fdo(enum ich_chipset cs, void *spibar, struct ich_d int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len) { static const char *const regions[] = { - "fd", "bios", "me", "gbe", "pd", "reg5", "reg6", "reg7", "ec", "reg9" + "fd", "bios", "me", "gbe", "pd", "reg5", "bios2", "reg7", "ec", "reg9", "ie", + "10gbe", "reg12", "reg13", "reg14", "reg15" }; struct ich_descriptors desc; @@ -389,11 +389,13 @@ static void prettyprint_ich9_reg_hsfs(uint16_t reg_val) pprint_reg(HSFS, FDONE, reg_val, ", "); pprint_reg(HSFS, FCERR, reg_val, ", "); pprint_reg(HSFS, AEL, reg_val, ", "); - if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) { + if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT && + ich_generation != CHIPSET_C620_SERIES_LEWISBURG) { pprint_reg(HSFS, BERASE, reg_val, ", "); } pprint_reg(HSFS, SCIP, reg_val, ", "); - if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) { + if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT || + ich_generation == CHIPSET_C620_SERIES_LEWISBURG) { pprint_reg(HSFS, PRR34_LOCKDN, reg_val, ", "); pprint_reg(HSFS, WRSDIS, reg_val, ", "); } @@ -406,7 +408,8 @@ static void prettyprint_ich9_reg_hsfc(uint16_t reg_val) { msg_pdbg("HSFC: "); pprint_reg(HSFC, FGO, reg_val, ", "); - if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) { + if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT && + ich_generation != CHIPSET_C620_SERIES_LEWISBURG) { pprint_reg(HSFC, FCYCLE, reg_val, ", "); } else { _pprint_reg(HSFC, PCH100_HSFC_FCYCLE, PCH100_HSFC_FCYCLE_OFF, reg_val, ", "); @@ -1703,7 +1706,18 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) /* Moving registers / bits */ if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) { num_freg = 10; - num_pr = 6; + num_pr = 6; /* Includes GPR0 */ + reg_pr0 = PCH100_REG_FPR0; + 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; + } if (ich_generation == CHIPSET_C620_SERIES_LEWISBURG) { + num_freg = 12; /* 12 MMIO regs, but 16 regions in FD spec */ + num_pr = 6; /* Includes GPR0 */ reg_pr0 = PCH100_REG_FPR0; swseq_data.reg_ssfsc = PCH100_REG_SSFSC; swseq_data.reg_preop = PCH100_REG_PREOP; @@ -1824,7 +1838,7 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) tmp = mmio_readl(ich_spibar + ICH9_REG_FADDR); msg_pdbg2("0x08: 0x%08x (FADDR)\n", tmp); - if (ich_gen == CHIPSET_100_SERIES_SUNRISE_POINT) { + if (ich_gen == CHIPSET_100_SERIES_SUNRISE_POINT || ich_gen == CHIPSET_C620_SERIES_LEWISBURG) { const uint32_t dlock = mmio_readl(ich_spibar + PCH100_REG_DLOCK); msg_pdbg("0x0c: 0x%08x (DLOCK)\n", dlock); prettyprint_pch100_reg_dlock(dlock); @@ -1890,7 +1904,8 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) msg_pdbg("0xC1: 0x%08x (VSCC)\n", tmp); msg_pdbg("VSCC: "); prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true); - } else if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT) { + } else if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT && + ich_generation != CHIPSET_C620_SERIES_LEWISBURG) { if (ich_generation != CHIPSET_BAYTRAIL && desc_valid) { ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR); msg_pdbg("0xA0: 0x%08x (BBAR)\n", diff --git a/programmer.h b/programmer.h index e58fd3257..a98b71359 100644 --- a/programmer.h +++ b/programmer.h @@ -656,6 +656,7 @@ enum ich_chipset { CHIPSET_9_SERIES_WILDCAT_POINT, CHIPSET_9_SERIES_WILDCAT_POINT_LP, CHIPSET_100_SERIES_SUNRISE_POINT, /* also 6th/7th gen Core i/o (LP) variants */ + CHIPSET_C620_SERIES_LEWISBURG, }; /* ichspi.c */ diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c index 82c74bd9c..5ab946fdd 100644 --- a/util/ich_descriptors_tool/ich_descriptors_tool.c +++ b/util/ich_descriptors_tool/ich_descriptors_tool.c @@ -42,7 +42,9 @@ static const char *const region_names[] = { "Descriptor", "BIOS", "ME", "GbE", "Platform", - "Region5", "Region6", "Region7", "EC", "Region9", + "Region5", "BIOS2", "Region7", "EC/BMC", "Region9", + "IE", "10GbE", "Region12", "Region13", "Region14", + "Region15" }; static void dump_file(const char *prefix, const uint32_t *dump, unsigned int len, |