Author: stefanct
Date: Fri Oct 25 02:33:37 2013
New Revision: 1761
URL: http://flashrom.org/trac/flashrom/changeset/1761

Log:
Refactor Intel Chipset Enables.

 - Combine enable_flash_ich_4e() and enable_flash_ich_dc() to
   enable_flash_ich_fwh().
 - Remove unjustified (chipset) name parameters from various
   enable_flash_ich* functions.
 - Make Poulsbo and Tunnel Creek use generic enables by refining existing
   functions to work with them, including everything in ichspi.c.
 - Refactor enable_flash_ich_fwh_decode() to be called unconditionally for
   all chipsets.
 - Add support for Intel Atom Centerton (S12x0).
 - Recombine ICH2/3/4/5 to CHIPSET_ICH2345 because we treat them equally
   anyway.
 - Move spibar handling out of ich_init_spi() into enable_flash_ich_spi()
 - Various small cleanups.

Signed-off-by: Stefan Tauner <[email protected]>
Acked-by: Stefan Tauner <[email protected]>

Modified:
   trunk/chipset_enable.c
   trunk/ichspi.c
   trunk/programmer.h

Modified: trunk/chipset_enable.c
==============================================================================
--- trunk/chipset_enable.c      Mon Oct 21 23:49:08 2013        (r1760)
+++ trunk/chipset_enable.c      Fri Oct 25 02:33:37 2013        (r1761)
@@ -260,20 +260,44 @@
        return 0;
 }
 
-/*
- * See ie. page 375 of "Intel I/O Controller Hub 7 (ICH7) Family Datasheet"
- * http://download.intel.com/design/chipsets/datashts/30701303.pdf
- */
-static int enable_flash_ich(struct pci_dev *dev, const char *name, uint8_t 
bios_cntl)
+/* Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, in Poulsbo, 
Tunnel Creek and other Atom
+ * chipsets/SoCs it is even 32b, but just treating it as 8 bit wide seems to 
work fine in practice. */
+static int enable_flash_ich_bios_cntl(struct pci_dev *dev, enum ich_chipset 
ich_generation, uint8_t bios_cntl)
 {
        uint8_t old, new, wanted;
 
-       /*
-        * Note: the ICH0-ICH5 BIOS_CNTL register is actually 16 bit wide, in 
Tunnel Creek it is even 32b, but
-        * just treating it as 8 bit wide seems to work fine in practice.
-        */
-       wanted = old = pci_read_byte(dev, bios_cntl);
+       switch (ich_generation) {
+       case CHIPSET_ICH_UNKNOWN:
+               return ERROR_FATAL;
+       /* Non-SPI-capable */
+       case CHIPSET_ICH:
+       case CHIPSET_ICH2345:
+               break;
+       /* Atom chipsets are special: The second byte of BIOS_CNTL (D9h) 
contains a prefetch bit similar to what
+        * other SPI-capable chipsets have at DCh.
+        * The Tunnel Creek datasheet contains a lot of details about the SPI 
controller, among other things it
+        * mentions that the prefetching and caching does only happen for 
direct memory reads.
+        * Therefore - at least for Tunnel Creek - it should not matter to 
flashrom because we use the
+        * programmed access only and not memory mapping. */
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_POULSBO:
+       case CHIPSET_CENTERTON:
+               old = pci_read_byte(dev, bios_cntl + 1);
+               msg_pdbg("BIOS Prefetch Enable: %sabled, ", (old & 1) ? "en" : 
"dis");
+               break;
+       case CHIPSET_ICH7:
+       default: /* Future version might behave the same */
+               old = (pci_read_byte(dev, bios_cntl) >> 2) & 0x3;
+               msg_pdbg("SPI Read Configuration: ");
+               if (old == 3)
+                       msg_pdbg("invalid prefetching/caching settings, ");
+               else
+                       msg_pdbg("prefetching %sabled, caching %sabled, ",
+                                    (old & 0x2) ? "en" : "dis",
+                                    (old & 0x1) ? "dis" : "en");
+       }
 
+       wanted = old = pci_read_byte(dev, bios_cntl);
        /*
         * Quote from the 6 Series datasheet (Document Number: 324645-004):
         * "Bit 5: SMM BIOS Write Protect Disable (SMM_BWP)
@@ -283,11 +307,23 @@
         *
         * Try to unset it in any case.
         * It won't hurt and makes sense in some cases according to Stefan 
Reinauer.
+        *
+        * At least in Centerton aforementioned bit is located at bit 7. It is 
unspecified in all other Atom
+        * and Desktop chipsets before Ibex Peak/5 Series, but we reset bit 5 
anyway.
         */
-       wanted &= ~(1 << 5);
+       int smm_bwp_bit;
+       if (ich_generation == CHIPSET_CENTERTON)
+               smm_bwp_bit = 7;
+       else
+               smm_bwp_bit = 5;
+       wanted &= ~(1 << smm_bwp_bit);
+
+       /* Tunnel Creek has a cache disable at bit 2 of the lowest BIOS_CNTL 
byte. */
+       if (ich_generation == CHIPSET_TUNNEL_CREEK)
+               wanted |= (1 << 2);
 
-       /* Set BIOS Write Enable */
-       wanted |= (1 << 0);
+       wanted |= (1 << 0); /* Set BIOS Write Enable */
+       wanted &= ~(1 << 1); /* Disable lock (futile) */
 
        /* Only write the register if it's necessary */
        if (wanted != old) {
@@ -299,76 +335,77 @@
        msg_pdbg("\nBIOS_CNTL = 0x%02x: ", new);
        msg_pdbg("BIOS Lock Enable: %sabled, ", (new & (1 << 1)) ? "en" : 
"dis");
        msg_pdbg("BIOS Write Enable: %sabled\n", (new & (1 << 0)) ? "en" : 
"dis");
-       if (new & (1 << 5))
+       if (new & (1 << smm_bwp_bit))
                msg_pwarn("Warning: BIOS region SMM protection is enabled!\n");
 
-
        if (new != wanted)
-               msg_pwarn("Warning: Setting Bios Control at 0x%x from 0x%02x to 
0x%02x on %s failed.\n"
-                         "New value is 0x%02x.\n", bios_cntl, old, wanted, 
name, new);
+               msg_pwarn("Warning: Setting Bios Control at 0x%x from 0x%02x to 
0x%02x failed.\n"
+                         "New value is 0x%02x.\n", bios_cntl, old, wanted, 
new);
 
-       /* Return an error if we could not set the write enable */
+       /* Return an error if we could not set the write enable only. */
        if (!(new & (1 << 0)))
                return -1;
 
        return 0;
 }
 
-static int enable_flash_ich0(struct pci_dev *dev, const char *name)
+static int enable_flash_ich_fwh_decode(struct pci_dev *dev, enum ich_chipset 
ich_generation)
 {
-       internal_buses_supported = BUS_FWH;
-       /* FIXME: Make this use enable_flash_ich_4e() too and add IDSEL 
support. Unlike later chipsets,
-        * ICH and ICH-0 do only support mapping of the top-most 4MB and 
therefore do only feature
-        * FWH_DEC_EN (E3h, different default too) and FWH_SEL (E8h). */
-       return enable_flash_ich(dev, name, 0x4e);
-}
-
-static int enable_flash_ich_fwh_decode(struct pci_dev *dev, const char *name, 
enum ich_chipset ich_generation)
-{
-       uint32_t fwh_conf;
-       uint8_t fwh_sel1, fwh_sel2, fwh_dec_en_lo, fwh_dec_en_hi;
-       int i, tmp;
-       char *idsel = NULL;
-       int max_decode_fwh_idsel = 0, max_decode_fwh_decode = 0;
-       int contiguous = 1;
-
-       if (ich_generation >= CHIPSET_ICH6) {
-               fwh_sel1 = 0xd0;
-               fwh_sel2 = 0xd4;
-               fwh_dec_en_lo = 0xd8;
-               fwh_dec_en_hi = 0xd9;
-       } else if (ich_generation >= CHIPSET_ICH2) {
+       uint8_t fwh_sel1 = 0, fwh_sel2 = 0, fwh_dec_en_lo = 0, fwh_dec_en_hi = 
0; /* silence compilers */
+       bool implemented = 0;
+       switch (ich_generation) {
+       case CHIPSET_ICH:
+               /* FIXME: Unlike later chipsets, ICH and ICH-0 do only support 
mapping of the top-most 4MB
+                * and therefore do only feature FWH_DEC_EN (E3h, different 
default too) and FWH_SEL (E8h). */
+               break;
+       case CHIPSET_ICH2345:
                fwh_sel1 = 0xe8;
                fwh_sel2 = 0xee;
                fwh_dec_en_lo = 0xf0;
                fwh_dec_en_hi = 0xe3;
-       } else {
-               msg_perr("Error: FWH decode setting not implemented.\n");
-               return ERROR_FATAL;
+               implemented = 1;
+               break;
+       case CHIPSET_POULSBO:
+       case CHIPSET_TUNNEL_CREEK:
+               /* FIXME: Similar to ICH and ICH-0, Tunnel Creek and Poulsbo do 
only feature one register each,
+                * FWH_DEC_EN (D7h) and FWH_SEL (D0h). */
+               break;
+       case CHIPSET_CENTERTON:
+               /* FIXME: Similar to above FWH_DEC_EN (D4h) and FWH_SEL (D0h). 
*/
+               break;
+       case CHIPSET_ICH6:
+       case CHIPSET_ICH7:
+       default: /* Future version might behave the same */
+               fwh_sel1 = 0xd0;
+               fwh_sel2 = 0xd4;
+               fwh_dec_en_lo = 0xd8;
+               fwh_dec_en_hi = 0xd9;
+               implemented = 1;
+               break;
        }
 
-       idsel = extract_programmer_param("fwh_idsel");
+       char *idsel = extract_programmer_param("fwh_idsel");
        if (idsel && strlen(idsel)) {
-               uint64_t fwh_idsel_old, fwh_idsel;
+               if (!implemented) {
+                       msg_perr("Error: fwh_idsel= specified, but (yet) 
unsupported on this chipset.\n");
+                       goto idsel_garbage_out;
+               }
                errno = 0;
                /* Base 16, nothing else makes sense. */
-               fwh_idsel = (uint64_t)strtoull(idsel, NULL, 16);
+               uint64_t fwh_idsel = (uint64_t)strtoull(idsel, NULL, 16);
                if (errno) {
-                       msg_perr("Error: fwh_idsel= specified, but value could "
-                                "not be converted.\n");
+                       msg_perr("Error: fwh_idsel= specified, but value could 
not be converted.\n");
                        goto idsel_garbage_out;
                }
                if (fwh_idsel & 0xffff000000000000ULL) {
-                       msg_perr("Error: fwh_idsel= specified, but value had "
-                                "unused bits set.\n");
+                       msg_perr("Error: fwh_idsel= specified, but value had 
unused bits set.\n");
                        goto idsel_garbage_out;
                }
-               fwh_idsel_old = pci_read_long(dev, fwh_sel1);
+               uint64_t fwh_idsel_old = pci_read_long(dev, fwh_sel1);
                fwh_idsel_old <<= 16;
                fwh_idsel_old |= pci_read_word(dev, fwh_sel2);
-               msg_pdbg("\nSetting IDSEL from 0x%012" PRIx64 " to "
-                        "0x%012" PRIx64 " for top 16 MB.", fwh_idsel_old,
-                        fwh_idsel);
+               msg_pdbg("\nSetting IDSEL from 0x%012" PRIx64 " to 0x%012" 
PRIx64 " for top 16 MB.",
+                        fwh_idsel_old, fwh_idsel);
                rpci_write_long(dev, fwh_sel1, (fwh_idsel >> 16) & 0xffffffff);
                rpci_write_word(dev, fwh_sel2, fwh_idsel & 0xffff);
                /* FIXME: Decode settings are not changed. */
@@ -380,15 +417,23 @@
        }
        free(idsel);
 
+       if (!implemented) {
+               msg_pdbg2("FWH IDSEL handling is not implemented on this 
chipset.");
+               return 0;
+       }
+
        /* Ignore all legacy ranges below 1 MB.
         * We currently only support flashing the chip which responds to
         * IDSEL=0. To support IDSEL!=0, flashbase and decode size calculations
         * have to be adjusted.
         */
+       int max_decode_fwh_idsel = 0, max_decode_fwh_decode = 0;
+       bool contiguous = 1;
+       uint32_t fwh_conf = pci_read_long(dev, fwh_sel1);
+       int i;
        /* FWH_SEL1 */
-       fwh_conf = pci_read_long(dev, fwh_sel1);
        for (i = 7; i >= 0; i--) {
-               tmp = (fwh_conf >> (i * 4)) & 0xf;
+               int tmp = (fwh_conf >> (i * 4)) & 0xf;
                msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x",
                         (0x1ff8 + i) * 0x80000,
                         (0x1ff0 + i) * 0x80000,
@@ -402,7 +447,7 @@
        /* FWH_SEL2 */
        fwh_conf = pci_read_word(dev, fwh_sel2);
        for (i = 3; i >= 0; i--) {
-               tmp = (fwh_conf >> (i * 4)) & 0xf;
+               int tmp = (fwh_conf >> (i * 4)) & 0xf;
                msg_pdbg("\n0x%08x/0x%08x FWH IDSEL: 0x%x",
                         (0xff4 + i) * 0x100000,
                         (0xff0 + i) * 0x100000,
@@ -419,7 +464,7 @@
        fwh_conf <<= 8;
        fwh_conf |= pci_read_byte(dev, fwh_dec_en_lo);
        for (i = 7; i >= 0; i--) {
-               tmp = (fwh_conf >> (i + 0x8)) & 0x1;
+               int tmp = (fwh_conf >> (i + 0x8)) & 0x1;
                msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled",
                         (0x1ff8 + i) * 0x80000,
                         (0x1ff0 + i) * 0x80000,
@@ -431,7 +476,7 @@
                }
        }
        for (i = 3; i >= 0; i--) {
-               tmp = (fwh_conf >> i) & 0x1;
+               int tmp = (fwh_conf >> i) & 0x1;
                msg_pdbg("\n0x%08x/0x%08x FWH decode %sabled",
                         (0xff4 + i) * 0x100000,
                         (0xff0 + i) * 0x100000,
@@ -448,146 +493,56 @@
        return 0;
 }
 
-static int enable_flash_ich_4e(struct pci_dev *dev, const char *name, enum 
ich_chipset ich_generation)
+static int enable_flash_ich_fwh(struct pci_dev *dev, enum ich_chipset 
ich_generation, uint8_t bios_cntl)
 {
        int err;
 
        /* Configure FWH IDSEL decoder maps. */
-       if ((err = enable_flash_ich_fwh_decode(dev, name, ich_generation)) != 0)
+       if ((err = enable_flash_ich_fwh_decode(dev, ich_generation)) != 0)
                return err;
 
        internal_buses_supported = BUS_FWH;
-       return enable_flash_ich(dev, name, 0x4e);
+       return enable_flash_ich_bios_cntl(dev, ich_generation, bios_cntl);
 }
 
-static int enable_flash_ich2(struct pci_dev *dev, const char *name)
-{
-       return enable_flash_ich_4e(dev, name, CHIPSET_ICH2);
-}
-
-static int enable_flash_ich3(struct pci_dev *dev, const char *name)
-{
-       return enable_flash_ich_4e(dev, name, CHIPSET_ICH3);
-}
-
-static int enable_flash_ich4(struct pci_dev *dev, const char *name)
+static int enable_flash_ich0(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_4e(dev, name, CHIPSET_ICH4);
+       return enable_flash_ich_fwh(dev, CHIPSET_ICH, 0x4e);
 }
 
-static int enable_flash_ich5(struct pci_dev *dev, const char *name)
+static int enable_flash_ich2345(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_4e(dev, name, CHIPSET_ICH5);
-}
-
-static int enable_flash_ich_dc(struct pci_dev *dev, const char *name, enum 
ich_chipset ich_generation)
-{
-       int err;
-
-       /* Configure FWH IDSEL decoder maps. */
-       if ((err = enable_flash_ich_fwh_decode(dev, name, ich_generation)) != 0)
-               return err;
-
-       /* If we're called by enable_flash_ich_dc_spi, it will override
-        * internal_buses_supported anyway.
-        */
-       internal_buses_supported = BUS_FWH;
-       return enable_flash_ich(dev, name, 0xdc);
+       return enable_flash_ich_fwh(dev, CHIPSET_ICH2345, 0x4e);
 }
 
 static int enable_flash_ich6(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc(dev, name, CHIPSET_ICH6);
+       return enable_flash_ich_fwh(dev, CHIPSET_ICH6, 0xdc);
 }
 
 static int enable_flash_poulsbo(struct pci_dev *dev, const char *name)
 {
-       uint16_t old, new;
-       int err;
-
-       if ((err = enable_flash_ich(dev, name, 0xd8)) != 0)
-               return err;
-
-       old = pci_read_byte(dev, 0xd9);
-       msg_pdbg("BIOS Prefetch Enable: %sabled, ",
-                (old & 1) ? "en" : "dis");
-       new = old & ~1;
-
-       if (new != old)
-               rpci_write_byte(dev, 0xd9, new);
-
-       internal_buses_supported = BUS_FWH;
-       return 0;
-}
-
-static int enable_flash_tunnelcreek(struct pci_dev *dev, const char *name)
-{
-       uint16_t old, new;
-       uint32_t tmp, bnt;
-       void *rcrb;
-       int ret;
-
-       /* Enable Flash Writes */
-       ret = enable_flash_ich(dev, name, 0xd8);
-       if (ret == ERROR_FATAL)
-               return ret;
-
-       /* Make sure BIOS prefetch mechanism is disabled */
-       old = pci_read_byte(dev, 0xd9);
-       msg_pdbg("BIOS Prefetch Enable: %sabled, ", (old & 1) ? "en" : "dis");
-       new = old & ~1;
-       if (new != old)
-               rpci_write_byte(dev, 0xd9, new);
-
-       /* Get physical address of Root Complex Register Block */
-       tmp = pci_read_long(dev, 0xf0) & 0xffffc000;
-       msg_pdbg("\nRoot Complex Register Block address = 0x%x\n", tmp);
-
-       /* Map RCBA to virtual memory */
-       rcrb = rphysmap("ICH RCRB", tmp, 0x4000);
-       if (rcrb == ERROR_PTR)
-               return ERROR_FATAL;
-
-       /* Test Boot BIOS Strap Status */
-       bnt = mmio_readl(rcrb + 0x3410);
-       if (bnt & 0x02) {
-               /* If strapped to LPC, no SPI initialization is required */
-               internal_buses_supported = BUS_FWH;
-               return 0;
-       }
-
-       /* This adds BUS_SPI */
-       if (ich_init_spi(dev, tmp, rcrb, 7) != 0) {
-               if (!ret)
-                       ret = ERROR_NONFATAL;
-       }
-
-       return ret;
+       return enable_flash_ich_fwh(dev, CHIPSET_POULSBO, 0xd8);
 }
 
-static int enable_flash_ich_dc_spi(struct pci_dev *dev, const char *name,
-                                  enum ich_chipset ich_generation)
+static int enable_flash_ich_spi(struct pci_dev *dev, enum ich_chipset 
ich_generation, uint8_t bios_cntl)
 {
-       int ret, ret_spi;
-       uint8_t bbs, buc;
-       uint32_t tmp, gcs;
-       void *rcrb;
-       const char *const *straps_names;
-
        static const char *const straps_names_EP80579[] = { "SPI", "reserved", 
"reserved", "LPC" };
        static const char *const straps_names_ich7_nm10[] = { "reserved", 
"SPI", "PCI", "LPC" };
+       static const char *const straps_names_tunnel_creek[] = { "SPI", "LPC" };
        static const char *const straps_names_ich8910[] = { "SPI", "SPI", 
"PCI", "LPC" };
        static const char *const straps_names_pch567[] = { "LPC", "reserved", 
"PCI", "SPI" };
        static const char *const straps_names_pch8[] = { "LPC", "reserved", 
"reserved", "SPI" };
-       static const char *const straps_names_pch8_lp[] = { "SPI", "LPC", 
"unknown", "unknown" };
+       static const char *const straps_names_pch8_lp[] = { "SPI", "LPC" };
        static const char *const straps_names_unknown[] = { "unknown", 
"unknown", "unknown", "unknown" };
 
+       const char *const *straps_names;
        switch (ich_generation) {
        case CHIPSET_ICH7:
                /* EP80579 may need further changes, but this is the least
                 * intrusive way to get correct BOOT Strap printing without
                 * changing the rest of its code path). */
-               if (strcmp(name, "EP80579") == 0)
+               if (dev->device_id == 0x5031)
                        straps_names = straps_names_EP80579;
                else
                        straps_names = straps_names_ich7_nm10;
@@ -597,6 +552,9 @@
        case CHIPSET_ICH10:
                straps_names = straps_names_ich8910;
                break;
+       case CHIPSET_TUNNEL_CREEK:
+               straps_names = straps_names_tunnel_creek;
+               break;
        case CHIPSET_5_SERIES_IBEX_PEAK:
        case CHIPSET_6_SERIES_COUGAR_POINT:
        case CHIPSET_7_SERIES_PANTHER_POINT:
@@ -609,35 +567,33 @@
                straps_names = straps_names_pch8_lp;
                break;
        case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet
+       case CHIPSET_CENTERTON: // FIXME: Datasheet does not mention GCS at all
                straps_names = straps_names_unknown;
                break;
        default:
-               msg_gerr("%s: unknown ICH generation. Please report!\n",
-                        __func__);
+               msg_gerr("%s: unknown ICH generation. Please report!\n", 
__func__);
                straps_names = straps_names_unknown;
                break;
        }
 
-       /* Enable Flash Writes */
-       ret = enable_flash_ich_dc(dev, name, ich_generation);
-       if (ret == ERROR_FATAL)
-               return ret;
-
        /* Get physical address of Root Complex Register Block */
-       tmp = pci_read_long(dev, 0xf0) & 0xffffc000;
-       msg_pdbg("Root Complex Register Block address = 0x%x\n", tmp);
+       uint32_t rcra = pci_read_long(dev, 0xf0) & 0xffffc000;
+       msg_pdbg("Root Complex Register Block address = 0x%x\n", rcra);
 
        /* Map RCBA to virtual memory */
-       rcrb = rphysmap("ICH RCRB", tmp, 0x4000);
+       void *rcrb = rphysmap("ICH RCRB", rcra, 0x4000);
        if (rcrb == ERROR_PTR)
                return ERROR_FATAL;
 
-       gcs = mmio_readl(rcrb + 0x3410);
+       uint32_t gcs = mmio_readl(rcrb + 0x3410);
        msg_pdbg("GCS = 0x%x: ", gcs);
-       msg_pdbg("BIOS Interface Lock-Down: %sabled, ",
-                (gcs & 0x1) ? "en" : "dis");
+       msg_pdbg("BIOS Interface Lock-Down: %sabled, ", (gcs & 0x1) ? "en" : 
"dis");
 
+       uint8_t bbs;
        switch (ich_generation) {
+       case CHIPSET_TUNNEL_CREEK:
+               bbs = (gcs >> 1) & 0x1;
+               break;
        case CHIPSET_8_SERIES_LYNX_POINT_LP:
        case CHIPSET_8_SERIES_WELLSBURG: // FIXME: check datasheet
                /* Lynx Point LP uses a single bit for GCS */
@@ -650,91 +606,110 @@
        }
        msg_pdbg("Boot BIOS Straps: 0x%x (%s)\n", bbs, straps_names[bbs]);
 
-       buc = mmio_readb(rcrb + 0x3414);
-       msg_pdbg("Top Swap : %s\n",
-                (buc & 1) ? "enabled (A16 inverted)" : "not enabled");
-
-       /* It seems the ICH7 does not support SPI and LPC chips at the same
-        * time. At least not with our current code. So we prevent searching
-        * on ICH7 when the southbridge is strapped to LPC
-        */
-       internal_buses_supported = BUS_FWH;
-       if (ich_generation == CHIPSET_ICH7) {
-               if (bbs == 0x03) {
-                       /* If strapped to LPC, no further SPI initialization is
-                        * required. */
-                       return ret;
-               } else {
-                       /* Disable LPC/FWH if strapped to PCI or SPI */
-                       internal_buses_supported = BUS_NONE;
-               }
+       if (ich_generation != CHIPSET_TUNNEL_CREEK && ich_generation != 
CHIPSET_CENTERTON) {
+               uint8_t buc = mmio_readb(rcrb + 0x3414);
+               msg_pdbg("Top Swap : %s\n", (buc & 1) ? "enabled (A16(+) 
inverted)" : "not enabled");
+       }
+
+       /* Handle FWH-related parameters and initialization */
+       int ret_fwh = enable_flash_ich_fwh(dev, ich_generation, bios_cntl);
+       if (ret_fwh == ERROR_FATAL)
+               return ret_fwh;
+
+       /* SPIBAR is at RCRB+0x3020 for ICH[78], Tunnel Creek and Centerton, 
and RCRB+0x3800 for ICH9. */
+       uint16_t spibar_offset;
+       switch (ich_generation) {
+       case CHIPSET_ICH_UNKNOWN:
+               return ERROR_FATAL;
+       case CHIPSET_ICH7:
+       case CHIPSET_ICH8:
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_CENTERTON:
+               spibar_offset = 0x3020;
+               break;
+       case CHIPSET_ICH9:
+       default:                /* Future version might behave the same */
+               spibar_offset = 0x3800;
+               break;
        }
+       msg_pdbg("SPIBAR = 0x%0*" PRIxPTR " + 0x%04x\n", PRIxPTR_WIDTH, 
(uintptr_t)rcrb, spibar_offset);
+       void *spibar = rcrb + spibar_offset;
 
        /* This adds BUS_SPI */
-       ret_spi = ich_init_spi(dev, tmp, rcrb, ich_generation);
+       int ret_spi = ich_init_spi(dev, spibar, ich_generation);
        if (ret_spi == ERROR_FATAL)
                return ret_spi;
        
-       if (ret || ret_spi)
-               ret = ERROR_NONFATAL;
+       if (ret_fwh || ret_spi)
+               return ERROR_NONFATAL;
 
-       return ret;
+       return 0;
+}
+
+static int enable_flash_tunnelcreek(struct pci_dev *dev, const char *name)
+{
+       return enable_flash_ich_spi(dev, CHIPSET_TUNNEL_CREEK, 0xd8);
+}
+
+static int enable_flash_s12x0(struct pci_dev *dev, const char *name)
+{
+       return enable_flash_ich_spi(dev, CHIPSET_CENTERTON, 0xd8);
 }
 
 static int enable_flash_ich7(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH7);
+       return enable_flash_ich_spi(dev, CHIPSET_ICH7, 0xdc);
 }
 
 static int enable_flash_ich8(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH8);
+       return enable_flash_ich_spi(dev, CHIPSET_ICH8, 0xdc);
 }
 
 static int enable_flash_ich9(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH9);
+       return enable_flash_ich_spi(dev, CHIPSET_ICH9, 0xdc);
 }
 
 static int enable_flash_ich10(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_ICH10);
+       return enable_flash_ich_spi(dev, CHIPSET_ICH10, 0xdc);
 }
 
 /* Ibex Peak aka. 5 series & 3400 series */
 static int enable_flash_pch5(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_5_SERIES_IBEX_PEAK);
+       return enable_flash_ich_spi(dev, CHIPSET_5_SERIES_IBEX_PEAK, 0xdc);
 }
 
 /* Cougar Point aka. 6 series & c200 series */
 static int enable_flash_pch6(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, 
CHIPSET_6_SERIES_COUGAR_POINT);
+       return enable_flash_ich_spi(dev, CHIPSET_6_SERIES_COUGAR_POINT, 0xdc);
 }
 
 /* Panther Point aka. 7 series */
 static int enable_flash_pch7(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, 
CHIPSET_7_SERIES_PANTHER_POINT);
+       return enable_flash_ich_spi(dev, CHIPSET_7_SERIES_PANTHER_POINT, 0xdc);
 }
 
 /* Lynx Point aka. 8 series */
 static int enable_flash_pch8(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_8_SERIES_LYNX_POINT);
+       return enable_flash_ich_spi(dev, CHIPSET_8_SERIES_LYNX_POINT, 0xdc);
 }
 
-/* Lynx Point aka. 8 series low-power */
+/* Lynx Point LP aka. 8 series low-power */
 static int enable_flash_pch8_lp(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, 
CHIPSET_8_SERIES_LYNX_POINT_LP);
+       return enable_flash_ich_spi(dev, CHIPSET_8_SERIES_LYNX_POINT_LP, 0xdc);
 }
 
 /* Wellsburg (for Haswell-EP Xeons) */
 static int enable_flash_pch8_wb(struct pci_dev *dev, const char *name)
 {
-       return enable_flash_ich_dc_spi(dev, name, CHIPSET_8_SERIES_WELLSBURG);
+       return enable_flash_ich_spi(dev, CHIPSET_8_SERIES_WELLSBURG, 0xdc);
 }
 
 static int via_no_byte_merge(struct pci_dev *dev, const char *name)
@@ -1503,6 +1478,7 @@
        {0x1166, 0x0200, OK, "Broadcom", "OSB4",        enable_flash_osb4},
        {0x1166, 0x0205, OK, "Broadcom", "HT-1000",     enable_flash_ht1000},
        {0x17f3, 0x6030, OK, "RDC", "R8610/R3210",      enable_flash_rdc_r8610},
+       {0x8086, 0x0c60, NT, "Intel", "S12x0",          enable_flash_s12x0},
        {0x8086, 0x122e, OK, "Intel", "PIIX",           enable_flash_piix4},
        {0x8086, 0x1234, NT, "Intel", "MPIIX",          enable_flash_piix4},
        {0x8086, 0x1c44, OK, "Intel", "Z68",            enable_flash_pch6},
@@ -1541,15 +1517,15 @@
        {0x8086, 0x2390, NT, "Intel", "Coleto Creek",   enable_flash_pch7},
        {0x8086, 0x2410, OK, "Intel", "ICH",            enable_flash_ich0},
        {0x8086, 0x2420, OK, "Intel", "ICH0",           enable_flash_ich0},
-       {0x8086, 0x2440, OK, "Intel", "ICH2",           enable_flash_ich2},
-       {0x8086, 0x244c, OK, "Intel", "ICH2-M",         enable_flash_ich2},
-       {0x8086, 0x2450, NT, "Intel", "C-ICH",          enable_flash_ich2},
-       {0x8086, 0x2480, OK, "Intel", "ICH3-S",         enable_flash_ich3},
-       {0x8086, 0x248c, OK, "Intel", "ICH3-M",         enable_flash_ich3},
-       {0x8086, 0x24c0, OK, "Intel", "ICH4/ICH4-L",    enable_flash_ich4},
-       {0x8086, 0x24cc, OK, "Intel", "ICH4-M",         enable_flash_ich4},
-       {0x8086, 0x24d0, OK, "Intel", "ICH5/ICH5R",     enable_flash_ich5},
-       {0x8086, 0x25a1, OK, "Intel", "6300ESB",        enable_flash_ich5},
+       {0x8086, 0x2440, OK, "Intel", "ICH2",           enable_flash_ich2345},
+       {0x8086, 0x244c, OK, "Intel", "ICH2-M",         enable_flash_ich2345},
+       {0x8086, 0x2450, NT, "Intel", "C-ICH",          enable_flash_ich2345},
+       {0x8086, 0x2480, OK, "Intel", "ICH3-S",         enable_flash_ich2345},
+       {0x8086, 0x248c, OK, "Intel", "ICH3-M",         enable_flash_ich2345},
+       {0x8086, 0x24c0, OK, "Intel", "ICH4/ICH4-L",    enable_flash_ich2345},
+       {0x8086, 0x24cc, OK, "Intel", "ICH4-M",         enable_flash_ich2345},
+       {0x8086, 0x24d0, OK, "Intel", "ICH5/ICH5R",     enable_flash_ich2345},
+       {0x8086, 0x25a1, OK, "Intel", "6300ESB",        enable_flash_ich2345},
        {0x8086, 0x2640, OK, "Intel", "ICH6/ICH6R",     enable_flash_ich6},
        {0x8086, 0x2641, OK, "Intel", "ICH6-M",         enable_flash_ich6},
        {0x8086, 0x2642, NT, "Intel", "ICH6W/ICH6RW",   enable_flash_ich6},

Modified: trunk/ichspi.c
==============================================================================
--- trunk/ichspi.c      Mon Oct 21 23:49:08 2013        (r1760)
+++ trunk/ichspi.c      Fri Oct 25 02:33:37 2013        (r1761)
@@ -466,6 +466,8 @@
 
        switch (ich_generation) {
        case CHIPSET_ICH7:
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_CENTERTON:
                preop = REGREAD16(ICH7_REG_PREOP);
                optype = REGREAD16(ICH7_REG_OPTYPE);
                opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
@@ -529,7 +531,7 @@
                opmenu[0] |= ((uint32_t) op->opcode[a].opcode) << (a * 8);
        }
 
-       /*Program Allowable Opcodes 4 - 7 */
+       /* Program Allowable Opcodes 4 - 7 */
        opmenu[1] = 0;
        for (a = 4; a < 8; a++) {
                opmenu[1] |= ((uint32_t) op->opcode[a].opcode) << ((a - 4) * 8);
@@ -538,6 +540,8 @@
        msg_pdbg2("\n%s: preop=%04x optype=%04x opmenu=%08x%08x\n", __func__, 
preop, optype, opmenu[0], opmenu[1]);
        switch (ich_generation) {
        case CHIPSET_ICH7:
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_CENTERTON:
                /* Register undo only for enable_undo=1, i.e. first call. */
                if (enable_undo) {
                        rmmio_valw(ich_spibar + ICH7_REG_PREOP);
@@ -603,6 +607,8 @@
        int bbar_off;
        switch (ich_generation) {
        case CHIPSET_ICH7:
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_CENTERTON:
                bbar_off = 0x50;
                break;
        case CHIPSET_ICH8:
@@ -975,6 +981,8 @@
 
        switch (ich_generation) {
        case CHIPSET_ICH7:
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_CENTERTON:
                return ich7_run_opcode(op, offset, datalength, data, maxlength);
        case CHIPSET_ICH8:
        default:                /* Future version might behave the same */
@@ -1545,12 +1553,10 @@
        .erase = ich_hwseq_block_erase,
 };
 
-int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
-                enum ich_chipset ich_gen)
+int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset ich_gen)
 {
        int i;
-       uint8_t old, new;
-       uint16_t spibar_offset, tmp2;
+       uint16_t tmp2;
        uint32_t tmp;
        char *arg;
        int ich_spi_force = 0;
@@ -1564,42 +1570,18 @@
        } ich_spi_mode = ich_auto;
 
        ich_generation = ich_gen;
-
-       switch (ich_generation) {
-       case CHIPSET_ICH_UNKNOWN:
-               return ERROR_FATAL;
-       case CHIPSET_ICH7:
-       case CHIPSET_ICH8:
-               spibar_offset = 0x3020;
-               break;
-       case CHIPSET_ICH9:
-       default:                /* Future version might behave the same */
-               spibar_offset = 0x3800;
-               break;
-       }
-
-       /* SPIBAR is at RCRB+0x3020 for ICH[78] and RCRB+0x3800 for ICH9. */
-       msg_pdbg("SPIBAR = 0x%x + 0x%04x\n", base, spibar_offset);
-
-       /* Assign Virtual Address */
-       ich_spibar = rcrb + spibar_offset;
+       ich_spibar = spibar;
 
        switch (ich_generation) {
        case CHIPSET_ICH7:
+       case CHIPSET_TUNNEL_CREEK:
+       case CHIPSET_CENTERTON:
                msg_pdbg("0x00: 0x%04x     (SPIS)\n",
                             mmio_readw(ich_spibar + 0));
                msg_pdbg("0x02: 0x%04x     (SPIC)\n",
                             mmio_readw(ich_spibar + 2));
                msg_pdbg("0x04: 0x%08x (SPIA)\n",
                             mmio_readl(ich_spibar + 4));
-               for (i = 0; i < 8; i++) {
-                       int offs;
-                       offs = 8 + (i * 8);
-                       msg_pdbg("0x%02x: 0x%08x (SPID%d)\n", offs,
-                                    mmio_readl(ich_spibar + offs), i);
-                       msg_pdbg("0x%02x: 0x%08x (SPID%d+4)\n", offs + 4,
-                                    mmio_readl(ich_spibar + offs + 4), i);
-               }
                ichspi_bbar = mmio_readl(ich_spibar + 0x50);
                msg_pdbg("0x50: 0x%08x (BBAR)\n",
                             ichspi_bbar);
@@ -1811,21 +1793,6 @@
                break;
        }
 
-       old = pci_read_byte(dev, 0xdc);
-       msg_pdbg("SPI Read Configuration: ");
-       new = (old >> 2) & 0x3;
-       switch (new) {
-       case 0:
-       case 1:
-       case 2:
-               msg_pdbg("prefetching %sabled, caching %sabled, ",
-                            (new & 0x2) ? "en" : "dis",
-                            (new & 0x1) ? "dis" : "en");
-               break;
-       default:
-               msg_pdbg("invalid prefetching/caching settings, ");
-               break;
-       }
        return 0;
 }
 

Modified: trunk/programmer.h
==============================================================================
--- trunk/programmer.h  Mon Oct 21 23:49:08 2013        (r1760)
+++ trunk/programmer.h  Fri Oct 25 02:33:37 2013        (r1761)
@@ -557,11 +557,12 @@
 /* The following enum is needed by ich_descriptor_tool and ich* code as well 
as in chipset_enable.c. */
 enum ich_chipset {
        CHIPSET_ICH_UNKNOWN,
-       CHIPSET_ICH2 = 2,
-       CHIPSET_ICH3,
-       CHIPSET_ICH4,
-       CHIPSET_ICH5,
+       CHIPSET_ICH,
+       CHIPSET_ICH2345,
        CHIPSET_ICH6,
+       CHIPSET_POULSBO, /* SCH U* */
+       CHIPSET_TUNNEL_CREEK, /* Atom E6xx */
+       CHIPSET_CENTERTON, /* Atom S1220 S1240 S1260 */
        CHIPSET_ICH7,
        CHIPSET_ICH8,
        CHIPSET_ICH9,
@@ -577,8 +578,7 @@
 /* ichspi.c */
 #if CONFIG_INTERNAL == 1
 extern uint32_t ichspi_bbar;
-int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
-                enum ich_chipset ich_generation);
+int ich_init_spi(struct pci_dev *dev, void *spibar, enum ich_chipset 
ich_generation);
 int via_init_spi(struct pci_dev *dev, uint32_t mmio_base);
 
 /* amd_imc.c */

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

Reply via email to