diff options
Diffstat (limited to 'drivers/spi/spi-davinci.c')
| -rw-r--r-- | drivers/spi/spi-davinci.c | 612 |
1 files changed, 322 insertions, 290 deletions
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 222d3e37fc28..21a14e800eed 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -1,45 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2009 Texas Instruments. * Copyright (C) 2010 EF Johnson Technologies - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/interrupt.h> #include <linux/io.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/delay.h> +#include <linux/platform_data/edma.h> #include <linux/platform_device.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> -#include <linux/edma.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/slab.h> -#include <linux/platform_data/spi-davinci.h> - -#define SPI_NO_RESOURCE ((resource_size_t)-1) - -#define SPI_MAX_CHIPSELECT 2 - #define CS_DEFAULT 0xFF #define SPIFMT_PHASE_MASK BIT(16) @@ -66,6 +46,7 @@ /* SPIDAT1 (upper 16 bit defines) */ #define SPIDAT1_CSHOLD_MASK BIT(12) +#define SPIDAT1_WDEL BIT(10) /* SPIGCR1 */ #define SPIGCR1_CLKMOD_MASK BIT(1) @@ -116,6 +97,69 @@ #define SPIDEF 0x4c #define SPIFMT0 0x50 +#define SPI_IO_TYPE_POLL 1 +#define SPI_IO_TYPE_DMA 2 + +#define DMA_MIN_BYTES 16 + +enum { + SPI_VERSION_1, /* For DM355/DM365/DM6467 */ + SPI_VERSION_2, /* For DA8xx */ +}; + +/** + * struct davinci_spi_platform_data - Platform data for SPI master device on DaVinci + * + * @version: version of the SPI IP. Different DaVinci devices have slightly + * varying versions of the same IP. + * @num_chipselect: number of chipselects supported by this SPI master + * @intr_line: interrupt line used to connect the SPI IP to the ARM interrupt + * controller withn the SoC. Possible values are 0 and 1. + * @prescaler_limit: max clock prescaler value + * @cshold_bug: set this to true if the SPI controller on your chip requires + * a write to CSHOLD bit in between transfers (like in DM355). + * @dma_event_q: DMA event queue to use if SPI_IO_TYPE_DMA is used for any + * device on the bus. + */ +struct davinci_spi_platform_data { + u8 version; + u8 num_chipselect; + u8 intr_line; + u8 prescaler_limit; + bool cshold_bug; + enum dma_event_q dma_event_q; +}; + +/** + * struct davinci_spi_config - Per-chip-select configuration for SPI slave devices + * + * @wdelay: amount of delay between transmissions. Measured in number of + * SPI module clocks. + * @odd_parity: polarity of parity flag at the end of transmit data stream. + * 0 - odd parity, 1 - even parity. + * @parity_enable: enable transmission of parity at end of each transmit + * data stream. + * @io_type: type of IO transfer. Choose between polled, interrupt and DMA. + * @timer_disable: disable chip-select timers (setup and hold) + * @c2tdelay: chip-select setup time. Measured in number of SPI module clocks. + * @t2cdelay: chip-select hold time. Measured in number of SPI module clocks. + * @t2edelay: transmit data finished to SPI ENAn pin inactive time. Measured + * in number of SPI clocks. + * @c2edelay: chip-select active to SPI ENAn signal active time. Measured in + * number of SPI clocks. + */ +struct davinci_spi_config { + u8 wdelay; + u8 odd_parity; + u8 parity_enable; + u8 io_type; + u8 timer_disable; + u8 c2tdelay; + u8 t2cdelay; + u8 t2edelay; + u8 c2edelay; +}; + /* SPI Controller driver's private data. */ struct davinci_spi { struct spi_bitbang bitbang; @@ -134,15 +178,15 @@ struct davinci_spi { struct dma_chan *dma_rx; struct dma_chan *dma_tx; - int dma_rx_chnum; - int dma_tx_chnum; struct davinci_spi_platform_data pdata; void (*get_rx)(u32 rx_data, struct davinci_spi *); u32 (*get_tx)(struct davinci_spi *); - u8 bytes_per_word[SPI_MAX_CHIPSELECT]; + u8 *bytes_per_word; + + u8 prescaler_limit; }; static struct davinci_spi_config davinci_spi_default_cfg; @@ -168,8 +212,10 @@ static void davinci_spi_rx_buf_u16(u32 data, struct davinci_spi *dspi) static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi) { u32 data = 0; + if (dspi->tx) { const u8 *tx = dspi->tx; + data = *tx++; dspi->tx = tx; } @@ -179,8 +225,10 @@ static u32 davinci_spi_tx_buf_u8(struct davinci_spi *dspi) static u32 davinci_spi_tx_buf_u16(struct davinci_spi *dspi) { u32 data = 0; + if (dspi->tx) { const u16 *tx = dspi->tx; + data = *tx++; dspi->tx = tx; } @@ -209,45 +257,45 @@ static inline void clear_io_bits(void __iomem *addr, u32 bits) static void davinci_spi_chipselect(struct spi_device *spi, int value) { struct davinci_spi *dspi; - struct davinci_spi_platform_data *pdata; - u8 chip_sel = spi->chip_select; + struct davinci_spi_config *spicfg = spi->controller_data; + u8 chip_sel = spi_get_chipselect(spi, 0); u16 spidat1 = CS_DEFAULT; - bool gpio_chipsel = false; - dspi = spi_master_get_devdata(spi->master); - pdata = &dspi->pdata; + dspi = spi_controller_get_devdata(spi->controller); - if (pdata->chip_sel && chip_sel < pdata->num_chipselect && - pdata->chip_sel[chip_sel] != SPI_INTERN_CS) - gpio_chipsel = true; + /* program delay transfers if tx_delay is non zero */ + if (spicfg && spicfg->wdelay) + spidat1 |= SPIDAT1_WDEL; /* * Board specific chip select logic decides the polarity and cs * line for the controller */ - if (gpio_chipsel) { + if (spi_get_csgpiod(spi, 0)) { if (value == BITBANG_CS_ACTIVE) - gpio_set_value(pdata->chip_sel[chip_sel], 0); + gpiod_set_value(spi_get_csgpiod(spi, 0), 1); else - gpio_set_value(pdata->chip_sel[chip_sel], 1); + gpiod_set_value(spi_get_csgpiod(spi, 0), 0); } else { if (value == BITBANG_CS_ACTIVE) { - spidat1 |= SPIDAT1_CSHOLD_MASK; + if (!(spi->mode & SPI_CS_WORD)) + spidat1 |= SPIDAT1_CSHOLD_MASK; spidat1 &= ~(0x1 << chip_sel); } - - iowrite16(spidat1, dspi->base + SPIDAT1 + 2); } + + iowrite16(spidat1, dspi->base + SPIDAT1 + 2); } /** * davinci_spi_get_prescale - Calculates the correct prescale value - * @maxspeed_hz: the maximum rate the SPI clock can run at + * @dspi: the controller data + * @max_speed_hz: the maximum rate the SPI clock can run at * * This function calculates the prescale value that generates a clock rate * less than or equal to the specified maximum. * - * Returns: calculated prescale - 1 for easy programming into SPI registers + * Returns: calculated prescale value for easy programming into SPI registers * or negative error number if valid prescalar cannot be updated. */ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, @@ -255,12 +303,13 @@ static inline int davinci_spi_get_prescale(struct davinci_spi *dspi, { int ret; - ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz); + /* Subtract 1 to match what will be programmed into SPI register. */ + ret = DIV_ROUND_UP(clk_get_rate(dspi->clk), max_speed_hz) - 1; - if (ret < 3 || ret > 256) + if (ret < dspi->prescaler_limit || ret > 255) return -EINVAL; - return ret - 1; + return ret; } /** @@ -279,10 +328,11 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, struct davinci_spi *dspi; struct davinci_spi_config *spicfg; u8 bits_per_word = 0; - u32 hz = 0, spifmt = 0, prescale = 0; + u32 hz = 0, spifmt = 0; + int prescale; - dspi = spi_master_get_devdata(spi->master); - spicfg = (struct davinci_spi_config *)spi->controller_data; + dspi = spi_controller_get_devdata(spi->controller); + spicfg = spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; @@ -302,11 +352,11 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, if (bits_per_word <= 8) { dspi->get_rx = davinci_spi_rx_buf_u8; dspi->get_tx = davinci_spi_tx_buf_u8; - dspi->bytes_per_word[spi->chip_select] = 1; + dspi->bytes_per_word[spi_get_chipselect(spi, 0)] = 1; } else { dspi->get_rx = davinci_spi_rx_buf_u16; dspi->get_tx = davinci_spi_tx_buf_u16; - dspi->bytes_per_word[spi->chip_select] = 2; + dspi->bytes_per_word[spi_get_chipselect(spi, 0)] = 2; } if (!hz) @@ -330,6 +380,14 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, spifmt |= SPIFMT_PHASE_MASK; /* + * Assume wdelay is used only on SPI peripherals that has this field + * in SPIFMTn register and when it's configured from board file or DT. + */ + if (spicfg->wdelay) + spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) + & SPIFMT_WDELAY_MASK); + + /* * Version 1 hardware supports two basic SPI modes: * - Standard SPI mode uses 4 pins, with chipselect * - 3 pin SPI is a 4 pin variant without CS (SPI_NO_CS) @@ -346,9 +404,6 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, u32 delay = 0; - spifmt |= ((spicfg->wdelay << SPIFMT_WDELAY_SHIFT) - & SPIFMT_WDELAY_MASK); - if (spicfg->odd_parity) spifmt |= SPIFMT_ODD_PARITY_MASK; @@ -380,6 +435,30 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, return 0; } +static int davinci_spi_of_setup(struct spi_device *spi) +{ + struct davinci_spi_config *spicfg = spi->controller_data; + struct device_node *np = spi->dev.of_node; + struct davinci_spi *dspi = spi_controller_get_devdata(spi->controller); + u32 prop; + + if (spicfg == NULL && np) { + spicfg = kzalloc(sizeof(*spicfg), GFP_KERNEL); + if (!spicfg) + return -ENOMEM; + *spicfg = davinci_spi_default_cfg; + /* override with dt configured values */ + if (!of_property_read_u32(np, "ti,spi-wdelay", &prop)) + spicfg->wdelay = (u8)prop; + spi->controller_data = spicfg; + + if (dspi->dma_rx && dspi->dma_tx) + spicfg->io_type = SPI_IO_TYPE_DMA; + } + + return 0; +} + /** * davinci_spi_setup - This functions will set default transfer method * @spi: spi device on which data transfer to be done @@ -388,22 +467,18 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, */ static int davinci_spi_setup(struct spi_device *spi) { - int retval = 0; struct davinci_spi *dspi; - struct davinci_spi_platform_data *pdata; - - dspi = spi_master_get_devdata(spi->master); - pdata = &dspi->pdata; + struct device_node *np = spi->dev.of_node; + bool internal_cs = true; - /* if bits per word length is zero then set it default 8 */ - if (!spi->bits_per_word) - spi->bits_per_word = 8; + dspi = spi_controller_get_devdata(spi->controller); if (!(spi->mode & SPI_NO_CS)) { - if ((pdata->chip_sel == NULL) || - (pdata->chip_sel[spi->chip_select] == SPI_INTERN_CS)) - set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select); + if (np && spi_get_csgpiod(spi, 0)) + internal_cs = false; + if (internal_cs) + set_io_bits(dspi->base + SPIPC0, 1 << spi_get_chipselect(spi, 0)); } if (spi->mode & SPI_READY) @@ -414,41 +489,66 @@ static int davinci_spi_setup(struct spi_device *spi) else clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_LOOPBACK_MASK); - return retval; + return davinci_spi_of_setup(spi); +} + +static void davinci_spi_cleanup(struct spi_device *spi) +{ + struct davinci_spi_config *spicfg = spi->controller_data; + + spi->controller_data = NULL; + if (spi->dev.of_node) + kfree(spicfg); +} + +static bool davinci_spi_can_dma(struct spi_controller *host, + struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct davinci_spi_config *spicfg = spi->controller_data; + bool can_dma = false; + + if (spicfg) + can_dma = (spicfg->io_type == SPI_IO_TYPE_DMA) && + (xfer->len >= DMA_MIN_BYTES) && + !is_vmalloc_addr(xfer->rx_buf) && + !is_vmalloc_addr(xfer->tx_buf); + + return can_dma; } static int davinci_spi_check_error(struct davinci_spi *dspi, int int_status) { - struct device *sdev = dspi->bitbang.master->dev.parent; + struct device *sdev = dspi->bitbang.ctlr->dev.parent; if (int_status & SPIFLG_TIMEOUT_MASK) { - dev_dbg(sdev, "SPI Time-out Error\n"); + dev_err(sdev, "SPI Time-out Error\n"); return -ETIMEDOUT; } if (int_status & SPIFLG_DESYNC_MASK) { - dev_dbg(sdev, "SPI Desynchronization Error\n"); + dev_err(sdev, "SPI Desynchronization Error\n"); return -EIO; } if (int_status & SPIFLG_BITERR_MASK) { - dev_dbg(sdev, "SPI Bit error\n"); + dev_err(sdev, "SPI Bit error\n"); return -EIO; } if (dspi->version == SPI_VERSION_2) { if (int_status & SPIFLG_DLEN_ERR_MASK) { - dev_dbg(sdev, "SPI Data Length Error\n"); + dev_err(sdev, "SPI Data Length Error\n"); return -EIO; } if (int_status & SPIFLG_PARERR_MASK) { - dev_dbg(sdev, "SPI Parity Error\n"); + dev_err(sdev, "SPI Parity Error\n"); return -EIO; } if (int_status & SPIFLG_OVRRUN_MASK) { - dev_dbg(sdev, "SPI Data Overrun error\n"); + dev_err(sdev, "SPI Data Overrun error\n"); return -EIO; } if (int_status & SPIFLG_BUF_INIT_ACTIVE_MASK) { - dev_dbg(sdev, "SPI Buffer Init Active\n"); + dev_err(sdev, "SPI Buffer Init Active\n"); return -EBUSY; } } @@ -530,18 +630,16 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) u32 errors = 0; struct davinci_spi_config *spicfg; struct davinci_spi_platform_data *pdata; - unsigned uninitialized_var(rx_buf_count); - void *dummy_buf = NULL; - struct scatterlist sg_rx, sg_tx; + unsigned long timeout; - dspi = spi_master_get_devdata(spi->master); + dspi = spi_controller_get_devdata(spi->controller); pdata = &dspi->pdata; spicfg = (struct davinci_spi_config *)spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; /* convert len to words based on bits_per_word */ - data_type = dspi->bytes_per_word[spi->chip_select]; + data_type = dspi->bytes_per_word[spi_get_chipselect(spi, 0)]; dspi->tx = t->tx_buf; dspi->rx = t->rx_buf; @@ -553,12 +651,11 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); set_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); - INIT_COMPLETION(dspi->done); - - if (spicfg->io_type == SPI_IO_TYPE_INTR) - set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT); + reinit_completion(&dspi->done); - if (spicfg->io_type != SPI_IO_TYPE_DMA) { + if (!davinci_spi_can_dma(spi->controller, spi, t)) { + if (spicfg->io_type != SPI_IO_TYPE_POLL) + set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT); /* start the transfer */ dspi->wcount--; tx_data = dspi->get_tx(dspi); @@ -580,51 +677,28 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) }; struct dma_async_tx_descriptor *rxdesc; struct dma_async_tx_descriptor *txdesc; - void *buf; - - dummy_buf = kzalloc(t->len, GFP_KERNEL); - if (!dummy_buf) - goto err_alloc_dummy_buf; dmaengine_slave_config(dspi->dma_rx, &dma_rx_conf); dmaengine_slave_config(dspi->dma_tx, &dma_tx_conf); - sg_init_table(&sg_rx, 1); - if (!t->rx_buf) - buf = dummy_buf; - else - buf = t->rx_buf; - t->rx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_FROM_DEVICE); - if (!t->rx_dma) { - ret = -EFAULT; - goto err_rx_map; - } - sg_dma_address(&sg_rx) = t->rx_dma; - sg_dma_len(&sg_rx) = t->len; - - sg_init_table(&sg_tx, 1); - if (!t->tx_buf) - buf = dummy_buf; - else - buf = (void *)t->tx_buf; - t->tx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_FROM_DEVICE); - if (!t->tx_dma) { - ret = -EFAULT; - goto err_tx_map; - } - sg_dma_address(&sg_tx) = t->tx_dma; - sg_dma_len(&sg_tx) = t->len; - rxdesc = dmaengine_prep_slave_sg(dspi->dma_rx, - &sg_rx, 1, DMA_DEV_TO_MEM, + t->rx_sg.sgl, t->rx_sg.nents, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!rxdesc) goto err_desc; + if (!t->tx_buf) { + /* To avoid errors when doing rx-only transfers with + * many SG entries (> 20), use the rx buffer as the + * dummy tx buffer so that dma reloads are done at the + * same time for rx and tx. + */ + t->tx_sg.sgl = t->rx_sg.sgl; + t->tx_sg.nents = t->rx_sg.nents; + } + txdesc = dmaengine_prep_slave_sg(dspi->dma_tx, - &sg_tx, 1, DMA_MEM_TO_DEV, + t->tx_sg.sgl, t->tx_sg.nents, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!txdesc) goto err_desc; @@ -648,7 +722,13 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) /* Wait for the transfer to complete */ if (spicfg->io_type != SPI_IO_TYPE_POLL) { - wait_for_completion_interruptible(&(dspi->done)); + timeout = DIV_ROUND_UP(t->speed_hz, MSEC_PER_SEC); + timeout = DIV_ROUND_UP(t->len * 8, timeout); + /* Assume we are at most 2x slower than the nominal bus speed */ + timeout = 2 * msecs_to_jiffies(timeout); + + if (wait_for_completion_timeout(&dspi->done, timeout) == 0) + errors = SPIFLG_TIMEOUT_MASK; } else { while (dspi->rcount > 0 || dspi->wcount > 0) { errors = davinci_spi_process_events(dspi); @@ -659,16 +739,9 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) } clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL); - if (spicfg->io_type == SPI_IO_TYPE_DMA) { + if (davinci_spi_can_dma(spi->controller, spi, t)) clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN); - dma_unmap_single(&spi->dev, t->rx_dma, - t->len, DMA_FROM_DEVICE); - dma_unmap_single(&spi->dev, t->tx_dma, - t->len, DMA_TO_DEVICE); - kfree(dummy_buf); - } - clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); @@ -691,19 +764,13 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) return t->len; err_desc: - dma_unmap_single(&spi->dev, t->tx_dma, t->len, DMA_TO_DEVICE); -err_tx_map: - dma_unmap_single(&spi->dev, t->rx_dma, t->len, DMA_FROM_DEVICE); -err_rx_map: - kfree(dummy_buf); -err_alloc_dummy_buf: return ret; } /** * dummy_thread_fn - dummy thread function * @irq: IRQ number for this SPI Master - * @context_data: structure for SPI Master controller davinci_spi + * @data: structure for SPI Master controller davinci_spi * * This is to satisfy the request_threaded_irq() API so that the irq * handler is called in interrupt context. @@ -716,7 +783,7 @@ static irqreturn_t dummy_thread_fn(s32 irq, void *data) /** * davinci_spi_irq - Interrupt handler for SPI Master Controller * @irq: IRQ number for this SPI Master - * @context_data: structure for SPI Master controller davinci_spi + * @data: structure for SPI Master controller davinci_spi * * ISR will determine that interrupt arrives either for READ or WRITE command. * According to command it will do the appropriate action. It will check @@ -741,45 +808,56 @@ static irqreturn_t davinci_spi_irq(s32 irq, void *data) static int davinci_spi_request_dma(struct davinci_spi *dspi) { - dma_cap_mask_t mask; - struct device *sdev = dspi->bitbang.master->dev.parent; - int r; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - dspi->dma_rx = dma_request_channel(mask, edma_filter_fn, - &dspi->dma_rx_chnum); - if (!dspi->dma_rx) { - dev_err(sdev, "request RX DMA channel failed\n"); - r = -ENODEV; - goto rx_dma_failed; - } + struct device *sdev = dspi->bitbang.ctlr->dev.parent; + + dspi->dma_rx = dma_request_chan(sdev, "rx"); + if (IS_ERR(dspi->dma_rx)) + return PTR_ERR(dspi->dma_rx); - dspi->dma_tx = dma_request_channel(mask, edma_filter_fn, - &dspi->dma_tx_chnum); - if (!dspi->dma_tx) { - dev_err(sdev, "request TX DMA channel failed\n"); - r = -ENODEV; - goto tx_dma_failed; + dspi->dma_tx = dma_request_chan(sdev, "tx"); + if (IS_ERR(dspi->dma_tx)) { + dma_release_channel(dspi->dma_rx); + return PTR_ERR(dspi->dma_tx); } return 0; - -tx_dma_failed: - dma_release_channel(dspi->dma_rx); -rx_dma_failed: - return r; } #if defined(CONFIG_OF) + +/* OF SPI data structure */ +struct davinci_spi_of_data { + u8 version; + u8 prescaler_limit; +}; + +static const struct davinci_spi_of_data dm6441_spi_data = { + .version = SPI_VERSION_1, + .prescaler_limit = 2, +}; + +static const struct davinci_spi_of_data da830_spi_data = { + .version = SPI_VERSION_2, + .prescaler_limit = 2, +}; + +static const struct davinci_spi_of_data keystone_spi_data = { + .version = SPI_VERSION_1, + .prescaler_limit = 0, +}; + static const struct of_device_id davinci_spi_of_match[] = { { .compatible = "ti,dm6441-spi", + .data = &dm6441_spi_data, }, { .compatible = "ti,da830-spi", - .data = (void *)SPI_VERSION_2, + .data = &da830_spi_data, + }, + { + .compatible = "ti,keystone-spi", + .data = &keystone_spi_data, }, { }, }; @@ -798,24 +876,20 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, struct davinci_spi *dspi) { struct device_node *node = pdev->dev.of_node; + const struct davinci_spi_of_data *spi_data; struct davinci_spi_platform_data *pdata; unsigned int num_cs, intr_line = 0; - const struct of_device_id *match; pdata = &dspi->pdata; - pdata->version = SPI_VERSION_1; - match = of_match_device(of_match_ptr(davinci_spi_of_match), - &pdev->dev); - if (!match) - return -ENODEV; - - /* match data has the SPI version number for SPI_VERSION_2 */ - if (match->data == (void *)SPI_VERSION_2) - pdata->version = SPI_VERSION_2; + spi_data = device_get_match_data(&pdev->dev); + pdata->version = spi_data->version; + pdata->prescaler_limit = spi_data->prescaler_limit; /* * default num_cs is 1 and all chipsel are internal to the chip + * indicated by chip_sel being NULL or cs_gpios being NULL or + * set to -ENOENT. num-cs includes internal as well as gpios. * indicated by chip_sel being NULL. GPIO based CS is not * supported yet in DT bindings. */ @@ -827,10 +901,8 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, return 0; } #else -#define davinci_spi_of_match NULL -static struct davinci_spi_platform_data - *spi_davinci_get_pdata(struct platform_device *pdev, - struct davinci_spi *dspi) +static int spi_davinci_get_pdata(struct platform_device *pdev, + struct davinci_spi *dspi) { return -ENODEV; } @@ -849,129 +921,105 @@ static struct davinci_spi_platform_data */ static int davinci_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct davinci_spi *dspi; struct davinci_spi_platform_data *pdata; - struct resource *r, *mem; - resource_size_t dma_rx_chan = SPI_NO_RESOURCE; - resource_size_t dma_tx_chan = SPI_NO_RESOURCE; - int i = 0, ret = 0; + struct resource *r; + int ret = 0; u32 spipc0; - master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); - if (master == NULL) { + host = spi_alloc_host(&pdev->dev, sizeof(struct davinci_spi)); + if (host == NULL) { ret = -ENOMEM; goto err; } - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - dspi = spi_master_get_devdata(master); - if (dspi == NULL) { - ret = -ENOENT; - goto free_master; - } + dspi = spi_controller_get_devdata(host); - if (pdev->dev.platform_data) { - pdata = pdev->dev.platform_data; + if (dev_get_platdata(&pdev->dev)) { + pdata = dev_get_platdata(&pdev->dev); dspi->pdata = *pdata; } else { /* update dspi pdata with that from the DT */ ret = spi_davinci_get_pdata(pdev, dspi); if (ret < 0) - goto free_master; + goto free_host; } /* pdata in dspi is now updated and point pdata to that */ pdata = &dspi->pdata; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - ret = -ENOENT; - goto free_master; + dspi->bytes_per_word = devm_kcalloc(&pdev->dev, + pdata->num_chipselect, + sizeof(*dspi->bytes_per_word), + GFP_KERNEL); + if (dspi->bytes_per_word == NULL) { + ret = -ENOMEM; + goto free_host; } - dspi->pbase = r->start; - - mem = request_mem_region(r->start, resource_size(r), pdev->name); - if (mem == NULL) { - ret = -EBUSY; - goto free_master; + dspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); + if (IS_ERR(dspi->base)) { + ret = PTR_ERR(dspi->base); + goto free_host; } + dspi->pbase = r->start; - dspi->base = ioremap(r->start, resource_size(r)); - if (dspi->base == NULL) { - ret = -ENOMEM; - goto release_region; - } + init_completion(&dspi->done); - dspi->irq = platform_get_irq(pdev, 0); - if (dspi->irq <= 0) { - ret = -EINVAL; - goto unmap_io; - } + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto free_host; + dspi->irq = ret; - ret = request_threaded_irq(dspi->irq, davinci_spi_irq, dummy_thread_fn, - 0, dev_name(&pdev->dev), dspi); + ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq, + dummy_thread_fn, 0, dev_name(&pdev->dev), dspi); if (ret) - goto unmap_io; + goto free_host; - dspi->bitbang.master = spi_master_get(master); - if (dspi->bitbang.master == NULL) { - ret = -ENODEV; - goto irq_free; - } + dspi->bitbang.ctlr = host; - dspi->clk = clk_get(&pdev->dev, NULL); + dspi->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { ret = -ENODEV; - goto put_master; + goto free_host; } - clk_prepare_enable(dspi->clk); - master->dev.of_node = pdev->dev.of_node; - master->bus_num = pdev->id; - master->num_chipselect = pdata->num_chipselect; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); - master->setup = davinci_spi_setup; + host->use_gpio_descriptors = true; + host->dev.of_node = pdev->dev.of_node; + host->bus_num = pdev->id; + host->num_chipselect = pdata->num_chipselect; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); + host->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_GPIO_SS; + host->setup = davinci_spi_setup; + host->cleanup = davinci_spi_cleanup; + host->can_dma = davinci_spi_can_dma; dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; - + dspi->prescaler_limit = pdata->prescaler_limit; dspi->version = pdata->version; - dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP; + dspi->bitbang.flags = SPI_NO_CS | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_WORD; if (dspi->version == SPI_VERSION_2) dspi->bitbang.flags |= SPI_READY; - r = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (r) - dma_rx_chan = r->start; - r = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (r) - dma_tx_chan = r->start; - dspi->bitbang.txrx_bufs = davinci_spi_bufs; - if (dma_rx_chan != SPI_NO_RESOURCE && - dma_tx_chan != SPI_NO_RESOURCE) { - dspi->dma_rx_chnum = dma_rx_chan; - dspi->dma_tx_chnum = dma_tx_chan; - - ret = davinci_spi_request_dma(dspi); - if (ret) - goto free_clk; - - dev_info(&pdev->dev, "DMA: supported\n"); - dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, " - "event queue: %d\n", dma_rx_chan, dma_tx_chan, - pdata->dma_event_q); + + ret = davinci_spi_request_dma(dspi); + if (ret == -EPROBE_DEFER) { + goto free_host; + } else if (ret) { + dev_info(&pdev->dev, "DMA is not supported (%d)\n", ret); + dspi->dma_rx = NULL; + dspi->dma_tx = NULL; } dspi->get_rx = davinci_spi_rx_buf_u8; dspi->get_tx = davinci_spi_tx_buf_u8; - init_completion(&dspi->done); - /* Reset In/OUT SPI module */ iowrite32(0, dspi->base + SPIGCR0); udelay(100); @@ -981,14 +1029,6 @@ static int davinci_spi_probe(struct platform_device *pdev) spipc0 = SPIPC0_DIFUN_MASK | SPIPC0_DOFUN_MASK | SPIPC0_CLKFUN_MASK; iowrite32(spipc0, dspi->base + SPIPC0); - /* initialize chip selects */ - if (pdata->chip_sel) { - for (i = 0; i < pdata->num_chipselect; i++) { - if (pdata->chip_sel[i] != SPI_INTERN_CS) - gpio_direction_output(pdata->chip_sel[i], 1); - } - } - if (pdata->intr_line) iowrite32(SPI_INTLVL_1, dspi->base + SPILVL); else @@ -996,7 +1036,7 @@ static int davinci_spi_probe(struct platform_device *pdev) iowrite32(CS_DEFAULT, dspi->base + SPIDEF); - /* master mode default */ + /* host mode default */ set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK); set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK); set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); @@ -1010,21 +1050,15 @@ static int davinci_spi_probe(struct platform_device *pdev) return ret; free_dma: - dma_release_channel(dspi->dma_rx); - dma_release_channel(dspi->dma_tx); -free_clk: - clk_disable_unprepare(dspi->clk); - clk_put(dspi->clk); -put_master: - spi_master_put(master); -irq_free: - free_irq(dspi->irq, dspi); -unmap_io: - iounmap(dspi->base); -release_region: - release_mem_region(dspi->pbase, resource_size(r)); -free_master: - kfree(master); + /* This bit needs to be cleared to disable dpsi->clk */ + clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); + + if (dspi->dma_rx) { + dma_release_channel(dspi->dma_rx); + dma_release_channel(dspi->dma_tx); + } +free_host: + spi_controller_put(host); err: return ret; } @@ -1038,33 +1072,31 @@ err: * It will also call spi_bitbang_stop to destroy the work queue which was * created by spi_bitbang_start. */ -static int davinci_spi_remove(struct platform_device *pdev) +static void davinci_spi_remove(struct platform_device *pdev) { struct davinci_spi *dspi; - struct spi_master *master; - struct resource *r; + struct spi_controller *host; - master = platform_get_drvdata(pdev); - dspi = spi_master_get_devdata(master); + host = platform_get_drvdata(pdev); + dspi = spi_controller_get_devdata(host); spi_bitbang_stop(&dspi->bitbang); - clk_disable_unprepare(dspi->clk); - clk_put(dspi->clk); - spi_master_put(master); - free_irq(dspi->irq, dspi); - iounmap(dspi->base); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(dspi->pbase, resource_size(r)); + /* This bit needs to be cleared to disable dpsi->clk */ + clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); - return 0; + if (dspi->dma_rx) { + dma_release_channel(dspi->dma_rx); + dma_release_channel(dspi->dma_tx); + } + + spi_controller_put(host); } static struct platform_driver davinci_spi_driver = { .driver = { .name = "spi_davinci", - .owner = THIS_MODULE, - .of_match_table = davinci_spi_of_match, + .of_match_table = of_match_ptr(davinci_spi_of_match), }, .probe = davinci_spi_probe, .remove = davinci_spi_remove, |
