summaryrefslogtreecommitdiff
path: root/src/soc/broadcom/cygnus/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/broadcom/cygnus/spi.c')
-rw-r--r--src/soc/broadcom/cygnus/spi.c327
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);