[coreboot-gerrit] New patch to review for coreboot: spi: Define and use spi_ctrlr structure

Furquan Shaikh (furquan@google.com) gerrit at coreboot.org
Thu Dec 1 17:08:02 CET 2016


Furquan Shaikh (furquan at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17684

-gerrit

commit 2cecf4c4a02c5c35f1a364d8348bb42c621cd75e
Author: Furquan Shaikh <furquan at chromium.org>
Date:   Thu Dec 1 07:12:32 2016 -0800

    spi: Define and use spi_ctrlr structure
    
    1. Define a new structure spi_ctrlr that allows platforms to define
    callbacks for spi operations (claim bus, release bus, transfer).
    2. Add a new member (pointer to spi_ctrlr structure) in spi_slave
    structure which will be initialized by call to spi_setup_slave.
    3. Define spi_claim_bus, spi_release_bus and spi_xfer in spi-generic.c
    which will make appropriate calls to ctrlr functions.
    
    BUG=chrome-os-partner:59832
    BRANCH=None
    TEST=Compiles successfully
    
    Change-Id: Icb2326e3aab1e8f4bef53f553f82b3836358c55e
    Signed-off-by: Furquan Shaikh <furquan at chromium.org>
---
 src/drivers/spi/Makefile.inc             |   5 ++
 src/drivers/spi/spi-generic.c            |  43 +++++++++++++
 src/include/spi-generic.h                |  18 ++++++
 src/soc/broadcom/cygnus/spi.c            |  87 +++++++++++++------------
 src/soc/imgtec/pistachio/spi.c           | 105 ++++++++++++++++---------------
 src/soc/intel/apollolake/spi.c           |  19 +-----
 src/soc/intel/baytrail/spi.c             |  34 +++++-----
 src/soc/intel/braswell/spi.c             |  34 +++++-----
 src/soc/intel/broadwell/spi.c            |  34 +++++-----
 src/soc/intel/fsp_baytrail/spi.c         |  34 +++++-----
 src/soc/intel/fsp_broadwell_de/spi.c     |  34 +++++-----
 src/soc/intel/skylake/flash_controller.c |  19 +-----
 src/soc/marvell/armada38x/spi.c          |  37 ++++++-----
 src/soc/marvell/bg4cd/spi.c              |  15 -----
 src/soc/mediatek/mt8173/spi.c            |  60 ++++++++++--------
 src/soc/nvidia/tegra124/spi.c            |  15 +++--
 src/soc/nvidia/tegra210/spi.c            |  15 +++--
 src/soc/qualcomm/ipq40xx/spi.c           |  93 ++++++++++++++-------------
 src/soc/qualcomm/ipq806x/spi.c           | 103 ++++++++++++++++--------------
 src/soc/rockchip/common/spi.c            |  35 ++++++-----
 src/soc/samsung/exynos5420/spi.c         |  47 ++++++++------
 src/southbridge/amd/agesa/hudson/spi.c   |  18 ++----
 src/southbridge/amd/cimx/sb800/spi.c     |  19 ++----
 src/southbridge/amd/sb700/spi.c          |  32 ++++------
 src/southbridge/intel/common/spi.c       |  32 ++++------
 src/southbridge/intel/fsp_rangeley/spi.c |  32 ++++------
 26 files changed, 524 insertions(+), 495 deletions(-)

diff --git a/src/drivers/spi/Makefile.inc b/src/drivers/spi/Makefile.inc
index 92baf62..c1bf307 100644
--- a/src/drivers/spi/Makefile.inc
+++ b/src/drivers/spi/Makefile.inc
@@ -7,6 +7,7 @@ ramstage-y += spiconsole.c
 smm-$(CONFIG_DEBUG_SMI) += spiconsole.c
 endif
 
+bootblock-y += spi-generic.c
 bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 bootblock-$(CONFIG_SPI_FLASH) += spi_flash.c
 bootblock-$(CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY) += boot_device_rw_nommap.c
@@ -22,6 +23,7 @@ bootblock-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
 bootblock-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 bootblock-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 
+romstage-y += spi-generic.c
 romstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 romstage-$(CONFIG_SPI_FLASH) += spi_flash.c
 romstage-$(CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY) += boot_device_rw_nommap.c
@@ -37,6 +39,7 @@ romstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
 romstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 romstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 
+verstage-y += spi-generic.c
 verstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 verstage-$(CONFIG_SPI_FLASH) += spi_flash.c
 verstage-$(CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP_EARLY) += boot_device_rw_nommap.c
@@ -52,6 +55,7 @@ verstage-$(CONFIG_SPI_FLASH_STMICRO) += stmicro.c
 verstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 verstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 
+ramstage-y += spi-generic.c
 ramstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 ramstage-$(CONFIG_SPI_FLASH) += spi_flash.c
 ramstage-$(CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP) += boot_device_rw_nommap.c
@@ -68,6 +72,7 @@ ramstage-$(CONFIG_SPI_FLASH_WINBOND) += winbond.c
 ramstage-$(CONFIG_SPI_FRAM_RAMTRON) += ramtron.c
 
 ifeq ($(CONFIG_SPI_FLASH_SMM),y)
+smm-y += spi-generic.c
 # SPI flash driver interface
 smm-$(CONFIG_SPI_FLASH) += spi_flash.c
 smm-$(CONFIG_BOOT_DEVICE_SPI_FLASH_RW_NOMMAP) += boot_device_rw_nommap.c
diff --git a/src/drivers/spi/spi-generic.c b/src/drivers/spi/spi-generic.c
new file mode 100644
index 0000000..7398ee9
--- /dev/null
+++ b/src/drivers/spi/spi-generic.c
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <spi-generic.h>
+#include <string.h>
+
+int spi_claim_bus(const struct spi_slave *slave)
+{
+	const struct spi_ctrlr *ctrlr = slave->ctrlr;
+	if (ctrlr && ctrlr->claim_bus)
+		return ctrlr->claim_bus(slave);
+	return 0;
+}
+
+void spi_release_bus(const struct spi_slave *slave)
+{
+	const struct spi_ctrlr *ctrlr = slave->ctrlr;
+	if (ctrlr && ctrlr->release_bus)
+		ctrlr->release_bus(slave);
+}
+
+int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
+	     void *din, size_t bytesin)
+{
+	const struct spi_ctrlr *ctrlr = slave->ctrlr;
+	if (ctrlr && ctrlr->xfer)
+		return ctrlr->xfer(slave, dout, bytesout, din, bytesin);
+
+	return -1;
+}
diff --git a/src/include/spi-generic.h b/src/include/spi-generic.h
index c8b209d..b4a10af 100644
--- a/src/include/spi-generic.h
+++ b/src/include/spi-generic.h
@@ -21,15 +21,33 @@
 
 /* Controller-specific definitions: */
 
+struct spi_ctrlr;
+
 /*-----------------------------------------------------------------------
  * Representation of a SPI slave, i.e. what we're communicating with.
  *
  *   bus:	ID of the bus that the slave is attached to.
  *   cs:	ID of the chip select connected to the slave.
+ *   ctrlr:	Pointer to SPI controller structure.
  */
 struct spi_slave {
 	unsigned int	bus;
 	unsigned int	cs;
+	const struct spi_ctrlr *ctrlr;
+};
+
+/*-----------------------------------------------------------------------
+ * Representation of a SPI contoller.
+ *
+ * claim_bus:	Claim SPI bus and prepare for communication.
+ * release_bus: Release SPI bus.
+ * xfer:	SPI transfer
+ */
+struct spi_ctrlr {
+	int (*claim_bus)(const struct spi_slave *slave);
+	void (*release_bus)(const struct spi_slave *slave);
+	int (*xfer)(const struct spi_slave *slave, const void *dout,
+		    size_t bytesout, void *din, size_t bytesin);
 };
 
 /*-----------------------------------------------------------------------
diff --git a/src/soc/broadcom/cygnus/spi.c b/src/soc/broadcom/cygnus/spi.c
index 810f2c2..e597efc 100644
--- a/src/soc/broadcom/cygnus/spi.c
+++ b/src/soc/broadcom/cygnus/spi.c
@@ -96,42 +96,6 @@ static struct qspi_priv *to_qspi_slave(const struct spi_slave *slave)
 	return &qspi_slave;
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	struct qspi_priv *priv = &qspi_slave;
-	unsigned int spbr;
-
-	slave->bus = bus;
-	slave->cs = cs;
-
-	priv->max_hz = QSPI_MAX_HZ;
-	priv->spi_mode = QSPI_MODE;
-	priv->reg = (void *)(IPROC_QSPI_BASE);
-	priv->mspi_enabled = 0;
-	priv->bus_claimed = 0;
-
-	/* MSPI: Basic hardware initialization */
-	REG_WR(priv->reg + MSPI_SPCR1_LSB_REG, 0);
-	REG_WR(priv->reg + MSPI_SPCR1_MSB_REG, 0);
-	REG_WR(priv->reg + MSPI_NEWQP_REG, 0);
-	REG_WR(priv->reg + MSPI_ENDQP_REG, 0);
-	REG_WR(priv->reg + MSPI_SPCR2_REG, 0);
-
-	/* MSPI: SCK configuration */
-	spbr = (IPROC_QSPI_CLK - 1) / (2 * priv->max_hz) + 1;
-	REG_WR(priv->reg + MSPI_SPCR0_LSB_REG,
-	       MAX(MIN(spbr, SPBR_MAX), SPBR_MIN));
-
-	/* MSPI: Mode configuration (8 bits by default) */
-	priv->mspi_16bit = 0;
-	REG_WR(priv->reg + MSPI_SPCR0_MSB_REG,
-	       0x80 |			/* Master */
-	       (8 << 2) |		/* 8 bits per word */
-	       (priv->spi_mode & 3));	/* mode: CPOL / CPHA */
-
-	return 0;
-}
-
 static int mspi_enable(struct qspi_priv *priv)
 {
 	struct stopwatch sw;
@@ -156,7 +120,7 @@ static int mspi_enable(struct qspi_priv *priv)
 	return 0;
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct qspi_priv *priv = to_qspi_slave(slave);
 
@@ -175,7 +139,7 @@ int spi_claim_bus(const struct spi_slave *slave)
 	return 0;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct qspi_priv *priv = to_qspi_slave(slave);
 
@@ -189,8 +153,8 @@ void spi_release_bus(const struct spi_slave *slave)
 #define RXRAM_8B(p, i)	(REG_RD((p)->reg + MSPI_RXRAM_REG + \
 				((((i) << 1) + 1) << 2)) & 0xff)
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
-	     void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			   size_t bytesout, void *din, size_t bytesin)
 {
 	struct qspi_priv *priv = to_qspi_slave(slave);
 	const u8 *tx = (const u8 *)dout;
@@ -311,6 +275,49 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
 	return 0;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	struct qspi_priv *priv = &qspi_slave;
+	unsigned int spbr;
+
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+
+	priv->max_hz = QSPI_MAX_HZ;
+	priv->spi_mode = QSPI_MODE;
+	priv->reg = (void *)(IPROC_QSPI_BASE);
+	priv->mspi_enabled = 0;
+	priv->bus_claimed = 0;
+
+	/* MSPI: Basic hardware initialization */
+	REG_WR(priv->reg + MSPI_SPCR1_LSB_REG, 0);
+	REG_WR(priv->reg + MSPI_SPCR1_MSB_REG, 0);
+	REG_WR(priv->reg + MSPI_NEWQP_REG, 0);
+	REG_WR(priv->reg + MSPI_ENDQP_REG, 0);
+	REG_WR(priv->reg + MSPI_SPCR2_REG, 0);
+
+	/* MSPI: SCK configuration */
+	spbr = (IPROC_QSPI_CLK - 1) / (2 * priv->max_hz) + 1;
+	REG_WR(priv->reg + MSPI_SPCR0_LSB_REG,
+	       MAX(MIN(spbr, SPBR_MAX), SPBR_MIN));
+
+	/* MSPI: Mode configuration (8 bits by default) */
+	priv->mspi_16bit = 0;
+	REG_WR(priv->reg + MSPI_SPCR0_MSB_REG,
+	       0x80 |			/* Master */
+	       (8 << 2) |		/* 8 bits per word */
+	       (priv->spi_mode & 3));	/* mode: CPOL / CPHA */
+
+	return 0;
+}
+
 unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 {
 	return min(65535, buf_len);
diff --git a/src/soc/imgtec/pistachio/spi.c b/src/soc/imgtec/pistachio/spi.c
index 2dd3ecd..bd7ea46 100644
--- a/src/soc/imgtec/pistachio/spi.c
+++ b/src/soc/imgtec/pistachio/spi.c
@@ -417,53 +417,8 @@ void spi_init(void)
 	memset(img_spi_slaves, 0, sizeof(img_spi_slaves));
 }
 
-/* Set up communications parameters for a SPI slave. */
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	struct img_spi_slave *img_slave = NULL;
-	struct spim_device_parameters *device_parameters;
-	u32 base;
-
-	switch (bus) {
-	case 0:
-		base = IMG_SPIM0_BASE_ADDRESS;
-		break;
-	case 1:
-		base = IMG_SPIM1_BASE_ADDRESS;
-		break;
-	default:
-		printk(BIOS_ERR, "%s: Error: unsupported bus.\n",
-				__func__);
-		return -1;
-	}
-	if (cs > SPIM_DEVICE4) {
-		printk(BIOS_ERR, "%s: Error: unsupported chipselect.\n",
-				__func__);
-		return -1;
-	}
-
-	slave->bus = bus;
-	slave->cs = cs;
-
-	img_slave = get_img_slave(slave);
-	device_parameters = &(img_slave->device_parameters);
-
-	img_slave->base = base;
-
-	device_parameters->bitrate = 64;
-	device_parameters->cs_setup = 0;
-	device_parameters->cs_hold = 0;
-	device_parameters->cs_delay = 0;
-	device_parameters->spi_mode = SPIM_MODE_0;
-	device_parameters->cs_idle_level = 1;
-	device_parameters->data_idle_level = 0;
-	img_slave->initialised = IMG_FALSE;
-
-	return 0;
-}
-
 /* Claim the bus and prepare it for communication */
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	int ret;
 	struct img_spi_slave *img_slave;
@@ -494,7 +449,7 @@ int spi_claim_bus(const struct spi_slave *slave)
 }
 
 /* Release the SPI bus */
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct img_spi_slave *img_slave;
 
@@ -536,8 +491,8 @@ static int do_spi_xfer(const struct spi_slave *slave, const void *dout,
 	return spim_io(slave, &buff_0, (dout && din) ? &buff_1 : NULL);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
-	     void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			      size_t bytesout, void *din, size_t bytesin)
 {
 	unsigned int in_sz, out_sz;
 	int ret;
@@ -578,6 +533,58 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytesout,
 	return SPIM_OK;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+/* Set up communications parameters for a SPI slave. */
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	struct img_spi_slave *img_slave = NULL;
+	struct spim_device_parameters *device_parameters;
+	u32 base;
+
+	switch (bus) {
+	case 0:
+		base = IMG_SPIM0_BASE_ADDRESS;
+		break;
+	case 1:
+		base = IMG_SPIM1_BASE_ADDRESS;
+		break;
+	default:
+		printk(BIOS_ERR, "%s: Error: unsupported bus.\n",
+				__func__);
+		return -1;
+	}
+	if (cs > SPIM_DEVICE4) {
+		printk(BIOS_ERR, "%s: Error: unsupported chipselect.\n",
+				__func__);
+		return -1;
+	}
+
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+
+	img_slave = get_img_slave(slave);
+	device_parameters = &(img_slave->device_parameters);
+
+	img_slave->base = base;
+
+	device_parameters->bitrate = 64;
+	device_parameters->cs_setup = 0;
+	device_parameters->cs_hold = 0;
+	device_parameters->cs_delay = 0;
+	device_parameters->spi_mode = SPIM_MODE_0;
+	device_parameters->cs_idle_level = 1;
+	device_parameters->data_idle_level = 0;
+	img_slave->initialised = IMG_FALSE;
+
+	return 0;
+}
+
 unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 {
 	return min(IMGTEC_SPI_MAX_TRANSFER_SIZE, buf_len);
diff --git a/src/soc/intel/apollolake/spi.c b/src/soc/intel/apollolake/spi.c
index ca56702..8992fa5 100644
--- a/src/soc/intel/apollolake/spi.c
+++ b/src/soc/intel/apollolake/spi.c
@@ -184,13 +184,6 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return MIN(buf_len, SPIBAR_FDATA_FIFO_SIZE);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-	     size_t bytesout, void *din, size_t bytesin)
-{
-	printk(BIOS_DEBUG, "NOT IMPLEMENTED: %s() !!!\n", __func__);
-	return E_NOT_IMPLEMENTED;
-}
-
 /*
  * Write-protection status for BIOS region (BIOS_CONTROL register):
  * EISS/WPD bits	00	01	10	11
@@ -215,17 +208,6 @@ void spi_init(void)
 	pci_write_config32(ctx->pci_dev, SPIBAR_BIOS_CONTROL, bios_ctl);
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* There's nothing we need to to here. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* No magic needed here. */
-}
-
 static int nuclear_spi_erase(const struct spi_flash *flash, uint32_t offset,
 			     size_t len)
 {
@@ -400,6 +382,7 @@ int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 
 	slave->bus = bus;
 	slave->cs = cs;
+	slave->ctrlr = NULL;
 
 	return 0;
 }
diff --git a/src/soc/intel/baytrail/spi.c b/src/soc/intel/baytrail/spi.c
index b4f95aa..0f7b0c6 100644
--- a/src/soc/intel/baytrail/spi.c
+++ b/src/soc/intel/baytrail/spi.c
@@ -260,13 +260,6 @@ static void ich_set_bbar(uint32_t minaddr)
 	writel_(ichspi_bbar, cntlr.bbar);
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 static ich9_spi_regs *spi_regs(void)
 {
 	device_t dev;
@@ -308,17 +301,6 @@ static void spi_init_cb(void *unused)
 
 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -480,8 +462,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-		size_t bytesout, void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+		    size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
 	int16_t opcode_index;
@@ -627,3 +609,15 @@ int spi_xfer(const struct spi_slave *slave, const void *dout,
 
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
diff --git a/src/soc/intel/braswell/spi.c b/src/soc/intel/braswell/spi.c
index 4236e6f..2a0ddf8 100644
--- a/src/soc/intel/braswell/spi.c
+++ b/src/soc/intel/braswell/spi.c
@@ -229,13 +229,6 @@ static void read_reg(void *src, void *value, uint32_t size)
 	}
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 static ich9_spi_regs *spi_regs(void)
 {
 	device_t dev;
@@ -287,17 +280,6 @@ static void spi_init_cb(void *unused)
 
 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -461,8 +443,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-		size_t bytesout, void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+		    size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
 	int16_t opcode_index;
@@ -611,3 +593,15 @@ int spi_xfer(const struct spi_slave *slave, const void *dout,
 
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
diff --git a/src/soc/intel/broadwell/spi.c b/src/soc/intel/broadwell/spi.c
index 5220970..d2ae943 100644
--- a/src/soc/intel/broadwell/spi.c
+++ b/src/soc/intel/broadwell/spi.c
@@ -259,13 +259,6 @@ static void ich_set_bbar(uint32_t minaddr)
 	writel_(ichspi_bbar, cntlr.bbar);
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 void spi_init(void)
 {
 	uint8_t *rcrb; /* Root Complex Register Block */
@@ -304,17 +297,6 @@ static void spi_init_cb(void *unused)
 
 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -476,8 +458,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-		size_t bytesout, void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+		    size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
 	int16_t opcode_index;
@@ -661,3 +643,15 @@ int spi_flash_protect(u32 start, u32 size)
 	       __func__, prr, start, end);
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
diff --git a/src/soc/intel/fsp_baytrail/spi.c b/src/soc/intel/fsp_baytrail/spi.c
index 06b160c..997bd13 100644
--- a/src/soc/intel/fsp_baytrail/spi.c
+++ b/src/soc/intel/fsp_baytrail/spi.c
@@ -249,13 +249,6 @@ static void read_reg(const void *src, void *value, uint32_t size)
 	}
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 static ich9_spi_regs *spi_regs(void)
 {
 	device_t dev;
@@ -288,17 +281,6 @@ void spi_init(void)
 	cntlr.preop = &ich9_spi->preop;
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -460,8 +442,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-		size_t bytesout, void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+		    size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
 	int16_t opcode_index;
@@ -607,3 +589,15 @@ spi_xfer_exit:
 
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
diff --git a/src/soc/intel/fsp_broadwell_de/spi.c b/src/soc/intel/fsp_broadwell_de/spi.c
index 8af5686..5848966 100644
--- a/src/soc/intel/fsp_broadwell_de/spi.c
+++ b/src/soc/intel/fsp_broadwell_de/spi.c
@@ -259,13 +259,6 @@ static void ich_set_bbar(uint32_t minaddr)
 	writel_(ichspi_bbar, cntlr.bbar);
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave * slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 void spi_init(void)
 {
 	uint8_t *rcrb; /* Root Complex Register Block */
@@ -303,17 +296,6 @@ void spi_init(void)
 	pci_write_config_byte(dev, 0xdc, bios_cntl | 0x1);
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -475,8 +457,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-		size_t bytesout, void *din, size_t bytesin)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+		    size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
 	int16_t opcode_index;
@@ -624,3 +606,15 @@ spi_xfer_exit:
 
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
diff --git a/src/soc/intel/skylake/flash_controller.c b/src/soc/intel/skylake/flash_controller.c
index 734d9d3..e0ac93d 100644
--- a/src/soc/intel/skylake/flash_controller.c
+++ b/src/soc/intel/skylake/flash_controller.c
@@ -151,13 +151,6 @@ static size_t spi_get_flash_size(pch_spi_regs *spi_bar)
 	return size;
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-		size_t bytesout, void *din, size_t bytesin)
-{
-	/* TODO: Define xfer for hardware sequencing. */
-	return -1;
-}
-
 void spi_init(void)
 {
 	uint8_t bios_cntl;
@@ -170,17 +163,6 @@ void spi_init(void)
 	pci_write_config_byte(dev, SPIBAR_BIOS_CNTL, bios_cntl);
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by PCH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by PCH automatically. */
-}
-
 int pch_hwseq_erase(const struct spi_flash *flash, u32 offset, size_t len)
 {
 	u32 start, end, erase_size;
@@ -377,6 +359,7 @@ int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 
 	slave->bus = bus;
 	slave->cs = cs;
+	slave->ctrlr = NULL;
 
 	return 0;
 }
diff --git a/src/soc/marvell/armada38x/spi.c b/src/soc/marvell/armada38x/spi.c
index b628170..3a6517b 100644
--- a/src/soc/marvell/armada38x/spi.c
+++ b/src/soc/marvell/armada38x/spi.c
@@ -442,22 +442,14 @@ static int mrvl_spi_xfer(const struct spi_slave *slave,
 	return 0;
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	mv_spi_sys_init(bus, cs, CONFIG_SF_DEFAULT_SPEED);
-	return 0;
-}
-
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	mv_spi_cs_set(slave->bus, slave->cs);
 	mv_spi_cs_assert(slave->bus);
 	return 0;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	mv_spi_cs_deassert(slave->bus);
 }
@@ -467,11 +459,11 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return buf_len;
 }
 
-int spi_xfer(const struct spi_slave *slave,
-	     const void *dout,
-	     size_t out_bytes,
-	     void *din,
-	     size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave,
+		       const void *dout,
+		       size_t out_bytes,
+		       void *din,
+		       size_t in_bytes)
 {
 	int ret = 0;
 
@@ -481,3 +473,18 @@ int spi_xfer(const struct spi_slave *slave,
 		ret = mrvl_spi_xfer(slave, in_bytes * 8, NULL, din);
 	return ret;
 }
+
+static const spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	mv_spi_sys_init(bus, cs, CONFIG_SF_DEFAULT_SPEED);
+	return 0;
+}
diff --git a/src/soc/marvell/bg4cd/spi.c b/src/soc/marvell/bg4cd/spi.c
index 54161bc..188a6bd 100644
--- a/src/soc/marvell/bg4cd/spi.c
+++ b/src/soc/marvell/bg4cd/spi.c
@@ -19,18 +19,3 @@ int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 {
 	return -1;
 }
-
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-}
-
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-	     size_t out_bytes, void *din, size_t in_bytes)
-{
-	return 0;
-}
diff --git a/src/soc/mediatek/mt8173/spi.c b/src/soc/mediatek/mt8173/spi.c
index d02f02d..120b652 100644
--- a/src/soc/mediatek/mt8173/spi.c
+++ b/src/soc/mediatek/mt8173/spi.c
@@ -160,29 +160,7 @@ static void mtk_spi_dump_data(const char *name, const uint8_t *data,
 #endif
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	struct mtk_spi_bus *eslave;
-
-	switch (bus) {
-	case CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS:
-		slave->bus = bus;
-		slave->cs = cs;
-		eslave = to_mtk_spi(slave);
-		assert(read32(&eslave->regs->spi_cfg0_reg) != 0);
-		spi_sw_reset(eslave->regs);
-		return 0;
-	case CONFIG_BOOT_DEVICE_SPI_FLASH_BUS:
-		slave->bus = bus;
-		slave->cs = cs;
-		return 0;
-	default:
-		die ("wrong bus number.\n");
-	};
-	return -1;
-}
-
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct mtk_spi_bus *mtk_slave = to_mtk_spi(slave);
 	struct mtk_spi_regs *regs = mtk_slave->regs;
@@ -269,8 +247,8 @@ error:
 	return -1;
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytes_out,
-	     void *din, size_t bytes_in)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			size_t bytes_out, void *din, size_t bytes_in)
 {
 	size_t min_size = 0;
 	int ret;
@@ -301,7 +279,7 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytes_out,
 	return 0;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct mtk_spi_bus *mtk_slave = to_mtk_spi(slave);
 	struct mtk_spi_regs *regs = mtk_slave->regs;
@@ -310,3 +288,33 @@ void spi_release_bus(const struct spi_slave *slave)
 	spi_sw_reset(regs);
 	mtk_slave->state = MTK_SPI_IDLE;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	struct mtk_spi_bus *eslave;
+
+	slave->ctrlr = &spi_ctrlr;
+
+	switch (bus) {
+	case CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS:
+		slave->bus = bus;
+		slave->cs = cs;
+		eslave = to_mtk_spi(slave);
+		assert(read32(&eslave->regs->spi_cfg0_reg) != 0);
+		spi_sw_reset(eslave->regs);
+		return 0;
+	case CONFIG_BOOT_DEVICE_SPI_FLASH_BUS:
+		slave->bus = bus;
+		slave->cs = cs;
+		return 0;
+	default:
+		die ("wrong bus number.\n");
+	};
+	return -1;
+}
diff --git a/src/soc/nvidia/tegra124/spi.c b/src/soc/nvidia/tegra124/spi.c
index d5b2915..e7844ce 100644
--- a/src/soc/nvidia/tegra124/spi.c
+++ b/src/soc/nvidia/tegra124/spi.c
@@ -209,7 +209,7 @@ static unsigned int tegra_spi_speed(unsigned int bus)
 	return 50000000;
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs;
 	u32 val;
@@ -232,7 +232,7 @@ int spi_claim_bus(const struct spi_slave *slave)
 	return 0;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs;
 	u32 val;
@@ -798,8 +798,8 @@ static int __spi_xfer(const struct spi_slave *slave, const void *dout,
 	return ret;
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
-	     void *din, size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			  size_t out_bytes, void *din, size_t in_bytes)
 {
 	int ret = 0;
 
@@ -811,6 +811,12 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
 	return ret;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
 int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 {
 	struct tegra_spi_channel *channel = to_tegra_spi(bus);
@@ -819,6 +825,7 @@ int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 
 	slave->bus = channel->slave.bus;
 	slave->cs = channel->slave.cs;
+	slave->ctrlr = &spi_ctrlr;
 
 	return 0;
 }
diff --git a/src/soc/nvidia/tegra210/spi.c b/src/soc/nvidia/tegra210/spi.c
index cecf573..6a70f48 100644
--- a/src/soc/nvidia/tegra210/spi.c
+++ b/src/soc/nvidia/tegra210/spi.c
@@ -208,7 +208,7 @@ static struct tegra_spi_channel * const to_tegra_spi(int bus) {
 	return &tegra_spi_channels[bus - 1];
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs;
 	u32 val;
@@ -231,7 +231,7 @@ int spi_claim_bus(const struct spi_slave *slave)
 	return 0;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct tegra_spi_regs *regs = to_tegra_spi(slave->bus)->regs;
 	u32 val;
@@ -834,8 +834,8 @@ static int __spi_xfer(const struct spi_slave *slave, const void *dout,
 	return ret;
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
-	     void *din, size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			  size_t out_bytes, void *din, size_t in_bytes)
 {
 	int ret = 0;
 
@@ -847,6 +847,12 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
 	return ret;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
 int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 {
 	struct tegra_spi_channel *channel = to_tegra_spi(bus);
@@ -855,6 +861,7 @@ int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 
 	slave->cs = channel->slave.cs;
 	slave->bus = channel->slave.bus;
+	slave->ctrlr = &spi_ctrlr;
 
 	return 0;
 }
diff --git a/src/soc/qualcomm/ipq40xx/spi.c b/src/soc/qualcomm/ipq40xx/spi.c
index cda3bea..6d044b3 100644
--- a/src/soc/qualcomm/ipq40xx/spi.c
+++ b/src/soc/qualcomm/ipq40xx/spi.c
@@ -226,45 +226,6 @@ static struct ipq_spi_slave *to_ipq_spi(const struct spi_slave *slave)
 	return NULL;
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	struct ipq_spi_slave *ds = NULL;
-	int i;
-
-	if ((bus < BLSP0_SPI) || (bus > BLSP1_SPI)
-		|| ((bus == BLSP0_SPI) && (cs > 2))
-		|| ((bus == BLSP1_SPI) && (cs > 0))) {
-		printk(BIOS_ERR,
-			"SPI error: unsupported bus %d (Supported busses 0, 1 and 2) "
-                        "or chipselect\n", bus);
-		return -1;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) {
-		if (spi_slave_pool[i].allocated)
-			continue;
-		ds = spi_slave_pool + i;
-
-		ds->slave.bus = slave->bus = bus;
-		ds->slave.cs = slave->cs = cs;
-		ds->regs = &spi_reg[bus];
-
-		/*
-		 * TODO(vbendeb):
-		 * hardcoded frequency and mode - we might need to find a way
-		 * to configure this
-		 */
-		ds->freq = 10000000;
-		ds->mode = SPI_MODE3;
-		ds->allocated = 1;
-
-		return 0;
-	}
-
-	printk(BIOS_ERR, "SPI error: all %d pools busy\n", i);
-	return -1;
-}
-
 /*
  * BLSP QUPn SPI Hardware Initialisation
  */
@@ -340,7 +301,7 @@ static int spi_hw_init(struct ipq_spi_slave *ds)
 	return SUCCESS;
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct ipq_spi_slave *ds = to_ipq_spi(slave);
 	unsigned int ret;
@@ -352,7 +313,7 @@ int spi_claim_bus(const struct spi_slave *slave)
 	return SUCCESS;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct ipq_spi_slave *ds = to_ipq_spi(slave);
 
@@ -653,8 +614,8 @@ static int blsp_spi_write(struct ipq_spi_slave *ds, u8 *cmd_buffer,
  * This function is invoked with either tx_buf or rx_buf.
  * Calling this function with both null does a chip select change.
  */
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-	     size_t out_bytes, void *din, size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			size_t out_bytes, void *din, size_t in_bytes)
 {
 	struct ipq_spi_slave *ds = to_ipq_spi(slave);
 	u8 *txp = (u8 *)dout;
@@ -690,3 +651,49 @@ out:
 
 	return ret;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	struct ipq_spi_slave *ds = NULL;
+	int i;
+
+	if ((bus < BLSP0_SPI) || (bus > BLSP1_SPI)
+		|| ((bus == BLSP0_SPI) && (cs > 2))
+		|| ((bus == BLSP1_SPI) && (cs > 0))) {
+		printk(BIOS_ERR,
+			"SPI error: unsupported bus %d (Supported busses 0, 1 and 2) "
+                        "or chipselect\n", bus);
+		return -1;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) {
+		if (spi_slave_pool[i].allocated)
+			continue;
+		ds = spi_slave_pool + i;
+
+		ds->slave.bus = slave->bus = bus;
+		ds->slave.cs = slave->cs = cs;
+		slave->ctrlr = &spi_ctrlr;
+		ds->regs = &spi_reg[bus];
+
+		/*
+		 * TODO(vbendeb):
+		 * hardcoded frequency and mode - we might need to find a way
+		 * to configure this
+		 */
+		ds->freq = 10000000;
+		ds->mode = SPI_MODE3;
+		ds->allocated = 1;
+
+		return 0;
+	}
+
+	printk(BIOS_ERR, "SPI error: all %d pools busy\n", i);
+	return -1;
+}
diff --git a/src/soc/qualcomm/ipq806x/spi.c b/src/soc/qualcomm/ipq806x/spi.c
index 81dc508..b5e7e73 100644
--- a/src/soc/qualcomm/ipq806x/spi.c
+++ b/src/soc/qualcomm/ipq806x/spi.c
@@ -518,49 +518,6 @@ static struct ipq_spi_slave *to_ipq_spi(const struct spi_slave *slave)
 	return NULL;
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	struct ipq_spi_slave *ds = NULL;
-	int i;
-
-	/*
-	 * IPQ GSBI (Generic Serial Bus Interface) supports SPI Flash
-	 * on different GSBI5, GSBI6 and GSBI7
-	 * with different number of chip selects (CS, channels):
-	*/
-	if ((bus < GSBI5_SPI) || (bus > GSBI7_SPI)
-		|| ((bus == GSBI5_SPI) && (cs > 3))
-		|| ((bus == GSBI6_SPI) && (cs > 0))
-		|| ((bus == GSBI7_SPI) && (cs > 0))) {
-		printk(BIOS_ERR, "SPI error: unsupported bus %d "
-			"(Supported busses 0,1 and 2) or chipselect\n", bus);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) {
-		if (spi_slave_pool[i].allocated)
-			continue;
-		ds = spi_slave_pool + i;
-
-		ds->slave.bus = slave->bus = bus;
-		ds->slave.cs = slave->cs = cs;
-		ds->regs = &spi_reg[bus];
-
-		/*
-		 * TODO(vbendeb):
-		 * hardcoded frequency and mode - we might need to find a way
-		 * to configure this
-		 */
-		ds->freq = 10000000;
-		ds->mode = GSBI_SPI_MODE_0;
-		ds->allocated = 1;
-
-		return 0;
-	}
-
-	printk(BIOS_ERR, "SPI error: all %d pools busy\n", i);
-	return -1;
-}
-
 /*
  * GSBIn SPI Hardware Initialisation
  */
@@ -638,7 +595,7 @@ static int spi_hw_init(struct ipq_spi_slave *ds)
 	return SUCCESS;
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct ipq_spi_slave *ds = to_ipq_spi(slave);
 	unsigned int ret;
@@ -661,7 +618,7 @@ int spi_claim_bus(const struct spi_slave *slave)
 	return SUCCESS;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct ipq_spi_slave *ds = to_ipq_spi(slave);
 
@@ -731,8 +688,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(MAX_PACKET_COUNT, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
-	     size_t out_bytes, void *din, size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			size_t out_bytes, void *din, size_t in_bytes)
 {
 	int ret;
 	struct ipq_spi_slave *ds = to_ipq_spi(slave);
@@ -799,3 +756,55 @@ out:
 
 	return ret;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	struct ipq_spi_slave *ds = NULL;
+	int i;
+
+	/*
+	 * IPQ GSBI (Generic Serial Bus Interface) supports SPI Flash
+	 * on different GSBI5, GSBI6 and GSBI7
+	 * with different number of chip selects (CS, channels):
+	*/
+	if ((bus < GSBI5_SPI) || (bus > GSBI7_SPI)
+		|| ((bus == GSBI5_SPI) && (cs > 3))
+		|| ((bus == GSBI6_SPI) && (cs > 0))
+		|| ((bus == GSBI7_SPI) && (cs > 0))) {
+		printk(BIOS_ERR, "SPI error: unsupported bus %d "
+			"(Supported busses 0,1 and 2) or chipselect\n", bus);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) {
+		if (spi_slave_pool[i].allocated)
+			continue;
+		ds = spi_slave_pool + i;
+
+		ds->slave.bus = slave->bus = bus;
+		ds->slave.cs = slave->cs = cs;
+		slave->ctrlr = &spi_ctrlr;
+		ds->regs = &spi_reg[bus];
+
+		/*
+		 * TODO(vbendeb):
+		 * hardcoded frequency and mode - we might need to find a way
+		 * to configure this
+		 */
+		ds->freq = 10000000;
+		ds->mode = GSBI_SPI_MODE_0;
+		ds->allocated = 1;
+
+		return 0;
+	}
+
+	printk(BIOS_ERR, "SPI error: all %d pools busy\n", i);
+	return -1;
+}
+
+
diff --git a/src/soc/rockchip/common/spi.c b/src/soc/rockchip/common/spi.c
index 216ac86..a3d2755 100644
--- a/src/soc/rockchip/common/spi.c
+++ b/src/soc/rockchip/common/spi.c
@@ -67,16 +67,6 @@ static struct rockchip_spi_slave *to_rockchip_spi(const struct spi_slave *slave)
 	return &rockchip_spi_slaves[slave->bus];
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	assert(bus >= 0 && bus < ARRAY_SIZE(rockchip_spi_slaves));
-
-	slave->bus = bus;
-	slave->cs = cs;
-
-	return 0;
-}
-
 static void spi_cs_activate(const struct spi_slave *slave)
 {
 	struct rockchip_spi *regs = to_rockchip_spi(slave)->regs;
@@ -155,13 +145,13 @@ void rockchip_spi_set_sample_delay(unsigned int bus, unsigned int delay_ns)
 			rsd << SPI_RXDSD_OFFSET);
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	spi_cs_activate(slave);
 	return 0;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	spi_cs_deactivate(slave);
 }
@@ -338,8 +328,8 @@ static int __spi_xfer(const struct spi_slave *slave, const void *dout,
 	return ret < 0 ? ret : 0;
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
-	     void *din, size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+		    size_t out_bytes, void *din, size_t in_bytes)
 {
 	int ret = 0;
 
@@ -350,3 +340,20 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
 
 	return ret;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	assert(bus >= 0 && bus < ARRAY_SIZE(rockchip_spi_slaves));
+
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+
+	return 0;
+}
diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c
index c809bb3..a3ac180 100644
--- a/src/soc/samsung/exynos5420/spi.c
+++ b/src/soc/samsung/exynos5420/spi.c
@@ -117,23 +117,7 @@ static void exynos_spi_init(struct exynos_spi *regs)
 	spi_sw_reset(regs, 1);
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	ASSERT(bus >= 0 && bus < 3);
-	struct exynos_spi_slave *eslave;
-
-	slave->bus = bus;
-	slave->cs = cs;
-
-	eslave = to_exynos_spi(slave);
-	if (!eslave->initialized) {
-		exynos_spi_init(eslave->regs);
-		eslave->initialized = 1;
-	}
-	return 0;
-}
-
-int spi_claim_bus(const struct spi_slave *slave)
+static int spi_ctrlr_claim_bus(const struct spi_slave *slave)
 {
 	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
 	// TODO(hungte) Add some delay if too many transactions happen at once.
@@ -218,8 +202,8 @@ static int __spi_xfer(const struct spi_slave *slave, const void *dout,
 	return 0;
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
-	     void *din, size_t in_bytes)
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
+			   size_t out_bytes, void *din, size_t in_bytes)
 {
 	int ret = 0;
 
@@ -231,12 +215,35 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, size_t out_bytes,
 	return ret;
 }
 
-void spi_release_bus(const struct spi_slave *slave)
+static void spi_ctrlr_release_bus(const struct spi_slave *slave)
 {
 	struct exynos_spi *regs = to_exynos_spi(slave)->regs;
 	setbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT);
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.claim_bus = spi_ctrlr_claim_bus,
+	.release_bus = spi_ctrlr_release_bus,
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	ASSERT(bus >= 0 && bus < 3);
+	struct exynos_spi_slave *eslave;
+
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+
+	eslave = to_exynos_spi(slave);
+	if (!eslave->initialized) {
+		exynos_spi_init(eslave->regs);
+		eslave->initialized = 1;
+	}
+	return 0;
+}
+
 static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len,
 			   uint32_t off)
 {
diff --git a/src/southbridge/amd/agesa/hudson/spi.c b/src/southbridge/amd/agesa/hudson/spi.c
index a8b3b2a..e228d1f 100644
--- a/src/southbridge/amd/agesa/hudson/spi.c
+++ b/src/southbridge/amd/agesa/hudson/spi.c
@@ -90,7 +90,7 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(AMD_SB_SPI_TX_LEN - cmd_len, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
+static xsint spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
 		size_t bytesout, void *din, size_t bytesin)
 {
 	/* First byte is cmd which can not being sent through FIFO. */
@@ -147,17 +147,6 @@ int spi_xfer(const struct spi_slave *slave, const void *dout,
 	return 0;
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Nothing is required. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Nothing is required. */
-}
-
 int chipset_volatile_group_begin(const struct spi_flash *flash)
 {
 	if (!IS_ENABLED (CONFIG_HUDSON_IMC_FWM))
@@ -176,9 +165,14 @@ int chipset_volatile_group_end(const struct spi_flash *flash)
 	return 0;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
 int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 {
 	slave->bus = bus;
 	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
 	return 0;
 }
diff --git a/src/southbridge/amd/cimx/sb800/spi.c b/src/southbridge/amd/cimx/sb800/spi.c
index d331060..edf192a 100644
--- a/src/southbridge/amd/cimx/sb800/spi.c
+++ b/src/southbridge/amd/cimx/sb800/spi.c
@@ -59,7 +59,7 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(AMD_SB_SPI_TX_LEN - cmd_len, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
 		size_t bytesout, void *din, size_t bytesin)
 {
 	/* First byte is cmd which can not being sent through FIFO. */
@@ -138,18 +138,6 @@ static void ImcWakeup(void)
 	WaitForEcLDN9MailboxCmdAck();
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Nothing is required. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Nothing is required. */
-	return;
-}
-
 int chipset_volatile_group_begin(const struct spi_flash *flash)
 {
 	if (!IS_ENABLED(CONFIG_SB800_IMC_FWM))
@@ -168,9 +156,14 @@ int chipset_volatile_group_end(const struct spi_flash *flash)
 	return 0;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
 int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
 {
 	slave->bus = bus;
 	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
 	return 0;
 }
diff --git a/src/southbridge/amd/sb700/spi.c b/src/southbridge/amd/sb700/spi.c
index fca401c..2e16ca8 100644
--- a/src/southbridge/amd/sb700/spi.c
+++ b/src/southbridge/amd/sb700/spi.c
@@ -65,25 +65,7 @@ static void execute_command(void)
 		(read8((void *)(spibar+3)) & 0x80));
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled internally by the SB700 */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled internally by the SB700 */
-}
-
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
-int spi_xfer(const struct spi_slave *slave, const void *dout,
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
 		size_t bytesout, void *din, size_t bytesin)
 {
 	/* First byte is cmd which cannot be sent through the FIFO. */
@@ -135,3 +117,15 @@ int spi_xfer(const struct spi_slave *slave, const void *dout,
 
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
diff --git a/src/southbridge/intel/common/spi.c b/src/southbridge/intel/common/spi.c
index 7e0cc20..42a2a74 100644
--- a/src/southbridge/intel/common/spi.c
+++ b/src/southbridge/intel/common/spi.c
@@ -285,13 +285,6 @@ static void ich_set_bbar(uint32_t minaddr)
 	writel_(ichspi_bbar, cntlr.bbar);
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 void spi_init(void)
 {
 	uint8_t *rcrb; /* Root Complex Register Block */
@@ -348,17 +341,6 @@ static void spi_init_cb(void *unused)
 
 BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_ENTRY, spi_init_cb, NULL);
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -527,7 +509,7 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
 		size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
@@ -675,6 +657,18 @@ int spi_xfer(const struct spi_slave *slave, const void *dout,
 	return 0;
 }
 
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}
+
 /* Sets FLA in FADDR to (addr & 0x01FFFFFF) without touching other bits. */
 static void ich_hwseq_set_addr(uint32_t addr)
 {
diff --git a/src/southbridge/intel/fsp_rangeley/spi.c b/src/southbridge/intel/fsp_rangeley/spi.c
index de676a9..acdb072 100644
--- a/src/southbridge/intel/fsp_rangeley/spi.c
+++ b/src/southbridge/intel/fsp_rangeley/spi.c
@@ -322,13 +322,6 @@ static void ich_set_bbar(uint32_t minaddr)
 	writel_(ichspi_bbar, cntlr.bbar);
 }
 
-int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
-{
-	slave->bus = bus;
-	slave->cs = cs;
-	return 0;
-}
-
 /*
  * Check if this device ID matches one of supported Intel SOC devices.
  *
@@ -420,17 +413,6 @@ void spi_init(void)
 	}
 }
 
-int spi_claim_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-	return 0;
-}
-
-void spi_release_bus(const struct spi_slave *slave)
-{
-	/* Handled by ICH automatically. */
-}
-
 typedef struct spi_transaction {
 	const uint8_t *out;
 	uint32_t bytesout;
@@ -592,7 +574,7 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
 	return min(cntlr.databytes, buf_len);
 }
 
-int spi_xfer(const struct spi_slave *slave, const void *dout,
+static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout,
 		size_t bytesout, void *din, size_t bytesin)
 {
 	uint16_t control;
@@ -739,3 +721,15 @@ spi_xfer_exit:
 
 	return 0;
 }
+
+static const struct spi_ctrlr spi_ctrlr = {
+	.xfer = spi_ctrlr_xfer,
+};
+
+int spi_setup_slave(unsigned int bus, unsigned int cs, struct spi_slave *slave)
+{
+	slave->bus = bus;
+	slave->cs = cs;
+	slave->ctrlr = &spi_ctrlr;
+	return 0;
+}



More information about the coreboot-gerrit mailing list