Possible values as well as encodings have changed in newer chipsets as follows. - Pre-PCH (i.e. ICH) chipsets had a maximum frequency of 33 MHz for all operations - Since Cougar Point the chipsets support dual output fast reads (encoded in bit 30). - Flash component density encoding has changed from 3 to 4 bits with Lynx Point, currently allowing for up to 64 MB chips.
Signed-off-by: Stefan Tauner stefan.tauner@alumni.tuwien.ac.at --- ich_descriptors.c | 182 +++++++++++++++++------ ich_descriptors.h | 39 ++++- ichspi.c | 24 ++- util/ich_descriptors_tool/ich_descriptors_tool.c | 4 + 4 files changed, 193 insertions(+), 56 deletions(-)
diff --git a/ich_descriptors.c b/ich_descriptors.c index 528717b..3977a4b 100644 --- a/ich_descriptors.c +++ b/ich_descriptors.c @@ -64,7 +64,7 @@ void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity) void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc) { prettyprint_ich_descriptor_content(&desc->content); - prettyprint_ich_descriptor_component(desc); + prettyprint_ich_descriptor_component(cs, desc); prettyprint_ich_descriptor_region(desc); prettyprint_ich_descriptor_master(&desc->master); #ifdef ICH_DESCRIPTORS_FROM_DUMP @@ -98,28 +98,97 @@ void prettyprint_ich_descriptor_content(const struct ich_desc_content *cont) msg_pdbg2("\n"); }
-void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc) +static const char *pprint_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx) +{ + if (idx > 1) { + msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n"); + return NULL; + } + + if (desc->content.NC == 0 && idx > 0) + return "unused"; + + static const char * const size_str[] = { + "512 kB", /* 0000 */ + "1 MB", /* 0001 */ + "2 MB", /* 0010 */ + "4 MB", /* 0011 */ + "8 MB", /* 0100 */ + "16 MB", /* 0101 */ /* Maximum up to Lynx Point (excl.) */ + "32 MB", /* 0110 */ + "64 MB", /* 0111 */ + }; + + switch (cs) { + case CHIPSET_ICH8: + case CHIPSET_ICH9: + case CHIPSET_ICH10: + case CHIPSET_5_SERIES_IBEX_PEAK: + case CHIPSET_6_SERIES_COUGAR_POINT: + case CHIPSET_7_SERIES_PANTHER_POINT: { + uint8_t size_enc; + if (idx == 0) { + size_enc = desc->component.old.comp1_density; + } else { + size_enc = desc->component.old.comp2_density; + } + if (size_enc > 5) + return "reserved"; + return size_str[size_enc]; + } + case CHIPSET_8_SERIES_LYNX_POINT: + case CHIPSET_8_SERIES_LYNX_POINT_LP: + case CHIPSET_8_SERIES_WELLSBURG: { + uint8_t size_enc; + if (idx == 0) { + size_enc = desc->component.new.comp1_density; + } else { + size_enc = desc->component.new.comp2_density; + } + if (size_enc > 7) + return "reserved"; + return size_str[size_enc]; + } + case CHIPSET_ICH_UNKNOWN: + default: + return "unknown"; + } +} + +static const char *pprint_freq(enum ich_chipset cs, uint8_t value) { static const char * const freq_str[8] = { "20 MHz", /* 000 */ "33 MHz", /* 001 */ "reserved", /* 010 */ "reserved", /* 011 */ - "50 MHz", /* 100 */ + "50 MHz", /* 100 */ /* New since Ibex Peak */ "reserved", /* 101 */ "reserved", /* 110 */ "reserved" /* 111 */ }; - static const char * const size_str[8] = { - "512 kB", /* 000 */ - " 1 MB", /* 001 */ - " 2 MB", /* 010 */ - " 4 MB", /* 011 */ - " 8 MB", /* 100 */ - " 16 MB", /* 101 */ - "reserved", /* 110 */ - "reserved", /* 111 */ - }; + + switch (cs) { + case CHIPSET_ICH8: + case CHIPSET_ICH9: + case CHIPSET_ICH10: + if (value > 1) + return "reserved"; + case CHIPSET_5_SERIES_IBEX_PEAK: + case CHIPSET_6_SERIES_COUGAR_POINT: + case CHIPSET_7_SERIES_PANTHER_POINT: + case CHIPSET_8_SERIES_LYNX_POINT: + case CHIPSET_8_SERIES_LYNX_POINT_LP: + case CHIPSET_8_SERIES_WELLSBURG: + return freq_str[value]; + case CHIPSET_ICH_UNKNOWN: + default: + return "unknown"; + } +} + +void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc) +{
msg_pdbg2("=== Component Section ===\n"); msg_pdbg2("FLCOMP 0x%08x\n", desc->component.FLCOMP); @@ -127,24 +196,21 @@ void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc) msg_pdbg2("\n");
msg_pdbg2("--- Details ---\n"); - msg_pdbg2("Component 1 density: %s\n", - size_str[desc->component.comp1_density]); + msg_pdbg2("Component 1 density: %s\n", pprint_density(cs, desc, 0)); if (desc->content.NC) - msg_pdbg2("Component 2 density: %s\n", - size_str[desc->component.comp2_density]); + msg_pdbg2("Component 2 density: %s\n", pprint_density(cs, desc, 1)); else msg_pdbg2("Component 2 is not used.\n"); - msg_pdbg2("Read Clock Frequency: %s\n", - freq_str[desc->component.freq_read]); - msg_pdbg2("Read ID and Status Clock Freq.: %s\n", - freq_str[desc->component.freq_read_id]); - msg_pdbg2("Write and Erase Clock Freq.: %s\n", - freq_str[desc->component.freq_write]); - msg_pdbg2("Fast Read is %ssupported.\n", - desc->component.fastread ? "" : "not "); - if (desc->component.fastread) + msg_pdbg2("Read Clock Frequency: %s\n", pprint_freq(cs, desc->component.common.freq_read)); + msg_pdbg2("Read ID and Status Clock Freq.: %s\n", pprint_freq(cs, desc->component.common.freq_read_id)); + msg_pdbg2("Write and Erase Clock Freq.: %s\n", pprint_freq(cs, desc->component.common.freq_write)); + msg_pdbg2("Fast Read is %ssupported.\n", desc->component.common.fastread ? "" : "not "); + if (desc->component.common.fastread) msg_pdbg2("Fast Read Clock Frequency: %s\n", - freq_str[desc->component.freq_fastread]); + pprint_freq(cs, desc->component.common.freq_fastread)); + if (cs > CHIPSET_6_SERIES_COUGAR_POINT) + msg_pdbg2("Dual Output Fast Read Support: %sabled\n", + desc->component.new.dual_output ? "dis" : "en"); if (desc->component.FLILL == 0) msg_pdbg2("No forbidden opcodes.\n"); else { @@ -273,7 +339,7 @@ static void prettyprint_ich_descriptor_straps_56_pciecs(uint8_t conf, uint8_t of msg_pdbg2("PCI Express Port Configuration Strap %d: ", off+1);
off *= 4; - switch(conf){ + switch (conf){ case 0: msg_pdbg2("4x1 Ports %d-%d (x1)", 1+off, 4+off); break; @@ -723,29 +789,57 @@ int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, struc #else /* ICH_DESCRIPTORS_FROM_DUMP */
/** Returns the integer representation of the component density with index -idx in bytes or 0 if a correct size can not be determined. */ -int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx) +\em idx in bytes or -1 if the correct size can not be determined. */ +int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx) { + if (idx > 1) { + msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n"); + return -1; + } + + if (desc->content.NC == 0 && idx > 0) + return 0; + uint8_t size_enc; - - switch(idx) { - case 0: - size_enc = desc->component.comp1_density; + uint8_t size_max; + + switch (cs) { + case CHIPSET_ICH8: + case CHIPSET_ICH9: + case CHIPSET_ICH10: + case CHIPSET_5_SERIES_IBEX_PEAK: + case CHIPSET_6_SERIES_COUGAR_POINT: + case CHIPSET_7_SERIES_PANTHER_POINT: + if (idx == 0) { + size_enc = desc->component.old.comp1_density; + } else { + size_enc = desc->component.old.comp2_density; + } + size_max = 5; break; - case 1: - if (desc->content.NC == 0) - return 0; - size_enc = desc->component.comp2_density; + case CHIPSET_8_SERIES_LYNX_POINT: + case CHIPSET_8_SERIES_LYNX_POINT_LP: + case CHIPSET_8_SERIES_WELLSBURG: + if (idx == 0) { + size_enc = desc->component.new.comp1_density; + } else { + size_enc = desc->component.new.comp2_density; + } + size_max = 7; break; + case CHIPSET_ICH_UNKNOWN: default: - msg_perr("Only ICH SPI component index 0 or 1 are supported yet.\n"); - return 0; + msg_pwarn("Density encoding is unknown on this chipset.\n"); + return -1; } - if (size_enc > 5) { - msg_perr("Density of ICH SPI component with index %d is invalid. Encoded density is 0x%x.\n", - idx, size_enc); - return 0; + + if (size_enc > size_max) { + msg_perr("Density of ICH SPI component with index %d is invalid." + "Encoded density is 0x%x while maximum allowed is 0x%x.\n", + idx, size_enc, size_max); + return -1; } + return (1 << (19 + size_enc)); }
diff --git a/ich_descriptors.h b/ich_descriptors.h index 3a44740..b9213c8 100644 --- a/ich_descriptors.h +++ b/ich_descriptors.h @@ -102,17 +102,44 @@ struct ich_desc_content { struct ich_desc_component { union { /* 0x00 */ uint32_t FLCOMP; /* Flash Components Register */ + /* FLCOMP encoding on various generations: + * + * Chipset/Generation max_speed dual_output density + * [MHz] bits max. bits + * ICH8: 33 N/A 5 0:2, 3:5 + * ICH9: 33 N/A 5 0:2, 3:5 + * ICH10: 33 N/A 5 0:2, 3:5 + * Ibex Peak/5: 50 N/A 5 0:2, 3:5 + * Cougar Point/6: 50 30 5 0:2, 3:5 + * Patsburg: 50 30 5 0:2, 3:5 + * Panther Point/7 50 30 5 0:2, 3:5 + * Lynx Point/8: 50 30 7 0:3, 4:7 + * Wildcat Point/9: 50 ?? (multi I/O) ? ?:?, ?:? + */ struct { - uint32_t comp1_density :3, - comp2_density :3, - :11, + uint32_t :17, freq_read :3, fastread :1, freq_fastread :3, freq_write :3, freq_read_id :3, :2; - }; + } common; + struct { + uint32_t comp1_density :3, + comp2_density :3, + :11, + :13, + :2; + } old; + struct { + uint32_t comp1_density :4, /* new since Lynx Point/8 */ + comp2_density :4, + :9, + :13, + dual_output :1, /* new since Cougar Point/6 */ + :1; + } new; }; union { /* 0x04 */ uint32_t FLILL; /* Flash Invalid Instructions Register */ @@ -555,7 +582,7 @@ struct ich_descriptors { void prettyprint_ich_descriptors(enum ich_chipset cs, const struct ich_descriptors *desc);
void prettyprint_ich_descriptor_content(const struct ich_desc_content *content); -void prettyprint_ich_descriptor_component(const struct ich_descriptors *desc); +void prettyprint_ich_descriptor_component(enum ich_chipset cs, const struct ich_descriptors *desc); void prettyprint_ich_descriptor_region(const struct ich_descriptors *desc); void prettyprint_ich_descriptor_master(const struct ich_desc_master *master);
@@ -568,7 +595,7 @@ int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, struc #else /* ICH_DESCRIPTORS_FROM_DUMP */
int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc); -int getFCBA_component_density(const struct ich_descriptors *desc, uint8_t idx); +int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx);
#endif /* ICH_DESCRIPTORS_FROM_DUMP */ #endif /* __ICH_DESCRIPTORS_H__ */ diff --git a/ichspi.c b/ichspi.c index 90bb0de..6744bef 100644 --- a/ichspi.c +++ b/ichspi.c @@ -1754,10 +1754,9 @@ int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_gen)
msg_pdbg("\n"); if (desc_valid) { - if (read_ich_descriptors_via_fdo(ich_spibar, &desc) == - ICH_RET_OK) - prettyprint_ich_descriptors(CHIPSET_ICH_UNKNOWN, - &desc); + if (read_ich_descriptors_via_fdo(ich_spibar, &desc) == ICH_RET_OK) + prettyprint_ich_descriptors(ich_gen, &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. @@ -1783,8 +1782,21 @@ int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_gen) "valid. Aborting.\n"); return ERROR_FATAL; } - hwseq_data.size_comp0 = getFCBA_component_density(&desc, 0); - hwseq_data.size_comp1 = getFCBA_component_density(&desc, 1); + + int tmpi = getFCBA_component_density(ich_generation, &desc, 0); + if (tmpi < 0) { + msg_perr("Could not determine density of flash component %d.\n", 0); + return ERROR_FATAL; + } + hwseq_data.size_comp0 = tmpi; + + tmpi = getFCBA_component_density(ich_generation, &desc, 1); + if (tmpi < 0) { + msg_perr("Could not determine density of flash component %d.\n", 1); + return ERROR_FATAL; + } + hwseq_data.size_comp1 = tmpi; + register_opaque_master(&opaque_master_ich_hwseq); } else { register_spi_master(&spi_master_ich9); diff --git a/util/ich_descriptors_tool/ich_descriptors_tool.c b/util/ich_descriptors_tool/ich_descriptors_tool.c index 00ad1f3..4c1f05c 100644 --- a/util/ich_descriptors_tool/ich_descriptors_tool.c +++ b/util/ich_descriptors_tool/ich_descriptors_tool.c @@ -121,6 +121,7 @@ static void usage(char *argv[], char *error) "\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" +"\t- "8" or "lynx" for Intel's 8 series chipsets.\n" "If '-d' is specified some regions such as the BIOS image as seen by the CPU or\n" "the GbE blob that is required to initialize the GbE are also dumped to files.\n", argv[0], argv[0]); @@ -198,6 +199,9 @@ int main(int argc, char *argv[]) else if ((strcmp(csn, "7") == 0) || (strcmp(csn, "panther") == 0)) cs = CHIPSET_7_SERIES_PANTHER_POINT; + else if ((strcmp(csn, "8") == 0) || + (strcmp(csn, "lynx") == 0)) + cs = CHIPSET_8_SERIES_LYNX_POINT; }
ret = read_ich_descriptors_from_dump(buf, len, &desc);