diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/cf_qspi.c | 2 | ||||
-rw-r--r-- | drivers/spi/cf_spi.c | 31 | ||||
-rw-r--r-- | drivers/spi/davinci_spi.c | 3 | ||||
-rw-r--r-- | drivers/spi/designware_spi.c | 4 | ||||
-rw-r--r-- | drivers/spi/ftssp010_spi.c | 4 | ||||
-rw-r--r-- | drivers/spi/lpc32xx_ssp.c | 144 | ||||
-rw-r--r-- | drivers/spi/ti_qspi.c | 7 |
8 files changed, 174 insertions, 22 deletions
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index edbd520141..ce6f1cc74e 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o obj-$(CONFIG_FTSSP010_SPI) += ftssp010_spi.o obj-$(CONFIG_ICH_SPI) += ich.o obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o +obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o obj-$(CONFIG_MXC_SPI) += mxc_spi.o diff --git a/drivers/spi/cf_qspi.c b/drivers/spi/cf_qspi.c index 6b8563366b..834c5bd259 100644 --- a/drivers/spi/cf_qspi.c +++ b/drivers/spi/cf_qspi.c @@ -20,7 +20,7 @@ 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, s) +#define to_cf_qspi_slave(s) container_of(s, struct cf_qspi_slave, slave) struct cf_qspi_slave { struct spi_slave slave; /* Specific bus:cs ID for each device */ diff --git a/drivers/spi/cf_spi.c b/drivers/spi/cf_spi.c index 879a809cba..6ce11012e8 100644 --- a/drivers/spi/cf_spi.c +++ b/drivers/spi/cf_spi.c @@ -20,13 +20,6 @@ struct cf_spi_slave { int charbit; }; -int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout, - void *din, ulong flags); -struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, uint mode); -void cfspi_init(void); -void cfspi_tx(u32 ctrl, u16 data); -u16 cfspi_rx(void); - extern void cfspi_port_conf(void); extern int cfspi_claim_bus(uint bus, uint cs); extern void cfspi_release_bus(uint bus, uint cs); @@ -46,7 +39,12 @@ DECLARE_GLOBAL_DATA_PTR; #define SPI_MODE_MOD 0x00200000 #define SPI_DBLRATE 0x00100000 -void cfspi_init(void) +static inline struct cf_spi_slave *to_cf_spi_slave(struct spi_slave *slave) +{ + return container_of(slave, struct cf_spi_slave, slave); +} + +static void cfspi_init(void) { volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; @@ -84,7 +82,7 @@ void cfspi_init(void) #endif } -void cfspi_tx(u32 ctrl, u16 data) +static void cfspi_tx(u32 ctrl, u16 data) { volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; @@ -93,7 +91,7 @@ void cfspi_tx(u32 ctrl, u16 data) dspi->tfr = (ctrl | data); } -u16 cfspi_rx(void) +static u16 cfspi_rx(void) { volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI; @@ -102,10 +100,10 @@ u16 cfspi_rx(void) return (dspi->rfr & 0xFFFF); } -int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout, - void *din, ulong flags) +static int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout, + void *din, ulong flags) { - struct cf_spi_slave *cfslave = (struct cf_spi_slave *)slave; + struct cf_spi_slave *cfslave = to_cf_spi_slave(slave); u16 *spi_rd16 = NULL, *spi_wr16 = NULL; u8 *spi_rd = NULL, *spi_wr = NULL; static u32 ctrl = 0; @@ -176,7 +174,8 @@ int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout, return 0; } -struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, uint mode) +static struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, + uint mode) { /* * bit definition for mode: @@ -326,7 +325,9 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, void spi_free_slave(struct spi_slave *slave) { - free(slave); + struct cf_spi_slave *cfslave = to_cf_spi_slave(slave); + + free(cfslave); } int spi_claim_bus(struct spi_slave *slave) diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 0ec5b9d859..bf18362baa 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -32,9 +32,6 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, if (!ds) return NULL; - ds->slave.bus = bus; - ds->slave.cs = cs; - switch (bus) { case SPI0_BUS: ds->regs = (struct davinci_spi_regs *)SPI0_BASE; diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 2624844d52..8f5c0fc802 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -164,13 +164,13 @@ static void spi_hw_init(struct dw_spi_priv *priv) if (!priv->fifo_len) { u32 fifo; - for (fifo = 2; fifo <= 256; fifo++) { + for (fifo = 1; fifo < 256; fifo++) { dw_writew(priv, DW_SPI_TXFLTR, fifo); if (fifo != dw_readw(priv, DW_SPI_TXFLTR)) break; } - priv->fifo_len = (fifo == 2) ? 0 : fifo - 1; + priv->fifo_len = (fifo == 1) ? 0 : fifo; dw_writew(priv, DW_SPI_TXFLTR, 0); } debug("%s: fifo_len=%d\n", __func__, priv->fifo_len); diff --git a/drivers/spi/ftssp010_spi.c b/drivers/spi/ftssp010_spi.c index 267e4d83bd..c7d6480478 100644 --- a/drivers/spi/ftssp010_spi.c +++ b/drivers/spi/ftssp010_spi.c @@ -431,7 +431,9 @@ free_out: void spi_free_slave(struct spi_slave *slave) { - free(slave); + struct ftssp010_spi *chip = to_ftssp010_spi(slave); + + free(chip); } int spi_claim_bus(struct spi_slave *slave) diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c new file mode 100644 index 0000000000..c5b766c0dd --- /dev/null +++ b/drivers/spi/lpc32xx_ssp.c @@ -0,0 +1,144 @@ +/* + * LPC32xx SSP interface (SPI mode) + * + * (C) Copyright 2014 DENX Software Engineering GmbH + * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/compat.h> +#include <asm/io.h> +#include <malloc.h> +#include <spi.h> +#include <asm/arch/clk.h> + +/* SSP chip registers */ +struct ssp_regs { + u32 cr0; + u32 cr1; + u32 data; + u32 sr; + u32 cpsr; + u32 imsc; + u32 ris; + u32 mis; + u32 icr; + u32 dmacr; +}; + +/* CR1 register defines */ +#define SSP_CR1_SSP_ENABLE 0x0002 + +/* SR register defines */ +#define SSP_SR_TNF 0x0002 +/* SSP status RX FIFO not empty bit */ +#define SSP_SR_RNE 0x0004 + +/* lpc32xx spi slave */ +struct lpc32xx_spi_slave { + struct spi_slave slave; + struct ssp_regs *regs; +}; + +static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave( + struct spi_slave *slave) +{ + return container_of(slave, struct lpc32xx_spi_slave, slave); +} + +/* spi_init is called during boot when CONFIG_CMD_SPI is defined */ +void spi_init(void) +{ + /* + * nothing to do: clocking was enabled in lpc32xx_ssp_enable() + * and configuration will be done in spi_setup_slave() + */ +} + +/* the following is called in sequence by do_spi_xfer() */ + +struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode) +{ + struct lpc32xx_spi_slave *lslave; + + /* we only set up SSP0 for now, so ignore bus */ + + if (mode & SPI_3WIRE) { + error("3-wire mode not supported"); + return NULL; + } + + if (mode & SPI_SLAVE) { + error("slave mode not supported\n"); + return NULL; + } + + if (mode & SPI_PREAMBLE) { + error("preamble byte skipping not supported\n"); + return NULL; + } + + lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs); + if (!lslave) { + printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n"); + return NULL; + } + + lslave->regs = (struct ssp_regs *)SSP0_BASE; + + /* + * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26. + * Set SCR to 0 and CPSDVSR to 26. + */ + + writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */ + writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */ + writel(0, &lslave->regs->imsc); /* do not raise any interrupts */ + writel(0, &lslave->regs->icr); /* clear any pending interrupt */ + writel(0, &lslave->regs->dmacr); /* do not do DMAs */ + writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */ + return &lslave->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave); + + debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave); + free(lslave); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + /* only one bus and slave so far, always available */ + return 0; +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave); + int bytelen = bitlen >> 3; + int idx_out = 0; + int idx_in = 0; + int start_time; + + start_time = get_timer(0); + while ((idx_out < bytelen) || (idx_in < bytelen)) { + int status = readl(&lslave->regs->sr); + if ((idx_out < bytelen) && (status & SSP_SR_TNF)) + writel(((u8 *)dout)[idx_out++], &lslave->regs->data); + if ((idx_in < bytelen) && (status & status & SSP_SR_RNE)) + ((u8 *)din)[idx_in++] = readl(&lslave->regs->data); + if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT) + return -1; + } + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + /* do nothing */ +} diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index 857b60455a..3356c0f072 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -109,10 +109,17 @@ static void ti_spi_setup_spi_register(struct ti_qspi_slave *qslave) slave->op_mode_rx = 8; #endif +#ifdef CONFIG_QSPI_QUAD_SUPPORT + memval |= (QSPI_CMD_READ_QUAD | QSPI_SETUP0_NUM_A_BYTES | + QSPI_SETUP0_NUM_D_BYTES_8_BITS | + QSPI_SETUP0_READ_QUAD | QSPI_CMD_WRITE | + QSPI_NUM_DUMMY_BITS); +#else memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES | QSPI_SETUP0_NUM_D_BYTES_NO_BITS | QSPI_SETUP0_READ_NORMAL | QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS; +#endif writel(memval, &qslave->base->setup0); } |