summaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig112
-rw-r--r--drivers/spi/Makefile13
-rw-r--r--drivers/spi/andes_spi.c284
-rw-r--r--drivers/spi/andes_spi.h115
-rw-r--r--drivers/spi/cf_qspi.c3
-rw-r--r--drivers/spi/davinci_spi.c369
-rw-r--r--drivers/spi/davinci_spi.h121
-rw-r--r--drivers/spi/ftssp010_spi.c498
-rw-r--r--drivers/spi/oc_tiny_spi.c245
-rw-r--r--drivers/spi/xilinx_spi.c318
-rw-r--r--drivers/spi/xilinx_spi.h138
-rw-r--r--drivers/spi/zynq_spi.c300
12 files changed, 722 insertions, 1794 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 357a33511f..c84a7b74d6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -1,3 +1,5 @@
+menu "SPI Support"
+
config DM_SPI
bool "Enable Driver Model for SPI drivers"
depends on DM
@@ -11,6 +13,51 @@ config DM_SPI
typically use driver-private data instead of extending the
spi_slave structure.
+if DM_SPI
+
+config CADENCE_QSPI
+ bool "Cadence QSPI driver"
+ help
+ Enable the Cadence Quad-SPI (QSPI) driver. This driver can be
+ used to access the SPI NOR flash on platforms embedding this
+ Cadence IP core.
+
+config DESIGNWARE_SPI
+ bool "Designware SPI driver"
+ help
+ Enable the Designware SPI driver. This driver can be used to
+ access the SPI NOR flash on platforms embedding this Designware
+ IP core.
+
+config EXYNOS_SPI
+ bool "Samsung Exynos SPI driver"
+ help
+ Enable the Samsung Exynos SPI driver. This driver can be used to
+ access the SPI NOR flash on platforms embedding this Samsung
+ Exynos IP core.
+
+config FSL_DSPI
+ bool "Freescale DSPI driver"
+ help
+ Enable the Freescale DSPI driver. This driver can be used to
+ access the SPI NOR flash and SPI Data flash on platforms embedding
+ this Freescale DSPI IP core. LS102xA and Colibri VF50/VF61 platforms
+ use this driver.
+
+config FSL_QSPI
+ bool "Freescale QSPI driver"
+ help
+ Enable the Freescale Quad-SPI (QSPI) driver. This driver can be
+ used to access the SPI NOR flash on platforms embedding this
+ Freescale IP core.
+
+config ICH_SPI
+ bool "Intel ICH SPI driver"
+ help
+ Enable the Intel ICH SPI driver. This driver can be used to
+ access the SPI NOR flash on platforms embedding this Intel
+ ICH IP core.
+
config SANDBOX_SPI
bool "Sandbox SPI driver"
depends on SANDBOX && DM
@@ -34,20 +81,61 @@ config SANDBOX_SPI
spi-max-frequency = <40000000>;
sandbox,filename = "spi.bin";
};
- };
+ };
-config DESIGNWARE_SPI
- bool "Designware SPI driver"
- depends on DM_SPI
+config TEGRA114_SPI
+ bool "nVidia Tegra114 SPI driver"
help
- Enable the Designware SPI driver. This driver can be used to
- access the SPI NOR flash on platforms embedding this Designware
+ Enable the nVidia Tegra114 SPI driver. This driver can be used to
+ access the SPI NOR flash on platforms embedding this nVidia Tegra114
IP core.
-config CADENCE_QSPI
- bool "Cadence QSPI driver"
- depends on DM_SPI
+ This controller is different than the older SoCs SPI controller and
+ also register interface get changed with this controller.
+
+config TEGRA20_SFLASH
+ bool "nVidia Tegra20 Serial Flash controller driver"
help
- Enable the Cadence Quad-SPI (QSPI) driver. This driver can be
- used to access the SPI NOR flash on platforms embedding this
- Cadence IP core.
+ Enable the nVidia Tegra20 Serial Flash controller driver. This driver
+ can be used to access the SPI NOR flash on platforms embedding this
+ nVidia Tegra20 IP core.
+
+config TEGRA20_SLINK
+ bool "nVidia Tegra20/Tegra30 SLINK driver"
+ help
+ Enable the nVidia Tegra20/Tegra30 SLINK driver. This driver can
+ be used to access the SPI NOR flash on platforms embedding this
+ nVidia Tegra20/Tegra30 IP cores.
+
+config XILINX_SPI
+ bool "Xilinx SPI driver"
+ help
+ Enable the Xilinx SPI driver from the Xilinx EDK. This SPI
+ controller support 8 bit SPI transfers only, with or w/o FIFO.
+ For more info on Xilinx SPI Register Definitions and Overview
+ see driver file - drivers/spi/xilinx_spi.c
+
+config ZYNQ_SPI
+ bool "Zynq SPI driver"
+ depends on ARCH_ZYNQ || TARGET_XILINX_ZYNQMP
+ help
+ Enable the Zynq SPI driver. This driver can be used to
+ access the SPI NOR flash on platforms embedding this Zynq
+ SPI IP core.
+
+endif # if DM_SPI
+
+config FSL_ESPI
+ bool "Freescale eSPI driver"
+ help
+ Enable the Freescale eSPI driver. This driver can be used to
+ access the SPI interface and SPI NOR flash on platforms embedding
+ this Freescale eSPI IP core.
+
+config TI_QSPI
+ bool "TI QSPI driver"
+ help
+ Enable the TI Quad-SPI (QSPI) driver for DRA7xx and AM43xx evms.
+ This driver support spi flash single, quad and memory reads.
+
+endmenu # menu "SPI Support"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e288692f26..ee88aa162b 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -15,9 +15,7 @@ obj-y += spi.o
obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o
endif
-obj-$(CONFIG_EP93XX_SPI) += ep93xx_spi.o
obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
-obj-$(CONFIG_ANDES_SPI) += andes_spi.o
obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o
obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
@@ -28,8 +26,11 @@ obj-$(CONFIG_CF_SPI) += cf_spi.o
obj-$(CONFIG_CF_QSPI) += cf_qspi.o
obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
obj-$(CONFIG_DESIGNWARE_SPI) += designware_spi.o
+obj-$(CONFIG_EP93XX_SPI) += ep93xx_spi.o
obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
-obj-$(CONFIG_FTSSP010_SPI) += ftssp010_spi.o
+obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
+obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
+obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
obj-$(CONFIG_ICH_SPI) += ich.o
obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
@@ -37,17 +38,13 @@ obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
obj-$(CONFIG_MXC_SPI) += mxc_spi.o
obj-$(CONFIG_MXS_SPI) += mxs_spi.o
-obj-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
obj-$(CONFIG_SH_SPI) += sh_spi.o
obj-$(CONFIG_SH_QSPI) += sh_qspi.o
-obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
+obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
-obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
obj-$(CONFIG_TI_QSPI) += ti_qspi.o
obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
-obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
-obj-$(CONFIG_FSL_DSPI) += fsl_dspi.o
diff --git a/drivers/spi/andes_spi.c b/drivers/spi/andes_spi.c
deleted file mode 100644
index 82aed75ca1..0000000000
--- a/drivers/spi/andes_spi.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Driver of Andes SPI Controller
- *
- * (C) Copyright 2011 Andes Technology
- * Macpaul Lin <macpaul@andestech.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <malloc.h>
-#include <spi.h>
-
-#include <asm/io.h>
-#include "andes_spi.h"
-
-void spi_init(void)
-{
- /* do nothing */
-}
-
-static void andes_spi_spit_en(struct andes_spi_slave *ds)
-{
- unsigned int dcr = readl(&ds->regs->dcr);
-
- debug("%s: dcr: %x, write value: %x\n",
- __func__, dcr, (dcr | ANDES_SPI_DCR_SPIT));
-
- writel((dcr | ANDES_SPI_DCR_SPIT), &ds->regs->dcr);
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
-{
- struct andes_spi_slave *ds;
-
- if (!spi_cs_is_valid(bus, cs))
- return NULL;
-
- ds = spi_alloc_slave(struct andes_spi_slave, bus, cs);
- if (!ds)
- return NULL;
-
- ds->regs = (struct andes_spi_regs *)CONFIG_SYS_SPI_BASE;
-
- /*
- * The hardware of andes_spi will set its frequency according
- * to APB/AHB bus clock. Hence the hardware doesn't allow changing of
- * requency and so the user requested speed is always ignored.
- */
- ds->freq = max_hz;
-
- return &ds->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- struct andes_spi_slave *ds = to_andes_spi(slave);
-
- free(ds);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
- struct andes_spi_slave *ds = to_andes_spi(slave);
- unsigned int apb;
- unsigned int baud;
-
- /* Enable the SPI hardware */
- writel(ANDES_SPI_CR_SPIRST, &ds->regs->cr);
- udelay(1000);
-
- /* setup format */
- baud = ((CONFIG_SYS_CLK_FREQ / CONFIG_SYS_SPI_CLK / 2) - 1) & 0xFF;
-
- /*
- * SPI_CLK = AHB bus clock / ((BAUD + 1)*2)
- * BAUD = AHB bus clock / SPI_CLK / 2) - 1
- */
- apb = (readl(&ds->regs->apb) & 0xffffff00) | baud;
- writel(apb, &ds->regs->apb);
-
- /* no interrupts */
- writel(0, &ds->regs->ie);
-
- return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
- struct andes_spi_slave *ds = to_andes_spi(slave);
-
- /* Disable the SPI hardware */
- writel(ANDES_SPI_CR_SPIRST, &ds->regs->cr);
-}
-
-static int andes_spi_read(struct spi_slave *slave, unsigned int len,
- u8 *rxp, unsigned long flags)
-{
- struct andes_spi_slave *ds = to_andes_spi(slave);
- unsigned int i, left;
- unsigned int data;
-
- debug("%s: slave: %x, len: %d, rxp: %x, flags: %d\n",
- __func__, slave, len, rxp, flags);
-
- debug("%s: data: ", __func__);
- while (len > 0) {
- left = min(len, 4);
- data = readl(&ds->regs->data);
-
- debug(" ");
- for (i = 0; i < left; i++) {
- debug("%02x ", data & 0xff);
- *rxp++ = data;
- data >>= 8;
- len--;
- }
- }
- debug("\n");
-
- return 0;
-}
-
-static int andes_spi_write(struct spi_slave *slave, unsigned int wlen,
- unsigned int rlen, const u8 *txp, unsigned long flags)
-{
- struct andes_spi_slave *ds = to_andes_spi(slave);
- unsigned int data;
- unsigned int i, left;
- unsigned int spit_enabled = 0;
-
- debug("%s: slave: %x, wlen: %d, rlen: %d, txp: %x, flags: %x\n",
- __func__, slave, wlen, rlen, txp, flags);
-
- /* The value of wlen and rlen wrote to register must minus 1 */
- if (rlen == 0) /* write only */
- writel(ANDES_SPI_DCR_MODE_WO | ANDES_SPI_DCR_WCNT(wlen-1) |
- ANDES_SPI_DCR_RCNT(0), &ds->regs->dcr);
- else /* write then read */
- writel(ANDES_SPI_DCR_MODE_WR | ANDES_SPI_DCR_WCNT(wlen-1) |
- ANDES_SPI_DCR_RCNT(rlen-1), &ds->regs->dcr);
-
- /* wait till SPIBSY is cleared */
- while (readl(&ds->regs->st) & ANDES_SPI_ST_SPIBSY)
- ;
-
- /* data write process */
- debug("%s: txp: ", __func__);
- while (wlen > 0) {
- /* clear the data */
- data = 0;
-
- /* data are usually be read 32bits once a time */
- left = min(wlen, 4);
-
- for (i = 0; i < left; i++) {
- debug("%x ", *txp);
- data |= *txp++ << (i * 8);
- wlen--;
- }
- debug("\n");
-
- debug("data: %08x\n", data);
- debug("streg before write: %08x\n", readl(&ds->regs->st));
- /* wait till TXFULL is deasserted */
- while (readl(&ds->regs->st) & ANDES_SPI_ST_TXFEL)
- ;
- writel(data, &ds->regs->data);
- debug("streg after write: %08x\n", readl(&ds->regs->st));
-
-
- if (spit_enabled == 0) {
- /* enable SPIT bit - trigger the tx and rx progress */
- andes_spi_spit_en(ds);
- spit_enabled = 1;
- }
-
- }
- debug("\n");
-
- return 0;
-}
-
-/*
- * spi_xfer:
- * Since andes_spi doesn't support independent command transaction,
- * that is, write and than read must be operated in continuous
- * execution, there is no need to set dcr and trigger spit again in
- * RX process.
- */
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
- const void *dout, void *din, unsigned long flags)
-{
- unsigned int len;
- static int op_nextime;
- static u8 tmp_cmd[5];
- static int tmp_wlen;
- unsigned int i;
-
- if (bitlen == 0)
- /* Finish any previously submitted transfers */
- goto out;
-
- if (bitlen % 8) {
- /* Errors always terminate an ongoing transfer */
- flags |= SPI_XFER_END;
- goto out;
- }
-
- len = bitlen / 8;
-
- debug("%s: slave: %08x, bitlen: %d, dout: "
- "%08x, din: %08x, flags: %d, len: %d\n",
- __func__, slave, bitlen, dout, din, flags, len);
-
- /*
- * Important:
- * andes_spi's hardware doesn't support 2 data channel. The read
- * and write cmd/data share the same register (data register).
- *
- * If a command has write and read transaction, you cannot do write
- * this time and then do read on next time.
- *
- * A command writes first with a read response must indicating
- * the read length in write operation. Hence the write action must
- * be stored temporary and wait until the next read action has been
- * arrived. Then we flush the write and read action out together.
- */
- if (!dout) {
- if (op_nextime == 1) {
- /* flags should be SPI_XFER_END, value is 2 */
- op_nextime = 0;
- andes_spi_write(slave, tmp_wlen, len, tmp_cmd, flags);
- }
- return andes_spi_read(slave, len, din, flags);
- } else if (!din) {
- if (flags == SPI_XFER_BEGIN) {
- /* store the write command and do operation next time */
- op_nextime = 1;
- memset(tmp_cmd, 0, sizeof(tmp_cmd));
- memcpy(tmp_cmd, dout, len);
-
- debug("%s: tmp_cmd: ", __func__);
- for (i = 0; i < len; i++)
- debug("%x ", *(tmp_cmd + i));
- debug("\n");
-
- tmp_wlen = len;
- } else {
- /*
- * flags should be (SPI_XFER_BEGIN | SPI_XFER_END),
- * the value is 3.
- */
- if (op_nextime == 1) {
- /* flags should be SPI_XFER_END, value is 2 */
- op_nextime = 0;
- /* flags 3 implies write only */
- andes_spi_write(slave, tmp_wlen, 0, tmp_cmd, 3);
- }
-
- debug("flags: %x\n", flags);
- return andes_spi_write(slave, len, 0, dout, flags);
- }
- }
-
-out:
- return 0;
-}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
- return bus == 0 && cs == 0;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
- /* do nothing */
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
- /* do nothing */
-}
diff --git a/drivers/spi/andes_spi.h b/drivers/spi/andes_spi.h
deleted file mode 100644
index b7d294599a..0000000000
--- a/drivers/spi/andes_spi.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Register definitions for the Andes SPI Controller
- *
- * (C) Copyright 2011 Andes Technology
- * Macpaul Lin <macpaul@andestech.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef __ANDES_SPI_H
-#define __ANDES_SPI_H
-
-struct andes_spi_regs {
- unsigned int apb; /* 0x00 - APB SPI interface setting */
- unsigned int pio; /* 0x04 - PIO reg */
- unsigned int cr; /* 0x08 - SPI Control reg */
- unsigned int st; /* 0x0c - SPI Status reg */
- unsigned int ie; /* 0x10 - Interrupt Enable reg */
- unsigned int ist; /* 0x14 - Interrupt Status reg */
- unsigned int dcr; /* 0x18 - data control reg */
- unsigned int data; /* 0x1c - data register */
- unsigned int ahb; /* 0x20 - AHB SPI interface setting */
- unsigned int ver; /* 0x3c - SPI version reg */
-};
-
-#define BIT(x) (1 << (x))
-
-/* 0x00 - APB SPI interface setting register */
-#define ANDES_SPI_APB_BAUD(x) (((x) & 0xff) < 0)
-#define ANDES_SPI_APB_CSHT(x) (((x) & 0xf) < 16)
-#define ANDES_SPI_APB_SPNTS BIT(20) /* 0: normal, 1: delay */
-#define ANDES_SPI_APB_CPHA BIT(24) /* 0: Sampling at odd edges */
-#define ANDES_SPI_APB_CPOL BIT(25) /* 0: SCK low, 1: SCK high */
-#define ANDES_SPI_APB_MSSL BIT(26) /* 0: SPI Master, 1: slave */
-
-/* 0x04 - PIO register */
-#define ANDES_SPI_PIO_MISO BIT(0) /* input value of pin MISO */
-#define ANDES_SPI_PIO_MOSI BIT(1) /* I/O value of pin MOSI */
-#define ANDES_SPI_PIO_SCK BIT(2) /* I/O value of pin SCK */
-#define ANDES_SPI_PIO_CS BIT(3) /* I/O value of pin CS */
-#define ANDES_SPI_PIO_PIOE BIT(4) /* Programming IO Enable */
-
-/* 0x08 - SPI Control register */
-#define ANDES_SPI_CR_SPIRST BIT(0) /* SPI mode reset */
-#define ANDES_SPI_CR_RXFRST BIT(1) /* RxFIFO reset */
-#define ANDES_SPI_CR_TXFRST BIT(2) /* TxFIFO reset */
-#define ANDES_SPI_CR_RXFTH(x) (((x) & 0x1f) << 10) /* RxFIFO Threshold */
-#define ANDES_SPI_CR_TXFTH(x) (((x) & 0x1f) << 18) /* TxFIFO Threshold */
-
-/* 0x0c - SPI Status register */
-#define ANDES_SPI_ST_SPIBSY BIT(0) /* SPI Transfer is active */
-#define ANDES_SPI_ST_RXFEM BIT(8) /* RxFIFO Empty Flag */
-#define ANDES_SPI_ST_RXFEL BIT(9) /* RxFIFO Full Flag */
-#define ANDES_SPI_ST_RXFVE(x) (((x) >> 10) & 0x1f)
-#define ANDES_SPI_ST_TXFEM BIT(16) /* TxFIFO Empty Flag */
-#define ANDES_SPI_ST_TXFEL BIT(7) /* TxFIFO Full Flag */
-#define ANDES_SPI_ST_TXFVE(x) (((x) >> 18) & 0x1f)
-
-/* 0x10 - Interrupt Enable register */
-#define ANDES_SPI_IE_RXFORIE BIT(0) /* RxFIFO overrun intr */
-#define ANDES_SPI_IE_TXFURIE BIT(1) /* TxFOFO underrun intr */
-#define ANDES_SPI_IE_RXFTHIE BIT(2) /* RxFIFO threshold intr */
-#define ANDES_SPI_IE_TXFTHIE BIT(3) /* TxFIFO threshold intr */
-#define ANDES_SPI_IE_SPIEIE BIT(4) /* SPI transmit END intr */
-#define ANDES_SPI_IE_SPCFIE BIT(5) /* AHB/APB TxReq conflict */
-
-/* 0x14 - Interrupt Status Register */
-#define ANDES_SPI_IST_RXFORI BIT(0) /* has RxFIFO overrun */
-#define ANDES_SPI_IST_TXFURI BIT(1) /* has TxFOFO underrun */
-#define ANDES_SPI_IST_RXFTHI BIT(2) /* has RxFIFO threshold */
-#define ANDES_SPI_IST_TXFTHI BIT(3) /* has TxFIFO threshold */
-#define ANDES_SPI_IST_SPIEI BIT(4) /* has SPI transmit END */
-#define ANDES_SPI_IST_SPCFI BIT(5) /* has AHB/APB TxReq conflict */
-
-/* 0x18 - Data Control Register */
-#define ANDES_SPI_DCR_RCNT(x) (((x) & 0x3ff) << 0)
-#define ANDES_SPI_DCR_DYCNT(x) (((x) & 0x7) << 12)
-#define ANDES_SPI_DCR_WCNT(x) (((x) & 0x3ff) << 16)
-#define ANDES_SPI_DCR_TRAMODE(x) (((x) & 0x7) << 28)
-#define ANDES_SPI_DCR_SPIT BIT(31) /* SPI bus trigger */
-
-#define ANDES_SPI_DCR_MODE_WRCON ANDES_SPI_DCR_TRAMODE(0) /* w/r at the same time */
-#define ANDES_SPI_DCR_MODE_WO ANDES_SPI_DCR_TRAMODE(1) /* write only */
-#define ANDES_SPI_DCR_MODE_RO ANDES_SPI_DCR_TRAMODE(2) /* read only */
-#define ANDES_SPI_DCR_MODE_WR ANDES_SPI_DCR_TRAMODE(3) /* write, read */
-#define ANDES_SPI_DCR_MODE_RW ANDES_SPI_DCR_TRAMODE(4) /* read, write */
-#define ANDES_SPI_DCR_MODE_WDR ANDES_SPI_DCR_TRAMODE(5) /* write, dummy, read */
-#define ANDES_SPI_DCR_MODE_RDW ANDES_SPI_DCR_TRAMODE(6) /* read, dummy, write */
-#define ANDES_SPI_DCR_MODE_RECEIVE ANDES_SPI_DCR_TRAMODE(7) /* receive */
-
-/* 0x20 - AHB SPI interface setting register */
-#define ANDES_SPI_AHB_BAUD(x) (((x) & 0xff) < 0)
-#define ANDES_SPI_AHB_CSHT(x) (((x) & 0xf) < 16)
-#define ANDES_SPI_AHB_SPNTS BIT(20) /* 0: normal, 1: delay */
-#define ANDES_SPI_AHB_CPHA BIT(24) /* 0: Sampling at odd edges */
-#define ANDES_SPI_AHB_CPOL BIT(25) /* 0: SCK low, 1: SCK high */
-#define ANDES_SPI_AHB_MSSL BIT(26) /* only Master mode */
-
-/* 0x3c - Version Register - (Year V.MAJOR.MINOR) */
-#define ANDES_SPI_VER_MINOR(x) (((x) >> 0) & 0xf)
-#define ANDES_SPI_VER_MAJOR(x) (((x) >> 8) & 0xf)
-#define ANDES_SPI_VER_YEAR(x) (((x) >> 16) & 0xf)
-
-struct andes_spi_slave {
- struct spi_slave slave;
- struct andes_spi_regs *regs;
- unsigned int freq;
-};
-
-static inline struct andes_spi_slave *to_andes_spi(struct spi_slave *slave)
-{
- return container_of(slave, struct andes_spi_slave, slave);
-}
-
-#endif /* __ANDES_SPI_H */
diff --git a/drivers/spi/cf_qspi.c b/drivers/spi/cf_qspi.c
index 834c5bd259..e57e63eb47 100644
--- a/drivers/spi/cf_qspi.c
+++ b/drivers/spi/cf_qspi.c
@@ -19,7 +19,6 @@
DECLARE_GLOBAL_DATA_PTR;
-#define clamp(x, low, high) (min(max(low, x), high))
#define to_cf_qspi_slave(s) container_of(s, struct cf_qspi_slave, slave)
struct cf_qspi_slave {
@@ -120,7 +119,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
dev->qmr = 2u;
else /* Get the closest baud rate */
dev->qmr = clamp(((gd->bus_clk >> 2) + max_hz - 1)/max_hz,
- 2u, 255u);
+ 2lu, 255lu);
/* Map mode to QMR[CPOL] and QMR[CPHA] */
if (mode & SPI_CPOL)
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index bf18362baa..0a036ccb00 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -8,116 +8,122 @@
*
* SPDX-License-Identifier: GPL-2.0+
*/
+
#include <common.h>
#include <spi.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
-#include "davinci_spi.h"
-void spi_init()
-{
- /* do nothing */
-}
+#define BIT(x) (1 << (x))
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
-{
- struct davinci_spi_slave *ds;
+/* SPIGCR0 */
+#define SPIGCR0_SPIENA_MASK 0x1
+#define SPIGCR0_SPIRST_MASK 0x0
- if (!spi_cs_is_valid(bus, cs))
- return NULL;
+/* SPIGCR0 */
+#define SPIGCR1_CLKMOD_MASK BIT(1)
+#define SPIGCR1_MASTER_MASK BIT(0)
+#define SPIGCR1_SPIENA_MASK BIT(24)
- ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs);
- if (!ds)
- return NULL;
+/* SPIPC0 */
+#define SPIPC0_DIFUN_MASK BIT(11) /* SIMO */
+#define SPIPC0_DOFUN_MASK BIT(10) /* SOMI */
+#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */
+#define SPIPC0_EN0FUN_MASK BIT(0)
- switch (bus) {
- case SPI0_BUS:
- ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
- break;
-#ifdef CONFIG_SYS_SPI1
- case SPI1_BUS:
- ds->regs = (struct davinci_spi_regs *)SPI1_BASE;
- break;
-#endif
-#ifdef CONFIG_SYS_SPI2
- case SPI2_BUS:
- ds->regs = (struct davinci_spi_regs *)SPI2_BASE;
- break;
-#endif
- default: /* Invalid bus number */
- return NULL;
- }
+/* SPIFMT0 */
+#define SPIFMT_SHIFTDIR_SHIFT 20
+#define SPIFMT_POLARITY_SHIFT 17
+#define SPIFMT_PHASE_SHIFT 16
+#define SPIFMT_PRESCALE_SHIFT 8
- ds->freq = max_hz;
+/* SPIDAT1 */
+#define SPIDAT1_CSHOLD_SHIFT 28
+#define SPIDAT1_CSNR_SHIFT 16
- return &ds->slave;
-}
+/* SPIDELAY */
+#define SPI_C2TDELAY_SHIFT 24
+#define SPI_T2CDELAY_SHIFT 16
-void spi_free_slave(struct spi_slave *slave)
-{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
+/* SPIBUF */
+#define SPIBUF_RXEMPTY_MASK BIT(31)
+#define SPIBUF_TXFULL_MASK BIT(29)
- free(ds);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
- unsigned int scalar;
-
- /* Enable the SPI hardware */
- writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
- udelay(1000);
- writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+/* SPIDEF */
+#define SPIDEF_CSDEF0_MASK BIT(0)
- /* Set master mode, powered up and not activated */
- writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
-
- /* CS, CLK, SIMO and SOMI are functional pins */
- writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
- SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
-
- /* setup format */
- scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
-
- /*
- * Use following format:
- * character length = 8,
- * clock signal delayed by half clk cycle,
- * clock low in idle state - Mode 0,
- * MSB shifted out first
- */
- writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
- (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
-
- /*
- * Including a minor delay. No science here. Should be good even with
- * no delay
- */
- writel((50 << SPI_C2TDELAY_SHIFT) |
- (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
-
- /* default chip select register */
- writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
-
- /* no interrupts */
- writel(0, &ds->regs->int0);
- writel(0, &ds->regs->lvl);
+#define SPI0_BUS 0
+#define SPI0_BASE CONFIG_SYS_SPI_BASE
+/*
+ * Define default SPI0_NUM_CS as 1 for existing platforms that uses this
+ * driver. Platform can configure number of CS using CONFIG_SYS_SPI0_NUM_CS
+ * if more than one CS is supported and by defining CONFIG_SYS_SPI0.
+ */
+#ifndef CONFIG_SYS_SPI0
+#define SPI0_NUM_CS 1
+#else
+#define SPI0_NUM_CS CONFIG_SYS_SPI0_NUM_CS
+#endif
- /* enable SPI */
- writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+/*
+ * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and
+ * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus
+ */
+#ifdef CONFIG_SYS_SPI1
+#define SPI1_BUS 1
+#define SPI1_NUM_CS CONFIG_SYS_SPI1_NUM_CS
+#define SPI1_BASE CONFIG_SYS_SPI1_BASE
+#endif
- return 0;
-}
+/*
+ * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and
+ * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus
+ */
+#ifdef CONFIG_SYS_SPI2
+#define SPI2_BUS 2
+#define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS
+#define SPI2_BASE CONFIG_SYS_SPI2_BASE
+#endif
-void spi_release_bus(struct spi_slave *slave)
+/* davinci spi register set */
+struct davinci_spi_regs {
+ dv_reg gcr0; /* 0x00 */
+ dv_reg gcr1; /* 0x04 */
+ dv_reg int0; /* 0x08 */
+ dv_reg lvl; /* 0x0c */
+ dv_reg flg; /* 0x10 */
+ dv_reg pc0; /* 0x14 */
+ dv_reg pc1; /* 0x18 */
+ dv_reg pc2; /* 0x1c */
+ dv_reg pc3; /* 0x20 */
+ dv_reg pc4; /* 0x24 */
+ dv_reg pc5; /* 0x28 */
+ dv_reg rsvd[3];
+ dv_reg dat0; /* 0x38 */
+ dv_reg dat1; /* 0x3c */
+ dv_reg buf; /* 0x40 */
+ dv_reg emu; /* 0x44 */
+ dv_reg delay; /* 0x48 */
+ dv_reg def; /* 0x4c */
+ dv_reg fmt0; /* 0x50 */
+ dv_reg fmt1; /* 0x54 */
+ dv_reg fmt2; /* 0x58 */
+ dv_reg fmt3; /* 0x5c */
+ dv_reg intvec0; /* 0x60 */
+ dv_reg intvec1; /* 0x64 */
+};
+
+/* davinci spi slave */
+struct davinci_spi_slave {
+ struct spi_slave slave;
+ struct davinci_spi_regs *regs;
+ unsigned int freq;
+};
+
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
-
- /* Disable the SPI hardware */
- writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+ return container_of(slave, struct davinci_spi_slave, slave);
}
/*
@@ -235,6 +241,149 @@ static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
}
#endif
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ int ret = 0;
+
+ switch (bus) {
+ case SPI0_BUS:
+ if (cs < SPI0_NUM_CS)
+ ret = 1;
+ break;
+#ifdef CONFIG_SYS_SPI1
+ case SPI1_BUS:
+ if (cs < SPI1_NUM_CS)
+ ret = 1;
+ break;
+#endif
+#ifdef CONFIG_SYS_SPI2
+ case SPI2_BUS:
+ if (cs < SPI2_NUM_CS)
+ ret = 1;
+ break;
+#endif
+ default:
+ /* Invalid bus number. Do nothing */
+ break;
+ }
+ return ret;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ /* do nothing */
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ /* do nothing */
+}
+
+void spi_init(void)
+{
+ /* do nothing */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct davinci_spi_slave *ds;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs);
+ if (!ds)
+ return NULL;
+
+ switch (bus) {
+ case SPI0_BUS:
+ ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
+ break;
+#ifdef CONFIG_SYS_SPI1
+ case SPI1_BUS:
+ ds->regs = (struct davinci_spi_regs *)SPI1_BASE;
+ break;
+#endif
+#ifdef CONFIG_SYS_SPI2
+ case SPI2_BUS:
+ ds->regs = (struct davinci_spi_regs *)SPI2_BASE;
+ break;
+#endif
+ default: /* Invalid bus number */
+ return NULL;
+ }
+
+ ds->freq = max_hz;
+
+ return &ds->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+ free(ds);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+ unsigned int scalar;
+
+ /* Enable the SPI hardware */
+ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+ udelay(1000);
+ writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+
+ /* Set master mode, powered up and not activated */
+ writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+
+ /* CS, CLK, SIMO and SOMI are functional pins */
+ writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
+ SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
+
+ /* setup format */
+ scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+
+ /*
+ * Use following format:
+ * character length = 8,
+ * clock signal delayed by half clk cycle,
+ * clock low in idle state - Mode 0,
+ * MSB shifted out first
+ */
+ writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
+ (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
+
+ /*
+ * Including a minor delay. No science here. Should be good even with
+ * no delay
+ */
+ writel((50 << SPI_C2TDELAY_SHIFT) |
+ (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
+
+ /* default chip select register */
+ writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
+
+ /* no interrupts */
+ writel(0, &ds->regs->int0);
+ writel(0, &ds->regs->lvl);
+
+ /* enable SPI */
+ writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+ /* Disable the SPI hardware */
+ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+}
+
int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
const void *dout, void *din, unsigned long flags)
{
@@ -278,41 +427,3 @@ out:
}
return 0;
}
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
- int ret = 0;
-
- switch (bus) {
- case SPI0_BUS:
- if (cs < SPI0_NUM_CS)
- ret = 1;
- break;
-#ifdef CONFIG_SYS_SPI1
- case SPI1_BUS:
- if (cs < SPI1_NUM_CS)
- ret = 1;
- break;
-#endif
-#ifdef CONFIG_SYS_SPI2
- case SPI2_BUS:
- if (cs < SPI2_NUM_CS)
- ret = 1;
- break;
-#endif
- default:
- /* Invalid bus number. Do nothing */
- break;
- }
- return ret;
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
- /* do nothing */
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
- /* do nothing */
-}
diff --git a/drivers/spi/davinci_spi.h b/drivers/spi/davinci_spi.h
deleted file mode 100644
index d4612d3527..0000000000
--- a/drivers/spi/davinci_spi.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Register definitions for the DaVinci SPI Controller
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#ifndef _DAVINCI_SPI_H_
-#define _DAVINCI_SPI_H_
-
-struct davinci_spi_regs {
- dv_reg gcr0; /* 0x00 */
- dv_reg gcr1; /* 0x04 */
- dv_reg int0; /* 0x08 */
- dv_reg lvl; /* 0x0c */
- dv_reg flg; /* 0x10 */
- dv_reg pc0; /* 0x14 */
- dv_reg pc1; /* 0x18 */
- dv_reg pc2; /* 0x1c */
- dv_reg pc3; /* 0x20 */
- dv_reg pc4; /* 0x24 */
- dv_reg pc5; /* 0x28 */
- dv_reg rsvd[3];
- dv_reg dat0; /* 0x38 */
- dv_reg dat1; /* 0x3c */
- dv_reg buf; /* 0x40 */
- dv_reg emu; /* 0x44 */
- dv_reg delay; /* 0x48 */
- dv_reg def; /* 0x4c */
- dv_reg fmt0; /* 0x50 */
- dv_reg fmt1; /* 0x54 */
- dv_reg fmt2; /* 0x58 */
- dv_reg fmt3; /* 0x5c */
- dv_reg intvec0; /* 0x60 */
- dv_reg intvec1; /* 0x64 */
-};
-
-#define BIT(x) (1 << (x))
-
-/* SPIGCR0 */
-#define SPIGCR0_SPIENA_MASK 0x1
-#define SPIGCR0_SPIRST_MASK 0x0
-
-/* SPIGCR0 */
-#define SPIGCR1_CLKMOD_MASK BIT(1)
-#define SPIGCR1_MASTER_MASK BIT(0)
-#define SPIGCR1_SPIENA_MASK BIT(24)
-
-/* SPIPC0 */
-#define SPIPC0_DIFUN_MASK BIT(11) /* SIMO */
-#define SPIPC0_DOFUN_MASK BIT(10) /* SOMI */
-#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */
-#define SPIPC0_EN0FUN_MASK BIT(0)
-
-/* SPIFMT0 */
-#define SPIFMT_SHIFTDIR_SHIFT 20
-#define SPIFMT_POLARITY_SHIFT 17
-#define SPIFMT_PHASE_SHIFT 16
-#define SPIFMT_PRESCALE_SHIFT 8
-
-/* SPIDAT1 */
-#define SPIDAT1_CSHOLD_SHIFT 28
-#define SPIDAT1_CSNR_SHIFT 16
-
-/* SPIDELAY */
-#define SPI_C2TDELAY_SHIFT 24
-#define SPI_T2CDELAY_SHIFT 16
-
-/* SPIBUF */
-#define SPIBUF_RXEMPTY_MASK BIT(31)
-#define SPIBUF_TXFULL_MASK BIT(29)
-
-/* SPIDEF */
-#define SPIDEF_CSDEF0_MASK BIT(0)
-
-#define SPI0_BUS 0
-#define SPI0_BASE CONFIG_SYS_SPI_BASE
-/*
- * Define default SPI0_NUM_CS as 1 for existing platforms that uses this
- * driver. Platform can configure number of CS using CONFIG_SYS_SPI0_NUM_CS
- * if more than one CS is supported and by defining CONFIG_SYS_SPI0.
- */
-#ifndef CONFIG_SYS_SPI0
-#define SPI0_NUM_CS 1
-#else
-#define SPI0_NUM_CS CONFIG_SYS_SPI0_NUM_CS
-#endif
-
-/*
- * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and
- * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus
- */
-#ifdef CONFIG_SYS_SPI1
-#define SPI1_BUS 1
-#define SPI1_NUM_CS CONFIG_SYS_SPI1_NUM_CS
-#define SPI1_BASE CONFIG_SYS_SPI1_BASE
-#endif
-
-/*
- * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and
- * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus
- */
-#ifdef CONFIG_SYS_SPI2
-#define SPI2_BUS 2
-#define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS
-#define SPI2_BASE CONFIG_SYS_SPI2_BASE
-#endif
-
-struct davinci_spi_slave {
- struct spi_slave slave;
- struct davinci_spi_regs *regs;
- unsigned int freq;
-};
-
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
-{
- return container_of(slave, struct davinci_spi_slave, slave);
-}
-
-#endif /* _DAVINCI_SPI_H_ */
diff --git a/drivers/spi/ftssp010_spi.c b/drivers/spi/ftssp010_spi.c
deleted file mode 100644
index c7d6480478..0000000000
--- a/drivers/spi/ftssp010_spi.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * (C) Copyright 2013
- * Faraday Technology Corporation. <http://www.faraday-tech.com/tw/>
- * Kuo-Jung Su <dantesu@gmail.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <linux/compat.h>
-#include <asm/io.h>
-#include <malloc.h>
-#include <spi.h>
-
-#ifndef CONFIG_FTSSP010_BASE_LIST
-#define CONFIG_FTSSP010_BASE_LIST { CONFIG_FTSSP010_BASE }
-#endif
-
-#ifndef CONFIG_FTSSP010_GPIO_BASE
-#define CONFIG_FTSSP010_GPIO_BASE 0
-#endif
-
-#ifndef CONFIG_FTSSP010_GPIO_LIST
-#define CONFIG_FTSSP010_GPIO_LIST { CONFIG_FTSSP010_GPIO_BASE }
-#endif
-
-#ifndef CONFIG_FTSSP010_CLOCK
-#define CONFIG_FTSSP010_CLOCK clk_get_rate("SSP");
-#endif
-
-#ifndef CONFIG_FTSSP010_TIMEOUT
-#define CONFIG_FTSSP010_TIMEOUT 100
-#endif
-
-/* FTSSP010 chip registers */
-struct ftssp010_regs {
- uint32_t cr[3];/* control register */
- uint32_t sr; /* status register */
- uint32_t icr; /* interrupt control register */
- uint32_t isr; /* interrupt status register */
- uint32_t dr; /* data register */
- uint32_t rsvd[17];
- uint32_t revr; /* revision register */
- uint32_t fear; /* feature register */
-};
-
-/* Control Register 0 */
-#define CR0_FFMT_MASK (7 << 12)
-#define CR0_FFMT_SSP (0 << 12)
-#define CR0_FFMT_SPI (1 << 12)
-#define CR0_FFMT_MICROWIRE (2 << 12)
-#define CR0_FFMT_I2S (3 << 12)
-#define CR0_FFMT_AC97 (4 << 12)
-#define CR0_FLASH (1 << 11)
-#define CR0_FSDIST(x) (((x) & 0x03) << 8)
-#define CR0_LOOP (1 << 7) /* loopback mode */
-#define CR0_LSB (1 << 6) /* LSB */
-#define CR0_FSPO (1 << 5) /* fs atcive low (I2S only) */
-#define CR0_FSJUSTIFY (1 << 4)
-#define CR0_OPM_SLAVE (0 << 2)
-#define CR0_OPM_MASTER (3 << 2)
-#define CR0_OPM_I2S_MSST (3 << 2) /* master stereo mode */
-#define CR0_OPM_I2S_MSMO (2 << 2) /* master mono mode */
-#define CR0_OPM_I2S_SLST (1 << 2) /* slave stereo mode */
-#define CR0_OPM_I2S_SLMO (0 << 2) /* slave mono mode */
-#define CR0_SCLKPO (1 << 1) /* clock polarity */
-#define CR0_SCLKPH (1 << 0) /* clock phase */
-
-/* Control Register 1 */
-#define CR1_PDL(x) (((x) & 0xff) << 24) /* padding length */
-#define CR1_SDL(x) ((((x) - 1) & 0x1f) << 16) /* data length */
-#define CR1_DIV(x) (((x) - 1) & 0xffff) /* clock divider */
-
-/* Control Register 2 */
-#define CR2_CS(x) (((x) & 3) << 10) /* CS/FS select */
-#define CR2_FS (1 << 9) /* CS/FS signal level */
-#define CR2_TXEN (1 << 8) /* tx enable */
-#define CR2_RXEN (1 << 7) /* rx enable */
-#define CR2_RESET (1 << 6) /* chip reset */
-#define CR2_TXFC (1 << 3) /* tx fifo Clear */
-#define CR2_RXFC (1 << 2) /* rx fifo Clear */
-#define CR2_TXDOE (1 << 1) /* tx data output enable */
-#define CR2_EN (1 << 0) /* chip enable */
-
-/* Status Register */
-#define SR_RFF (1 << 0) /* rx fifo full */
-#define SR_TFNF (1 << 1) /* tx fifo not full */
-#define SR_BUSY (1 << 2) /* chip busy */
-#define SR_RFVE(reg) (((reg) >> 4) & 0x1f) /* rx fifo valid entries */
-#define SR_TFVE(reg) (((reg) >> 12) & 0x1f) /* tx fifo valid entries */
-
-/* Feature Register */
-#define FEAR_BITS(reg) ((((reg) >> 0) & 0xff) + 1) /* data width */
-#define FEAR_RFSZ(reg) ((((reg) >> 8) & 0xff) + 1) /* rx fifo size */
-#define FEAR_TFSZ(reg) ((((reg) >> 16) & 0xff) + 1) /* tx fifo size */
-#define FEAR_AC97 (1 << 24)
-#define FEAR_I2S (1 << 25)
-#define FEAR_SPI_MWR (1 << 26)
-#define FEAR_SSP (1 << 27)
-#define FEAR_SPDIF (1 << 28)
-
-/* FTGPIO010 chip registers */
-struct ftgpio010_regs {
- uint32_t out; /* 0x00: Data Output */
- uint32_t in; /* 0x04: Data Input */
- uint32_t dir; /* 0x08: Direction */
- uint32_t bypass; /* 0x0c: Bypass */
- uint32_t set; /* 0x10: Data Set */
- uint32_t clr; /* 0x14: Data Clear */
- uint32_t pull_up; /* 0x18: Pull-Up Enabled */
- uint32_t pull_st; /* 0x1c: Pull State (0=pull-down, 1=pull-up) */
-};
-
-struct ftssp010_gpio {
- struct ftgpio010_regs *regs;
- uint32_t pin;
-};
-
-struct ftssp010_spi {
- struct spi_slave slave;
- struct ftssp010_gpio gpio;
- struct ftssp010_regs *regs;
- uint32_t fifo;
- uint32_t mode;
- uint32_t div;
- uint32_t clk;
- uint32_t speed;
- uint32_t revision;
-};
-
-static inline struct ftssp010_spi *to_ftssp010_spi(struct spi_slave *slave)
-{
- return container_of(slave, struct ftssp010_spi, slave);
-}
-
-static int get_spi_chip(int bus, struct ftssp010_spi *chip)
-{
- uint32_t fear, base[] = CONFIG_FTSSP010_BASE_LIST;
-
- if (bus >= ARRAY_SIZE(base) || !base[bus])
- return -1;
-
- chip->regs = (struct ftssp010_regs *)base[bus];
-
- chip->revision = readl(&chip->regs->revr);
-
- fear = readl(&chip->regs->fear);
- chip->fifo = min_t(uint32_t, FEAR_TFSZ(fear), FEAR_RFSZ(fear));
-
- return 0;
-}
-
-static int get_spi_gpio(int bus, struct ftssp010_gpio *chip)
-{
- uint32_t base[] = CONFIG_FTSSP010_GPIO_LIST;
-
- if (bus >= ARRAY_SIZE(base) || !base[bus])
- return -1;
-
- chip->regs = (struct ftgpio010_regs *)(base[bus] & 0xfff00000);
- chip->pin = base[bus] & 0x1f;
-
- /* make it an output pin */
- setbits_le32(&chip->regs->dir, 1 << chip->pin);
-
- return 0;
-}
-
-static int ftssp010_wait(struct ftssp010_spi *chip)
-{
- struct ftssp010_regs *regs = chip->regs;
- ulong t;
-
- /* wait until device idle */
- for (t = get_timer(0); get_timer(t) < CONFIG_FTSSP010_TIMEOUT; ) {
- if (!(readl(&regs->sr) & SR_BUSY))
- return 0;
- }
-
- puts("ftspi010: busy timeout\n");
-
- return -1;
-}
-
-static int ftssp010_wait_tx(struct ftssp010_spi *chip)
-{
- struct ftssp010_regs *regs = chip->regs;
- ulong t;
-
- /* wait until tx fifo not full */
- for (t = get_timer(0); get_timer(t) < CONFIG_FTSSP010_TIMEOUT; ) {
- if (readl(&regs->sr) & SR_TFNF)
- return 0;
- }
-
- puts("ftssp010: tx timeout\n");
-
- return -1;
-}
-
-static int ftssp010_wait_rx(struct ftssp010_spi *chip)
-{
- struct ftssp010_regs *regs = chip->regs;
- ulong t;
-
- /* wait until rx fifo not empty */
- for (t = get_timer(0); get_timer(t) < CONFIG_FTSSP010_TIMEOUT; ) {
- if (SR_RFVE(readl(&regs->sr)))
- return 0;
- }
-
- puts("ftssp010: rx timeout\n");
-
- return -1;
-}
-
-static int ftssp010_spi_work_transfer_v2(struct ftssp010_spi *chip,
- const void *tx_buf, void *rx_buf, int len, uint flags)
-{
- struct ftssp010_regs *regs = chip->regs;
- const uint8_t *txb = tx_buf;
- uint8_t *rxb = rx_buf;
-
- while (len > 0) {
- int i, depth = min(chip->fifo >> 2, len);
- uint32_t xmsk = 0;
-
- if (tx_buf) {
- for (i = 0; i < depth; ++i) {
- ftssp010_wait_tx(chip);
- writel(*txb++, &regs->dr);
- }
- xmsk |= CR2_TXEN | CR2_TXDOE;
- if ((readl(&regs->cr[2]) & xmsk) != xmsk)
- setbits_le32(&regs->cr[2], xmsk);
- }
- if (rx_buf) {
- xmsk |= CR2_RXEN;
- if ((readl(&regs->cr[2]) & xmsk) != xmsk)
- setbits_le32(&regs->cr[2], xmsk);
- for (i = 0; i < depth; ++i) {
- ftssp010_wait_rx(chip);
- *rxb++ = (uint8_t)readl(&regs->dr);
- }
- }
-
- len -= depth;
- }
-
- return 0;
-}
-
-static int ftssp010_spi_work_transfer_v1(struct ftssp010_spi *chip,
- const void *tx_buf, void *rx_buf, int len, uint flags)
-{
- struct ftssp010_regs *regs = chip->regs;
- const uint8_t *txb = tx_buf;
- uint8_t *rxb = rx_buf;
-
- while (len > 0) {
- int i, depth = min(chip->fifo >> 2, len);
- uint32_t tmp;
-
- for (i = 0; i < depth; ++i) {
- ftssp010_wait_tx(chip);
- writel(txb ? (*txb++) : 0, &regs->dr);
- }
- for (i = 0; i < depth; ++i) {
- ftssp010_wait_rx(chip);
- tmp = readl(&regs->dr);
- if (rxb)
- *rxb++ = (uint8_t)tmp;
- }
-
- len -= depth;
- }
-
- return 0;
-}
-
-static void ftssp010_cs_set(struct ftssp010_spi *chip, int high)
-{
- struct ftssp010_regs *regs = chip->regs;
- struct ftssp010_gpio *gpio = &chip->gpio;
- uint32_t mask;
-
- /* cs pull high/low */
- if (chip->revision >= 0x11900) {
- mask = CR2_CS(chip->slave.cs) | (high ? CR2_FS : 0);
- writel(mask, &regs->cr[2]);
- } else if (gpio->regs) {
- mask = 1 << gpio->pin;
- if (high)
- writel(mask, &gpio->regs->set);
- else
- writel(mask, &gpio->regs->clr);
- }
-
- /* extra delay for signal propagation */
- udelay_masked(1);
-}
-
-/*
- * Determine if a SPI chipselect is valid.
- * This function is provided by the board if the low-level SPI driver
- * needs it to determine if a given chipselect is actually valid.
- *
- * Returns: 1 if bus:cs identifies a valid chip on this board, 0
- * otherwise.
- */
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
- struct ftssp010_spi chip;
-
- if (get_spi_chip(bus, &chip))
- return 0;
-
- if (!cs)
- return 1;
- else if ((cs < 4) && (chip.revision >= 0x11900))
- return 1;
-
- return 0;
-}
-
-/*
- * Activate a SPI chipselect.
- * This function is provided by the board code when using a driver
- * that can't control its chipselects automatically (e.g.
- * common/soft_spi.c). When called, it should activate the chip select
- * to the device identified by "slave".
- */
-void spi_cs_activate(struct spi_slave *slave)
-{
- struct ftssp010_spi *chip = to_ftssp010_spi(slave);
- struct ftssp010_regs *regs = chip->regs;
-
- /* cs pull */
- if (chip->mode & SPI_CS_HIGH)
- ftssp010_cs_set(chip, 1);
- else
- ftssp010_cs_set(chip, 0);
-
- /* chip enable + fifo clear */
- setbits_le32(&regs->cr[2], CR2_EN | CR2_TXFC | CR2_RXFC);
-}
-
-/*
- * Deactivate a SPI chipselect.
- * This function is provided by the board code when using a driver
- * that can't control its chipselects automatically (e.g.
- * common/soft_spi.c). When called, it should deactivate the chip
- * select to the device identified by "slave".
- */
-void spi_cs_deactivate(struct spi_slave *slave)
-{
- struct ftssp010_spi *chip = to_ftssp010_spi(slave);
-
- /* wait until chip idle */
- ftssp010_wait(chip);
-
- /* cs pull */
- if (chip->mode & SPI_CS_HIGH)
- ftssp010_cs_set(chip, 0);
- else
- ftssp010_cs_set(chip, 1);
-}
-
-void spi_init(void)
-{
- /* nothing to do */
-}
-
-struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
-{
- struct ftssp010_spi *chip;
-
- if (mode & SPI_3WIRE) {
- puts("ftssp010: can't do 3-wire\n");
- return NULL;
- }
-
- if (mode & SPI_SLAVE) {
- puts("ftssp010: can't do slave mode\n");
- return NULL;
- }
-
- if (mode & SPI_PREAMBLE) {
- puts("ftssp010: can't skip preamble bytes\n");
- return NULL;
- }
-
- if (!spi_cs_is_valid(bus, cs)) {
- puts("ftssp010: invalid (bus, cs)\n");
- return NULL;
- }
-
- chip = spi_alloc_slave(struct ftssp010_spi, bus, cs);
- if (!chip)
- return NULL;
-
- if (get_spi_chip(bus, chip))
- goto free_out;
-
- if (chip->revision < 0x11900 && get_spi_gpio(bus, &chip->gpio)) {
- puts("ftssp010: Before revision 1.19.0, its clock & cs are\n"
- "controlled by tx engine which is not synced with rx engine,\n"
- "so the clock & cs might be shutdown before rx engine\n"
- "finishs its jobs.\n"
- "If possible, please add a dedicated gpio for it.\n");
- }
-
- chip->mode = mode;
- chip->clk = CONFIG_FTSSP010_CLOCK;
- chip->div = 2;
- if (max_hz) {
- while (chip->div < 0xffff) {
- if ((chip->clk / (2 * chip->div)) <= max_hz)
- break;
- chip->div += 1;
- }
- }
- chip->speed = chip->clk / (2 * chip->div);
-
- return &chip->slave;
-
-free_out:
- free(chip);
- return NULL;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- struct ftssp010_spi *chip = to_ftssp010_spi(slave);
-
- free(chip);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
- struct ftssp010_spi *chip = to_ftssp010_spi(slave);
- struct ftssp010_regs *regs = chip->regs;
-
- writel(CR1_SDL(8) | CR1_DIV(chip->div), &regs->cr[1]);
-
- if (chip->revision >= 0x11900) {
- writel(CR0_OPM_MASTER | CR0_FFMT_SPI | CR0_FSPO | CR0_FLASH,
- &regs->cr[0]);
- writel(CR2_TXFC | CR2_RXFC,
- &regs->cr[2]);
- } else {
- writel(CR0_OPM_MASTER | CR0_FFMT_SPI | CR0_FSPO,
- &regs->cr[0]);
- writel(CR2_TXFC | CR2_RXFC | CR2_EN | CR2_TXDOE,
- &regs->cr[2]);
- }
-
- if (chip->mode & SPI_LOOP)
- setbits_le32(&regs->cr[0], CR0_LOOP);
-
- if (chip->mode & SPI_CPOL)
- setbits_le32(&regs->cr[0], CR0_SCLKPO);
-
- if (chip->mode & SPI_CPHA)
- setbits_le32(&regs->cr[0], CR0_SCLKPH);
-
- spi_cs_deactivate(slave);
-
- return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
- struct ftssp010_spi *chip = to_ftssp010_spi(slave);
- struct ftssp010_regs *regs = chip->regs;
-
- writel(0, &regs->cr[2]);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
- const void *dout, void *din, unsigned long flags)
-{
- struct ftssp010_spi *chip = to_ftssp010_spi(slave);
- uint32_t len = bitlen >> 3;
-
- if (flags & SPI_XFER_BEGIN)
- spi_cs_activate(slave);
-
- if (chip->revision >= 0x11900)
- ftssp010_spi_work_transfer_v2(chip, dout, din, len, flags);
- else
- ftssp010_spi_work_transfer_v1(chip, dout, din, len, flags);
-
- if (flags & SPI_XFER_END)
- spi_cs_deactivate(slave);
-
- return 0;
-}
diff --git a/drivers/spi/oc_tiny_spi.c b/drivers/spi/oc_tiny_spi.c
deleted file mode 100644
index 4de5d008aa..0000000000
--- a/drivers/spi/oc_tiny_spi.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Opencore tiny_spi driver
- *
- * http://opencores.org/project,tiny_spi
- *
- * based on bfin_spi.c
- * Copyright (c) 2005-2008 Analog Devices Inc.
- * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <malloc.h>
-#include <spi.h>
-#include <asm/gpio.h>
-
-#define TINY_SPI_STATUS_TXE 0x1
-#define TINY_SPI_STATUS_TXR 0x2
-
-struct tiny_spi_regs {
- unsigned rxdata; /* Rx data reg */
- unsigned txdata; /* Tx data reg */
- unsigned status; /* Status reg */
- unsigned control; /* Control reg */
- unsigned baud; /* Baud reg */
-};
-
-struct tiny_spi_host {
- uint base;
- uint freq;
- uint baudwidth;
-};
-static const struct tiny_spi_host tiny_spi_host_list[] =
- CONFIG_SYS_TINY_SPI_LIST;
-
-struct tiny_spi_slave {
- struct spi_slave slave;
- const struct tiny_spi_host *host;
- uint mode;
- uint baud;
- uint flg;
-};
-#define to_tiny_spi_slave(s) container_of(s, struct tiny_spi_slave, slave)
-
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
- return bus < ARRAY_SIZE(tiny_spi_host_list) && gpio_is_valid(cs);
-}
-
-void spi_cs_activate(struct spi_slave *slave)
-{
- struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
- unsigned int cs = slave->cs;
-
- gpio_set_value(cs, tiny_spi->flg);
- debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
-}
-
-void spi_cs_deactivate(struct spi_slave *slave)
-{
- struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
- unsigned int cs = slave->cs;
-
- gpio_set_value(cs, !tiny_spi->flg);
- debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
-}
-
-void spi_set_speed(struct spi_slave *slave, uint hz)
-{
- struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
- const struct tiny_spi_host *host = tiny_spi->host;
-
- tiny_spi->baud = min(DIV_ROUND_UP(host->freq, hz * 2),
- (1 << host->baudwidth)) - 1;
- debug("%s: speed %u actual %u\n", __func__, hz,
- host->freq / ((tiny_spi->baud + 1) * 2));
-}
-
-void spi_init(void)
-{
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int hz, unsigned int mode)
-{
- struct tiny_spi_slave *tiny_spi;
-
- if (!spi_cs_is_valid(bus, cs) || gpio_request(cs, "tiny_spi"))
- return NULL;
-
- tiny_spi = spi_alloc_slave(struct tiny_spi_slave, bus, cs);
- if (!tiny_spi)
- return NULL;
-
- tiny_spi->host = &tiny_spi_host_list[bus];
- tiny_spi->mode = mode & (SPI_CPOL | SPI_CPHA);
- tiny_spi->flg = mode & SPI_CS_HIGH ? 1 : 0;
- spi_set_speed(&tiny_spi->slave, hz);
-
- debug("%s: bus:%i cs:%i base:%lx\n", __func__,
- bus, cs, tiny_spi->host->base);
- return &tiny_spi->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
-
- gpio_free(slave->cs);
- free(tiny_spi);
-}
-
-int spi_claim_bus(struct spi_slave *slave)
-{
- struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
- struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
-
- debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
- gpio_direction_output(slave->cs, !tiny_spi->flg);
- writel(tiny_spi->mode, &regs->control);
- writel(tiny_spi->baud, &regs->baud);
- return 0;
-}
-
-void spi_release_bus(struct spi_slave *slave)
-{
- debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
-}
-
-#ifndef CONFIG_TINY_SPI_IDLE_VAL
-# define CONFIG_TINY_SPI_IDLE_VAL 0xff
-#endif
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
- void *din, unsigned long flags)
-{
- struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
- struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
- const u8 *txp = dout;
- u8 *rxp = din;
- uint bytes = bitlen / 8;
- uint i;
-
- debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
- slave->bus, slave->cs, bitlen, bytes, flags);
- if (bitlen == 0)
- goto done;
-
- /* assume to do 8 bits transfers */
- if (bitlen % 8) {
- flags |= SPI_XFER_END;
- goto done;
- }
-
- if (flags & SPI_XFER_BEGIN)
- spi_cs_activate(slave);
-
- /* we need to tighten the transfer loop */
- if (txp && rxp) {
- writeb(*txp++, &regs->txdata);
- if (bytes > 1) {
- writeb(*txp++, &regs->txdata);
- for (i = 2; i < bytes; i++) {
- u8 rx, tx = *txp++;
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXR))
- ;
- rx = readb(&regs->txdata);
- writeb(tx, &regs->txdata);
- *rxp++ = rx;
- }
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXR))
- ;
- *rxp++ = readb(&regs->txdata);
- }
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXE))
- ;
- *rxp++ = readb(&regs->rxdata);
- } else if (rxp) {
- writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
- if (bytes > 1) {
- writeb(CONFIG_TINY_SPI_IDLE_VAL,
- &regs->txdata);
- for (i = 2; i < bytes; i++) {
- u8 rx;
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXR))
- ;
- rx = readb(&regs->txdata);
- writeb(CONFIG_TINY_SPI_IDLE_VAL,
- &regs->txdata);
- *rxp++ = rx;
- }
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXR))
- ;
- *rxp++ = readb(&regs->txdata);
- }
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXE))
- ;
- *rxp++ = readb(&regs->rxdata);
- } else if (txp) {
- writeb(*txp++, &regs->txdata);
- if (bytes > 1) {
- writeb(*txp++, &regs->txdata);
- for (i = 2; i < bytes; i++) {
- u8 tx = *txp++;
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXR))
- ;
- writeb(tx, &regs->txdata);
- }
- }
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXE))
- ;
- } else {
- writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
- if (bytes > 1) {
- writeb(CONFIG_TINY_SPI_IDLE_VAL,
- &regs->txdata);
- for (i = 2; i < bytes; i++) {
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXR))
- ;
- writeb(CONFIG_TINY_SPI_IDLE_VAL,
- &regs->txdata);
- }
- }
- while (!(readb(&regs->status) &
- TINY_SPI_STATUS_TXE))
- ;
- }
-
- done:
- if (flags & SPI_XFER_END)
- spi_cs_deactivate(slave);
-
- return 0;
-}
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 56d99d17c7..6c21acda57 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -1,149 +1,175 @@
/*
* Xilinx SPI driver
*
- * supports 8 bit SPI transfers only, with or w/o FIFO
+ * Supports 8 bit SPI transfers only, with or w/o FIFO
*
- * based on bfin_spi.c, by way of altera_spi.c
- * Copyright (c) 2005-2008 Analog Devices Inc.
- * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
- * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
+ * Based on bfin_spi.c, by way of altera_spi.c
+ * Copyright (c) 2015 Jagan Teki <jteki@openedev.com>
* Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
+ * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
+ * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (c) 2005-2008 Analog Devices Inc.
*
* SPDX-License-Identifier: GPL-2.0+
- *
- * [0]: http://www.xilinx.com/support/documentation
- *
- * [S]: [0]/ip_documentation/xps_spi.pdf
- * [0]/ip_documentation/axi_spi_ds742.pdf
*/
+
#include <config.h>
#include <common.h>
+#include <dm.h>
+#include <errno.h>
#include <malloc.h>
#include <spi.h>
+#include <asm/io.h>
-#include "xilinx_spi.h"
+/*
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * Xilinx SPI Register Definitions
+ * [1]: [0]/ip_documentation/xps_spi.pdf
+ * page 8, Register Descriptions
+ * [2]: [0]/ip_documentation/axi_spi_ds742.pdf
+ * page 7, Register Overview Table
+ */
-#ifndef CONFIG_SYS_XILINX_SPI_LIST
-#define CONFIG_SYS_XILINX_SPI_LIST { CONFIG_SYS_SPI_BASE }
-#endif
+/* SPI Control Register (spicr), [1] p9, [2] p8 */
+#define SPICR_LSB_FIRST (1 << 9)
+#define SPICR_MASTER_INHIBIT (1 << 8)
+#define SPICR_MANUAL_SS (1 << 7)
+#define SPICR_RXFIFO_RESEST (1 << 6)
+#define SPICR_TXFIFO_RESEST (1 << 5)
+#define SPICR_CPHA (1 << 4)
+#define SPICR_CPOL (1 << 3)
+#define SPICR_MASTER_MODE (1 << 2)
+#define SPICR_SPE (1 << 1)
+#define SPICR_LOOP (1 << 0)
+
+/* SPI Status Register (spisr), [1] p11, [2] p10 */
+#define SPISR_SLAVE_MODE_SELECT (1 << 5)
+#define SPISR_MODF (1 << 4)
+#define SPISR_TX_FULL (1 << 3)
+#define SPISR_TX_EMPTY (1 << 2)
+#define SPISR_RX_FULL (1 << 1)
+#define SPISR_RX_EMPTY (1 << 0)
+
+/* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */
+#define SPIDTR_8BIT_MASK (0xff << 0)
+#define SPIDTR_16BIT_MASK (0xffff << 0)
+#define SPIDTR_32BIT_MASK (0xffffffff << 0)
+
+/* SPI Data Receive Register (spidrr), [1] p12, [2] p12 */
+#define SPIDRR_8BIT_MASK (0xff << 0)
+#define SPIDRR_16BIT_MASK (0xffff << 0)
+#define SPIDRR_32BIT_MASK (0xffffffff << 0)
+
+/* SPI Slave Select Register (spissr), [1] p13, [2] p13 */
+#define SPISSR_MASK(cs) (1 << (cs))
+#define SPISSR_ACT(cs) ~SPISSR_MASK(cs)
+#define SPISSR_OFF ~0UL
+
+/* SPI Software Reset Register (ssr) */
+#define SPISSR_RESET_VALUE 0x0a
+
+#define XILSPI_MAX_XFER_BITS 8
+#define XILSPI_SPICR_DFLT_ON (SPICR_MANUAL_SS | SPICR_MASTER_MODE | \
+ SPICR_SPE)
+#define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | SPICR_MANUAL_SS)
#ifndef CONFIG_XILINX_SPI_IDLE_VAL
#define CONFIG_XILINX_SPI_IDLE_VAL 0xff
#endif
-#define XILSPI_SPICR_DFLT_ON (SPICR_MANUAL_SS | \
- SPICR_MASTER_MODE | \
- SPICR_SPE)
-
-#define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | \
- SPICR_MANUAL_SS)
+#ifndef CONFIG_SYS_XILINX_SPI_LIST
+#define CONFIG_SYS_XILINX_SPI_LIST { CONFIG_SYS_SPI_BASE }
+#endif
-#define XILSPI_MAX_XFER_BITS 8
+/* xilinx spi register set */
+struct xilinx_spi_regs {
+ u32 __space0__[7];
+ u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */
+ u32 ipisr; /* IP Interrupt Status Register (IPISR) */
+ u32 __space1__;
+ u32 ipier; /* IP Interrupt Enable Register (IPIER) */
+ u32 __space2__[5];
+ u32 srr; /* Softare Reset Register (SRR) */
+ u32 __space3__[7];
+ u32 spicr; /* SPI Control Register (SPICR) */
+ u32 spisr; /* SPI Status Register (SPISR) */
+ u32 spidtr; /* SPI Data Transmit Register (SPIDTR) */
+ u32 spidrr; /* SPI Data Receive Register (SPIDRR) */
+ u32 spissr; /* SPI Slave Select Register (SPISSR) */
+ u32 spitfor; /* SPI Transmit FIFO Occupancy Register (SPITFOR) */
+ u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */
+};
+
+/* xilinx spi priv */
+struct xilinx_spi_priv {
+ struct xilinx_spi_regs *regs;
+ unsigned int freq;
+ unsigned int mode;
+};
static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST;
-
-__attribute__((weak))
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+static int xilinx_spi_probe(struct udevice *bus)
{
- return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32;
-}
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
-__attribute__((weak))
-void spi_cs_activate(struct spi_slave *slave)
-{
- struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ priv->regs = (struct xilinx_spi_regs *)xilinx_spi_base_list[bus->seq];
- writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr);
-}
+ writel(SPISSR_RESET_VALUE, &regs->srr);
-__attribute__((weak))
-void spi_cs_deactivate(struct spi_slave *slave)
-{
- struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
-
- writel(SPISSR_OFF, &xilspi->regs->spissr);
+ return 0;
}
-void spi_init(void)
+static void spi_cs_activate(struct udevice *dev, uint cs)
{
- /* do nothing */
-}
+ struct udevice *bus = dev_get_parent(dev);
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
-void spi_set_speed(struct spi_slave *slave, uint hz)
-{
- /* xilinx spi core does not support programmable speed */
+ writel(SPISSR_ACT(cs), &regs->spissr);
}
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
+static void spi_cs_deactivate(struct udevice *dev)
{
- struct xilinx_spi_slave *xilspi;
-
- if (!spi_cs_is_valid(bus, cs)) {
- printf("XILSPI error: %s: unsupported bus %d / cs %d\n",
- __func__, bus, cs);
- return NULL;
- }
-
- xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs);
- if (!xilspi) {
- printf("XILSPI error: %s: malloc of SPI structure failed\n",
- __func__);
- return NULL;
- }
- xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus];
- xilspi->freq = max_hz;
- xilspi->mode = mode;
- debug("%s: bus:%i cs:%i base:%p mode:%x max_hz:%d\n", __func__,
- bus, cs, xilspi->regs, xilspi->mode, xilspi->freq);
+ struct udevice *bus = dev_get_parent(dev);
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
- writel(SPISSR_RESET_VALUE, &xilspi->regs->srr);
-
- return &xilspi->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
-
- free(xilspi);
+ writel(SPISSR_OFF, &regs->spissr);
}
-int spi_claim_bus(struct spi_slave *slave)
+static int xilinx_spi_claim_bus(struct udevice *dev)
{
- struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
- u32 spicr;
+ struct udevice *bus = dev_get_parent(dev);
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
- debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
- writel(SPISSR_OFF, &xilspi->regs->spissr);
+ writel(SPISSR_OFF, &regs->spissr);
+ writel(XILSPI_SPICR_DFLT_ON, &regs->spicr);
- spicr = XILSPI_SPICR_DFLT_ON;
- if (xilspi->mode & SPI_LSB_FIRST)
- spicr |= SPICR_LSB_FIRST;
- if (xilspi->mode & SPI_CPHA)
- spicr |= SPICR_CPHA;
- if (xilspi->mode & SPI_CPOL)
- spicr |= SPICR_CPOL;
- if (xilspi->mode & SPI_LOOP)
- spicr |= SPICR_LOOP;
-
- writel(spicr, &xilspi->regs->spicr);
return 0;
}
-void spi_release_bus(struct spi_slave *slave)
+static int xilinx_spi_release_bus(struct udevice *dev)
{
- struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ struct udevice *bus = dev_get_parent(dev);
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
+
+ writel(SPISSR_OFF, &regs->spissr);
+ writel(XILSPI_SPICR_DFLT_OFF, &regs->spicr);
- debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
- writel(SPISSR_OFF, &xilspi->regs->spissr);
- writel(XILSPI_SPICR_DFLT_OFF, &xilspi->regs->spicr);
+ return 0;
}
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
- void *din, unsigned long flags)
+static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
{
- struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ struct udevice *bus = dev_get_parent(dev);
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
+ struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
/* assume spi core configured to do 8 bit transfers */
unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS;
const unsigned char *txp = dout;
@@ -151,65 +177,125 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
unsigned rxecount = 17; /* max. 16 elements in FIFO, leftover 1 */
unsigned global_timeout;
- debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
- slave->bus, slave->cs, bitlen, bytes, flags);
+ debug("spi_xfer: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n",
+ bus->seq, slave_plat->cs, bitlen, bytes, flags);
+
if (bitlen == 0)
goto done;
if (bitlen % XILSPI_MAX_XFER_BITS) {
- printf("XILSPI warning: %s: Not a multiple of %d bits\n",
- __func__, XILSPI_MAX_XFER_BITS);
+ printf("XILSPI warning: Not a multiple of %d bits\n",
+ XILSPI_MAX_XFER_BITS);
flags |= SPI_XFER_END;
goto done;
}
/* empty read buffer */
- while (rxecount && !(readl(&xilspi->regs->spisr) & SPISR_RX_EMPTY)) {
- readl(&xilspi->regs->spidrr);
+ while (rxecount && !(readl(&regs->spisr) & SPISR_RX_EMPTY)) {
+ readl(&regs->spidrr);
rxecount--;
}
if (!rxecount) {
- printf("XILSPI error: %s: Rx buffer not empty\n", __func__);
+ printf("XILSPI error: Rx buffer not empty\n");
return -1;
}
if (flags & SPI_XFER_BEGIN)
- spi_cs_activate(slave);
+ spi_cs_activate(dev, slave_plat->cs);
/* at least 1usec or greater, leftover 1 */
- global_timeout = xilspi->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
- (XILSPI_MAX_XFER_BITS * 1000000 / xilspi->freq) + 1;
+ global_timeout = priv->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
+ (XILSPI_MAX_XFER_BITS * 1000000 / priv->freq) + 1;
while (bytes--) {
unsigned timeout = global_timeout;
/* get Tx element from data out buffer and count up */
unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
- debug("%s: tx:%x ", __func__, d);
+ debug("spi_xfer: tx:%x ", d);
/* write out and wait for processing (receive data) */
- writel(d & SPIDTR_8BIT_MASK, &xilspi->regs->spidtr);
- while (timeout && readl(&xilspi->regs->spisr)
+ writel(d & SPIDTR_8BIT_MASK, &regs->spidtr);
+ while (timeout && readl(&regs->spisr)
& SPISR_RX_EMPTY) {
timeout--;
udelay(1);
}
if (!timeout) {
- printf("XILSPI error: %s: Xfer timeout\n", __func__);
+ printf("XILSPI error: Xfer timeout\n");
return -1;
}
/* read Rx element and push into data in buffer */
- d = readl(&xilspi->regs->spidrr) & SPIDRR_8BIT_MASK;
+ d = readl(&regs->spidrr) & SPIDRR_8BIT_MASK;
if (rxp)
*rxp++ = d;
- debug("rx:%x\n", d);
+ debug("spi_xfer: rx:%x\n", d);
}
done:
if (flags & SPI_XFER_END)
- spi_cs_deactivate(slave);
+ spi_cs_deactivate(dev);
return 0;
}
+
+static int xilinx_spi_set_speed(struct udevice *bus, uint speed)
+{
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+
+ priv->freq = speed;
+
+ debug("xilinx_spi_set_speed: regs=%p, mode=%d\n", priv->regs,
+ priv->freq);
+
+ return 0;
+}
+
+static int xilinx_spi_set_mode(struct udevice *bus, uint mode)
+{
+ struct xilinx_spi_priv *priv = dev_get_priv(bus);
+ struct xilinx_spi_regs *regs = priv->regs;
+ uint32_t spicr;
+
+ spicr = readl(&regs->spicr);
+ if (priv->mode & SPI_LSB_FIRST)
+ spicr |= SPICR_LSB_FIRST;
+ if (priv->mode & SPI_CPHA)
+ spicr |= SPICR_CPHA;
+ if (priv->mode & SPI_CPOL)
+ spicr |= SPICR_CPOL;
+ if (priv->mode & SPI_LOOP)
+ spicr |= SPICR_LOOP;
+
+ writel(spicr, &regs->spicr);
+ priv->mode = mode;
+
+ debug("xilinx_spi_set_mode: regs=%p, mode=%d\n", priv->regs,
+ priv->mode);
+
+ return 0;
+}
+
+static const struct dm_spi_ops xilinx_spi_ops = {
+ .claim_bus = xilinx_spi_claim_bus,
+ .release_bus = xilinx_spi_release_bus,
+ .xfer = xilinx_spi_xfer,
+ .set_speed = xilinx_spi_set_speed,
+ .set_mode = xilinx_spi_set_mode,
+};
+
+static const struct udevice_id xilinx_spi_ids[] = {
+ { .compatible = "xlnx,xilinx-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(xilinx_spi) = {
+ .name = "xilinx_spi",
+ .id = UCLASS_SPI,
+ .of_match = xilinx_spi_ids,
+ .ops = &xilinx_spi_ops,
+ .priv_auto_alloc_size = sizeof(struct xilinx_spi_priv),
+ .probe = xilinx_spi_probe,
+};
diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h
deleted file mode 100644
index ce7d82c394..0000000000
--- a/drivers/spi/xilinx_spi.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Xilinx SPI driver
- *
- * XPS/AXI bus interface
- *
- * based on bfin_spi.c, by way of altera_spi.c
- * Copyright (c) 2005-2008 Analog Devices Inc.
- * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
- * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
- * Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
- *
- * SPDX-License-Identifier: GPL-2.0+
- *
- * [0]: http://www.xilinx.com/support/documentation
- *
- * [S]: [0]/ip_documentation/xps_spi.pdf
- * [0]/ip_documentation/axi_spi_ds742.pdf
- */
-#ifndef _XILINX_SPI_
-#define _XILINX_SPI_
-
-#include <asm/types.h>
-#include <asm/io.h>
-
-/*
- * Xilinx SPI Register Definition
- *
- * [1]: [0]/ip_documentation/xps_spi.pdf
- * page 8, Register Descriptions
- * [2]: [0]/ip_documentation/axi_spi_ds742.pdf
- * page 7, Register Overview Table
- */
-struct xilinx_spi_reg {
- u32 __space0__[7];
- u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */
- u32 ipisr; /* IP Interrupt Status Register (IPISR) */
- u32 __space1__;
- u32 ipier; /* IP Interrupt Enable Register (IPIER) */
- u32 __space2__[5];
- u32 srr; /* Softare Reset Register (SRR) */
- u32 __space3__[7];
- u32 spicr; /* SPI Control Register (SPICR) */
- u32 spisr; /* SPI Status Register (SPISR) */
- u32 spidtr; /* SPI Data Transmit Register (SPIDTR) */
- u32 spidrr; /* SPI Data Receive Register (SPIDRR) */
- u32 spissr; /* SPI Slave Select Register (SPISSR) */
- u32 spitfor; /* SPI Transmit FIFO Occupancy Register (SPITFOR) */
- u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */
-};
-
-/* Device Global Interrupt Enable Register (dgier), [1] p15, [2] p15 */
-#define DGIER_GIE (1 << 31)
-
-/* IP Interrupt Status Register (ipisr), [1] p15, [2] p15 */
-#define IPISR_DRR_NOT_EMPTY (1 << 8)
-#define IPISR_SLAVE_SELECT (1 << 7)
-#define IPISR_TXF_HALF_EMPTY (1 << 6)
-#define IPISR_DRR_OVERRUN (1 << 5)
-#define IPISR_DRR_FULL (1 << 4)
-#define IPISR_DTR_UNDERRUN (1 << 3)
-#define IPISR_DTR_EMPTY (1 << 2)
-#define IPISR_SLAVE_MODF (1 << 1)
-#define IPISR_MODF (1 << 0)
-
-/* IP Interrupt Enable Register (ipier), [1] p17, [2] p18 */
-#define IPIER_DRR_NOT_EMPTY (1 << 8)
-#define IPIER_SLAVE_SELECT (1 << 7)
-#define IPIER_TXF_HALF_EMPTY (1 << 6)
-#define IPIER_DRR_OVERRUN (1 << 5)
-#define IPIER_DRR_FULL (1 << 4)
-#define IPIER_DTR_UNDERRUN (1 << 3)
-#define IPIER_DTR_EMPTY (1 << 2)
-#define IPIER_SLAVE_MODF (1 << 1)
-#define IPIER_MODF (1 << 0)
-
-/* Softare Reset Register (srr), [1] p9, [2] p8 */
-#define SRR_RESET_CODE 0x0000000A
-
-/* SPI Control Register (spicr), [1] p9, [2] p8 */
-#define SPICR_LSB_FIRST (1 << 9)
-#define SPICR_MASTER_INHIBIT (1 << 8)
-#define SPICR_MANUAL_SS (1 << 7)
-#define SPICR_RXFIFO_RESEST (1 << 6)
-#define SPICR_TXFIFO_RESEST (1 << 5)
-#define SPICR_CPHA (1 << 4)
-#define SPICR_CPOL (1 << 3)
-#define SPICR_MASTER_MODE (1 << 2)
-#define SPICR_SPE (1 << 1)
-#define SPICR_LOOP (1 << 0)
-
-/* SPI Status Register (spisr), [1] p11, [2] p10 */
-#define SPISR_SLAVE_MODE_SELECT (1 << 5)
-#define SPISR_MODF (1 << 4)
-#define SPISR_TX_FULL (1 << 3)
-#define SPISR_TX_EMPTY (1 << 2)
-#define SPISR_RX_FULL (1 << 1)
-#define SPISR_RX_EMPTY (1 << 0)
-
-/* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */
-#define SPIDTR_8BIT_MASK (0xff << 0)
-#define SPIDTR_16BIT_MASK (0xffff << 0)
-#define SPIDTR_32BIT_MASK (0xffffffff << 0)
-
-/* SPI Data Receive Register (spidrr), [1] p12, [2] p12 */
-#define SPIDRR_8BIT_MASK (0xff << 0)
-#define SPIDRR_16BIT_MASK (0xffff << 0)
-#define SPIDRR_32BIT_MASK (0xffffffff << 0)
-
-/* SPI Slave Select Register (spissr), [1] p13, [2] p13 */
-#define SPISSR_MASK(cs) (1 << (cs))
-#define SPISSR_ACT(cs) ~SPISSR_MASK(cs)
-#define SPISSR_OFF ~0UL
-
-/* SPI Transmit FIFO Occupancy Register (spitfor), [1] p13, [2] p14 */
-#define SPITFOR_OCYVAL_POS 0
-#define SPITFOR_OCYVAL_MASK (0xf << SPITFOR_OCYVAL_POS)
-
-/* SPI Receive FIFO Occupancy Register (spirfor), [1] p14, [2] p14 */
-#define SPIRFOR_OCYVAL_POS 0
-#define SPIRFOR_OCYVAL_MASK (0xf << SPIRFOR_OCYVAL_POS)
-
-/* SPI Software Reset Register (ssr) */
-#define SPISSR_RESET_VALUE 0x0a
-
-struct xilinx_spi_slave {
- struct spi_slave slave;
- struct xilinx_spi_reg *regs;
- unsigned int freq;
- unsigned int mode;
-};
-
-static inline struct xilinx_spi_slave *to_xilinx_spi_slave(
- struct spi_slave *slave)
-{
- return container_of(slave, struct xilinx_spi_slave, slave);
-}
-
-#endif /* _XILINX_SPI_ */
diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c
index e9129da79d..c5c3e1044f 100644
--- a/drivers/spi/zynq_spi.c
+++ b/drivers/spi/zynq_spi.c
@@ -1,5 +1,6 @@
/*
* (C) Copyright 2013 Inc.
+ * (C) Copyright 2015 Jagan Teki <jteki@openedev.com>
*
* Xilinx Zynq PS SPI controller driver (master mode only)
*
@@ -8,11 +9,16 @@
#include <config.h>
#include <common.h>
+#include <dm.h>
+#include <errno.h>
#include <malloc.h>
#include <spi.h>
+#include <fdtdec.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
+DECLARE_GLOBAL_DATA_PTR;
+
/* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */
#define ZYNQ_SPI_CR_MSA_MASK (1 << 15) /* Manual start enb */
#define ZYNQ_SPI_CR_MCS_MASK (1 << 14) /* Manual chip select */
@@ -44,180 +50,141 @@ struct zynq_spi_regs {
u32 rxdr; /* 0x20 */
};
-/* zynq spi slave */
-struct zynq_spi_slave {
- struct spi_slave slave;
- struct zynq_spi_regs *base;
+
+/* zynq spi platform data */
+struct zynq_spi_platdata {
+ struct zynq_spi_regs *regs;
+ u32 frequency; /* input frequency */
+ u32 speed_hz;
+};
+
+/* zynq spi priv */
+struct zynq_spi_priv {
+ struct zynq_spi_regs *regs;
u8 mode;
u8 fifo_depth;
- u32 speed_hz;
- u32 input_hz;
- u32 req_hz;
+ u32 freq; /* required frequency */
};
-static inline struct zynq_spi_slave *to_zynq_spi_slave(struct spi_slave *slave)
+static int zynq_spi_ofdata_to_platdata(struct udevice *bus)
{
- return container_of(slave, struct zynq_spi_slave, slave);
-}
+ struct zynq_spi_platdata *plat = bus->platdata;
+ const void *blob = gd->fdt_blob;
+ int node = bus->of_offset;
-static inline struct zynq_spi_regs *get_zynq_spi_base(int dev)
-{
- if (dev)
- return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1;
- else
- return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
+ plat->regs = (struct zynq_spi_regs *)fdtdec_get_addr(blob, node, "reg");
+
+ /* FIXME: Use 250MHz as a suitable default */
+ plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+ 250000000);
+ plat->speed_hz = plat->frequency / 2;
+
+ debug("zynq_spi_ofdata_to_platdata: regs=%p max-frequency=%d\n",
+ plat->regs, plat->frequency);
+
+ return 0;
}
-static void zynq_spi_init_hw(struct zynq_spi_slave *zslave)
+static void zynq_spi_init_hw(struct zynq_spi_priv *priv)
{
+ struct zynq_spi_regs *regs = priv->regs;
u32 confr;
/* Disable SPI */
- writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+ writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
/* Disable Interrupts */
- writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->idr);
+ writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->idr);
/* Clear RX FIFO */
- while (readl(&zslave->base->isr) &
+ while (readl(&regs->isr) &
ZYNQ_SPI_IXR_RXNEMPTY_MASK)
- readl(&zslave->base->rxdr);
+ readl(&regs->rxdr);
/* Clear Interrupts */
- writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->isr);
+ writel(ZYNQ_SPI_IXR_ALL_MASK, &regs->isr);
/* Manual slave select and Auto start */
confr = ZYNQ_SPI_CR_MCS_MASK | ZYNQ_SPI_CR_CS_MASK |
ZYNQ_SPI_CR_MSTREN_MASK;
confr &= ~ZYNQ_SPI_CR_MSA_MASK;
- writel(confr, &zslave->base->cr);
+ writel(confr, &regs->cr);
/* Enable SPI */
- writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+ writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
}
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+static int zynq_spi_probe(struct udevice *bus)
{
- /* 2 bus with 3 chipselect */
- return bus < 2 && cs < 3;
+ struct zynq_spi_platdata *plat = dev_get_platdata(bus);
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+
+ priv->regs = plat->regs;
+ priv->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
+
+ /* init the zynq spi hw */
+ zynq_spi_init_hw(priv);
+
+ return 0;
}
-void spi_cs_activate(struct spi_slave *slave)
+static void spi_cs_activate(struct udevice *dev, uint cs)
{
- struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+ struct udevice *bus = dev->parent;
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
u32 cr;
- debug("spi_cs_activate: 0x%08x\n", (u32)slave);
-
- clrbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
- cr = readl(&zslave->base->cr);
+ clrbits_le32(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
+ cr = readl(&regs->cr);
/*
* CS cal logic: CS[13:10]
* xxx0 - cs0
* xx01 - cs1
* x011 - cs2
*/
- cr |= (~(0x1 << slave->cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
- writel(cr, &zslave->base->cr);
+ cr |= (~(0x1 << cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
+ writel(cr, &regs->cr);
}
-void spi_cs_deactivate(struct spi_slave *slave)
+static void spi_cs_deactivate(struct udevice *dev)
{
- struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
-
- debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
+ struct udevice *bus = dev->parent;
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
- setbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
-}
-
-void spi_init()
-{
- /* nothing to do */
+ setbits_le32(&regs->cr, ZYNQ_SPI_CR_CS_MASK);
}
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
- unsigned int max_hz, unsigned int mode)
+static int zynq_spi_claim_bus(struct udevice *dev)
{
- struct zynq_spi_slave *zslave;
+ struct udevice *bus = dev->parent;
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
- if (!spi_cs_is_valid(bus, cs))
- return NULL;
+ writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
- zslave = spi_alloc_slave(struct zynq_spi_slave, bus, cs);
- if (!zslave) {
- printf("SPI_error: Fail to allocate zynq_spi_slave\n");
- return NULL;
- }
-
- zslave->base = get_zynq_spi_base(bus);
- zslave->mode = mode;
- zslave->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
- zslave->input_hz = 166666700;
- zslave->speed_hz = zslave->input_hz / 2;
- zslave->req_hz = max_hz;
-
- /* init the zynq spi hw */
- zynq_spi_init_hw(zslave);
-
- return &zslave->slave;
-}
-
-void spi_free_slave(struct spi_slave *slave)
-{
- struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
-
- debug("spi_free_slave: 0x%08x\n", (u32)slave);
- free(zslave);
+ return 0;
}
-int spi_claim_bus(struct spi_slave *slave)
+static int zynq_spi_release_bus(struct udevice *dev)
{
- struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
- u32 confr = 0;
- u8 baud_rate_val = 0;
+ struct udevice *bus = dev->parent;
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
- writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
-
- /* Set the SPI Clock phase and polarities */
- confr = readl(&zslave->base->cr);
- confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
- if (zslave->mode & SPI_CPHA)
- confr |= ZYNQ_SPI_CR_CPHA_MASK;
- if (zslave->mode & SPI_CPOL)
- confr |= ZYNQ_SPI_CR_CPOL_MASK;
-
- /* Set the clock frequency */
- if (zslave->req_hz == 0) {
- /* Set baudrate x8, if the req_hz is 0 */
- baud_rate_val = 0x2;
- } else if (zslave->speed_hz != zslave->req_hz) {
- while ((baud_rate_val < 8) &&
- ((zslave->input_hz /
- (2 << baud_rate_val)) > zslave->req_hz))
- baud_rate_val++;
- zslave->speed_hz = zslave->req_hz / (2 << baud_rate_val);
- }
- confr &= ~ZYNQ_SPI_CR_BRD_MASK;
- confr |= (baud_rate_val << 3);
- writel(confr, &zslave->base->cr);
-
- writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+ writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &regs->enr);
return 0;
}
-void spi_release_bus(struct spi_slave *slave)
+static int zynq_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
{
- struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
-
- debug("spi_release_bus: 0x%08x\n", (u32)slave);
- writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
-}
-
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
- void *din, unsigned long flags)
-{
- struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+ struct udevice *bus = dev->parent;
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
+ struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
u32 len = bitlen / 8;
u32 tx_len = len, rx_len = len, tx_tvl;
const u8 *tx_buf = dout;
@@ -225,7 +192,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
u32 ts, status;
debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
- slave->bus, slave->cs, bitlen, len, flags);
+ bus->seq, slave_plat->cs, bitlen, len, flags);
if (bitlen % 8) {
debug("spi_xfer: Non byte aligned SPI transfer\n");
@@ -233,45 +200,126 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
}
if (flags & SPI_XFER_BEGIN)
- spi_cs_activate(slave);
+ spi_cs_activate(dev, slave_plat->cs);
while (rx_len > 0) {
/* Write the data into TX FIFO - tx threshold is fifo_depth */
tx_tvl = 0;
- while ((tx_tvl < zslave->fifo_depth) && tx_len) {
+ while ((tx_tvl < priv->fifo_depth) && tx_len) {
if (tx_buf)
buf = *tx_buf++;
else
buf = 0;
- writel(buf, &zslave->base->txdr);
+ writel(buf, &regs->txdr);
tx_len--;
tx_tvl++;
}
/* Check TX FIFO completion */
ts = get_timer(0);
- status = readl(&zslave->base->isr);
+ status = readl(&regs->isr);
while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) {
if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) {
printf("spi_xfer: Timeout! TX FIFO not full\n");
return -1;
}
- status = readl(&zslave->base->isr);
+ status = readl(&regs->isr);
}
/* Read the data from RX FIFO */
- status = readl(&zslave->base->isr);
+ status = readl(&regs->isr);
while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
- buf = readl(&zslave->base->rxdr);
+ buf = readl(&regs->rxdr);
if (rx_buf)
*rx_buf++ = buf;
- status = readl(&zslave->base->isr);
+ status = readl(&regs->isr);
rx_len--;
}
}
if (flags & SPI_XFER_END)
- spi_cs_deactivate(slave);
+ spi_cs_deactivate(dev);
return 0;
}
+
+static int zynq_spi_set_speed(struct udevice *bus, uint speed)
+{
+ struct zynq_spi_platdata *plat = bus->platdata;
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
+ uint32_t confr;
+ u8 baud_rate_val = 0;
+
+ if (speed > plat->frequency)
+ speed = plat->frequency;
+
+ /* Set the clock frequency */
+ confr = readl(&regs->cr);
+ if (speed == 0) {
+ /* Set baudrate x8, if the freq is 0 */
+ baud_rate_val = 0x2;
+ } else if (plat->speed_hz != speed) {
+ while ((baud_rate_val < 8) &&
+ ((plat->frequency /
+ (2 << baud_rate_val)) > speed))
+ baud_rate_val++;
+ plat->speed_hz = speed / (2 << baud_rate_val);
+ }
+ confr &= ~ZYNQ_SPI_CR_BRD_MASK;
+ confr |= (baud_rate_val << 3);
+
+ writel(confr, &regs->cr);
+ priv->freq = speed;
+
+ debug("zynq_spi_set_speed: regs=%p, mode=%d\n", priv->regs, priv->freq);
+
+ return 0;
+}
+
+static int zynq_spi_set_mode(struct udevice *bus, uint mode)
+{
+ struct zynq_spi_priv *priv = dev_get_priv(bus);
+ struct zynq_spi_regs *regs = priv->regs;
+ uint32_t confr;
+
+ /* Set the SPI Clock phase and polarities */
+ confr = readl(&regs->cr);
+ confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
+
+ if (priv->mode & SPI_CPHA)
+ confr |= ZYNQ_SPI_CR_CPHA_MASK;
+ if (priv->mode & SPI_CPOL)
+ confr |= ZYNQ_SPI_CR_CPOL_MASK;
+
+ writel(confr, &regs->cr);
+ priv->mode = mode;
+
+ debug("zynq_spi_set_mode: regs=%p, mode=%d\n", priv->regs, priv->mode);
+
+ return 0;
+}
+
+static const struct dm_spi_ops zynq_spi_ops = {
+ .claim_bus = zynq_spi_claim_bus,
+ .release_bus = zynq_spi_release_bus,
+ .xfer = zynq_spi_xfer,
+ .set_speed = zynq_spi_set_speed,
+ .set_mode = zynq_spi_set_mode,
+};
+
+static const struct udevice_id zynq_spi_ids[] = {
+ { .compatible = "xlnx,zynq-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(zynq_spi) = {
+ .name = "zynq_spi",
+ .id = UCLASS_SPI,
+ .of_match = zynq_spi_ids,
+ .ops = &zynq_spi_ops,
+ .ofdata_to_platdata = zynq_spi_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct zynq_spi_platdata),
+ .priv_auto_alloc_size = sizeof(struct zynq_spi_priv),
+ .probe = zynq_spi_probe,
+};
OpenPOWER on IntegriCloud