src/sb/intel/common/spi.c: Adapt and link in romstage

Based on Nicola Corna's work.

This allows for CONFIG_CONSOLE_SPI_FLASH to be used, which writes the
console output to the SPI flash.

TESTED to still work in ramstage on x220 (correctly writes MRC CACHE),
the option CONFIG_CONSOLE_SPI_FLASH compiles for targets using the
common Intel SPI code (untested though).

Change-Id: I4671653c0b07ab5c4bf91128f18f142ce4f893cf
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/25414
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
diff --git a/src/southbridge/intel/common/Makefile.inc b/src/southbridge/intel/common/Makefile.inc
index f5534c8..2a0bca6 100644
--- a/src/southbridge/intel/common/Makefile.inc
+++ b/src/southbridge/intel/common/Makefile.inc
@@ -28,6 +28,7 @@
 romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
 ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SMBUS) += smbus.c
 
+romstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c
 ramstage-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c
 ifeq ($(CONFIG_SPI_FLASH_SMM),y)
 smm-$(CONFIG_SOUTHBRIDGE_INTEL_COMMON_SPI) += spi.c
diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c
index 082a3d7..bd89025 100644
--- a/src/southbridge/intel/common/spi.c
+++ b/src/southbridge/intel/common/spi.c
@@ -15,6 +15,7 @@
  */
 
 /* This file is derived from the flashrom project. */
+#include <arch/early_variables.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -71,7 +72,7 @@
 
 typedef struct spi_slave ich_spi_slave;
 
-static int ichspi_lock = 0;
+static int g_ichspi_lock CAR_GLOBAL = 0;
 
 typedef struct ich7_spi_regs {
 	uint16_t spis;
@@ -139,7 +140,7 @@
 	uint8_t fpr_max;
 } ich_spi_controller;
 
-static ich_spi_controller cntlr;
+static ich_spi_controller g_cntlr CAR_GLOBAL;
 
 enum {
 	SPIS_SCIP =		0x0001,
@@ -281,17 +282,19 @@
 
 static void ich_set_bbar(uint32_t minaddr)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	const uint32_t bbar_mask = 0x00ffff00;
 	uint32_t ichspi_bbar;
 
 	minaddr &= bbar_mask;
-	ichspi_bbar = readl_(cntlr.bbar) & ~bbar_mask;
+	ichspi_bbar = readl_(cntlr->bbar) & ~bbar_mask;
 	ichspi_bbar |= minaddr;
-	writel_(ichspi_bbar, cntlr.bbar);
+	writel_(ichspi_bbar, cntlr->bbar);
 }
 
 void spi_init(void)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	uint8_t *rcrb; /* Root Complex Register Block */
 	uint32_t rcba; /* Root Complex Base Address */
 	uint8_t bios_cntl;
@@ -300,7 +303,7 @@
 	ich7_spi_regs *ich7_spi;
 	uint16_t hsfs;
 
-#ifdef __SMM__
+#ifdef __SIMPLE_DEVICE__
 	dev = PCI_DEV(0, 31, 0);
 #else
 	dev = dev_find_slot(0, PCI_DEVFN(31, 0));
@@ -311,41 +314,41 @@
 	rcrb = (uint8_t *)(rcba & 0xffffc000);
 	if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX)) {
 		ich7_spi = (ich7_spi_regs *)(rcrb + 0x3020);
-		cntlr.opmenu = ich7_spi->opmenu;
-		cntlr.menubytes = sizeof(ich7_spi->opmenu);
-		cntlr.optype = &ich7_spi->optype;
-		cntlr.addr = &ich7_spi->spia;
-		cntlr.data = (uint8_t *)ich7_spi->spid;
-		cntlr.databytes = sizeof(ich7_spi->spid);
-		cntlr.status = (uint8_t *)&ich7_spi->spis;
-		ichspi_lock = readw_(&ich7_spi->spis) & HSFS_FLOCKDN;
-		cntlr.control = &ich7_spi->spic;
-		cntlr.bbar = &ich7_spi->bbar;
-		cntlr.preop = &ich7_spi->preop;
-		cntlr.fpr = &ich7_spi->pbr[0];
-		cntlr.fpr_max = 3;
+		cntlr->opmenu = ich7_spi->opmenu;
+		cntlr->menubytes = sizeof(ich7_spi->opmenu);
+		cntlr->optype = &ich7_spi->optype;
+		cntlr->addr = &ich7_spi->spia;
+		cntlr->data = (uint8_t *)ich7_spi->spid;
+		cntlr->databytes = sizeof(ich7_spi->spid);
+		cntlr->status = (uint8_t *)&ich7_spi->spis;
+		car_set_var(g_ichspi_lock, readw_(&ich7_spi->spis) & HSFS_FLOCKDN);
+		cntlr->control = &ich7_spi->spic;
+		cntlr->bbar = &ich7_spi->bbar;
+		cntlr->preop = &ich7_spi->preop;
+		cntlr->fpr = &ich7_spi->pbr[0];
+		cntlr->fpr_max = 3;
 	} else {
 		ich9_spi = (ich9_spi_regs *)(rcrb + 0x3800);
-		cntlr.ich9_spi = ich9_spi;
+		cntlr->ich9_spi = ich9_spi;
 		hsfs = readw_(&ich9_spi->hsfs);
-		ichspi_lock = hsfs & HSFS_FLOCKDN;
-		cntlr.hsfs = hsfs;
-		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.bbar = &ich9_spi->bbar;
-		cntlr.preop = &ich9_spi->preop;
-		cntlr.fpr = &ich9_spi->pr[0];
-		cntlr.fpr_max = 5;
+		car_set_var(g_ichspi_lock, hsfs & HSFS_FLOCKDN);
+		cntlr->hsfs = hsfs;
+		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->bbar = &ich9_spi->bbar;
+		cntlr->preop = &ich9_spi->preop;
+		cntlr->fpr = &ich9_spi->pr[0];
+		cntlr->fpr_max = 5;
 
-		if (cntlr.hsfs & HSFS_FDV) {
+		if (cntlr->hsfs & HSFS_FDV) {
 			writel_ (4, &ich9_spi->fdoc);
-			cntlr.flmap0 = readl_(&ich9_spi->fdod);
+			cntlr->flmap0 = readl_(&ich9_spi->fdod);
 		}
 	}
 
@@ -423,17 +426,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. */
@@ -444,20 +448,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 &&
@@ -503,14 +507,15 @@
  */
 static int ich_status_poll(u16 bitmask, int wait_til_set)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	int timeout = 600000; /* This will result in 6 seconds */
 	u16 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);
@@ -523,14 +528,16 @@
 
 static int spi_is_multichip (void)
 {
-	if (!(cntlr.hsfs & HSFS_FDV))
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
+	if (!(cntlr->hsfs & HSFS_FDV))
 		return 0;
-	return !!((cntlr.flmap0 >> 8) & 3);
+	return !!((cntlr->flmap0 >> 8) & 3);
 }
 
 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;
@@ -556,7 +563,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)
@@ -570,8 +577,8 @@
 		 * in order to prevent the Management Engine from
 		 * issuing a transaction between WREN and DATA.
 		 */
-		if (!ichspi_lock)
-			writew_(trans.opcode, cntlr.preop);
+		if (!car_get_var(g_ichspi_lock))
+			writew_(trans.opcode, cntlr->preop);
 		return 0;
 	}
 
@@ -579,13 +586,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
@@ -593,7 +600,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);
@@ -615,7 +622,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;
@@ -629,28 +636,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);
@@ -663,7 +670,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;
@@ -671,7 +678,7 @@
 	}
 
 	/* Clear atomic preop now that xfer is done */
-	writew_(0, cntlr.preop);
+	writew_(0, cntlr->preop);
 
 	return 0;
 }
@@ -679,8 +686,9 @@
 /* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */
 static void ich_hwseq_set_addr(uint32_t addr)
 {
-	uint32_t addr_old = readl_(&cntlr.ich9_spi->faddr) & ~0x01FFFFFF;
-	writel_((addr & 0x01FFFFFF) | addr_old, &cntlr.ich9_spi->faddr);
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
+	uint32_t addr_old = readl_(&cntlr->ich9_spi->faddr) & ~0x01FFFFFF;
+	writel_((addr & 0x01FFFFFF) | addr_old, &cntlr->ich9_spi->faddr);
 }
 
 /* Polls for Cycle Done Status, Flash Cycle Error or timeout in 8 us intervals.
@@ -690,21 +698,22 @@
 static int ich_hwseq_wait_for_cycle_complete(unsigned int timeout,
 					     unsigned int len)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	uint16_t hsfs;
 	uint32_t addr;
 
 	timeout /= 8; /* scale timeout duration to counter */
-	while ((((hsfs = readw_(&cntlr.ich9_spi->hsfs)) &
+	while ((((hsfs = readw_(&cntlr->ich9_spi->hsfs)) &
 		 (HSFS_FDONE | HSFS_FCERR)) == 0) &&
 	       --timeout) {
 		udelay(8);
 	}
-	writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);
+	writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);
 
 	if (!timeout) {
 		uint16_t hsfc;
-		addr = readl_(&cntlr.ich9_spi->faddr) & 0x01FFFFFF;
-		hsfc = readw_(&cntlr.ich9_spi->hsfc);
+		addr = readl_(&cntlr->ich9_spi->faddr) & 0x01FFFFFF;
+		hsfc = readw_(&cntlr->ich9_spi->hsfc);
 		printk(BIOS_ERR, "Transaction timeout between offset 0x%08x and "
 		       "0x%08x (= 0x%08x + %d) HSFC=%x HSFS=%x!\n",
 		       addr, addr + len - 1, addr, len - 1,
@@ -714,8 +723,8 @@
 
 	if (hsfs & HSFS_FCERR) {
 		uint16_t hsfc;
-		addr = readl_(&cntlr.ich9_spi->faddr) & 0x01FFFFFF;
-		hsfc = readw_(&cntlr.ich9_spi->hsfc);
+		addr = readl_(&cntlr->ich9_spi->faddr) & 0x01FFFFFF;
+		hsfc = readw_(&cntlr->ich9_spi->hsfc);
 		printk(BIOS_ERR, "Transaction error between offset 0x%08x and "
 		       "0x%08x (= 0x%08x + %d) HSFC=%x HSFS=%x!\n",
 		       addr, addr + len - 1, addr, len - 1,
@@ -729,6 +738,7 @@
 static int ich_hwseq_erase(const struct spi_flash *flash, u32 offset,
 			size_t len)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	u32 start, end, erase_size;
 	int ret;
 	uint16_t hsfc;
@@ -751,17 +761,17 @@
 
 	while (offset < end) {
 		/* make sure FDONE, FCERR, AEL are cleared by writing 1 to them */
-		writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);
+		writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);
 
 		ich_hwseq_set_addr(offset);
 
 		offset += erase_size;
 
-		hsfc = readw_(&cntlr.ich9_spi->hsfc);
+		hsfc = readw_(&cntlr->ich9_spi->hsfc);
 		hsfc &= ~HSFC_FCYCLE; /* clear operation */
 		hsfc |= (0x3 << HSFC_FCYCLE_OFF); /* set erase operation */
 		hsfc |= HSFC_FGO; /* start */
-		writew_(hsfc, &cntlr.ich9_spi->hsfc);
+		writew_(hsfc, &cntlr->ich9_spi->hsfc);
 		if (ich_hwseq_wait_for_cycle_complete(timeout, len))
 		{
 			printk(BIOS_ERR, "SF: Erase failed at %x\n", offset - erase_size);
@@ -779,12 +789,13 @@
 
 static void ich_read_data(uint8_t *data, int len)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	int i;
 	uint32_t temp32 = 0;
 
 	for (i = 0; i < len; i++) {
 		if ((i % 4) == 0)
-			temp32 = readl_(cntlr.data + i);
+			temp32 = readl_(cntlr->data + i);
 
 		data[i] = (temp32 >> ((i % 4) * 8)) & 0xff;
 	}
@@ -793,6 +804,7 @@
 static int ich_hwseq_read(const struct spi_flash *flash, u32 addr, size_t len,
 			void *buf)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	uint16_t hsfc;
 	uint16_t timeout = 100 * 60;
 	uint8_t block_len;
@@ -806,20 +818,20 @@
 	}
 
 	/* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
-	writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);
+	writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);
 
 	while (len > 0) {
-		block_len = min(len, cntlr.databytes);
+		block_len = min(len, cntlr->databytes);
 		if (block_len > (~addr & 0xff))
 			block_len = (~addr & 0xff) + 1;
 		ich_hwseq_set_addr(addr);
-		hsfc = readw_(&cntlr.ich9_spi->hsfc);
+		hsfc = readw_(&cntlr->ich9_spi->hsfc);
 		hsfc &= ~HSFC_FCYCLE; /* set read operation */
 		hsfc &= ~HSFC_FDBC; /* clear byte count */
 		/* set byte count */
 		hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
 		hsfc |= HSFC_FGO; /* start */
-		writew_(hsfc, &cntlr.ich9_spi->hsfc);
+		writew_(hsfc, &cntlr->ich9_spi->hsfc);
 
 		if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))
 			return 1;
@@ -838,6 +850,7 @@
  */
 static void ich_fill_data(const uint8_t *data, int len)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	uint32_t temp32 = 0;
 	int i;
 
@@ -851,16 +864,17 @@
 		temp32 |= ((uint32_t) data[i]) << ((i % 4) * 8);
 
 		if ((i % 4) == 3) /* 32 bits are full, write them to regs. */
-			writel_(temp32, cntlr.data + (i - (i % 4)));
+			writel_(temp32, cntlr->data + (i - (i % 4)));
 	}
 	i--;
 	if ((i % 4) != 3) /* Write remaining data to regs. */
-		writel_(temp32, cntlr.data + (i - (i % 4)));
+		writel_(temp32, cntlr->data + (i - (i % 4)));
 }
 
 static int ich_hwseq_write(const struct spi_flash *flash, u32 addr, size_t len,
 			const void *buf)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	uint16_t hsfc;
 	uint16_t timeout = 100 * 60;
 	uint8_t block_len;
@@ -874,24 +888,24 @@
 	}
 
 	/* clear FDONE, FCERR, AEL by writing 1 to them (if they are set) */
-	writew_(readw_(&cntlr.ich9_spi->hsfs), &cntlr.ich9_spi->hsfs);
+	writew_(readw_(&cntlr->ich9_spi->hsfs), &cntlr->ich9_spi->hsfs);
 
 	while (len > 0) {
-		block_len = min(len, cntlr.databytes);
+		block_len = min(len, cntlr->databytes);
 		if (block_len > (~addr & 0xff))
 			block_len = (~addr & 0xff) + 1;
 
 		ich_hwseq_set_addr(addr);
 
 		ich_fill_data(buf, block_len);
-		hsfc = readw_(&cntlr.ich9_spi->hsfc);
+		hsfc = readw_(&cntlr->ich9_spi->hsfc);
 		hsfc &= ~HSFC_FCYCLE; /* clear operation */
 		hsfc |= (0x2 << HSFC_FCYCLE_OFF); /* set write operation */
 		hsfc &= ~HSFC_FDBC; /* clear byte count */
 		/* set byte count */
 		hsfc |= (((block_len - 1) << HSFC_FDBC_OFF) & HSFC_FDBC);
 		hsfc |= HSFC_FGO; /* start */
-		writew_(hsfc, &cntlr.ich9_spi->hsfc);
+		writew_(hsfc, &cntlr->ich9_spi->hsfc);
 
 		if (ich_hwseq_wait_for_cycle_complete(timeout, block_len))
 		{
@@ -917,6 +931,7 @@
 static int spi_flash_programmer_probe(const struct spi_slave *spi,
 					struct spi_flash *flash)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	uint32_t flcomp;
 
 	if (IS_ENABLED(CONFIG_SOUTHBRIDGE_INTEL_I82801GX))
@@ -930,7 +945,7 @@
 	flash->name = "Opaque HW-sequencing";
 
 	ich_hwseq_set_addr (0);
-	switch ((cntlr.hsfs >> 3) & 3)
+	switch ((cntlr->hsfs >> 3) & 3)
 	{
 	case 0:
 		flash->sector_size = 256;
@@ -946,14 +961,14 @@
 		break;
 	}
 
-	writel_ (0x1000, &cntlr.ich9_spi->fdoc);
-	flcomp = readl_(&cntlr.ich9_spi->fdod);
+	writel_ (0x1000, &cntlr->ich9_spi->fdoc);
+	flcomp = readl_(&cntlr->ich9_spi->fdod);
 
 	flash->size = 1 << (19 + (flcomp & 7));
 
 	flash->ops = &spi_flash_ops;
 
-	if ((cntlr.hsfs & HSFS_FDV) && ((cntlr.flmap0 >> 8) & 3))
+	if ((cntlr->hsfs & HSFS_FDV) && ((cntlr->flmap0 >> 8) & 3))
 		flash->size += 1 << (19 + ((flcomp >> 3) & 7));
 	printk (BIOS_DEBUG, "flash size 0x%x bytes\n", flash->size);
 
@@ -999,22 +1014,23 @@
 static int spi_flash_protect(const struct spi_flash *flash,
 			const struct region *region)
 {
+	ich_spi_controller *cntlr = car_get_var_ptr(&g_cntlr);
 	u32 start = region_offset(region);
 	u32 end = start + region_sz(region) - 1;
 	u32 reg;
 	int fpr;
 	uint32_t *fpr_base;
 
-	fpr_base = cntlr.fpr;
+	fpr_base = cntlr->fpr;
 
 	/* Find first empty FPR */
-	for (fpr = 0; fpr < cntlr.fpr_max; fpr++) {
+	for (fpr = 0; fpr < cntlr->fpr_max; fpr++) {
 		reg = read32(&fpr_base[fpr]);
 		if (reg == 0)
 			break;
 	}
 
-	if (fpr == cntlr.fpr_max) {
+	if (fpr == cntlr->fpr_max) {
 		printk(BIOS_ERR, "ERROR: No SPI FPR free!\n");
 		return -1;
 	}