Author: stepan
Date: 2008-12-08 19:16:58 +0100 (Mon, 08 Dec 2008)
New Revision: 3805

Modified:
   trunk/util/flashrom/chipset_enable.c
   trunk/util/flashrom/flash.h
   trunk/util/flashrom/ichspi.c
Log:
Generates OPCODES struct from the ICH7/ICH9/VIA chipset if its SPI
configuration is locked down.

Signed-off-by: FENG yu ning <[EMAIL PROTECTED]>
Acked-by: Stefan Reinauer <[EMAIL PROTECTED]>



Modified: trunk/util/flashrom/chipset_enable.c
===================================================================
--- trunk/util/flashrom/chipset_enable.c        2008-12-08 18:15:10 UTC (rev 
3804)
+++ trunk/util/flashrom/chipset_enable.c        2008-12-08 18:16:58 UTC (rev 
3805)
@@ -47,6 +47,8 @@
 flashbus_t flashbus = BUS_TYPE_LPC;
 void *spibar = NULL;
 
+extern int ichspi_lock;
+
 static int enable_flash_ali_m1533(struct pci_dev *dev, const char *name)
 {
        uint8_t tmp;
@@ -335,6 +337,7 @@
                printf_debug("\n");
                if ((*(uint16_t *) spibar) & (1 << 15)) {
                        printf("WARNING: SPI Configuration Lockdown 
activated.\n");
+                       ichspi_lock = 1;
                }
                break;
        case BUS_TYPE_ICH9_SPI:

Modified: trunk/util/flashrom/flash.h
===================================================================
--- trunk/util/flashrom/flash.h 2008-12-08 18:15:10 UTC (rev 3804)
+++ trunk/util/flashrom/flash.h 2008-12-08 18:16:58 UTC (rev 3805)
@@ -51,6 +51,12 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
+/* for pairing opcodes with their required preop */
+struct preop_opcode_pair {
+       uint8_t preop;
+       uint8_t opcode;
+};
+
 struct flashchip {
        const char *vendor;
        const char *name;
@@ -76,6 +82,8 @@
        int (*write) (struct flashchip *flash, uint8_t *buf);
        int (*read) (struct flashchip *flash, uint8_t *buf);
 
+       struct preop_opcode_pair *preop_opcode_pairs;
+
        /* Some flash devices have an additional register space. */
        volatile uint8_t *virtual_memory;
        volatile uint8_t *virtual_registers;

Modified: trunk/util/flashrom/ichspi.c
===================================================================
--- trunk/util/flashrom/ichspi.c        2008-12-08 18:15:10 UTC (rev 3804)
+++ trunk/util/flashrom/ichspi.c        2008-12-08 18:16:58 UTC (rev 3805)
@@ -101,6 +101,9 @@
 #define ICH7_REG_OPTYPE                0x56    /* 16 Bits */
 #define ICH7_REG_OPMENU                0x58    /* 64 Bits */
 
+/* ICH SPI configuration lock-down. May be set during chipset enabling. */
+int ichspi_lock = 0;
+
 typedef struct _OPCODE {
        uint8_t opcode;         //This commands spi opcode
        uint8_t spi_type;       //This commands spi type
@@ -147,7 +150,11 @@
 #define REGWRITE8(X,Y)  (*(uint8_t *)((uint8_t *)spibar+X)=Y)
 
 /* Common SPI functions */
+static inline int find_opcode(OPCODES *op, uint8_t opcode);
+static inline int find_preop(OPCODES *op, uint8_t preop);
+static int generate_opcodes(struct flashchip * flash, OPCODES * op);
 static int program_opcodes(OPCODES * op);
+int ich_check_opcodes(struct flashchip * flash);
 static int run_opcode(OPCODE op, uint32_t offset,
                      uint8_t datalength, uint8_t * data);
 static int ich_spi_read_page(struct flashchip *flash, uint8_t * buf,
@@ -171,6 +178,98 @@
         }
 };
 
+OPCODES O_EXISTING = {};
+
+static inline int find_opcode(OPCODES *op, uint8_t opcode)
+{
+       int a;
+
+       for (a = 0; a < 8; a++) {
+               if (op->opcode[a].opcode == opcode)
+                       return a;
+       }
+
+       return -1;
+}
+
+static inline int find_preop(OPCODES *op, uint8_t preop)
+{
+       int a;
+
+       for (a = 0; a < 2; a++) {
+               if (op->preop[a] == preop)
+                       return a;
+       }
+
+       return -1;
+}
+
+static int generate_opcodes(struct flashchip * flash, OPCODES * op)
+{
+  int a, b, i;
+       uint16_t preop, optype;
+       uint32_t opmenu[2];
+       struct preop_opcode_pair *pair;
+
+       if (op == NULL) {
+               printf_debug("\n%s: null OPCODES pointer!\n", __FUNCTION__);
+               return -1;
+       }
+
+       switch (flashbus) {
+       case BUS_TYPE_ICH7_SPI:
+       case BUS_TYPE_VIA_SPI:
+               preop = REGREAD16(ICH7_REG_PREOP);
+               optype = REGREAD16(ICH7_REG_OPTYPE);
+               opmenu[0] = REGREAD32(ICH7_REG_OPMENU);
+               opmenu[1] = REGREAD32(ICH7_REG_OPMENU + 4);
+               break;
+       case BUS_TYPE_ICH9_SPI:
+               preop = REGREAD16(ICH9_REG_PREOP);
+               optype = REGREAD16(ICH9_REG_OPTYPE);
+               opmenu[0] = REGREAD32(ICH9_REG_OPMENU);
+               opmenu[1] = REGREAD32(ICH9_REG_OPMENU + 4);
+               break;
+       default:
+               printf_debug("%s: unsupported chipset\n", __FUNCTION__);
+               return -1;
+       }
+
+       op->preop[0] = (uint8_t) preop;
+       op->preop[1] = (uint8_t) (preop >> 8);
+
+       for (a = 0; a < 8; a++) {
+               op->opcode[a].spi_type = (uint8_t) (optype & 0x3);
+               optype >>= 2;
+       }
+
+       for (a = 0; a < 4; a++) {
+               op->opcode[a].opcode = (uint8_t) (opmenu[0] & 0xff);
+               opmenu[0] >>= 8;
+       }
+
+       for (a = 4; a < 8; a++) {
+               op->opcode[a].opcode = (uint8_t) (opmenu[1] & 0xff);
+               opmenu[1] >>= 8;
+       }
+
+       /* atomic (link opcode with required pre-op) */
+       for (a = 4; a < 8; a++)
+               op->opcode[a].atomic = 0;
+
+       pair = flash->preop_opcode_pairs;
+       if (pair) {
+               for (i = 0; pair[i].opcode; i++) {
+                       a = find_opcode(op, pair[i].opcode);
+                       b = find_preop(op, pair[i].preop);
+                       if ((a != -1) && (b != -1))
+                               op->opcode[a].atomic = (uint8_t) ++b;
+               }
+       }
+
+       return 0;
+}
+
 int program_opcodes(OPCODES * op)
 {
        uint8_t a;
@@ -224,6 +323,41 @@
        return 0;
 }
 
+/* This function generates OPCODES from or programs OPCODES to the chipset
+ * according to its SPI configuration lock.
+ *
+ * It should be called in the ICH7/ICH9/VIA part of each operation driver(i.e.
+ * probe, read, erase, write, etc.) before any command is sent.
+ */
+int ich_check_opcodes(struct flashchip * flash)
+{
+       int rc = 0;
+       OPCODES *curopcodes_done;
+
+       if (curopcodes)
+               return 0;
+
+       if (ichspi_lock) {
+               printf_debug("Generating OPCODES... ");
+               curopcodes_done = &O_EXISTING;
+               rc = generate_opcodes(flash, curopcodes_done);
+       } else {
+               printf_debug("Programming OPCODES... ");
+               curopcodes_done = &O_ST_M25P;
+               rc = program_opcodes(curopcodes_done);
+       }
+
+       if (rc) {
+               curopcodes = NULL;
+               printf_debug("failed\n");
+               return 1;
+       } else {
+               curopcodes = curopcodes_done;
+               printf_debug("done\n");
+               return 0;
+       }
+}
+
 static int ich7_run_opcode(OPCODE op, uint32_t offset,
                           uint8_t datalength, uint8_t * data, int maxdata)
 {


--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to