diff options
Diffstat (limited to 'src/soc/broadcom/cygnus/spi.c')
-rw-r--r-- | src/soc/broadcom/cygnus/spi.c | 327 |
1 files changed, 0 insertions, 327 deletions
diff --git a/src/soc/broadcom/cygnus/spi.c b/src/soc/broadcom/cygnus/spi.c deleted file mode 100644 index 65c9c9698d..0000000000 --- a/src/soc/broadcom/cygnus/spi.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (C) 2015 Broadcom Corporation - * - * 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; version 2 of the License. - * - * 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 <arch/io.h> -#include <timer.h> -#include <delay.h> -#include <stdlib.h> -#include <spi-generic.h> -#include <spi_flash.h> -#include <soc/addressmap.h> - -#define IPROC_QSPI_CLK 100000000 - -/* SPI mode flags */ -#define SPI_CPHA 0x01 /* clock phase */ -#define SPI_CPOL 0x02 /* clock polarity */ -#define SPI_MODE_0 (0|0) /* original MicroWire */ -#define SPI_MODE_1 (0|SPI_CPHA) -#define SPI_MODE_2 (SPI_CPOL|0) -#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) - -#define QSPI_MAX_HZ 50000000 -#define QSPI_MODE SPI_MODE_3 - -#define QSPI_WAIT_TIMEOUT 200U /* msec */ - -/* Controller attributes */ -#define SPBR_MIN 8U -#define SPBR_MAX 255U -#define NUM_TXRAM 32 -#define NUM_RXRAM 32 -#define NUM_CDRAM 16 - -/* - * Register fields - */ -#define MSPI_SPCR0_MSB_BITS_8 0x00000020 - -/* BSPI registers */ -#define BSPI_MAST_N_BOOT_CTRL_REG 0x008 -#define BSPI_BUSY_STATUS_REG 0x00c - -/* MSPI registers */ -#define MSPI_SPCR0_LSB_REG 0x200 -#define MSPI_SPCR0_MSB_REG 0x204 -#define MSPI_SPCR1_LSB_REG 0x208 -#define MSPI_SPCR1_MSB_REG 0x20c -#define MSPI_NEWQP_REG 0x210 -#define MSPI_ENDQP_REG 0x214 -#define MSPI_SPCR2_REG 0x218 -#define MSPI_STATUS_REG 0x220 -#define MSPI_CPTQP_REG 0x224 -#define MSPI_TXRAM_REG 0x240 -#define MSPI_RXRAM_REG 0x2c0 -#define MSPI_CDRAM_REG 0x340 -#define MSPI_WRITE_LOCK_REG 0x380 -#define MSPI_DISABLE_FLUSH_GEN_REG 0x384 - -/* - * Register access macros - */ -#define REG_RD(x) read32(x) -#define REG_WR(x, y) write32((x), (y)) -#define REG_CLR(x, y) REG_WR((x), REG_RD(x) & ~(y)) -#define REG_SET(x, y) REG_WR((x), REG_RD(x) | (y)) - -/* QSPI private data */ -struct qspi_priv { - /* Specified SPI parameters */ - unsigned int max_hz; - unsigned int spi_mode; - - int mspi_enabled; - int mspi_16bit; - - int bus_claimed; - - /* Registers */ - void *reg; -}; - -static struct qspi_priv qspi_slave; - -static struct qspi_priv *to_qspi_slave(const struct spi_slave *slave) -{ - return &qspi_slave; -} - -static int mspi_enable(struct qspi_priv *priv) -{ - struct stopwatch sw; - - /* Switch to MSPI if not yet */ - if ((REG_RD(priv->reg + BSPI_MAST_N_BOOT_CTRL_REG) & 1) == 0) { - stopwatch_init_msecs_expire(&sw, QSPI_WAIT_TIMEOUT); - while (!stopwatch_expired(&sw)) { - if ((REG_RD(priv->reg + BSPI_BUSY_STATUS_REG) & 1) - == 0) { - REG_WR(priv->reg + BSPI_MAST_N_BOOT_CTRL_REG, - 1); - udelay(1); - break; - } - udelay(1); - } - if (REG_RD(priv->reg + BSPI_MAST_N_BOOT_CTRL_REG) != 1) - return -1; - } - priv->mspi_enabled = 1; - return 0; -} - -static int spi_ctrlr_claim_bus(const struct spi_slave *slave) -{ - struct qspi_priv *priv = to_qspi_slave(slave); - - if (priv->bus_claimed) - return -1; - - if (!priv->mspi_enabled) - if (mspi_enable(priv)) - return -1; - - /* MSPI: Enable write lock */ - REG_WR(priv->reg + MSPI_WRITE_LOCK_REG, 1); - - priv->bus_claimed = 1; - - return 0; -} - -static void spi_ctrlr_release_bus(const struct spi_slave *slave) -{ - struct qspi_priv *priv = to_qspi_slave(slave); - - /* MSPI: Disable write lock */ - REG_WR(priv->reg + MSPI_WRITE_LOCK_REG, 0); - - priv->bus_claimed = 0; -} - -#define RXRAM_16B(p, i) (REG_RD((p)->reg + MSPI_RXRAM_REG + ((i) << 2)) & 0xff) -#define RXRAM_8B(p, i) (REG_RD((p)->reg + MSPI_RXRAM_REG + \ - ((((i) << 1) + 1) << 2)) & 0xff) - -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; - u8 *rx = (u8 *)din; - unsigned int bytes = bytesout + bytesin; - unsigned int rx_idx = 0; - unsigned int tx_idx = 0; - unsigned int in = 0; - unsigned int chunk; - unsigned int queues; - unsigned int i; - struct stopwatch sw; - - if (!priv->bus_claimed) - return -1; - - if (bytes & 1) { - /* Use 8-bit queue for odd-bytes transfer */ - if (priv->mspi_16bit) { - REG_SET(priv->reg + MSPI_SPCR0_MSB_REG, - MSPI_SPCR0_MSB_BITS_8); - priv->mspi_16bit = 0; - } - } else { - /* Use 16-bit queue for even-bytes transfer */ - if (!priv->mspi_16bit) { - REG_CLR(priv->reg + MSPI_SPCR0_MSB_REG, - MSPI_SPCR0_MSB_BITS_8); - priv->mspi_16bit = 1; - } - } - - while (bytes) { - /* Separate code for 16bit and 8bit transfers for performance */ - if (priv->mspi_16bit) { - /* Determine how many bytes to process this time */ - chunk = min(bytes, NUM_CDRAM * 2); - queues = (chunk - 1) / 2 + 1; - bytes -= chunk; - - /* Fill CDRAMs */ - for (i = 0; i < queues; i++) - REG_WR(priv->reg + MSPI_CDRAM_REG + (i << 2), - 0xc2); - - /* Fill TXRAMs */ - for (i = 0; i < chunk; i++) { - REG_WR(priv->reg + MSPI_TXRAM_REG + (i << 2), - (tx && (tx_idx < bytesout)) ? - tx[tx_idx] : 0xff); - tx_idx++; - } - } else { - /* Determine how many bytes to process this time */ - chunk = min(bytes, NUM_CDRAM); - queues = chunk; - bytes -= chunk; - - /* Fill CDRAMs and TXRAMS */ - for (i = 0; i < chunk; i++) { - REG_WR(priv->reg + MSPI_CDRAM_REG + (i << 2), - 0x82); - REG_WR(priv->reg + MSPI_TXRAM_REG + (i << 3), - (tx && (tx_idx < bytesout)) ? - tx[tx_idx] : 0xff); - tx_idx++; - } - } - - /* Setup queue pointers */ - REG_WR(priv->reg + MSPI_NEWQP_REG, 0); - REG_WR(priv->reg + MSPI_ENDQP_REG, queues - 1); - - /* Deassert CS */ - if (bytes == 0) - REG_CLR(priv->reg + MSPI_CDRAM_REG + - ((queues - 1) << 2), 0x0); - - /* Kick off */ - REG_WR(priv->reg + MSPI_STATUS_REG, 0); - REG_WR(priv->reg + MSPI_SPCR2_REG, 0xc0); /* cont | spe */ - - /* Wait for completion */ - stopwatch_init_msecs_expire(&sw, QSPI_WAIT_TIMEOUT); - while (!stopwatch_expired(&sw)) { - if (REG_RD(priv->reg + MSPI_STATUS_REG) & 1) - break; - } - if ((REG_RD(priv->reg + MSPI_STATUS_REG) & 1) == 0) { - /* Make sure no operation is in progress */ - REG_WR(priv->reg + MSPI_SPCR2_REG, 0); - udelay(1); - return -1; - } - - /* Read data */ - if (rx) { - if (priv->mspi_16bit) { - for (i = 0; i < chunk; i++) { - if (rx_idx >= bytesout) { - rx[in] = RXRAM_16B(priv, i); - in++; - } - rx_idx++; - } - } else { - for (i = 0; i < chunk; i++) { - if (rx_idx >= bytesout) { - rx[in] = RXRAM_8B(priv, i); - in++; - } - rx_idx++; - } - } - } - } - - return 0; -} - -static int spi_ctrlr_setup(const struct spi_slave *slave) -{ - struct qspi_priv *priv = &qspi_slave; - unsigned int spbr; - - 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 const struct spi_ctrlr spi_ctrlr = { - .setup = spi_ctrlr_setup, - .claim_bus = spi_ctrlr_claim_bus, - .release_bus = spi_ctrlr_release_bus, - .xfer = spi_ctrlr_xfer, - .max_xfer_size = 65535, -}; - -const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = { - { - .ctrlr = &spi_ctrlr, - .bus_start = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, - .bus_end = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, - }, -}; - -const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map); |