From 94f8699d447ef94df339d318b836b664273e89ff Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Thu, 1 Dec 2016 07:12:32 -0800 Subject: [PATCH] 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 Reviewed-on: https://review.coreboot.org/17684 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- 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 | 101 ++++++++++++---------- src/soc/rockchip/common/spi.c | 35 +++++--- src/soc/samsung/exynos5420/spi.c | 45 ++++++---- 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, 521 insertions(+), 494 deletions(-) create mode 100644 src/drivers/spi/spi-generic.c diff --git a/src/drivers/spi/Makefile.inc b/src/drivers/spi/Makefile.inc index 92baf62bc3..c1bf307cc5 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 0000000000..7398ee928f --- /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 +#include + +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 c8b209da21..b4a10af0c0 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 810f2c266c..e597efced9 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 86c452a55a..e956e46f7a 100644 --- a/src/soc/imgtec/pistachio/spi.c +++ b/src/soc/imgtec/pistachio/spi.c @@ -421,53 +421,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; @@ -498,7 +453,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; @@ -540,8 +495,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; @@ -582,6 +537,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 ca56702dcf..8992fa55ca 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 b4f95aa832..0f7b0c6ced 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 4236e6ff50..2a0ddf8179 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 5220970532..d2ae94314d 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 06b160c8b5..997bd138ae 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 8af56860fa..5848966f38 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 734d9d3532..e0ac93da03 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 8f9686793f..25480e49ff 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 = -1; @@ -483,3 +475,18 @@ int spi_xfer(const struct spi_slave *slave, die("Unexpected condition in spi_xfer\n"); 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 54161bcf33..188a6bd483 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 d6bcc0bd0a..53d5b8ce15 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 0cb48657d6..5d8084fbdf 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; @@ -719,8 +719,8 @@ 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) { struct tegra_spi_channel *spi = to_tegra_spi(slave->bus); u8 *out_buf = (u8 *)dout; @@ -798,6 +798,12 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, 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); @@ -806,6 +812,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 3a2dd17230..292135542a 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; @@ -755,8 +755,8 @@ 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) { struct tegra_spi_channel *spi = to_tegra_spi(slave->bus); u8 *out_buf = (u8 *)dout; @@ -834,6 +834,12 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, 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); @@ -842,6 +848,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 cda3bea7e6..6d044b32f2 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 81dc508cd7..e907729a13 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,53 @@ 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 85597f2b79..16143b5ac8 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 < 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); } @@ -266,8 +256,8 @@ unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len) return min(65535, buf_len); } -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) { struct rockchip_spi *regs = to_rockchip_spi(slave)->regs; int ret = 0; @@ -337,3 +327,20 @@ int spi_xfer(const struct spi_slave *slave, const void *dout, rockchip_spi_enable_chip(regs, 0); return ret < 0 ? ret : 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) +{ + assert(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 5dbe024f71..f17566e2c5 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. @@ -193,7 +177,7 @@ static void spi_transfer(struct exynos_spi *regs, void *in, const void *out, } } -int spi_xfer(const struct spi_slave *slave, const void *dout, size_t bytes_out, +static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, size_t bytes_out, void *din, size_t bytes_in) { struct exynos_spi *regs = to_exynos_spi(slave)->regs; @@ -218,12 +202,35 @@ 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 exynos_spi *regs = to_exynos_spi(slave)->regs; setbits_le32(®s->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 a8b3b2a409..8a4adfb14b 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 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. */ @@ -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 d33106011c..edf192ae0b 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 fca401cbbf..2e16ca8d5c 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 7e0cc201c7..42a2a748de 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 de676a9dfa..acdb0729c7 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; +}