GPIO operations, you should be able to leverage that for better
speed with a custom version of this driver; see the source code.
+++++config SPI_IMG_SPFI
+++++ tristate "IMG SPFI controller"
+++++ depends on MIPS || COMPILE_TEST
+++++ help
+++++ This enables support for the SPFI master controller found on
+++++ IMG SoCs.
+++++
config SPI_IMX
tristate "Freescale i.MX SPI controllers"
depends on ARCH_MXC || COMPILE_TEST
From MPC8536, 85xx platform uses the controller, and all P10xx,
P20xx, P30xx,P40xx, P50xx uses this controller.
+++++config SPI_MESON_SPIFC
+++++ tristate "Amlogic Meson SPIFC controller"
+++++ depends on ARCH_MESON || COMPILE_TEST
+++++ select REGMAP_MMIO
+++++ help
+++++ This enables master mode support for the SPIFC (SPI flash
+++++ controller) available in Amlogic Meson SoCs.
+++++
config SPI_OC_TINY
tristate "OpenCores tiny SPI"
depends on GPIOLIB
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
---- - depends on PLAT_SAMSUNG
++++ + depends on (PLAT_SAMSUNG || ARCH_EXYNOS)
select S3C64XX_PL080 if ARCH_S3C64XX
help
SPI driver for Samsung S3C64XX and newer SoCs.
#define RXBUSY (1 << 0)
#define TXBUSY (1 << 1)
+ +++/* sclk_out: spi master internal logic in rk3x can support 50Mhz */
+ +++#define MAX_SCLK_OUT 50000000
+ +++
enum rockchip_ssi_type {
SSI_MOTO_SPI = 0,
SSI_TI_SSP,
spin_unlock_irqrestore(&rs->lock, flags);
+ +++ spi_enable_chip(rs, 0);
+ +++
return 0;
}
if (rs->tx)
wait_for_idle(rs);
+ +++ spi_enable_chip(rs, 0);
+ +++
return 0;
}
spin_lock_irqsave(&rs->lock, flags);
rs->state &= ~RXBUSY;
- --- if (!(rs->state & TXBUSY))
+ +++ if (!(rs->state & TXBUSY)) {
+ +++ spi_enable_chip(rs, 0);
spi_finalize_current_transfer(rs->master);
+ +++ }
spin_unlock_irqrestore(&rs->lock, flags);
}
spin_lock_irqsave(&rs->lock, flags);
rs->state &= ~TXBUSY;
- --- if (!(rs->state & RXBUSY))
+ +++ if (!(rs->state & RXBUSY)) {
+ +++ spi_enable_chip(rs, 0);
spi_finalize_current_transfer(rs->master);
+ +++ }
spin_unlock_irqrestore(&rs->lock, flags);
}
dmacr |= RF_DMA_EN;
}
+ +++ if (WARN_ON(rs->speed > MAX_SCLK_OUT))
+ +++ rs->speed = MAX_SCLK_OUT;
+ +++
+ +++ /* the minimum divsor is 2 */
+ +++ if (rs->max_freq < 2 * rs->speed) {
+ +++ clk_set_rate(rs->spiclk, 2 * rs->speed);
+ +++ rs->max_freq = clk_get_rate(rs->spiclk);
+ +++ }
+ +++
/* div doesn't support odd number */
div = max_t(u32, rs->max_freq / rs->speed, 1);
div = (div + 1) & 0xfffe;
- --- spi_enable_chip(rs, 0);
- ---
writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
spi_set_clk(rs, div);
dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div);
- ---
- --- spi_enable_chip(rs, 1);
}
static int rockchip_spi_transfer_one(
struct spi_device *spi,
struct spi_transfer *xfer)
{
- --- int ret = 0;
+ +++ int ret = 1;
struct rockchip_spi *rs = spi_master_get_devdata(master);
WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
rs->tmode = CR0_XFM_RO;
/* we need prepare dma before spi was enabled */
- --- if (master->can_dma && master->can_dma(master, spi, xfer)) {
+ +++ if (master->can_dma && master->can_dma(master, spi, xfer))
rs->use_dma = 1;
- --- rockchip_spi_prepare_dma(rs);
- --- } else {
+ +++ else
rs->use_dma = 0;
- --- }
rockchip_spi_config(rs);
- --- if (!rs->use_dma)
+ +++ if (rs->use_dma) {
+ +++ if (rs->tmode == CR0_XFM_RO) {
+ +++ /* rx: dma must be prepared first */
+ +++ rockchip_spi_prepare_dma(rs);
+ +++ spi_enable_chip(rs, 1);
+ +++ } else {
+ +++ /* tx or tr: spi must be enabled first */
+ +++ spi_enable_chip(rs, 1);
+ +++ rockchip_spi_prepare_dma(rs);
+ +++ }
+ +++ } else {
+ +++ spi_enable_chip(rs, 1);
ret = rockchip_spi_pio_transfer(rs);
+ +++ }
return ret;
}
if (rs->dma_rx.ch)
dma_release_channel(rs->dma_rx.ch);
--- -- spi_master_put(master);
--- --
return 0;
}
#include <linux/dmaengine.h>
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
+++++ #include <linux/reset.h>
#define DRIVER_NAME "sirfsoc_spi"
ALIGNED(x->len) && (x->len < 2 * PAGE_SIZE))
#define SIRFSOC_MAX_CMD_BYTES 4
+++++ #define SIRFSOC_SPI_DEFAULT_FRQ 1000000
struct sirfsoc_spi {
struct spi_bitbang bitbang;
sspi->word_width = DIV_ROUND_UP(bits_per_word, 8);
txfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
----- sspi->word_width;
+++++ (sspi->word_width >> 1);
rxfifo_ctrl = SIRFSOC_SPI_FIFO_THD(SIRFSOC_SPI_FIFO_SIZE / 2) |
----- sspi->word_width;
+++++ (sspi->word_width >> 1);
if (!(spi->mode & SPI_CS_HIGH))
regval |= SIRFSOC_SPI_CS_IDLE_STAT;
{
struct sirfsoc_spi *sspi;
----- if (!spi->max_speed_hz)
----- return -EINVAL;
-----
sspi = spi_master_get_devdata(spi->master);
if (spi->cs_gpio == -ENOENT)
int irq;
int i, ret;
+++++ ret = device_reset(&pdev->dev);
+++++ if (ret) {
+++++ dev_err(&pdev->dev, "SPI reset failed!\n");
+++++ return ret;
+++++ }
+++++
master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
if (!master) {
dev_err(&pdev->dev, "Unable to allocate SPI master\n");
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) |
SPI_BPW_MASK(16) | SPI_BPW_MASK(32);
+++++ master->max_speed_hz = SIRFSOC_SPI_DEFAULT_FRQ;
sspi->bitbang.master->dev.of_node = pdev->dev.of_node;
/* request DMA channels */