<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>