<p>Arthur Heymans has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/25414">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">src/sb/intel/common/spi.c: Adapt and link in romstage<br><br>Based on Nicola Corna's work.<br><br>This allows for CONFIG_CONSOLE_SPI_FLASH to be used, which writes the<br>console output to the SPI flash.<br><br>TESTED to still work in ramstage on x220 (correctly writes MRC CACHE),<br>the option CONFIG_CONSOLE_SPI_FLASH compiles for targets using the<br>common Intel SPI code (untested though).<br><br>Change-Id: I4671653c0b07ab5c4bf91128f18f142ce4f893cf<br>Signed-off-by: Arthur Heymans <arthur@aheymans.xyz><br>---<br>M src/southbridge/intel/common/Makefile.inc<br>M src/southbridge/intel/common/spi.c<br>2 files changed, 101 insertions(+), 85 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/14/25414/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc</span><br><span>index f5534c8..2a0bca6 100644</span><br><span>--- a/src/southbridge/intel/common/Makefile.inc</span><br><span>+++ b/src/southbridge/intel/common/Makefile.inc</span><br><span>@@ -28,6 +28,7 @@</span><br><span> romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c</span><br><span> ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c</span><br><span> ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c</span><br><span> ifeq ($(CONFIG_SPI_FLASH_SMM),y)</span><br><span> smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c</span><br><span>diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c</span><br><span>index 63f6e57..d956d3e 100644</span><br><span>--- a/src/southbridge/intel/common/spi.c</span><br><span>+++ b/src/southbridge/intel/common/spi.c</span><br><span>@@ -15,6 +15,7 @@</span><br><span>  */</span><br><span> </span><br><span> /* This file is derived from the flashrom project. */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <arch/early_variables.h></span><br><span> #include <stdint.h></span><br><span> #include <stdlib.h></span><br><span> #include <string.h></span><br><span>@@ -71,7 +72,7 @@</span><br><span> </span><br><span> typedef struct spi_slave ich_spi_slave;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int ichspi_lock = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+static int g_ichspi_lock CAR_GLOBAL = 0;</span><br><span> </span><br><span> typedef struct ich7_spi_regs {</span><br><span>        uint16_t spis;</span><br><span>@@ -136,7 +137,7 @@</span><br><span>         uint32_t *bbar;</span><br><span> } ich_spi_controller;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static ich_spi_controller cntlr;</span><br><span style="color: hsl(120, 100%, 40%);">+static ich_spi_controller g_cntlr CAR_GLOBAL;</span><br><span> </span><br><span> enum {</span><br><span>    SPIS_SCIP =             0x0001,</span><br><span>@@ -278,17 +279,19 @@</span><br><span> </span><br><span> static void ich_set_bbar(uint32_t minaddr)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+        ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   const uint32_t bbar_mask = 0x00ffff00;</span><br><span>       uint32_t ichspi_bbar;</span><br><span> </span><br><span>    minaddr &= bbar_mask;</span><br><span style="color: hsl(0, 100%, 40%);">-       ichspi_bbar = readl_(cntlr.bbar) & ~bbar_mask;</span><br><span style="color: hsl(120, 100%, 40%);">+    ichspi_bbar = readl_(cntlr->bbar) & ~bbar_mask;</span><br><span>       ichspi_bbar |= minaddr;</span><br><span style="color: hsl(0, 100%, 40%);">- writel_(ichspi_bbar, cntlr.bbar);</span><br><span style="color: hsl(120, 100%, 40%);">+     writel_(ichspi_bbar, cntlr->bbar);</span><br><span> }</span><br><span> </span><br><span> void spi_init(void)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+    ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint8_t *rcrb; /* Root Complex Register Block */</span><br><span>     uint32_t rcba; /* Root Complex Base Address */</span><br><span>       uint8_t bios_cntl;</span><br><span>@@ -297,7 +300,7 @@</span><br><span>     ich7_spi_regs *ich7_spi;</span><br><span>     uint16_t hsfs;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef __SMM__</span><br><span style="color: hsl(120, 100%, 40%);">+#ifdef __SIMPLE_DEVICE__</span><br><span>   dev = PCI_DEV(0, 31, 0);</span><br><span> #else</span><br><span>    dev = dev_find_slot(0, PCI_DEVFN(31, 0));</span><br><span>@@ -308,37 +311,37 @@</span><br><span>    rcrb = (uint8_t *)(rcba & 0xffffc000);</span><br><span>   if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX)) {</span><br><span>                 ich7_spi = (ich7_spi_regs *)(rcrb + 0x3020);</span><br><span style="color: hsl(0, 100%, 40%);">-            cntlr.opmenu = ich7_spi->opmenu;</span><br><span style="color: hsl(0, 100%, 40%);">-             cntlr.menubytes = sizeof(ich7_spi->opmenu);</span><br><span style="color: hsl(0, 100%, 40%);">-          cntlr.optype = &ich7_spi->optype;</span><br><span style="color: hsl(0, 100%, 40%);">-                cntlr.addr = &ich7_spi->spia;</span><br><span style="color: hsl(0, 100%, 40%);">-            cntlr.data = (uint8_t *)ich7_spi->spid;</span><br><span style="color: hsl(0, 100%, 40%);">-              cntlr.databytes = sizeof(ich7_spi->spid);</span><br><span style="color: hsl(0, 100%, 40%);">-            cntlr.status = (uint8_t *)&ich7_spi->spis;</span><br><span style="color: hsl(0, 100%, 40%);">-               ichspi_lock = readw_(&ich7_spi->spis) & HSFS_FLOCKDN;</span><br><span style="color: hsl(0, 100%, 40%);">-                cntlr.control = &ich7_spi->spic;</span><br><span style="color: hsl(0, 100%, 40%);">-         cntlr.bbar = &ich7_spi->bbar;</span><br><span style="color: hsl(0, 100%, 40%);">-            cntlr.preop = &ich7_spi->preop;</span><br><span style="color: hsl(120, 100%, 40%);">+                cntlr->opmenu = ich7_spi->opmenu;</span><br><span style="color: hsl(120, 100%, 40%);">+               cntlr->menubytes = sizeof(ich7_spi->opmenu);</span><br><span style="color: hsl(120, 100%, 40%);">+            cntlr->optype = &ich7_spi->optype;</span><br><span style="color: hsl(120, 100%, 40%);">+          cntlr->addr = &ich7_spi->spia;</span><br><span style="color: hsl(120, 100%, 40%);">+              cntlr->data = (uint8_t *)ich7_spi->spid;</span><br><span style="color: hsl(120, 100%, 40%);">+                cntlr->databytes = sizeof(ich7_spi->spid);</span><br><span style="color: hsl(120, 100%, 40%);">+              cntlr->status = (uint8_t *)&ich7_spi->spis;</span><br><span style="color: hsl(120, 100%, 40%);">+         car_set_var(g_ichspi_lock, readw_(&ich7_spi->spis) & HSFS_FLOCKDN);</span><br><span style="color: hsl(120, 100%, 40%);">+                cntlr->control = &ich7_spi->spic;</span><br><span style="color: hsl(120, 100%, 40%);">+           cntlr->bbar = &ich7_spi->bbar;</span><br><span style="color: hsl(120, 100%, 40%);">+              cntlr->preop = &ich7_spi->preop;</span><br><span>   } else {</span><br><span>             ich9_spi = (ich9_spi_regs *)(rcrb + 0x3800);</span><br><span style="color: hsl(0, 100%, 40%);">-            cntlr.ich9_spi = ich9_spi;</span><br><span style="color: hsl(120, 100%, 40%);">+            cntlr->ich9_spi = ich9_spi;</span><br><span>               hsfs = readw_(&ich9_spi->hsfs);</span><br><span style="color: hsl(0, 100%, 40%);">-          ichspi_lock = hsfs & HSFS_FLOCKDN;</span><br><span style="color: hsl(0, 100%, 40%);">-          cntlr.hsfs = hsfs;</span><br><span style="color: hsl(0, 100%, 40%);">-              cntlr.opmenu = ich9_spi->opmenu;</span><br><span style="color: hsl(0, 100%, 40%);">-             cntlr.menubytes = sizeof(ich9_spi->opmenu);</span><br><span style="color: hsl(0, 100%, 40%);">-          cntlr.optype = &ich9_spi->optype;</span><br><span style="color: hsl(0, 100%, 40%);">-                cntlr.addr = &ich9_spi->faddr;</span><br><span style="color: hsl(0, 100%, 40%);">-           cntlr.data = (uint8_t *)ich9_spi->fdata;</span><br><span style="color: hsl(0, 100%, 40%);">-             cntlr.databytes = sizeof(ich9_spi->fdata);</span><br><span style="color: hsl(0, 100%, 40%);">-           cntlr.status = &ich9_spi->ssfs;</span><br><span style="color: hsl(0, 100%, 40%);">-          cntlr.control = (uint16_t *)ich9_spi->ssfc;</span><br><span style="color: hsl(0, 100%, 40%);">-          cntlr.bbar = &ich9_spi->bbar;</span><br><span style="color: hsl(0, 100%, 40%);">-            cntlr.preop = &ich9_spi->preop;</span><br><span style="color: hsl(120, 100%, 40%);">+                car_set_var(g_ichspi_lock, hsfs & HSFS_FLOCKDN);</span><br><span style="color: hsl(120, 100%, 40%);">+          cntlr->hsfs = hsfs;</span><br><span style="color: hsl(120, 100%, 40%);">+                cntlr->opmenu = ich9_spi->opmenu;</span><br><span style="color: hsl(120, 100%, 40%);">+               cntlr->menubytes = sizeof(ich9_spi->opmenu);</span><br><span style="color: hsl(120, 100%, 40%);">+            cntlr->optype = &ich9_spi->optype;</span><br><span style="color: hsl(120, 100%, 40%);">+          cntlr->addr = &ich9_spi->faddr;</span><br><span style="color: hsl(120, 100%, 40%);">+             cntlr->data = (uint8_t *)ich9_spi->fdata;</span><br><span style="color: hsl(120, 100%, 40%);">+               cntlr->databytes = sizeof(ich9_spi->fdata);</span><br><span style="color: hsl(120, 100%, 40%);">+             cntlr->status = &ich9_spi->ssfs;</span><br><span style="color: hsl(120, 100%, 40%);">+            cntlr->control = (uint16_t *)ich9_spi->ssfc;</span><br><span style="color: hsl(120, 100%, 40%);">+            cntlr->bbar = &ich9_spi->bbar;</span><br><span style="color: hsl(120, 100%, 40%);">+              cntlr->preop = &ich9_spi->preop;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-          if (cntlr.hsfs & HSFS_FDV) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (cntlr->hsfs & HSFS_FDV) {</span><br><span>                         writel_ (4, &ich9_spi->fdoc);</span><br><span style="color: hsl(0, 100%, 40%);">-                    cntlr.flmap0 = readl_(&ich9_spi->fdod);</span><br><span style="color: hsl(120, 100%, 40%);">+                        cntlr->flmap0 = readl_(&ich9_spi->fdod);</span><br><span>           }</span><br><span>    }</span><br><span> </span><br><span>@@ -416,17 +419,18 @@</span><br><span> </span><br><span> static int spi_setup_opcode(spi_transaction *trans)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint16_t optypes;</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t opmenu[cntlr.menubytes];</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t opmenu[cntlr->menubytes];</span><br><span> </span><br><span>     trans->opcode = trans->out[0];</span><br><span>         spi_use_out(trans, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!ichspi_lock) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!car_get_var(g_ichspi_lock)) {</span><br><span>           /* The lock is off, so just use index 0. */</span><br><span style="color: hsl(0, 100%, 40%);">-             writeb_(trans->opcode, cntlr.opmenu);</span><br><span style="color: hsl(0, 100%, 40%);">-                optypes = readw_(cntlr.optype);</span><br><span style="color: hsl(120, 100%, 40%);">+               writeb_(trans->opcode, cntlr->opmenu);</span><br><span style="color: hsl(120, 100%, 40%);">+          optypes = readw_(cntlr->optype);</span><br><span>          optypes = (optypes & 0xfffc) | (trans->type & 0x3);</span><br><span style="color: hsl(0, 100%, 40%);">-          writew_(optypes, cntlr.optype);</span><br><span style="color: hsl(120, 100%, 40%);">+               writew_(optypes, cntlr->optype);</span><br><span>          return 0;</span><br><span>    } else {</span><br><span>             /* The lock is on. See if what we need is on the menu. */</span><br><span>@@ -437,20 +441,20 @@</span><br><span>            if (trans->opcode == SPI_OPCODE_WREN)</span><br><span>                     return 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           read_reg(cntlr.opmenu, opmenu, sizeof(opmenu));</span><br><span style="color: hsl(0, 100%, 40%);">-         for (opcode_index = 0; opcode_index < cntlr.menubytes;</span><br><span style="color: hsl(120, 100%, 40%);">+             read_reg(cntlr->opmenu, opmenu, sizeof(opmenu));</span><br><span style="color: hsl(120, 100%, 40%);">+           for (opcode_index = 0; opcode_index < cntlr->menubytes;</span><br><span>                                opcode_index++) {</span><br><span>                    if (opmenu[opcode_index] == trans->opcode)</span><br><span>                                break;</span><br><span>               }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (opcode_index == cntlr.menubytes) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (opcode_index == cntlr->menubytes) {</span><br><span>                   printk(BIOS_DEBUG, "ICH SPI: Opcode %x not found\n",</span><br><span>                               trans->opcode);</span><br><span>                   return -1;</span><br><span>           }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           optypes = readw_(cntlr.optype);</span><br><span style="color: hsl(120, 100%, 40%);">+               optypes = readw_(cntlr->optype);</span><br><span>          optype = (optypes >> (opcode_index * 2)) & 0x3;</span><br><span>            if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&</span><br><span>                    optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&</span><br><span>@@ -496,14 +500,15 @@</span><br><span>  */</span><br><span> static int ich_status_poll(u16 bitmask, int wait_til_set)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   int timeout = 600000; /* This will result in 6 seconds */</span><br><span>    u16 status = 0;</span><br><span> </span><br><span>  while (timeout--) {</span><br><span style="color: hsl(0, 100%, 40%);">-             status = readw_(cntlr.status);</span><br><span style="color: hsl(120, 100%, 40%);">+                status = readw_(cntlr->status);</span><br><span>           if (wait_til_set ^ ((status & bitmask) == 0)) {</span><br><span>                  if (wait_til_set)</span><br><span style="color: hsl(0, 100%, 40%);">-                               writew_((status & bitmask), cntlr.status);</span><br><span style="color: hsl(120, 100%, 40%);">+                                writew_((status & bitmask), cntlr->status);</span><br><span>                   return status;</span><br><span>               }</span><br><span>            udelay(10);</span><br><span>@@ -516,14 +521,16 @@</span><br><span> </span><br><span> static int spi_is_multichip (void)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!(cntlr.hsfs & HSFS_FDV))</span><br><span style="color: hsl(120, 100%, 40%);">+     ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!(cntlr->hsfs & HSFS_FDV))</span><br><span>                return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-       return !!((cntlr.flmap0 >> 8) & 3);</span><br><span style="color: hsl(120, 100%, 40%);">+ return !!((cntlr->flmap0 >> 8) & 3);</span><br><span> }</span><br><span> </span><br><span> static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,</span><br><span>             size_t bytesout, void *din, size_t bytesin)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint16_t control;</span><br><span>    int16_t opcode_index;</span><br><span>        int with_address;</span><br><span>@@ -549,7 +556,7 @@</span><br><span>      if (ich_status_poll(SPIS_SCIP, 0) == -1)</span><br><span>             return -1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  writew_(SPIS_CDS | SPIS_FCERR, cntlr.status);</span><br><span style="color: hsl(120, 100%, 40%);">+ writew_(SPIS_CDS | SPIS_FCERR, cntlr->status);</span><br><span> </span><br><span>        spi_setup_type(&trans);</span><br><span>  if ((opcode_index = spi_setup_opcode(&trans)) < 0)</span><br><span>@@ -563,8 +570,8 @@</span><br><span>               * in order to prevent the Management Engine from</span><br><span>             * issuing a transaction between WREN and DATA.</span><br><span>               */</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!ichspi_lock)</span><br><span style="color: hsl(0, 100%, 40%);">-                       writew_(trans.opcode, cntlr.preop);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!car_get_var(g_ichspi_lock))</span><br><span style="color: hsl(120, 100%, 40%);">+                      writew_(trans.opcode, cntlr->preop);</span><br><span>              return 0;</span><br><span>    }</span><br><span> </span><br><span>@@ -572,13 +579,13 @@</span><br><span>        control = SPIC_SCGO | ((opcode_index & 0x07) << 4);</span><br><span> </span><br><span>    /* Issue atomic preop cycle if needed */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (readw_(cntlr.preop))</span><br><span style="color: hsl(120, 100%, 40%);">+      if (readw_(cntlr->preop))</span><br><span>                 control |= SPIC_ACS;</span><br><span> </span><br><span>     if (!trans.bytesout && !trans.bytesin) {</span><br><span>             /* SPI addresses are 24 bit only */</span><br><span>          if (with_address)</span><br><span style="color: hsl(0, 100%, 40%);">-                       writel_(trans.offset & 0x00FFFFFF, cntlr.addr);</span><br><span style="color: hsl(120, 100%, 40%);">+                   writel_(trans.offset & 0x00FFFFFF, cntlr->addr);</span><br><span> </span><br><span>          /*</span><br><span>            * This is a 'no data' command (like Write Enable), its</span><br><span>@@ -586,7 +593,7 @@</span><br><span>                 * spi_setup_opcode() above. Tell the chip to send the</span><br><span>                * command.</span><br><span>           */</span><br><span style="color: hsl(0, 100%, 40%);">-             writew_(control, cntlr.control);</span><br><span style="color: hsl(120, 100%, 40%);">+              writew_(control, cntlr->control);</span><br><span> </span><br><span>             /* wait for the result */</span><br><span>            status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);</span><br><span>@@ -608,7 +615,7 @@</span><br><span>     * and followed by other SPI commands, and this sequence is controlled</span><br><span>        * by the SPI chip driver.</span><br><span>    */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (trans.bytesout > cntlr.databytes) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (trans.bytesout > cntlr->databytes) {</span><br><span>               printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use"</span><br><span>                  " spi_crop_chunk()?\n");</span><br><span>              return -1;</span><br><span>@@ -622,28 +629,28 @@</span><br><span>           uint32_t data_length;</span><br><span> </span><br><span>            /* SPI addresses are 24 bit only */</span><br><span style="color: hsl(0, 100%, 40%);">-             writel_(trans.offset & 0x00FFFFFF, cntlr.addr);</span><br><span style="color: hsl(120, 100%, 40%);">+           writel_(trans.offset & 0x00FFFFFF, cntlr->addr);</span><br><span> </span><br><span>          if (trans.bytesout)</span><br><span style="color: hsl(0, 100%, 40%);">-                     data_length = min(trans.bytesout, cntlr.databytes);</span><br><span style="color: hsl(120, 100%, 40%);">+                   data_length = min(trans.bytesout, cntlr->databytes);</span><br><span>              else</span><br><span style="color: hsl(0, 100%, 40%);">-                    data_length = min(trans.bytesin, cntlr.databytes);</span><br><span style="color: hsl(120, 100%, 40%);">+                    data_length = min(trans.bytesin, cntlr->databytes);</span><br><span> </span><br><span>           /* Program data into FDATA0 to N */</span><br><span>          if (trans.bytesout) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   write_reg(trans.out, cntlr.data, data_length);</span><br><span style="color: hsl(120, 100%, 40%);">+                        write_reg(trans.out, cntlr->data, data_length);</span><br><span>                   spi_use_out(&trans, data_length);</span><br><span>                        if (with_address)</span><br><span>                            trans.offset += data_length;</span><br><span>                 }</span><br><span> </span><br><span>                /* Add proper control fields' values */</span><br><span style="color: hsl(0, 100%, 40%);">-             control &= ~((cntlr.databytes - 1) << 8);</span><br><span style="color: hsl(120, 100%, 40%);">+           control &= ~((cntlr->databytes - 1) << 8);</span><br><span>              control |= SPIC_DS;</span><br><span>          control |= (data_length - 1) << 8;</span><br><span> </span><br><span>                 /* write it */</span><br><span style="color: hsl(0, 100%, 40%);">-          writew_(control, cntlr.control);</span><br><span style="color: hsl(120, 100%, 40%);">+              writew_(control, cntlr->control);</span><br><span> </span><br><span>             /* Wait for Cycle Done Status or Flash Cycle Error. */</span><br><span>               status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);</span><br><span>@@ -656,7 +663,7 @@</span><br><span>            }</span><br><span> </span><br><span>                if (trans.bytesin) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    read_reg(cntlr.data, trans.in, data_length);</span><br><span style="color: hsl(120, 100%, 40%);">+                  read_reg(cntlr->data, trans.in, data_length);</span><br><span>                     spi_use_in(&trans, data_length);</span><br><span>                         if (with_address)</span><br><span>                            trans.offset += data_length;</span><br><span>@@ -664,7 +671,7 @@</span><br><span>   }</span><br><span> </span><br><span>        /* Clear atomic preop now that xfer is done */</span><br><span style="color: hsl(0, 100%, 40%);">-  writew_(0, cntlr.preop);</span><br><span style="color: hsl(120, 100%, 40%);">+      writew_(0, cntlr->preop);</span><br><span> </span><br><span>     return 0;</span><br><span> }</span><br><span>@@ -672,8 +679,9 @@</span><br><span> /* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */</span><br><span> static void ich_hwseq_set_addr(uint32_t addr)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   uint32_t addr_old = readl_(&cntlr.ich9_spi->faddr) & ~0x01FFFFFF;</span><br><span style="color: hsl(0, 100%, 40%);">-    writel_((addr & 0x01FFFFFF) | addr_old, &cntlr.ich9_spi->faddr);</span><br><span style="color: hsl(120, 100%, 40%);">+   ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t addr_old = readl_(&cntlr->ich9_spi->faddr) & ~0x01FFFFFF;</span><br><span style="color: hsl(120, 100%, 40%);">+      writel_((addr & 0x01FFFFFF) | addr_old, &cntlr->ich9_spi->faddr);</span><br><span> }</span><br><span> </span><br><span> /* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals.</span><br><span>@@ -683,21 +691,22 @@</span><br><span> static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,</span><br><span>                                         unsigned int len)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+   ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint16_t hsfs;</span><br><span>       uint32_t addr;</span><br><span> </span><br><span>   timeout /= 8; /* scale timeout duration to counter */</span><br><span style="color: hsl(0, 100%, 40%);">-   while ((((hsfs = readw_(&cntlr.ich9_spi->hsfs)) &</span><br><span style="color: hsl(120, 100%, 40%);">+  while ((((hsfs = readw_(&cntlr->ich9_spi->hsfs)) &</span><br><span>              (HSFS_FDONE | HSFS_FCERR)) == 0) &&</span><br><span>                --timeout) {</span><br><span>          udelay(8);</span><br><span>   }</span><br><span style="color: hsl(0, 100%, 40%);">-       writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);</span><br><span style="color: hsl(120, 100%, 40%);">+  writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);</span><br><span> </span><br><span>     if (!timeout) {</span><br><span>              uint16_t hsfc;</span><br><span style="color: hsl(0, 100%, 40%);">-          addr = readl_(&cntlr.ich9_spi->faddr) & 0x01FFFFFF;</span><br><span style="color: hsl(0, 100%, 40%);">-          hsfc = readw_(&cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          addr = readl_(&cntlr->ich9_spi->faddr) & 0x01FFFFFF;</span><br><span style="color: hsl(120, 100%, 40%);">+            hsfc = readw_(&cntlr->ich9_spi->hsfc);</span><br><span>             printk(BIOS_ERR, "Transaction timeout between offset 0x%08x and "</span><br><span>                 "0x%08x (= 0x%08x + %d) HSFC=%x HSFS=%x!\n",</span><br><span>                       addr, addr + len - 1, addr, len - 1,</span><br><span>@@ -707,8 +716,8 @@</span><br><span> </span><br><span>        if (hsfs & HSFS_FCERR) {</span><br><span>                 uint16_t hsfc;</span><br><span style="color: hsl(0, 100%, 40%);">-          addr = readl_(&cntlr.ich9_spi->faddr) & 0x01FFFFFF;</span><br><span style="color: hsl(0, 100%, 40%);">-          hsfc = readw_(&cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          addr = readl_(&cntlr->ich9_spi->faddr) & 0x01FFFFFF;</span><br><span style="color: hsl(120, 100%, 40%);">+            hsfc = readw_(&cntlr->ich9_spi->hsfc);</span><br><span>             printk(BIOS_ERR, "Transaction error between offset 0x%08x and "</span><br><span>                   "0x%08x (= 0x%08x + %d) HSFC=%x HSFS=%x!\n",</span><br><span>                       addr, addr + len - 1, addr, len - 1,</span><br><span>@@ -722,6 +731,7 @@</span><br><span> static int ich_hwseq_erase(const struct spi_flash *flash, u32 offset,</span><br><span>                   size_t len)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   u32 start, end, erase_size;</span><br><span>  int ret;</span><br><span>     uint16_t hsfc;</span><br><span>@@ -744,17 +754,17 @@</span><br><span> </span><br><span>   while (offset < end) {</span><br><span>            /* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */</span><br><span style="color: hsl(0, 100%, 40%);">-              writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);</span><br><span style="color: hsl(120, 100%, 40%);">+          writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);</span><br><span> </span><br><span>             ich_hwseq_set_addr(offset);</span><br><span> </span><br><span>              offset += erase_size;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-               hsfc = readw_(&cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          hsfc = readw_(&cntlr->ich9_spi->hsfc);</span><br><span>             hsfc &= ~HSFC_FCYCLE; /* clear operation */</span><br><span>              hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */</span><br><span>            hsfc |= HSFC_FGO; /* start */</span><br><span style="color: hsl(0, 100%, 40%);">-           writew_(hsfc, &cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          writew_(hsfc, &cntlr->ich9_spi->hsfc);</span><br><span>             if (ich_hwseq_wait_for_cycle_complete(timeout, len))</span><br><span>                 {</span><br><span>                    printk(BIOS_ERR, "SF: Erase failed at %x\n", offset - erase_size);</span><br><span>@@ -772,12 +782,13 @@</span><br><span> </span><br><span> static void ich_read_data(uint8_t *data, int len)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+    ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   int i;</span><br><span>       uint32_t temp32 = 0;</span><br><span> </span><br><span>     for (i = 0; i < len; i++) {</span><br><span>               if ((i % 4) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                       temp32 = readl_(cntlr.data + i);</span><br><span style="color: hsl(120, 100%, 40%);">+                      temp32 = readl_(cntlr->data + i);</span><br><span> </span><br><span>             data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;</span><br><span>        }</span><br><span>@@ -786,6 +797,7 @@</span><br><span> static int ich_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len,</span><br><span>                    void *buf)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+       ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint16_t hsfc;</span><br><span>       uint16_t timeout = 100 * 60;</span><br><span>         uint8_t block_len;</span><br><span>@@ -799,20 +811,20 @@</span><br><span>   }</span><br><span> </span><br><span>        /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */</span><br><span style="color: hsl(0, 100%, 40%);">-    writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);</span><br><span style="color: hsl(120, 100%, 40%);">+  writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);</span><br><span> </span><br><span>     while (len > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-            block_len = min(len, cntlr.databytes);</span><br><span style="color: hsl(120, 100%, 40%);">+                block_len = min(len, cntlr->databytes);</span><br><span>           if (block_len > (~addr & 0xff))</span><br><span>                       block_len = (~addr & 0xff) + 1;</span><br><span>          ich_hwseq_set_addr(addr);</span><br><span style="color: hsl(0, 100%, 40%);">-               hsfc = readw_(&cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          hsfc = readw_(&cntlr->ich9_spi->hsfc);</span><br><span>             hsfc &= ~HSFC_FCYCLE; /* set read operation */</span><br><span>           hsfc &= ~HSFC_FDBC; /* clear byte count */</span><br><span>               /* set byte count */</span><br><span>                 hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);</span><br><span>          hsfc |= HSFC_FGO; /* start */</span><br><span style="color: hsl(0, 100%, 40%);">-           writew_(hsfc, &cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          writew_(hsfc, &cntlr->ich9_spi->hsfc);</span><br><span> </span><br><span>                 if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))</span><br><span>                   return 1;</span><br><span>@@ -831,6 +843,7 @@</span><br><span>  */</span><br><span> static void ich_fill_data(const uint8_t *data, int len)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+        ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint32_t temp32 = 0;</span><br><span>         int i;</span><br><span> </span><br><span>@@ -844,16 +857,17 @@</span><br><span>           temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);</span><br><span> </span><br><span>           if ((i % 4) == 3) /* 32 bits are full, write them to regs. */</span><br><span style="color: hsl(0, 100%, 40%);">-                   writel_(temp32, cntlr.data + (i - (i % 4)));</span><br><span style="color: hsl(120, 100%, 40%);">+                  writel_(temp32, cntlr->data + (i - (i % 4)));</span><br><span>     }</span><br><span>    i--;</span><br><span>         if ((i % 4) != 3) /* Write remaining data to regs. */</span><br><span style="color: hsl(0, 100%, 40%);">-           writel_(temp32, cntlr.data + (i - (i % 4)));</span><br><span style="color: hsl(120, 100%, 40%);">+          writel_(temp32, cntlr->data + (i - (i % 4)));</span><br><span> }</span><br><span> </span><br><span> static int ich_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len,</span><br><span>                         const void *buf)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint16_t hsfc;</span><br><span>       uint16_t timeout = 100 * 60;</span><br><span>         uint8_t block_len;</span><br><span>@@ -867,24 +881,24 @@</span><br><span>   }</span><br><span> </span><br><span>        /* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */</span><br><span style="color: hsl(0, 100%, 40%);">-    writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);</span><br><span style="color: hsl(120, 100%, 40%);">+  writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);</span><br><span> </span><br><span>     while (len > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-            block_len = min(len, cntlr.databytes);</span><br><span style="color: hsl(120, 100%, 40%);">+                block_len = min(len, cntlr->databytes);</span><br><span>           if (block_len > (~addr & 0xff))</span><br><span>                       block_len = (~addr & 0xff) + 1;</span><br><span> </span><br><span>              ich_hwseq_set_addr(addr);</span><br><span> </span><br><span>                ich_fill_data(buf, block_len);</span><br><span style="color: hsl(0, 100%, 40%);">-          hsfc = readw_(&cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          hsfc = readw_(&cntlr->ich9_spi->hsfc);</span><br><span>             hsfc &= ~HSFC_FCYCLE; /* clear operation */</span><br><span>              hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */</span><br><span>            hsfc &= ~HSFC_FDBC; /* clear byte count */</span><br><span>               /* set byte count */</span><br><span>                 hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);</span><br><span>          hsfc |= HSFC_FGO; /* start */</span><br><span style="color: hsl(0, 100%, 40%);">-           writew_(hsfc, &cntlr.ich9_spi->hsfc);</span><br><span style="color: hsl(120, 100%, 40%);">+          writew_(hsfc, &cntlr->ich9_spi->hsfc);</span><br><span> </span><br><span>                 if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))</span><br><span>           {</span><br><span>@@ -910,6 +924,7 @@</span><br><span> static int spi_flash_programmer_probe(const struct spi_slave *spi,</span><br><span>                                        struct spi_flash *flash)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);</span><br><span>   uint32_t flcomp;</span><br><span> </span><br><span>         if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX))</span><br><span>@@ -923,7 +938,7 @@</span><br><span>     flash->name = "Opaque HW-sequencing";</span><br><span> </span><br><span>       ich_hwseq_set_addr (0);</span><br><span style="color: hsl(0, 100%, 40%);">- switch ((cntlr.hsfs >> 3) & 3)</span><br><span style="color: hsl(120, 100%, 40%);">+      switch ((cntlr->hsfs >> 3) & 3)</span><br><span>         {</span><br><span>    case 0:</span><br><span>              flash->sector_size = 256;</span><br><span>@@ -939,14 +954,14 @@</span><br><span>                 break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   writel_ (0x1000, &cntlr.ich9_spi->fdoc);</span><br><span style="color: hsl(0, 100%, 40%);">- flcomp = readl_(&cntlr.ich9_spi->fdod);</span><br><span style="color: hsl(120, 100%, 40%);">+        writel_ (0x1000, &cntlr->ich9_spi->fdoc);</span><br><span style="color: hsl(120, 100%, 40%);">+   flcomp = readl_(&cntlr->ich9_spi->fdod);</span><br><span> </span><br><span>       flash->size = 1 << (19 + (flcomp & 7));</span><br><span> </span><br><span>     flash->ops = &spi_flash_ops;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if ((cntlr.hsfs & HSFS_FDV) && ((cntlr.flmap0 >> 8) & 3))</span><br><span style="color: hsl(120, 100%, 40%);">+       if ((cntlr->hsfs & HSFS_FDV) && ((cntlr->flmap0 >> 8) & 3))</span><br><span>              flash->size += 1 << (19 + ((flcomp >> 3) & 7));</span><br><span>   printk (BIOS_DEBUG, "flash size 0x%x bytes\n", flash->size);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25414">change 25414</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/25414"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I4671653c0b07ab5c4bf91128f18f142ce4f893cf </div>
<div style="display:none"> Gerrit-Change-Number: 25414 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz> </div>