Author: stefanct
Date: Wed Aug 20 17:39:19 2014
New Revision: 1843
URL: http://flashrom.org/trac/flashrom/changeset/1843

Log:
Refine Flash Component descriptor handling.

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 <[email protected]>
Acked-by: Stefan Tauner <[email protected]>

Modified:
   trunk/ich_descriptors.c
   trunk/ich_descriptors.h
   trunk/ichspi.c
   trunk/util/ich_descriptors_tool/ich_descriptors_tool.c

Modified: trunk/ich_descriptors.c
==============================================================================
--- trunk/ich_descriptors.c     Fri Aug 15 19:17:59 2014        (r1842)
+++ trunk/ich_descriptors.c     Wed Aug 20 17:39:19 2014        (r1843)
@@ -45,14 +45,16 @@
 #define min(a, b) (a < b) ? a : b
 #endif
 
-void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity)
+void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
 {
        print(verbosity, "BES=0x%x, ",  (reg_val & VSCC_BES)  >> VSCC_BES_OFF);
        print(verbosity, "WG=%d, ",     (reg_val & VSCC_WG)   >> VSCC_WG_OFF);
        print(verbosity, "WSR=%d, ",    (reg_val & VSCC_WSR)  >> VSCC_WSR_OFF);
        print(verbosity, "WEWS=%d, ",   (reg_val & VSCC_WEWS) >> VSCC_WEWS_OFF);
-       print(verbosity, "EO=0x%x, ",   (reg_val & VSCC_EO)   >> VSCC_EO_OFF);
-       print(verbosity, "VCL=%d\n",    (reg_val & VSCC_VCL)  >> VSCC_VCL_OFF);
+       print(verbosity, "EO=0x%x",     (reg_val & VSCC_EO)   >> VSCC_EO_OFF);
+       if (print_vcl)
+               print(verbosity, ", VCL=%d", (reg_val & VSCC_VCL)  >> 
VSCC_VCL_OFF);
+       print(verbosity, "\n");
 }
 
 #define getFCBA(cont)  (((cont)->FLMAP0 <<  4) & 0x00000ff0)
@@ -64,7 +66,7 @@
 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 +100,97 @@
        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 +198,21 @@
        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 +341,7 @@
        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;
@@ -630,7 +698,7 @@
                msg_pdbg2("    "); /* indention */
                prettyprint_rdid(jid);
                msg_pdbg2("    "); /* indention */
-               prettyprint_ich_reg_vscc(vscc, 0);
+               prettyprint_ich_reg_vscc(vscc, 0, false);
        }
        msg_pdbg2("\n");
 }
@@ -723,29 +791,57 @@
 #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;
-               break;
-       case 1:
-               if (desc->content.NC == 0)
-                       return 0;
-               size_enc = desc->component.comp2_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 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));
 }
 

Modified: trunk/ich_descriptors.h
==============================================================================
--- trunk/ich_descriptors.h     Fri Aug 15 19:17:59 2014        (r1842)
+++ trunk/ich_descriptors.h     Wed Aug 20 17:39:19 2014        (r1843)
@@ -64,7 +64,7 @@
 #define ICH_FREG_BASE(flreg)  (((flreg) << 12) & 0x01fff000)
 #define ICH_FREG_LIMIT(flreg) (((flreg) >>  4) & 0x01fff000)
 
-void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity);
+void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl);
 
 struct ich_desc_content {
        uint32_t FLVALSIG;      /* 0x00 */
@@ -102,17 +102,44 @@
 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 @@
 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 @@
 #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__ */

Modified: trunk/ichspi.c
==============================================================================
--- trunk/ichspi.c      Fri Aug 15 19:17:59 2014        (r1842)
+++ trunk/ichspi.c      Wed Aug 20 17:39:19 2014        (r1843)
@@ -1737,7 +1737,7 @@
                        tmp = mmio_readl(ich_spibar + ICH8_REG_VSCC);
                        msg_pdbg("0xC1: 0x%08x (VSCC)\n", tmp);
                        msg_pdbg("VSCC: ");
-                       prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);
+                       prettyprint_ich_reg_vscc(tmp, MSG_DEBUG, true);
                } else {
                        ichspi_bbar = mmio_readl(ich_spibar + ICH9_REG_BBAR);
                        msg_pdbg("0xA0: 0x%08x (BBAR)\n",
@@ -1747,12 +1747,12 @@
                                tmp = mmio_readl(ich_spibar + ICH9_REG_LVSCC);
                                msg_pdbg("0xC4: 0x%08x (LVSCC)\n", tmp);
                                msg_pdbg("LVSCC: ");
-                               prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);
+                               prettyprint_ich_reg_vscc(tmp, MSG_DEBUG, true);
 
                                tmp = mmio_readl(ich_spibar + ICH9_REG_UVSCC);
                                msg_pdbg("0xC8: 0x%08x (UVSCC)\n", tmp);
                                msg_pdbg("UVSCC: ");
-                               prettyprint_ich_reg_vscc(tmp, MSG_DEBUG);
+                               prettyprint_ich_reg_vscc(tmp, MSG_DEBUG, false);
 
                                tmp = mmio_readl(ich_spibar + ICH9_REG_FPB);
                                msg_pdbg("0xD0: 0x%08x (FPB)\n", tmp);
@@ -1762,10 +1762,9 @@
 
                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.
@@ -1791,8 +1790,21 @@
                                         "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);

Modified: trunk/util/ich_descriptors_tool/ich_descriptors_tool.c
==============================================================================
--- trunk/util/ich_descriptors_tool/ich_descriptors_tool.c      Fri Aug 15 
19:17:59 2014        (r1842)
+++ trunk/util/ich_descriptors_tool/ich_descriptors_tool.c      Wed Aug 20 
17:39:19 2014        (r1843)
@@ -113,7 +113,7 @@
 "where <image file name> points to an image of the contents of the SPI 
flash.\n"
 "In case the image is really in descriptor mode %s\n"
 "will pretty print some of the contained information.\n"
-"To also print the data stored in the descriptor strap you have to indicate\n"
+"To also print the data stored in the descriptor straps you have to indicate\n"
 "the chipset series with the '-c' parameter and one of the possible 
arguments:\n"
 "\t- \"ich8\",\n"
 "\t- \"ich9\",\n"
@@ -121,6 +121,7 @@
 "\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 @@
                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);

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to