diff options
-rw-r--r-- | chipset_enable.c | 2 | ||||
-rw-r--r-- | ich_descriptors.c | 99 | ||||
-rw-r--r-- | ichspi.c | 112 | ||||
-rw-r--r-- | util/ich_descriptors_tool/ich_descriptors_tool.c | 3 |
4 files changed, 155 insertions, 61 deletions
diff --git a/chipset_enable.c b/chipset_enable.c index 24ac64a3..08feda52 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -2026,7 +2026,7 @@ const struct penable chipset_enables[] = { {0x8086, 0xa2c8, B_S, NT, "Intel", "B250", enable_flash_pch100}, {0x8086, 0xa2c9, B_S, NT, "Intel", "Z370", enable_flash_pch100}, {0x8086, 0xa2d2, B_S, NT, "Intel", "X299", enable_flash_pch100}, - {0x8086, 0x5ae8, B_S, BAD, "Intel", "Apollo Lake", enable_flash_apl}, + {0x8086, 0x5ae8, B_S, DEP, "Intel", "Apollo Lake", enable_flash_apl}, #endif {0}, }; diff --git a/ich_descriptors.c b/ich_descriptors.c index bfe92bbc..a757addd 100644 --- a/ich_descriptors.c +++ b/ich_descriptors.c @@ -42,6 +42,8 @@ ssize_t ich_number_of_regions(const enum ich_chipset cs, const struct ich_desc_content *const cont) { switch (cs) { + case CHIPSET_APOLLO_LAKE: + return 6; case CHIPSET_C620_SERIES_LEWISBURG: return 16; case CHIPSET_100_SERIES_SUNRISE_POINT: @@ -67,6 +69,7 @@ ssize_t ich_number_of_masters(const enum ich_chipset cs, const struct ich_desc_c { switch (cs) { case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: if (cont->NM <= MAX_NUM_MASTERS) return cont->NM; break; @@ -103,7 +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", + "C620 series Lewisburg", "Apollo Lake", }; if (cs < CHIPSET_ICH8 || cs - CHIPSET_ICH8 + 1 >= ARRAY_SIZE(chipset_names)) cs = 0; @@ -140,8 +143,8 @@ void prettyprint_ich_descriptor_content(enum ich_chipset cs, const struct ich_de msg_pdbg2("FRBA (Flash Region Base Address): 0x%03x\n", getFRBA(cont)); msg_pdbg2("NC (Number of Components): %5d\n", cont->NC + 1); msg_pdbg2("FCBA (Flash Component Base Address): 0x%03x\n", getFCBA(cont)); - msg_pdbg2("ISL (ICH/PCH Strap Length): %5d\n", cont->ISL); - msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x%03x\n", getFISBA(cont)); + msg_pdbg2("ISL (ICH/PCH/SoC Strap Length): %5d\n", cont->ISL); + msg_pdbg2("FISBA/FPSBA (Flash ICH/PCH/SoC Strap Base Addr): 0x%03x\n", getFISBA(cont)); msg_pdbg2("NM (Number of Masters): %5zd\n", ich_number_of_masters(cs, cont)); msg_pdbg2("FMBA (Flash Master Base Address): 0x%03x\n", getFMBA(cont)); msg_pdbg2("MSL/PSL (MCH/PROC Strap Length): %5d\n", cont->MSL); @@ -194,7 +197,8 @@ static const char *pprint_density(enum ich_chipset cs, const struct ich_descript case CHIPSET_9_SERIES_WILDCAT_POINT: case CHIPSET_9_SERIES_WILDCAT_POINT_LP: case CHIPSET_100_SERIES_SUNRISE_POINT: - case CHIPSET_C620_SERIES_LEWISBURG: { + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: { uint8_t size_enc; if (idx == 0) { size_enc = desc->component.dens_new.comp1_density; @@ -213,7 +217,7 @@ static const char *pprint_density(enum ich_chipset cs, const struct ich_descript static const char *pprint_freq(enum ich_chipset cs, uint8_t value) { - static const char *const freq_str[2][8] = { { + static const char *const freq_str[3][8] = { { "20 MHz", "33 MHz", "reserved", @@ -231,6 +235,15 @@ static const char *pprint_freq(enum ich_chipset cs, uint8_t value) "reserved", "17 MHz", "reserved" + }, { + "reserved", + "50 MHz", + "40 MHz", + "reserved", + "25 MHz", + "reserved", + "14 MHz / 17 MHz", + "reserved" } }; switch (cs) { @@ -253,6 +266,8 @@ static const char *pprint_freq(enum ich_chipset cs, uint8_t value) case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: return freq_str[1][value]; + case CHIPSET_APOLLO_LAKE: + return freq_str[2][value]; case CHIPSET_ICH_UNKNOWN: default: return "unknown"; @@ -261,11 +276,23 @@ static const char *pprint_freq(enum ich_chipset cs, uint8_t value) void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc) { + bool has_flill1; + + switch (cs) { + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: + has_flill1 = true; + break; + default: + has_flill1 = false; + break; + } 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 || cs == CHIPSET_C620_SERIES_LEWISBURG) + if (has_flill1) msg_pdbg2("FLILL1 0x%08x\n", desc->component.FLILL1); msg_pdbg2("\n"); @@ -298,7 +325,7 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ msg_pdbg2("Invalid instruction 3: 0x%02x\n", desc->component.invalid_instr3); } - if (cs == CHIPSET_100_SERIES_SUNRISE_POINT || cs == CHIPSET_C620_SERIES_LEWISBURG) { + if (has_flill1) { if (desc->component.FLILL1 != 0) { has_forbidden_opcode = 1; msg_pdbg2("Invalid instruction 4: 0x%02x\n", @@ -320,7 +347,7 @@ void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_ 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", "BIOS2", "unknown", + "Descr.", "BIOS", "ME", "GbE", "Platf.", "DevExp", "BIOS2", "unknown", "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown" }; if (i >= ARRAY_SIZE(region_names)) { @@ -417,6 +444,23 @@ 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_APOLLO_LAKE) { + const char *const master_names[] = { "BIOS", "TXE", }; + if (nm > ARRAY_SIZE(master_names)) { + msg_pdbg2("%s: number of masters too high (%d).\n", __func__, desc->content.NM); + return; + } + + msg_pdbg2(" FD IFWI TXE n/a Platf DevExp\n"); + for (i = 0; i < nm; i++) { + size_t j; + msg_pdbg2("%-4s", master_names[i]); + for (j = 0; j < ich_number_of_regions(cs, &desc->content); 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"); @@ -859,6 +903,11 @@ static enum ich_chipset guess_ich_chipset_from_content(const struct ich_desc_con return CHIPSET_ICH10; else if (content->ISL <= 16) return CHIPSET_5_SERIES_IBEX_PEAK; + else if (content->FLMAP2 == 0) { + if (content->ISL != 19) + msg_pwarn("Peculiar firmware descriptor, assuming Apollo Lake compatibility.\n"); + return CHIPSET_APOLLO_LAKE; + } msg_pwarn("Peculiar firmware descriptor, assuming Ibex Peak compatibility.\n"); return CHIPSET_5_SERIES_IBEX_PEAK; } else if (content->ICCRIBA < 0x31 && content->FMSBA < 0x30) { @@ -888,26 +937,28 @@ 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) && (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" + switch (guess) { + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: + if (component->modes.freq_read != 6) { + 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" "your descriptor and the output of `lspci -nn` to flashrom@flashrom.org\n\n"); - return CHIPSET_100_SERIES_SUNRISE_POINT; + return CHIPSET_9_SERIES_WILDCAT_POINT; } return guess; - } else { - 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" + default: + if (component->modes.freq_read == 6) { + 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_9_SERIES_WILDCAT_POINT; + return CHIPSET_100_SERIES_SUNRISE_POINT; } + return guess; } - - return guess; } /* len is the length of dump in bytes */ @@ -1038,6 +1089,7 @@ int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors case CHIPSET_9_SERIES_WILDCAT_POINT_LP: case CHIPSET_100_SERIES_SUNRISE_POINT: case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: if (idx == 0) { size_enc = desc->component.dens_new.comp1_density; } else { @@ -1068,10 +1120,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 || cs == CHIPSET_C620_SERIES_LEWISBURG) { + switch (cs) { + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: mmio_le_writel(control, spibar + PCH100_REG_FDOC); return mmio_le_readl(spibar + PCH100_REG_FDOD); - } else { + default: mmio_le_writel(control, spibar + ICH9_REG_FDOC); return mmio_le_readl(spibar + ICH9_REG_FDOD); } @@ -29,6 +29,9 @@ #include "spi.h" #include "ich_descriptors.h" +/* Apollo Lake */ +#define APL_REG_FREG12 0xe0 /* 32 Bytes Flash Region 12 */ + /* Sunrise Point */ /* Added HSFS Status bits */ @@ -1564,15 +1567,17 @@ static const char *const access_names[] = { static enum ich_access_protection ich9_handle_frap(uint32_t frap, int i) { const int rwperms_unknown = ARRAY_SIZE(access_names); - static const char *const region_names[5] = { + static const char *const region_names[6] = { "Flash Descriptor", "BIOS", "Management Engine", - "Gigabit Ethernet", "Platform Data" + "Gigabit Ethernet", "Platform Data", "Device Expansion", }; const char *const region_name = i < ARRAY_SIZE(region_names) ? region_names[i] : "unknown"; uint32_t base, limit; int rwperms; - int offset = ICH9_REG_FREG0 + i * 4; + const int offset = i < 12 + ? ICH9_REG_FREG0 + i * 4 + : APL_REG_FREG12 + (i - 12) * 4; uint32_t freg = mmio_readl(ich_spibar + offset); if (i < 8) { @@ -1716,19 +1721,10 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) memset(&desc, 0x00, sizeof(struct ich_descriptors)); /* Moving registers / bits */ - if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) { - num_freg = 10; - 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; - } else if (ich_generation == CHIPSET_C620_SERIES_LEWISBURG) { - num_freg = 12; /* 12 MMIO regs, but 16 regions in FD spec */ + switch (ich_generation) { + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: num_pr = 6; /* Includes GPR0 */ reg_pr0 = PCH100_REG_FPR0; swseq_data.reg_ssfsc = PCH100_REG_SSFSC; @@ -1738,8 +1734,8 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) hwseq_data.addr_mask = PCH100_FADDR_FLA; hwseq_data.only_4k = true; hwseq_data.hsfc_fcycle = PCH100_HSFC_FCYCLE; - } else { - num_freg = 5; + break; + default: num_pr = 5; reg_pr0 = ICH9_REG_PR0; swseq_data.reg_ssfsc = ICH9_REG_SSFS; @@ -1749,6 +1745,21 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) hwseq_data.addr_mask = ICH9_FADDR_FLA; hwseq_data.only_4k = false; hwseq_data.hsfc_fcycle = HSFC_FCYCLE; + break; + } + switch (ich_generation) { + case CHIPSET_100_SERIES_SUNRISE_POINT: + num_freg = 10; + break; + case CHIPSET_C620_SERIES_LEWISBURG: + num_freg = 12; /* 12 MMIO regs, but 16 regions in FD spec */ + break; + case CHIPSET_APOLLO_LAKE: + num_freg = 16; + break; + default: + num_freg = 5; + break; } switch (ich_generation) { @@ -1834,10 +1845,16 @@ 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 || 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); + switch (ich_gen) { + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: + tmp = mmio_readl(ich_spibar + PCH100_REG_DLOCK); + msg_pdbg("0x0c: 0x%08x (DLOCK)\n", tmp); + prettyprint_pch100_reg_dlock(tmp); + break; + default: + break; } if (desc_valid) { @@ -1898,37 +1915,51 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) 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, FLASHROM_MSG_DEBUG, true); - } else if (ich_generation != CHIPSET_100_SERIES_SUNRISE_POINT && - ich_generation != CHIPSET_C620_SERIES_LEWISBURG) { - if (ich_generation != CHIPSET_BAYTRAIL && desc_valid) { + + if (desc_valid) { + switch (ich_gen) { + case CHIPSET_ICH8: + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: + case CHIPSET_BAYTRAIL: + break; + default: ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR); - msg_pdbg("0xA0: 0x%08x (BBAR)\n", - ichspi_bbar); + msg_pdbg("0x%x: 0x%08x (BBAR)\n", ICH9_REG_BBAR, ichspi_bbar); ich_set_bbar(0); + break; } - if (desc_valid) { + if (ich_gen == CHIPSET_ICH8) { + tmp = mmio_readl(ich_spibar + ICH8_REG_VSCC); + msg_pdbg("0x%x: 0x%08x (VSCC)\n", ICH8_REG_VSCC, tmp); + msg_pdbg("VSCC: "); + prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true); + } else { tmp = mmio_readl(ich_spibar + ICH9_REG_LVSCC); - msg_pdbg("0xC4: 0x%08x (LVSCC)\n", tmp); + msg_pdbg("0x%x: 0x%08x (LVSCC)\n", ICH9_REG_LVSCC, tmp); msg_pdbg("LVSCC: "); prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, true); tmp = mmio_readl(ich_spibar + ICH9_REG_UVSCC); - msg_pdbg("0xC8: 0x%08x (UVSCC)\n", tmp); + msg_pdbg("0x%x: 0x%08x (UVSCC)\n", ICH9_REG_UVSCC, tmp); msg_pdbg("UVSCC: "); prettyprint_ich_reg_vscc(tmp, FLASHROM_MSG_DEBUG, false); + } + switch (ich_gen) { + case CHIPSET_ICH8: + case CHIPSET_100_SERIES_SUNRISE_POINT: + case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: + break; + default: tmp = mmio_readl(ich_spibar + ICH9_REG_FPB); - msg_pdbg("0xD0: 0x%08x (FPB)\n", tmp); + msg_pdbg("0x%x: 0x%08x (FPB)\n", ICH9_REG_FPB, tmp); + break; } - } - if (desc_valid) { if (read_ich_descriptors_via_fdo(ich_gen, ich_spibar, &desc) == ICH_RET_OK) prettyprint_ich_descriptors(ich_gen, &desc); @@ -1955,6 +1986,11 @@ int ich_init_spi(void *spibar, enum ich_chipset ich_gen) ich_spi_mode = ich_hwseq; } + if (ich_spi_mode == ich_auto && ich_gen == CHIPSET_APOLLO_LAKE) { + msg_pdbg("Enabling hardware sequencing by default for Apollo Lake.\n"); + ich_spi_mode = ich_hwseq; + } + if (ich_spi_mode == ich_hwseq) { if (!desc_valid) { msg_perr("Hardware sequencing was requested " diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c index aa857c88..2c7966d2 100644 --- a/util/ich_descriptors_tool/ich_descriptors_tool.c +++ b/util/ich_descriptors_tool/ich_descriptors_tool.c @@ -126,6 +126,7 @@ static void usage(char *argv[], char *error) "\t- \"ich9\",\n" "\t- \"ich10\",\n" "\t- \"silvermont\" for chipsets from Intel's Silvermont architecture (e.g. Bay Trail),\n" +"\t- \"apollo\" for Intel's Apollo Lake SoC.\n" "\t- \"5\" or \"ibex\" for Intel's 5 series chipsets,\n" "\t- \"6\" or \"cougar\" for Intel's 6 series chipsets,\n" "\t- \"7\" or \"panther\" for Intel's 7 series chipsets.\n" @@ -220,6 +221,8 @@ int main(int argc, char *argv[]) else if ((strcmp(csn, "100") == 0) || (strcmp(csn, "sunrise") == 0)) cs = CHIPSET_100_SERIES_SUNRISE_POINT; + else if (strcmp(csn, "apollo") == 0) + cs = CHIPSET_APOLLO_LAKE; } ret = read_ich_descriptors_from_dump(buf, len, &cs, &desc); |