Matt DeVillier has uploaded this change for review.

View Change

soc/fsp_baytrail: fix flashconsole on platform

Include spi.c in romstage. Since FSP 1.0 can't use
NO_CAR_GLOBAL_MIGRATION, adjust global variables in spi.c
to use CAR_GLOBAL.

Adapted from early versions of CB:21107

Change-Id: I3487fb8ac317ce920bf1c3ef9d89590051932378
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
---
M src/soc/intel/fsp_baytrail/Makefile.inc
M src/soc/intel/fsp_baytrail/spi.c
2 files changed, 44 insertions(+), 39 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/79/32879/1
diff --git a/src/soc/intel/fsp_baytrail/Makefile.inc b/src/soc/intel/fsp_baytrail/Makefile.inc
index 5ed635d..ca2b353 100644
--- a/src/soc/intel/fsp_baytrail/Makefile.inc
+++ b/src/soc/intel/fsp_baytrail/Makefile.inc
@@ -35,6 +35,7 @@
postcar-y += tsc_freq.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += tsc_freq.c
ramstage-y += spi.c
+romstage-y += spi.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += spi.c
ramstage-y += chip.c
ramstage-y += iosf.c
diff --git a/src/soc/intel/fsp_baytrail/spi.c b/src/soc/intel/fsp_baytrail/spi.c
index 979ee57..9375d19 100644
--- a/src/soc/intel/fsp_baytrail/spi.c
+++ b/src/soc/intel/fsp_baytrail/spi.c
@@ -15,7 +15,7 @@
*/

/* This file is derived from the flashrom project. */
-
+#include <arch/early_variables.h>
#include <stdint.h>
#include <stdlib.h>
#include <commonlib/helpers.h>
@@ -33,7 +33,7 @@

typedef struct spi_slave ich_spi_slave;

-static int ichspi_lock = 0;
+static int g_ichspi_lock CAR_GLOBAL = 0;

typedef struct ich9_spi_regs {
uint32_t bfpr;
@@ -81,7 +81,7 @@
uint16_t *control;
} ich_spi_controller;

-static ich_spi_controller cntlr;
+static ich_spi_controller g_cntlr CAR_GLOBAL;

enum {
SPIS_SCIP = 0x0001,
@@ -239,18 +239,19 @@

void spi_init(void)
{
+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
ich9_spi_regs *ich9_spi = spi_regs();

- ichspi_lock = readw_(&ich9_spi->hsfs) & HSFS_FLOCKDN;
- cntlr.opmenu = ich9_spi->opmenu;
- cntlr.menubytes = sizeof(ich9_spi->opmenu);
- cntlr.optype = &ich9_spi->optype;
- cntlr.addr = &ich9_spi->faddr;
- cntlr.data = (uint8_t *)ich9_spi->fdata;
- cntlr.databytes = sizeof(ich9_spi->fdata);
- cntlr.status = &ich9_spi->ssfs;
- cntlr.control = (uint16_t *)ich9_spi->ssfc;
- cntlr.preop = &ich9_spi->preop;
+ car_set_var(g_ichspi_lock, readw_(&ich9_spi->hsfs) & HSFS_FLOCKDN);
+ cntlr->opmenu = ich9_spi->opmenu;
+ cntlr->menubytes = sizeof(ich9_spi->opmenu);
+ cntlr->optype = &ich9_spi->optype;
+ cntlr->addr = &ich9_spi->faddr;
+ cntlr->data = (uint8_t *)ich9_spi->fdata;
+ cntlr->databytes = sizeof(ich9_spi->fdata);
+ cntlr->status = &ich9_spi->ssfs;
+ cntlr->control = (uint16_t *)ich9_spi->ssfc;
+ cntlr->preop = &ich9_spi->preop;
}

typedef struct spi_transaction {
@@ -311,17 +312,18 @@

static int spi_setup_opcode(spi_transaction *trans)
{
+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
uint16_t optypes;
- uint8_t opmenu[cntlr.menubytes];
+ uint8_t opmenu[cntlr->menubytes];

trans->opcode = trans->out[0];
spi_use_out(trans, 1);
- if (!ichspi_lock) {
+ if (!car_get_var(g_ichspi_lock)) {
/* The lock is off, so just use index 0. */
- writeb_(trans->opcode, cntlr.opmenu);
- optypes = readw_(cntlr.optype);
+ writeb_(trans->opcode, cntlr->opmenu);
+ optypes = readw_(cntlr->optype);
optypes = (optypes & 0xfffc) | (trans->type & 0x3);
- writew_(optypes, cntlr.optype);
+ writew_(optypes, cntlr->optype);
return 0;
} else {
/* The lock is on. See if what we need is on the menu. */
@@ -332,20 +334,20 @@
if (trans->opcode == SPI_OPCODE_WREN)
return 0;

- read_reg(cntlr.opmenu, opmenu, sizeof(opmenu));
- for (opcode_index = 0; opcode_index < cntlr.menubytes;
+ read_reg(cntlr->opmenu, opmenu, sizeof(opmenu));
+ for (opcode_index = 0; opcode_index < cntlr->menubytes;
opcode_index++) {
if (opmenu[opcode_index] == trans->opcode)
break;
}

- if (opcode_index == cntlr.menubytes) {
+ if (opcode_index == cntlr->menubytes) {
printk(BIOS_DEBUG, "ICH SPI: Opcode %x not found\n",
trans->opcode);
return -1;
}

- optypes = readw_(cntlr.optype);
+ optypes = readw_(cntlr->optype);
optype = (optypes >> (opcode_index * 2)) & 0x3;
if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
@@ -391,14 +393,15 @@
*/
static int ich_status_poll(uint16_t bitmask, int wait_til_set)
{
+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
int timeout = 40000; /* This will result in 400 ms */
uint16_t status = 0;

while (timeout--) {
- status = readw_(cntlr.status);
+ status = readw_(cntlr->status);
if (wait_til_set ^ ((status & bitmask) == 0)) {
if (wait_til_set)
- writew_((status & bitmask), cntlr.status);
+ writew_((status & bitmask), cntlr->status);
return status;
}
udelay(10);
@@ -412,6 +415,7 @@
static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
size_t bytesout, void *din, size_t bytesin)
{
+ ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
uint16_t control;
int16_t opcode_index;
int with_address;
@@ -437,7 +441,7 @@
if (ich_status_poll(SPIS_SCIP, 0) == -1)
return -1;

- writew_(SPIS_CDS | SPIS_FCERR, cntlr.status);
+ writew_(SPIS_CDS | SPIS_FCERR, cntlr->status);

spi_setup_type(&trans);
if ((opcode_index = spi_setup_opcode(&trans)) < 0)
@@ -445,13 +449,13 @@
if ((with_address = spi_setup_offset(&trans)) < 0)
return -1;

- if (!ichspi_lock && trans.opcode == SPI_OPCODE_WREN) {
+ if (!car_get_var(g_ichspi_lock) && trans.opcode == SPI_OPCODE_WREN) {
/*
* Treat Write Enable as Atomic Pre-Op if possible
* in order to prevent the Management Engine from
* issuing a transaction between WREN and DATA.
*/
- writew_(trans.opcode, cntlr.preop);
+ writew_(trans.opcode, cntlr->preop);
return 0;
}

@@ -459,13 +463,13 @@
control = SPIC_SCGO | ((opcode_index & 0x07) << 4);

/* Issue atomic preop cycle if needed */
- if (readw_(cntlr.preop))
+ if (readw_(cntlr->preop))
control |= SPIC_ACS;

if (!trans.bytesout && !trans.bytesin) {
/* SPI addresses are 24 bit only */
if (with_address)
- writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
+ writel_(trans.offset & 0x00FFFFFF, cntlr->addr);

/*
* This is a 'no data' command (like Write Enable), its
@@ -473,7 +477,7 @@
* spi_setup_opcode() above. Tell the chip to send the
* command.
*/
- writew_(control, cntlr.control);
+ writew_(control, cntlr->control);

/* wait for the result */
status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
@@ -495,7 +499,7 @@
* and followed by other SPI commands, and this sequence is controlled
* by the SPI chip driver.
*/
- if (trans.bytesout > cntlr.databytes) {
+ if (trans.bytesout > cntlr->databytes) {
printk(BIOS_DEBUG, "ICH SPI: Too much to write. Does your SPI chip driver use"
" spi_crop_chunk()?\n");
return -1;
@@ -509,28 +513,28 @@
uint32_t data_length;

/* SPI addresses are 24 bit only */
- writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
+ writel_(trans.offset & 0x00FFFFFF, cntlr->addr);

if (trans.bytesout)
- data_length = min(trans.bytesout, cntlr.databytes);
+ data_length = min(trans.bytesout, cntlr->databytes);
else
- data_length = min(trans.bytesin, cntlr.databytes);
+ data_length = min(trans.bytesin, cntlr->databytes);

/* Program data into FDATA0 to N */
if (trans.bytesout) {
- write_reg(trans.out, cntlr.data, data_length);
+ write_reg(trans.out, cntlr->data, data_length);
spi_use_out(&trans, data_length);
if (with_address)
trans.offset += data_length;
}

/* Add proper control fields' values */
- control &= ~((cntlr.databytes - 1) << 8);
+ control &= ~((cntlr->databytes - 1) << 8);
control |= SPIC_DS;
control |= (data_length - 1) << 8;

/* write it */
- writew_(control, cntlr.control);
+ writew_(control, cntlr->control);

/* Wait for Cycle Done Status or Flash Cycle Error. */
status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
@@ -543,7 +547,7 @@
}

if (trans.bytesin) {
- read_reg(cntlr.data, trans.in, data_length);
+ read_reg(cntlr->data, trans.in, data_length);
spi_use_in(&trans, data_length);
if (with_address)
trans.offset += data_length;
@@ -552,7 +556,7 @@

spi_xfer_exit:
/* Clear atomic preop now that xfer is done */
- writew_(0, cntlr.preop);
+ writew_(0, cntlr->preop);

return 0;
}

To view, visit change 32879. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I3487fb8ac317ce920bf1c3ef9d89590051932378
Gerrit-Change-Number: 32879
Gerrit-PatchSet: 1
Gerrit-Owner: Matt DeVillier <matt.devillier@gmail.com>
Gerrit-Reviewer: Huang Jin <huang.jin@intel.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Matt DeVillier <matt.devillier@gmail.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org>
Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Gerrit-MessageType: newchange