diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7183be8a3c92..ec40a27a4b76 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -395,16 +395,9 @@ config SPI_PPC4xx help This selects a driver for the PPC4xx SPI Controller. -config SPI_PXA2XX_PXADMA - bool "PXA2xx SSP legacy PXA DMA API support" - depends on SPI_PXA2XX && ARCH_PXA - help - Enable PXA private legacy DMA API support. Note that this is - deprecated in favor of generic DMA engine API. - config SPI_PXA2XX_DMA def_bool y - depends on SPI_PXA2XX && !SPI_PXA2XX_PXADMA + depends on SPI_PXA2XX config SPI_PXA2XX tristate "PXA2xx SSP SPI master" @@ -430,6 +423,12 @@ config SPI_ROCKCHIP The main usecase of this controller is to use spi flash as boot device. +config SPI_RB4XX + tristate "Mikrotik RB4XX SPI master" + depends on SPI_MASTER && ATH79 + help + SPI controller driver for the Mikrotik RB4xx series boards. + config SPI_RSPI tristate "Renesas RSPI/QSPI controller" depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index d8cbf654976b..2e7089fbc799 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -60,12 +60,12 @@ obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o spi-pxa2xx-platform-objs := spi-pxa2xx.o -spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_PXADMA) += spi-pxa2xx-pxadma.o spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_QUP) += spi-qup.o obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o +obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o obj-$(CONFIG_SPI_RSPI) += spi-rspi.o obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o spi-s3c24xx-hw-y := spi-s3c24xx.o diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index fa7399e84bbb..3cfd4357489a 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -62,7 +62,7 @@ static struct pxa_spi_info spi_info_configs[] = { .max_clk_rate = 3686400, }, [PORT_BYT] = { - .type = LPSS_SSP, + .type = LPSS_BYT_SSP, .port_id = 0, .num_chipselect = 1, .max_clk_rate = 50000000, @@ -70,7 +70,7 @@ static struct pxa_spi_info spi_info_configs[] = { .rx_param = &byt_rx_param, }, [PORT_BSW0] = { - .type = LPSS_SSP, + .type = LPSS_BYT_SSP, .port_id = 0, .num_chipselect = 1, .max_clk_rate = 50000000, @@ -78,7 +78,7 @@ static struct pxa_spi_info spi_info_configs[] = { .rx_param = &bsw0_rx_param, }, [PORT_BSW1] = { - .type = LPSS_SSP, + .type = LPSS_BYT_SSP, .port_id = 1, .num_chipselect = 1, .max_clk_rate = 50000000, @@ -86,7 +86,7 @@ static struct pxa_spi_info spi_info_configs[] = { .rx_param = &bsw1_rx_param, }, [PORT_BSW2] = { - .type = LPSS_SSP, + .type = LPSS_BYT_SSP, .port_id = 2, .num_chipselect = 1, .max_clk_rate = 50000000, diff --git a/drivers/spi/spi-pxa2xx-pxadma.c b/drivers/spi/spi-pxa2xx-pxadma.c deleted file mode 100644 index 2e0796a0003f..000000000000 --- a/drivers/spi/spi-pxa2xx-pxadma.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * PXA2xx SPI private DMA support. - * - * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include "spi-pxa2xx.h" - -#define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) -#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) - -bool pxa2xx_spi_dma_is_possible(size_t len) -{ - /* Try to map dma buffer and do a dma transfer if successful, but - * only if the length is non-zero and less than MAX_DMA_LEN. - * - * Zero-length non-descriptor DMA is illegal on PXA2xx; force use - * of PIO instead. Care is needed above because the transfer may - * have have been passed with buffers that are already dma mapped. - * A zero-length transfer in PIO mode will not try to write/read - * to/from the buffers - * - * REVISIT large transfers are exactly where we most want to be - * using DMA. If this happens much, split those transfers into - * multiple DMA segments rather than forcing PIO. - */ - return len > 0 && len <= MAX_DMA_LEN; -} - -int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data) -{ - struct spi_message *msg = drv_data->cur_msg; - struct device *dev = &msg->spi->dev; - - if (!drv_data->cur_chip->enable_dma) - return 0; - - if (msg->is_dma_mapped) - return drv_data->rx_dma && drv_data->tx_dma; - - if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx)) - return 0; - - /* Modify setup if rx buffer is null */ - if (drv_data->rx == NULL) { - *drv_data->null_dma_buf = 0; - drv_data->rx = drv_data->null_dma_buf; - drv_data->rx_map_len = 4; - } else - drv_data->rx_map_len = drv_data->len; - - - /* Modify setup if tx buffer is null */ - if (drv_data->tx == NULL) { - *drv_data->null_dma_buf = 0; - drv_data->tx = drv_data->null_dma_buf; - drv_data->tx_map_len = 4; - } else - drv_data->tx_map_len = drv_data->len; - - /* Stream map the tx buffer. Always do DMA_TO_DEVICE first - * so we flush the cache *before* invalidating it, in case - * the tx and rx buffers overlap. - */ - drv_data->tx_dma = dma_map_single(dev, drv_data->tx, - drv_data->tx_map_len, DMA_TO_DEVICE); - if (dma_mapping_error(dev, drv_data->tx_dma)) - return 0; - - /* Stream map the rx buffer */ - drv_data->rx_dma = dma_map_single(dev, drv_data->rx, - drv_data->rx_map_len, DMA_FROM_DEVICE); - if (dma_mapping_error(dev, drv_data->rx_dma)) { - dma_unmap_single(dev, drv_data->tx_dma, - drv_data->tx_map_len, DMA_TO_DEVICE); - return 0; - } - - return 1; -} - -static void pxa2xx_spi_unmap_dma_buffers(struct driver_data *drv_data) -{ - struct device *dev; - - if (!drv_data->dma_mapped) - return; - - if (!drv_data->cur_msg->is_dma_mapped) { - dev = &drv_data->cur_msg->spi->dev; - dma_unmap_single(dev, drv_data->rx_dma, - drv_data->rx_map_len, DMA_FROM_DEVICE); - dma_unmap_single(dev, drv_data->tx_dma, - drv_data->tx_map_len, DMA_TO_DEVICE); - } - - drv_data->dma_mapped = 0; -} - -static int wait_ssp_rx_stall(struct driver_data *drv_data) -{ - unsigned long limit = loops_per_jiffy << 1; - - while ((pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY) && --limit) - cpu_relax(); - - return limit; -} - -static int wait_dma_channel_stop(int channel) -{ - unsigned long limit = loops_per_jiffy << 1; - - while (!(DCSR(channel) & DCSR_STOPSTATE) && --limit) - cpu_relax(); - - return limit; -} - -static void pxa2xx_spi_dma_error_stop(struct driver_data *drv_data, - const char *msg) -{ - /* Stop and reset */ - DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; - DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; - write_SSSR_CS(drv_data, drv_data->clear_sr); - pxa2xx_spi_write(drv_data, SSCR1, - pxa2xx_spi_read(drv_data, SSCR1) - & ~drv_data->dma_cr1); - if (!pxa25x_ssp_comp(drv_data)) - pxa2xx_spi_write(drv_data, SSTO, 0); - pxa2xx_spi_flush(drv_data); - pxa2xx_spi_write(drv_data, SSCR0, - pxa2xx_spi_read(drv_data, SSCR0) & ~SSCR0_SSE); - - pxa2xx_spi_unmap_dma_buffers(drv_data); - - dev_err(&drv_data->pdev->dev, "%s\n", msg); - - drv_data->cur_msg->state = ERROR_STATE; - tasklet_schedule(&drv_data->pump_transfers); -} - -static void pxa2xx_spi_dma_transfer_complete(struct driver_data *drv_data) -{ - struct spi_message *msg = drv_data->cur_msg; - - /* Clear and disable interrupts on SSP and DMA channels*/ - pxa2xx_spi_write(drv_data, SSCR1, - pxa2xx_spi_read(drv_data, SSCR1) - & ~drv_data->dma_cr1); - write_SSSR_CS(drv_data, drv_data->clear_sr); - DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; - DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; - - if (wait_dma_channel_stop(drv_data->rx_channel) == 0) - dev_err(&drv_data->pdev->dev, - "dma_handler: dma rx channel stop failed\n"); - - if (wait_ssp_rx_stall(drv_data->ioaddr) == 0) - dev_err(&drv_data->pdev->dev, - "dma_transfer: ssp rx stall failed\n"); - - pxa2xx_spi_unmap_dma_buffers(drv_data); - - /* update the buffer pointer for the amount completed in dma */ - drv_data->rx += drv_data->len - - (DCMD(drv_data->rx_channel) & DCMD_LENGTH); - - /* read trailing data from fifo, it does not matter how many - * bytes are in the fifo just read until buffer is full - * or fifo is empty, which ever occurs first */ - drv_data->read(drv_data); - - /* return count of what was actually read */ - msg->actual_length += drv_data->len - - (drv_data->rx_end - drv_data->rx); - - /* Transfer delays and chip select release are - * handled in pump_transfers or giveback - */ - - /* Move to next transfer */ - msg->state = pxa2xx_spi_next_transfer(drv_data); - - /* Schedule transfer tasklet */ - tasklet_schedule(&drv_data->pump_transfers); -} - -void pxa2xx_spi_dma_handler(int channel, void *data) -{ - struct driver_data *drv_data = data; - u32 irq_status = DCSR(channel) & DMA_INT_MASK; - - if (irq_status & DCSR_BUSERR) { - - if (channel == drv_data->tx_channel) - pxa2xx_spi_dma_error_stop(drv_data, - "dma_handler: bad bus address on tx channel"); - else - pxa2xx_spi_dma_error_stop(drv_data, - "dma_handler: bad bus address on rx channel"); - return; - } - - /* PXA255x_SSP has no timeout interrupt, wait for tailing bytes */ - if ((channel == drv_data->tx_channel) - && (irq_status & DCSR_ENDINTR) - && (drv_data->ssp_type == PXA25x_SSP)) { - - /* Wait for rx to stall */ - if (wait_ssp_rx_stall(drv_data) == 0) - dev_err(&drv_data->pdev->dev, - "dma_handler: ssp rx stall failed\n"); - - /* finish this transfer, start the next */ - pxa2xx_spi_dma_transfer_complete(drv_data); - } -} - -irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data) -{ - u32 irq_status; - - irq_status = pxa2xx_spi_read(drv_data, SSSR) & drv_data->mask_sr; - if (irq_status & SSSR_ROR) { - pxa2xx_spi_dma_error_stop(drv_data, - "dma_transfer: fifo overrun"); - return IRQ_HANDLED; - } - - /* Check for false positive timeout */ - if ((irq_status & SSSR_TINT) - && (DCSR(drv_data->tx_channel) & DCSR_RUN)) { - pxa2xx_spi_write(drv_data, SSSR, SSSR_TINT); - return IRQ_HANDLED; - } - - if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { - - /* Clear and disable timeout interrupt, do the rest in - * dma_transfer_complete */ - if (!pxa25x_ssp_comp(drv_data)) - pxa2xx_spi_write(drv_data, SSTO, 0); - - /* finish this transfer, start the next */ - pxa2xx_spi_dma_transfer_complete(drv_data); - - return IRQ_HANDLED; - } - - /* Opps problem detected */ - return IRQ_NONE; -} - -int pxa2xx_spi_dma_prepare(struct driver_data *drv_data, u32 dma_burst) -{ - u32 dma_width; - - switch (drv_data->n_bytes) { - case 1: - dma_width = DCMD_WIDTH1; - break; - case 2: - dma_width = DCMD_WIDTH2; - break; - default: - dma_width = DCMD_WIDTH4; - break; - } - - /* Setup rx DMA Channel */ - DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; - DSADR(drv_data->rx_channel) = drv_data->ssdr_physical; - DTADR(drv_data->rx_channel) = drv_data->rx_dma; - if (drv_data->rx == drv_data->null_dma_buf) - /* No target address increment */ - DCMD(drv_data->rx_channel) = DCMD_FLOWSRC - | dma_width - | dma_burst - | drv_data->len; - else - DCMD(drv_data->rx_channel) = DCMD_INCTRGADDR - | DCMD_FLOWSRC - | dma_width - | dma_burst - | drv_data->len; - - /* Setup tx DMA Channel */ - DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; - DSADR(drv_data->tx_channel) = drv_data->tx_dma; - DTADR(drv_data->tx_channel) = drv_data->ssdr_physical; - if (drv_data->tx == drv_data->null_dma_buf) - /* No source address increment */ - DCMD(drv_data->tx_channel) = DCMD_FLOWTRG - | dma_width - | dma_burst - | drv_data->len; - else - DCMD(drv_data->tx_channel) = DCMD_INCSRCADDR - | DCMD_FLOWTRG - | dma_width - | dma_burst - | drv_data->len; - - /* Enable dma end irqs on SSP to detect end of transfer */ - if (drv_data->ssp_type == PXA25x_SSP) - DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN; - - return 0; -} - -void pxa2xx_spi_dma_start(struct driver_data *drv_data) -{ - DCSR(drv_data->rx_channel) |= DCSR_RUN; - DCSR(drv_data->tx_channel) |= DCSR_RUN; -} - -int pxa2xx_spi_dma_setup(struct driver_data *drv_data) -{ - struct device *dev = &drv_data->pdev->dev; - struct ssp_device *ssp = drv_data->ssp; - - /* Get two DMA channels (rx and tx) */ - drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx", - DMA_PRIO_HIGH, - pxa2xx_spi_dma_handler, - drv_data); - if (drv_data->rx_channel < 0) { - dev_err(dev, "problem (%d) requesting rx channel\n", - drv_data->rx_channel); - return -ENODEV; - } - drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx", - DMA_PRIO_MEDIUM, - pxa2xx_spi_dma_handler, - drv_data); - if (drv_data->tx_channel < 0) { - dev_err(dev, "problem (%d) requesting tx channel\n", - drv_data->tx_channel); - pxa_free_dma(drv_data->rx_channel); - return -ENODEV; - } - - DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel; - DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel; - - return 0; -} - -void pxa2xx_spi_dma_release(struct driver_data *drv_data) -{ - struct ssp_device *ssp = drv_data->ssp; - - DRCMR(ssp->drcmr_rx) = 0; - DRCMR(ssp->drcmr_tx) = 0; - - if (drv_data->tx_channel != 0) - pxa_free_dma(drv_data->tx_channel); - if (drv_data->rx_channel != 0) - pxa_free_dma(drv_data->rx_channel); -} - -void pxa2xx_spi_dma_resume(struct driver_data *drv_data) -{ - if (drv_data->rx_channel != -1) - DRCMR(drv_data->ssp->drcmr_rx) = - DRCMR_MAPVLD | drv_data->rx_channel; - if (drv_data->tx_channel != -1) - DRCMR(drv_data->ssp->drcmr_tx) = - DRCMR_MAPVLD | drv_data->tx_channel; -} - -int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip, - struct spi_device *spi, - u8 bits_per_word, u32 *burst_code, - u32 *threshold) -{ - struct pxa2xx_spi_chip *chip_info = - (struct pxa2xx_spi_chip *)spi->controller_data; - int bytes_per_word; - int burst_bytes; - int thresh_words; - int req_burst_size; - int retval = 0; - - /* Set the threshold (in registers) to equal the same amount of data - * as represented by burst size (in bytes). The computation below - * is (burst_size rounded up to nearest 8 byte, word or long word) - * divided by (bytes/register); the tx threshold is the inverse of - * the rx, so that there will always be enough data in the rx fifo - * to satisfy a burst, and there will always be enough space in the - * tx fifo to accept a burst (a tx burst will overwrite the fifo if - * there is not enough space), there must always remain enough empty - * space in the rx fifo for any data loaded to the tx fifo. - * Whenever burst_size (in bytes) equals bits/word, the fifo threshold - * will be 8, or half the fifo; - * The threshold can only be set to 2, 4 or 8, but not 16, because - * to burst 16 to the tx fifo, the fifo would have to be empty; - * however, the minimum fifo trigger level is 1, and the tx will - * request service when the fifo is at this level, with only 15 spaces. - */ - - /* find bytes/word */ - if (bits_per_word <= 8) - bytes_per_word = 1; - else if (bits_per_word <= 16) - bytes_per_word = 2; - else - bytes_per_word = 4; - - /* use struct pxa2xx_spi_chip->dma_burst_size if available */ - if (chip_info) - req_burst_size = chip_info->dma_burst_size; - else { - switch (chip->dma_burst_size) { - default: - /* if the default burst size is not set, - * do it now */ - chip->dma_burst_size = DCMD_BURST8; - case DCMD_BURST8: - req_burst_size = 8; - break; - case DCMD_BURST16: - req_burst_size = 16; - break; - case DCMD_BURST32: - req_burst_size = 32; - break; - } - } - if (req_burst_size <= 8) { - *burst_code = DCMD_BURST8; - burst_bytes = 8; - } else if (req_burst_size <= 16) { - if (bytes_per_word == 1) { - /* don't burst more than 1/2 the fifo */ - *burst_code = DCMD_BURST8; - burst_bytes = 8; - retval = 1; - } else { - *burst_code = DCMD_BURST16; - burst_bytes = 16; - } - } else { - if (bytes_per_word == 1) { - /* don't burst more than 1/2 the fifo */ - *burst_code = DCMD_BURST8; - burst_bytes = 8; - retval = 1; - } else if (bytes_per_word == 2) { - /* don't burst more than 1/2 the fifo */ - *burst_code = DCMD_BURST16; - burst_bytes = 16; - retval = 1; - } else { - *burst_code = DCMD_BURST32; - burst_bytes = 32; - } - } - - thresh_words = burst_bytes / bytes_per_word; - - /* thresh_words will be between 2 and 8 */ - *threshold = (SSCR1_RxTresh(thresh_words) & SSCR1_RFT) - | (SSCR1_TxTresh(16-thresh_words) & SSCR1_TFT); - - return retval; -} diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index e3223ac75a7c..7293d6d875c5 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -60,21 +60,60 @@ MODULE_ALIAS("platform:pxa2xx-spi"); | QUARK_X1000_SSCR1_TFT \ | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) -#define LPSS_RX_THRESH_DFLT 64 -#define LPSS_TX_LOTHRESH_DFLT 160 -#define LPSS_TX_HITHRESH_DFLT 224 - -/* Offset from drv_data->lpss_base */ -#define GENERAL_REG 0x08 #define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) -#define SSP_REG 0x0c -#define SPI_CS_CONTROL 0x18 #define SPI_CS_CONTROL_SW_MODE BIT(0) #define SPI_CS_CONTROL_CS_HIGH BIT(1) +struct lpss_config { + /* LPSS offset from drv_data->ioaddr */ + unsigned offset; + /* Register offsets from drv_data->lpss_base or -1 */ + int reg_general; + int reg_ssp; + int reg_cs_ctrl; + /* FIFO thresholds */ + u32 rx_threshold; + u32 tx_threshold_lo; + u32 tx_threshold_hi; +}; + +/* Keep these sorted with enum pxa_ssp_type */ +static const struct lpss_config lpss_platforms[] = { + { /* LPSS_LPT_SSP */ + .offset = 0x800, + .reg_general = 0x08, + .reg_ssp = 0x0c, + .reg_cs_ctrl = 0x18, + .rx_threshold = 64, + .tx_threshold_lo = 160, + .tx_threshold_hi = 224, + }, + { /* LPSS_BYT_SSP */ + .offset = 0x400, + .reg_general = 0x08, + .reg_ssp = 0x0c, + .reg_cs_ctrl = 0x18, + .rx_threshold = 64, + .tx_threshold_lo = 160, + .tx_threshold_hi = 224, + }, +}; + +static inline const struct lpss_config +*lpss_get_config(const struct driver_data *drv_data) +{ + return &lpss_platforms[drv_data->ssp_type - LPSS_LPT_SSP]; +} + static bool is_lpss_ssp(const struct driver_data *drv_data) { - return drv_data->ssp_type == LPSS_SSP; + switch (drv_data->ssp_type) { + case LPSS_LPT_SSP: + case LPSS_BYT_SSP: + return true; + default: + return false; + } } static bool is_quark_x1000_ssp(const struct driver_data *drv_data) @@ -192,63 +231,43 @@ static void __lpss_ssp_write_priv(struct driver_data *drv_data, */ static void lpss_ssp_setup(struct driver_data *drv_data) { - unsigned offset = 0x400; - u32 value, orig; + const struct lpss_config *config; + u32 value; - /* - * Perform auto-detection of the LPSS SSP private registers. They - * can be either at 1k or 2k offset from the base address. - */ - orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); - - /* Test SPI_CS_CONTROL_SW_MODE bit enabling */ - value = orig | SPI_CS_CONTROL_SW_MODE; - writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); - value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); - if (value != (orig | SPI_CS_CONTROL_SW_MODE)) { - offset = 0x800; - goto detection_done; - } - - orig = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); - - /* Test SPI_CS_CONTROL_SW_MODE bit disabling */ - value = orig & ~SPI_CS_CONTROL_SW_MODE; - writel(value, drv_data->ioaddr + offset + SPI_CS_CONTROL); - value = readl(drv_data->ioaddr + offset + SPI_CS_CONTROL); - if (value != (orig & ~SPI_CS_CONTROL_SW_MODE)) { - offset = 0x800; - goto detection_done; - } - -detection_done: - /* Now set the LPSS base */ - drv_data->lpss_base = drv_data->ioaddr + offset; + config = lpss_get_config(drv_data); + drv_data->lpss_base = drv_data->ioaddr + config->offset; /* Enable software chip select control */ value = SPI_CS_CONTROL_SW_MODE | SPI_CS_CONTROL_CS_HIGH; - __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); + __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); /* Enable multiblock DMA transfers */ if (drv_data->master_info->enable_dma) { - __lpss_ssp_write_priv(drv_data, SSP_REG, 1); + __lpss_ssp_write_priv(drv_data, config->reg_ssp, 1); - value = __lpss_ssp_read_priv(drv_data, GENERAL_REG); - value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE; - __lpss_ssp_write_priv(drv_data, GENERAL_REG, value); + if (config->reg_general >= 0) { + value = __lpss_ssp_read_priv(drv_data, + config->reg_general); + value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE; + __lpss_ssp_write_priv(drv_data, + config->reg_general, value); + } } } static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) { + const struct lpss_config *config; u32 value; - value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL); + config = lpss_get_config(drv_data); + + value = __lpss_ssp_read_priv(drv_data, config->reg_cs_ctrl); if (enable) value &= ~SPI_CS_CONTROL_CS_HIGH; else value |= SPI_CS_CONTROL_CS_HIGH; - __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); + __lpss_ssp_write_priv(drv_data, config->reg_cs_ctrl, value); } static void cs_assert(struct driver_data *drv_data) @@ -1075,6 +1094,7 @@ static int setup(struct spi_device *spi) { struct pxa2xx_spi_chip *chip_info = NULL; struct chip_data *chip; + const struct lpss_config *config; struct driver_data *drv_data = spi_master_get_devdata(spi->master); unsigned int clk_div; uint tx_thres, tx_hi_thres, rx_thres; @@ -1085,10 +1105,12 @@ static int setup(struct spi_device *spi) tx_hi_thres = 0; rx_thres = RX_THRESH_QUARK_X1000_DFLT; break; - case LPSS_SSP: - tx_thres = LPSS_TX_LOTHRESH_DFLT; - tx_hi_thres = LPSS_TX_HITHRESH_DFLT; - rx_thres = LPSS_RX_THRESH_DFLT; + case LPSS_LPT_SSP: + case LPSS_BYT_SSP: + config = lpss_get_config(drv_data); + tx_thres = config->tx_threshold_lo; + tx_hi_thres = config->tx_threshold_hi; + rx_thres = config->rx_threshold; break; default: tx_thres = TX_THRESH_DFLT; @@ -1242,6 +1264,18 @@ static void cleanup(struct spi_device *spi) } #ifdef CONFIG_ACPI + +static const struct acpi_device_id pxa2xx_spi_acpi_match[] = { + { "INT33C0", LPSS_LPT_SSP }, + { "INT33C1", LPSS_LPT_SSP }, + { "INT3430", LPSS_LPT_SSP }, + { "INT3431", LPSS_LPT_SSP }, + { "80860F0E", LPSS_BYT_SSP }, + { "8086228E", LPSS_BYT_SSP }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); + static struct pxa2xx_spi_master * pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) { @@ -1249,12 +1283,19 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) struct acpi_device *adev; struct ssp_device *ssp; struct resource *res; - int devid; + const struct acpi_device_id *id; + int devid, type; if (!ACPI_HANDLE(&pdev->dev) || acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) return NULL; + id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); + if (id) + type = (int)id->driver_data; + else + return NULL; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; @@ -1272,7 +1313,7 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) ssp->clk = devm_clk_get(&pdev->dev, NULL); ssp->irq = platform_get_irq(pdev, 0); - ssp->type = LPSS_SSP; + ssp->type = type; ssp->pdev = pdev; ssp->port_id = -1; @@ -1285,16 +1326,6 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) return pdata; } -static struct acpi_device_id pxa2xx_spi_acpi_match[] = { - { "INT33C0", 0 }, - { "INT33C1", 0 }, - { "INT3430", 0 }, - { "INT3431", 0 }, - { "80860F0E", 0 }, - { "8086228E", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); #else static inline struct pxa2xx_spi_master * pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 85a58c906869..9f01e9c9aa75 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -162,11 +162,7 @@ extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data); /* * Select the right DMA implementation. */ -#if defined(CONFIG_SPI_PXA2XX_PXADMA) -#define SPI_PXA2XX_USE_DMA 1 -#define MAX_DMA_LEN 8191 -#define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TINTE) -#elif defined(CONFIG_SPI_PXA2XX_DMA) +#if defined(CONFIG_SPI_PXA2XX_DMA) #define SPI_PXA2XX_USE_DMA 1 #define MAX_DMA_LEN SZ_64K #define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL) diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c new file mode 100644 index 000000000000..3641d0e20135 --- /dev/null +++ b/drivers/spi/spi-rb4xx.c @@ -0,0 +1,210 @@ +/* + * SPI controller driver for the Mikrotik RB4xx boards + * + * Copyright (C) 2010 Gabor Juhos + * Copyright (C) 2015 Bert Vermeulen + * + * This file was based on the patches for Linux 2.6.27.39 published by + * MikroTik for their RouterBoard 4xx series devices. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +struct rb4xx_spi { + void __iomem *base; + struct clk *clk; +}; + +static inline u32 rb4xx_read(struct rb4xx_spi *rbspi, u32 reg) +{ + return __raw_readl(rbspi->base + reg); +} + +static inline void rb4xx_write(struct rb4xx_spi *rbspi, u32 reg, u32 value) +{ + __raw_writel(value, rbspi->base + reg); +} + +static inline void do_spi_clk(struct rb4xx_spi *rbspi, u32 spi_ioc, int value) +{ + u32 regval; + + regval = spi_ioc; + if (value & BIT(0)) + regval |= AR71XX_SPI_IOC_DO; + + rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval); + rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK); +} + +static void do_spi_byte(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte) +{ + int i; + + for (i = 7; i >= 0; i--) + do_spi_clk(rbspi, spi_ioc, byte >> i); +} + +/* The CS2 pin is used to clock in a second bit per clock cycle. */ +static inline void do_spi_clk_two(struct rb4xx_spi *rbspi, u32 spi_ioc, + u8 value) +{ + u32 regval; + + regval = spi_ioc; + if (value & BIT(1)) + regval |= AR71XX_SPI_IOC_DO; + if (value & BIT(0)) + regval |= AR71XX_SPI_IOC_CS2; + + rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval); + rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, regval | AR71XX_SPI_IOC_CLK); +} + +/* Two bits at a time, msb first */ +static void do_spi_byte_two(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte) +{ + do_spi_clk_two(rbspi, spi_ioc, byte >> 6); + do_spi_clk_two(rbspi, spi_ioc, byte >> 4); + do_spi_clk_two(rbspi, spi_ioc, byte >> 2); + do_spi_clk_two(rbspi, spi_ioc, byte >> 0); +} + +static void rb4xx_set_cs(struct spi_device *spi, bool enable) +{ + struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master); + + /* + * Setting CS is done along with bitbanging the actual values, + * since it's all on the same hardware register. However the + * CPLD needs CS deselected after every command. + */ + if (enable) + rb4xx_write(rbspi, AR71XX_SPI_REG_IOC, + AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1); +} + +static int rb4xx_transfer_one(struct spi_master *master, + struct spi_device *spi, struct spi_transfer *t) +{ + struct rb4xx_spi *rbspi = spi_master_get_devdata(master); + int i; + u32 spi_ioc; + u8 *rx_buf; + const u8 *tx_buf; + + /* + * Prime the SPI register with the SPI device selected. The m25p80 boot + * flash and CPLD share the CS0 pin. This works because the CPLD's + * command set was designed to almost not clash with that of the + * boot flash. + */ + if (spi->chip_select == 2) + /* MMC */ + spi_ioc = AR71XX_SPI_IOC_CS0; + else + /* Boot flash and CPLD */ + spi_ioc = AR71XX_SPI_IOC_CS1; + + tx_buf = t->tx_buf; + rx_buf = t->rx_buf; + for (i = 0; i < t->len; ++i) { + if (t->tx_nbits == SPI_NBITS_DUAL) + /* CPLD can use two-wire transfers */ + do_spi_byte_two(rbspi, spi_ioc, tx_buf[i]); + else + do_spi_byte(rbspi, spi_ioc, tx_buf[i]); + if (!rx_buf) + continue; + rx_buf[i] = rb4xx_read(rbspi, AR71XX_SPI_REG_RDS); + } + spi_finalize_current_transfer(master); + + return 0; +} + +static int rb4xx_spi_probe(struct platform_device *pdev) +{ + struct spi_master *master; + struct clk *ahb_clk; + struct rb4xx_spi *rbspi; + struct resource *r; + int err; + void __iomem *spi_base; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + spi_base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(spi_base)) + return PTR_ERR(spi_base); + + master = spi_alloc_master(&pdev->dev, sizeof(*rbspi)); + if (!master) + return -ENOMEM; + + ahb_clk = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(ahb_clk)) + return PTR_ERR(ahb_clk); + + master->bus_num = 0; + master->num_chipselect = 3; + master->mode_bits = SPI_TX_DUAL; + master->bits_per_word_mask = BIT(7); + master->flags = SPI_MASTER_MUST_TX; + master->transfer_one = rb4xx_transfer_one; + master->set_cs = rb4xx_set_cs; + + err = devm_spi_register_master(&pdev->dev, master); + if (err) { + dev_err(&pdev->dev, "failed to register SPI master\n"); + return err; + } + + err = clk_prepare_enable(ahb_clk); + if (err) + return err; + + rbspi = spi_master_get_devdata(master); + rbspi->base = spi_base; + rbspi->clk = ahb_clk; + platform_set_drvdata(pdev, rbspi); + + /* Enable SPI */ + rb4xx_write(rbspi, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); + + return 0; +} + +static int rb4xx_spi_remove(struct platform_device *pdev) +{ + struct rb4xx_spi *rbspi = platform_get_drvdata(pdev); + + clk_disable_unprepare(rbspi->clk); + + return 0; +} + +static struct platform_driver rb4xx_spi_drv = { + .probe = rb4xx_spi_probe, + .remove = rb4xx_spi_remove, + .driver = { + .name = "rb4xx-spi", + }, +}; + +module_platform_driver(rb4xx_spi_drv); + +MODULE_DESCRIPTION("Mikrotik RB4xx SPI controller driver"); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_AUTHOR("Bert Vermeulen "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index f6bac9e77d06..f9189a0c8cec 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -665,15 +665,12 @@ static bool rspi_can_dma(struct spi_master *master, struct spi_device *spi, static int rspi_dma_check_then_transfer(struct rspi_data *rspi, struct spi_transfer *xfer) { - if (rspi->master->can_dma && __rspi_can_dma(rspi, xfer)) { - /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ - int ret = rspi_dma_transfer(rspi, &xfer->tx_sg, - xfer->rx_buf ? &xfer->rx_sg : NULL); - if (ret != -EAGAIN) - return 0; - } + if (!rspi->master->can_dma || !__rspi_can_dma(rspi, xfer)) + return -EAGAIN; - return -EAGAIN; + /* rx_buf can be NULL on RSPI on SH in TX-only Mode */ + return rspi_dma_transfer(rspi, &xfer->tx_sg, + xfer->rx_buf ? &xfer->rx_sg : NULL); } static int rspi_common_transfer(struct rspi_data *rspi, @@ -724,7 +721,7 @@ static int rspi_rz_transfer_one(struct spi_master *master, return rspi_common_transfer(rspi, xfer); } -static int qspi_trigger_transfer_out_int(struct rspi_data *rspi, const u8 *tx, +static int qspi_trigger_transfer_out_in(struct rspi_data *rspi, const u8 *tx, u8 *rx, unsigned int len) { int i, n, ret; @@ -771,12 +768,8 @@ static int qspi_transfer_out_in(struct rspi_data *rspi, if (ret != -EAGAIN) return ret; - ret = qspi_trigger_transfer_out_int(rspi, xfer->tx_buf, + return qspi_trigger_transfer_out_in(rspi, xfer->tx_buf, xfer->rx_buf, xfer->len); - if (ret < 0) - return ret; - - return 0; } static int qspi_transfer_out(struct rspi_data *rspi, struct spi_transfer *xfer) @@ -1300,7 +1293,7 @@ error1: return ret; } -static struct platform_device_id spi_driver_ids[] = { +static const struct platform_device_id spi_driver_ids[] = { { "rspi", (kernel_ulong_t)&rspi_ops }, { "rspi-rz", (kernel_ulong_t)&rspi_rz_ops }, { "qspi", (kernel_ulong_t)&qspi_ops }, diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index b1c6731fbf27..2a8c513c4d07 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1347,7 +1347,7 @@ static struct s3c64xx_spi_port_config exynos7_spi_port_config = { .quirks = S3C64XX_SPI_QUIRK_CS_AUTO, }; -static struct platform_device_id s3c64xx_spi_driver_ids[] = { +static const struct platform_device_id s3c64xx_spi_driver_ids[] = { { .name = "s3c2443-spi", .driver_data = (kernel_ulong_t)&s3c2443_spi_port_config, diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index bcc7c635d8e7..d3370a612d84 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1263,7 +1263,7 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) return 0; } -static struct platform_device_id spi_driver_ids[] = { +static const struct platform_device_id spi_driver_ids[] = { { "spi_sh_msiof", (kernel_ulong_t)&sh_data }, { "spi_r8a7790_msiof", (kernel_ulong_t)&r8a779x_data }, { "spi_r8a7791_msiof", (kernel_ulong_t)&r8a779x_data }, diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index dab545bb66b3..0485bab061fd 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h @@ -194,8 +194,9 @@ enum pxa_ssp_type { PXA168_SSP, PXA910_SSP, CE4100_SSP, - LPSS_SSP, QUARK_X1000_SSP, + LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ + LPSS_BYT_SSP, }; struct ssp_device {