Nico Huber has uploaded this change for review.

View Change

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.

Original-Change-Id: I96c89bc28bdfcd953229c17679f2c28f8b874d0b
Original-Reviewed-on: https://review.coreboot.org/20922
Original-Reviewed-by: Nico Huber <nico.h@gmx.de>
Original-Tested-by: build bot (Jenkins) <no-reply@coreboot.org>

Change-Id: Ia93f4616c9279173b5cd47be1999939aa2f02379
Signed-off-by: David Hendricks <dhendricks@fb.com>
---
M chipset_enable.c
M ich_descriptors.c
M ichspi.c
M programmer.h
M util/ich_descriptors_tool/ich_descriptors_tool.c
5 files changed, 119 insertions(+), 28 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/19/21819/1
diff --git a/chipset_enable.c b/chipset_enable.c
index 36e2838..a3b7f8d 100644
--- a/chipset_enable.c
+++ b/chipset_enable.c
@@ -601,6 +601,7 @@
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 @@
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 @@
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 @@
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;

/*
@@ -886,6 +888,16 @@
pci_free_dev(spi_dev);
pacc = saved_pacc;
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.
@@ -1915,6 +1927,19 @@
{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 7916152..69fcd75 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_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 @@
"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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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__);
@@ -372,6 +389,32 @@
msg_pdbg2("%-4s", master_names[i]);
for (j = 0; j < 10; 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 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");
@@ -829,6 +872,8 @@
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 @@
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 @@
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 @@
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 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;
diff --git a/ichspi.c b/ichspi.c
index 9ee8044..9d6b62b 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -389,11 +389,13 @@
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 @@
{
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 @@
/* 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 @@
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 @@
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 e58fd32..a98b713 100644
--- a/programmer.h
+++ b/programmer.h
@@ -656,6 +656,7 @@
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 82c74bd..5ab946f 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,

To view, visit change 21819. To unsubscribe, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: stable
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ia93f4616c9279173b5cd47be1999939aa2f02379
Gerrit-Change-Number: 21819
Gerrit-PatchSet: 1
Gerrit-Owner: Nico Huber <nico.h@gmx.de>