Nico Huber has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/30995
Change subject: ichspi: Add Apollo Lake support ......................................................................
ichspi: Add Apollo Lake support
It's almost identical to 100 series PCHs and later. There are some addition FREGs (12..15). To not clutter the `if` conditions further, make more use of `switch` statements.
Tested on Kontron mAL10. Mark it as DEP as usually the last sector is not covered by the descriptor layout and can't be read.
Change-Id: I1c464b5b3d151e6d28d5db96495fe874a0a45718 Signed-off-by: Nico Huber nico.huber@secunet.com --- M chipset_enable.c M ich_descriptors.c M ichspi.c 3 files changed, 153 insertions(+), 62 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/95/30995/1
diff --git a/chipset_enable.c b/chipset_enable.c index 547f21a..2f73ded 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -1965,7 +1965,7 @@ {0x8086, 0xa2c8, NT, "Intel", "B250", enable_flash_pch100}, {0x8086, 0xa2c9, NT, "Intel", "Z370", enable_flash_pch100}, {0x8086, 0xa2d2, NT, "Intel", "X299", enable_flash_pch100}, - {0x8086, 0x5ae8, BAD, "Intel", "Apollo Lake", enable_flash_apl}, + {0x8086, 0x5ae8, DEP, "Intel", "Apollo Lake", enable_flash_apl}, #endif {0}, }; diff --git a/ich_descriptors.c b/ich_descriptors.c index 56e846f..dcbcfae 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 @@ { switch (cs) { case CHIPSET_C620_SERIES_LEWISBURG: + case CHIPSET_APOLLO_LAKE: if (cont->NM <= MAX_NUM_MASTERS) return cont->NM; default: @@ -139,8 +142,8 @@ 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); @@ -193,7 +196,8 @@ 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; @@ -212,7 +216,7 @@
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", /* 000 */ "33 MHz", /* 001 */ "reserved", /* 010 */ @@ -230,6 +234,15 @@ "reserved", /* 101 */ "17 MHz", /* 110 */ "reserved" /* 111 */ + }, { + "reserved", /* 000 */ + "50 MHz", /* 001 */ + "40 MHz", /* 010 */ + "reserved", /* 011 */ + "25 MHz", /* 100 */ + "reserved", /* 101 */ + "17 MHz", /* 110 */ + "reserved" /* 111 */ } };
switch (cs) { @@ -251,6 +264,8 @@ 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"; @@ -259,11 +274,23 @@
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");
@@ -296,7 +323,7 @@ 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", @@ -318,7 +345,7 @@ 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.", "DevExt", "BIOS2", "unknown", "EC/BMC", "unknown", "IE", "10GbE", "unknown", "unknown", "unknown", "unknown" }; if (i >= ARRAY_SIZE(region_names)) { @@ -415,6 +442,23 @@ 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 DevExt\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"); @@ -857,6 +901,11 @@ 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) { @@ -886,8 +935,20 @@ { 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)) { + 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_9_SERIES_WILDCAT_POINT; + } + return guess; + 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" @@ -895,17 +956,7 @@ return CHIPSET_100_SERIES_SUNRISE_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" - "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 guess; }
/* len is the length of dump in bytes */ @@ -1036,6 +1087,7 @@ 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 { @@ -1066,10 +1118,13 @@ 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); } diff --git a/ichspi.c b/ichspi.c index 9eb24a9..2c8a89f 100644 --- a/ichspi.c +++ b/ichspi.c @@ -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 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 Extension", }; 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,8 +1721,10 @@ ich_spibar = spibar;
/* Moving registers / bits */ - if (ich_generation == CHIPSET_100_SERIES_SUNRISE_POINT) { - num_freg = 10; + 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; @@ -1727,19 +1734,8 @@ 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 */ - 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 { - num_freg = 5; + break; + default: num_pr = 5; reg_pr0 = ICH9_REG_PR0; swseq_data.reg_ssfsc = ICH9_REG_SSFS; @@ -1749,6 +1745,21 @@ 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 @@ 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 @@ 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); - - tmp = mmio_readl(ich_spibar + ICH9_REG_FPB); - msg_pdbg("0xD0: 0x%08x (FPB)\n", tmp); } - }
- if (desc_valid) { + 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("0x%x: 0x%08x (FPB)\n", ICH9_REG_FPB, tmp); + break; + } + if (read_ich_descriptors_via_fdo(ich_gen, ich_spibar, &desc) == ICH_RET_OK) prettyprint_ich_descriptors(ich_gen, &desc);
@@ -1955,6 +1986,11 @@ 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 "