Loading drivers/spi/spi-armada-3700.c +92 −18 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ #define DRIVER_NAME "armada_3700_spi" #define A3700_SPI_MAX_SPEED_HZ 100000000 #define A3700_SPI_MAX_PRESCALE 30 #define A3700_SPI_TIMEOUT 10 /* SPI Register Offest */ Loading Loading @@ -184,12 +186,15 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, return 0; } static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi) static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi, bool enable) { u32 val; val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); if (enable) val |= A3700_SPI_FIFO_MODE; else val &= ~A3700_SPI_FIFO_MODE; spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val); } Loading Loading @@ -297,7 +302,7 @@ static int a3700_spi_init(struct a3700_spi *a3700_spi) a3700_spi_deactivate_cs(a3700_spi, i); /* Enable FIFO mode */ a3700_spi_fifo_mode_set(a3700_spi); a3700_spi_fifo_mode_set(a3700_spi, true); /* Set SPI mode */ a3700_spi_mode_set(a3700_spi, master->mode_bits); Loading Loading @@ -416,15 +421,20 @@ static void a3700_spi_transfer_setup(struct spi_device *spi, struct spi_transfer *xfer) { struct a3700_spi *a3700_spi; unsigned int byte_len; a3700_spi = spi_master_get_devdata(spi->master); a3700_spi_clock_set(a3700_spi, xfer->speed_hz); byte_len = xfer->bits_per_word >> 3; /* Use 4 bytes long transfers. Each transfer method has its way to deal * with the remaining bytes for non 4-bytes aligned transfers. */ a3700_spi_bytelen_set(a3700_spi, 4); a3700_spi_fifo_thres_set(a3700_spi, byte_len); /* Initialize the working buffers */ a3700_spi->tx_buf = xfer->tx_buf; a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; } static void a3700_spi_set_cs(struct spi_device *spi, bool enable) Loading Loading @@ -491,7 +501,7 @@ static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi) u32 val; while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) { val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); val = *(u32 *)a3700_spi->tx_buf; spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); a3700_spi->buf_len -= 4; a3700_spi->tx_buf += 4; Loading @@ -514,9 +524,8 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi) while (!a3700_is_rfifo_empty(a3700_spi) && a3700_spi->buf_len) { val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); if (a3700_spi->buf_len >= 4) { u32 data = le32_to_cpu(val); memcpy(a3700_spi->rx_buf, &data, 4); memcpy(a3700_spi->rx_buf, &val, 4); a3700_spi->buf_len -= 4; a3700_spi->rx_buf += 4; Loading Loading @@ -579,27 +588,26 @@ static int a3700_spi_prepare_message(struct spi_master *master, if (ret) return ret; a3700_spi_bytelen_set(a3700_spi, 4); a3700_spi_mode_set(a3700_spi, spi->mode); return 0; } static int a3700_spi_transfer_one(struct spi_master *master, static int a3700_spi_transfer_one_fifo(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { struct a3700_spi *a3700_spi = spi_master_get_devdata(master); int ret = 0, timeout = A3700_SPI_TIMEOUT; unsigned int nbits = 0; unsigned int nbits = 0, byte_len; u32 val; a3700_spi_transfer_setup(spi, xfer); /* Make sure we use FIFO mode */ a3700_spi_fifo_mode_set(a3700_spi, true); a3700_spi->tx_buf = xfer->tx_buf; a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; /* Configure FIFO thresholds */ byte_len = xfer->bits_per_word >> 3; a3700_spi_fifo_thres_set(a3700_spi, byte_len); if (xfer->tx_buf) nbits = xfer->tx_nbits; Loading @@ -615,6 +623,11 @@ static int a3700_spi_transfer_one(struct spi_master *master, a3700_spi_header_set(a3700_spi); if (xfer->rx_buf) { /* Clear WFIFO, since it's last 2 bytes are shifted out during * a read operation */ spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, 0); /* Set read data length */ spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG, a3700_spi->buf_len); Loading Loading @@ -729,6 +742,63 @@ static int a3700_spi_transfer_one(struct spi_master *master, return ret; } static int a3700_spi_transfer_one_full_duplex(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { struct a3700_spi *a3700_spi = spi_master_get_devdata(master); u32 val; /* Disable FIFO mode */ a3700_spi_fifo_mode_set(a3700_spi, false); while (a3700_spi->buf_len) { /* When we have less than 4 bytes to transfer, switch to 1 byte * mode. This is reset after each transfer */ if (a3700_spi->buf_len < 4) a3700_spi_bytelen_set(a3700_spi, 1); if (a3700_spi->byte_len == 1) val = *a3700_spi->tx_buf; else val = *(u32 *)a3700_spi->tx_buf; spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); /* Wait for all the data to be shifted in / out */ while (!(spireg_read(a3700_spi, A3700_SPI_IF_CTRL_REG) & A3700_SPI_XFER_DONE)) cpu_relax(); val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); memcpy(a3700_spi->rx_buf, &val, a3700_spi->byte_len); a3700_spi->buf_len -= a3700_spi->byte_len; a3700_spi->tx_buf += a3700_spi->byte_len; a3700_spi->rx_buf += a3700_spi->byte_len; } spi_finalize_current_transfer(master); return 0; } static int a3700_spi_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { a3700_spi_transfer_setup(spi, xfer); if (xfer->tx_buf && xfer->rx_buf) return a3700_spi_transfer_one_full_duplex(master, spi, xfer); return a3700_spi_transfer_one_fifo(master, spi, xfer); } static int a3700_spi_unprepare_message(struct spi_master *master, struct spi_message *message) { Loading Loading @@ -778,7 +848,6 @@ static int a3700_spi_probe(struct platform_device *pdev) master->transfer_one = a3700_spi_transfer_one; master->unprepare_message = a3700_spi_unprepare_message; master->set_cs = a3700_spi_set_cs; master->flags = SPI_MASTER_HALF_DUPLEX; master->mode_bits |= (SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD); Loading Loading @@ -818,6 +887,11 @@ static int a3700_spi_probe(struct platform_device *pdev) goto error; } master->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ, clk_get_rate(spi->clk)); master->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk), A3700_SPI_MAX_PRESCALE); ret = a3700_spi_init(spi); if (ret) goto error_clk; Loading drivers/spi/spi-atmel.c +84 −29 Original line number Diff line number Diff line Loading @@ -291,6 +291,10 @@ struct atmel_spi { struct spi_transfer *current_transfer; int current_remaining_bytes; int done_status; dma_addr_t dma_addr_rx_bbuf; dma_addr_t dma_addr_tx_bbuf; void *addr_rx_bbuf; void *addr_tx_bbuf; struct completion xfer_completion; Loading Loading @@ -436,6 +440,11 @@ static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock) spin_unlock_irqrestore(&as->lock, as->flags); } static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer) { return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf); } static inline bool atmel_spi_use_dma(struct atmel_spi *as, struct spi_transfer *xfer) { Loading @@ -448,7 +457,12 @@ static bool atmel_spi_can_dma(struct spi_master *master, { struct atmel_spi *as = spi_master_get_devdata(master); if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) return atmel_spi_use_dma(as, xfer) && !atmel_spi_is_vmalloc_xfer(xfer); else return atmel_spi_use_dma(as, xfer); } static int atmel_spi_dma_slave_config(struct atmel_spi *as, Loading Loading @@ -594,6 +608,11 @@ static void dma_callback(void *data) struct spi_master *master = data; struct atmel_spi *as = spi_master_get_devdata(master); if (is_vmalloc_addr(as->current_transfer->rx_buf) && IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf, as->current_transfer->len); } complete(&as->xfer_completion); } Loading Loading @@ -744,17 +763,41 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, goto err_exit; /* Send both scatterlists */ if (atmel_spi_is_vmalloc_xfer(xfer) && IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { rxdesc = dmaengine_prep_slave_single(rxchan, as->dma_addr_rx_bbuf, xfer->len, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } else { rxdesc = dmaengine_prep_slave_sg(rxchan, xfer->rx_sg.sgl, xfer->rx_sg.nents, xfer->rx_sg.sgl, xfer->rx_sg.nents, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (!rxdesc) goto err_dma; if (atmel_spi_is_vmalloc_xfer(xfer) && IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len); txdesc = dmaengine_prep_slave_single(txchan, as->dma_addr_tx_bbuf, xfer->len, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } else { txdesc = dmaengine_prep_slave_sg(txchan, xfer->tx_sg.sgl, xfer->tx_sg.nents, xfer->tx_sg.sgl, xfer->tx_sg.nents, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (!txdesc) goto err_dma; Loading Loading @@ -1426,27 +1469,7 @@ static void atmel_get_caps(struct atmel_spi *as) as->caps.is_spi2 = version > 0x121; as->caps.has_wdrbt = version >= 0x210; #ifdef CONFIG_SOC_SAM_V4_V5 /* * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf() * since this later function tries to map buffers with dma_map_sg() * even if they have not been allocated inside DMA-safe areas. * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for * those ARM cores, the data cache follows the PIPT model. * Also the L2 cache controller of SAMA5D2 uses the PIPT model too. * In case of PIPT caches, there cannot be cache aliases. * However on ARM9 cores, the data cache follows the VIVT model, hence * the cache aliases issue can occur when buffers are allocated from * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is * not taken into account or at least not handled completely (cache * lines of aliases are not invalidated). * This is not a theorical issue: it was reproduced when trying to mount * a UBI file-system on a at91sam9g35ek board. */ as->caps.has_dma_support = false; #else as->caps.has_dma_support = version >= 0x212; #endif as->caps.has_pdc_support = version < 0x212; } Loading Loading @@ -1592,6 +1615,30 @@ static int atmel_spi_probe(struct platform_device *pdev) as->use_pdc = true; } if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev, SPI_MAX_DMA_XFER, &as->dma_addr_rx_bbuf, GFP_KERNEL | GFP_DMA); if (!as->addr_rx_bbuf) { as->use_dma = false; } else { as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev, SPI_MAX_DMA_XFER, &as->dma_addr_tx_bbuf, GFP_KERNEL | GFP_DMA); if (!as->addr_tx_bbuf) { as->use_dma = false; dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, as->addr_rx_bbuf, as->dma_addr_rx_bbuf); } } if (!as->use_dma) dev_info(master->dev.parent, " can not allocate dma coherent memory\n"); } if (as->caps.has_dma_support && !as->use_dma) dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n"); Loading Loading @@ -1664,6 +1711,14 @@ static int atmel_spi_remove(struct platform_device *pdev) if (as->use_dma) { atmel_spi_stop_dma(master); atmel_spi_release_dma(master); if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, as->addr_tx_bbuf, as->dma_addr_tx_bbuf); dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, as->addr_rx_bbuf, as->dma_addr_rx_bbuf); } } spin_lock_irq(&as->lock); Loading drivers/spi/spi-bcm53xx.c +10 −16 Original line number Diff line number Diff line Loading @@ -27,8 +27,6 @@ struct bcm53xxspi { struct bcma_device *core; struct spi_master *master; void __iomem *mmio_base; size_t read_offset; bool bspi; /* Boot SPI mode with memory mapping */ }; Loading Loading @@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct bcm53xxspi *b53spi, u8 *w_buf, if (!cont) bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); b53spi->read_offset = len; } static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, Loading @@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, u32 tmp; int i; for (i = 0; i < b53spi->read_offset + len; i++) { for (i = 0; i < len; i++) { tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | B53SPI_CDRAM_PCS_DSCK; if (!cont && i == b53spi->read_offset + len - 1) if (!cont && i == len - 1) tmp &= ~B53SPI_CDRAM_CONT; tmp &= ~0x1; /* Command Register File */ Loading @@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, /* Set queue pointers */ bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, b53spi->read_offset + len - 1); bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); if (cont) bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); Loading @@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); for (i = 0; i < len; ++i) { int offset = b53spi->read_offset + i; u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); /* Data stored in the transmit register file LSB */ r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); } b53spi->read_offset = 0; } static int bcm53xxspi_transfer_one(struct spi_master *master, Loading @@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struct spi_master *master, left = t->len; while (left) { size_t to_write = min_t(size_t, 16, left); bool cont = left - to_write > 0; bool cont = !spi_transfer_is_last(master, t) || left - to_write > 0; bcm53xxspi_buf_write(b53spi, buf, to_write, cont); left -= to_write; Loading @@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struct spi_master *master, buf = (u8 *)t->rx_buf; left = t->len; while (left) { size_t to_read = min_t(size_t, 16 - b53spi->read_offset, left); bool cont = left - to_read > 0; size_t to_read = min_t(size_t, 16, left); bool cont = !spi_transfer_is_last(master, t) || left - to_read > 0; bcm53xxspi_buf_read(b53spi, buf, to_read, cont); left -= to_read; Loading drivers/spi/spi-davinci.c +2 −2 Original line number Diff line number Diff line Loading @@ -945,6 +945,8 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_master; } init_completion(&dspi->done); ret = platform_get_irq(pdev, 0); if (ret == 0) ret = -EINVAL; Loading Loading @@ -1021,8 +1023,6 @@ static int davinci_spi_probe(struct platform_device *pdev) 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); Loading drivers/spi/spi-dw.c +0 −2 Original line number Diff line number Diff line Loading @@ -30,13 +30,11 @@ /* Slave spi_dev related */ struct chip_data { u8 cs; /* chip select pin */ u8 tmode; /* TR/TO/RO/EEPROM */ u8 type; /* SPI/SSP/MicroWire */ u8 poll_mode; /* 1 means use poll mode */ u8 enable_dma; u16 clk_div; /* baud rate divider */ u32 speed_hz; /* baud rate */ void (*cs_control)(u32 command); Loading Loading
drivers/spi/spi-armada-3700.c +92 −18 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ #define DRIVER_NAME "armada_3700_spi" #define A3700_SPI_MAX_SPEED_HZ 100000000 #define A3700_SPI_MAX_PRESCALE 30 #define A3700_SPI_TIMEOUT 10 /* SPI Register Offest */ Loading Loading @@ -184,12 +186,15 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, return 0; } static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi) static void a3700_spi_fifo_mode_set(struct a3700_spi *a3700_spi, bool enable) { u32 val; val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); if (enable) val |= A3700_SPI_FIFO_MODE; else val &= ~A3700_SPI_FIFO_MODE; spireg_write(a3700_spi, A3700_SPI_IF_CFG_REG, val); } Loading Loading @@ -297,7 +302,7 @@ static int a3700_spi_init(struct a3700_spi *a3700_spi) a3700_spi_deactivate_cs(a3700_spi, i); /* Enable FIFO mode */ a3700_spi_fifo_mode_set(a3700_spi); a3700_spi_fifo_mode_set(a3700_spi, true); /* Set SPI mode */ a3700_spi_mode_set(a3700_spi, master->mode_bits); Loading Loading @@ -416,15 +421,20 @@ static void a3700_spi_transfer_setup(struct spi_device *spi, struct spi_transfer *xfer) { struct a3700_spi *a3700_spi; unsigned int byte_len; a3700_spi = spi_master_get_devdata(spi->master); a3700_spi_clock_set(a3700_spi, xfer->speed_hz); byte_len = xfer->bits_per_word >> 3; /* Use 4 bytes long transfers. Each transfer method has its way to deal * with the remaining bytes for non 4-bytes aligned transfers. */ a3700_spi_bytelen_set(a3700_spi, 4); a3700_spi_fifo_thres_set(a3700_spi, byte_len); /* Initialize the working buffers */ a3700_spi->tx_buf = xfer->tx_buf; a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; } static void a3700_spi_set_cs(struct spi_device *spi, bool enable) Loading Loading @@ -491,7 +501,7 @@ static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi) u32 val; while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) { val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); val = *(u32 *)a3700_spi->tx_buf; spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); a3700_spi->buf_len -= 4; a3700_spi->tx_buf += 4; Loading @@ -514,9 +524,8 @@ static int a3700_spi_fifo_read(struct a3700_spi *a3700_spi) while (!a3700_is_rfifo_empty(a3700_spi) && a3700_spi->buf_len) { val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); if (a3700_spi->buf_len >= 4) { u32 data = le32_to_cpu(val); memcpy(a3700_spi->rx_buf, &data, 4); memcpy(a3700_spi->rx_buf, &val, 4); a3700_spi->buf_len -= 4; a3700_spi->rx_buf += 4; Loading Loading @@ -579,27 +588,26 @@ static int a3700_spi_prepare_message(struct spi_master *master, if (ret) return ret; a3700_spi_bytelen_set(a3700_spi, 4); a3700_spi_mode_set(a3700_spi, spi->mode); return 0; } static int a3700_spi_transfer_one(struct spi_master *master, static int a3700_spi_transfer_one_fifo(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { struct a3700_spi *a3700_spi = spi_master_get_devdata(master); int ret = 0, timeout = A3700_SPI_TIMEOUT; unsigned int nbits = 0; unsigned int nbits = 0, byte_len; u32 val; a3700_spi_transfer_setup(spi, xfer); /* Make sure we use FIFO mode */ a3700_spi_fifo_mode_set(a3700_spi, true); a3700_spi->tx_buf = xfer->tx_buf; a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; /* Configure FIFO thresholds */ byte_len = xfer->bits_per_word >> 3; a3700_spi_fifo_thres_set(a3700_spi, byte_len); if (xfer->tx_buf) nbits = xfer->tx_nbits; Loading @@ -615,6 +623,11 @@ static int a3700_spi_transfer_one(struct spi_master *master, a3700_spi_header_set(a3700_spi); if (xfer->rx_buf) { /* Clear WFIFO, since it's last 2 bytes are shifted out during * a read operation */ spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, 0); /* Set read data length */ spireg_write(a3700_spi, A3700_SPI_IF_DIN_CNT_REG, a3700_spi->buf_len); Loading Loading @@ -729,6 +742,63 @@ static int a3700_spi_transfer_one(struct spi_master *master, return ret; } static int a3700_spi_transfer_one_full_duplex(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { struct a3700_spi *a3700_spi = spi_master_get_devdata(master); u32 val; /* Disable FIFO mode */ a3700_spi_fifo_mode_set(a3700_spi, false); while (a3700_spi->buf_len) { /* When we have less than 4 bytes to transfer, switch to 1 byte * mode. This is reset after each transfer */ if (a3700_spi->buf_len < 4) a3700_spi_bytelen_set(a3700_spi, 1); if (a3700_spi->byte_len == 1) val = *a3700_spi->tx_buf; else val = *(u32 *)a3700_spi->tx_buf; spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); /* Wait for all the data to be shifted in / out */ while (!(spireg_read(a3700_spi, A3700_SPI_IF_CTRL_REG) & A3700_SPI_XFER_DONE)) cpu_relax(); val = spireg_read(a3700_spi, A3700_SPI_DATA_IN_REG); memcpy(a3700_spi->rx_buf, &val, a3700_spi->byte_len); a3700_spi->buf_len -= a3700_spi->byte_len; a3700_spi->tx_buf += a3700_spi->byte_len; a3700_spi->rx_buf += a3700_spi->byte_len; } spi_finalize_current_transfer(master); return 0; } static int a3700_spi_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *xfer) { a3700_spi_transfer_setup(spi, xfer); if (xfer->tx_buf && xfer->rx_buf) return a3700_spi_transfer_one_full_duplex(master, spi, xfer); return a3700_spi_transfer_one_fifo(master, spi, xfer); } static int a3700_spi_unprepare_message(struct spi_master *master, struct spi_message *message) { Loading Loading @@ -778,7 +848,6 @@ static int a3700_spi_probe(struct platform_device *pdev) master->transfer_one = a3700_spi_transfer_one; master->unprepare_message = a3700_spi_unprepare_message; master->set_cs = a3700_spi_set_cs; master->flags = SPI_MASTER_HALF_DUPLEX; master->mode_bits |= (SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD); Loading Loading @@ -818,6 +887,11 @@ static int a3700_spi_probe(struct platform_device *pdev) goto error; } master->max_speed_hz = min_t(unsigned long, A3700_SPI_MAX_SPEED_HZ, clk_get_rate(spi->clk)); master->min_speed_hz = DIV_ROUND_UP(clk_get_rate(spi->clk), A3700_SPI_MAX_PRESCALE); ret = a3700_spi_init(spi); if (ret) goto error_clk; Loading
drivers/spi/spi-atmel.c +84 −29 Original line number Diff line number Diff line Loading @@ -291,6 +291,10 @@ struct atmel_spi { struct spi_transfer *current_transfer; int current_remaining_bytes; int done_status; dma_addr_t dma_addr_rx_bbuf; dma_addr_t dma_addr_tx_bbuf; void *addr_rx_bbuf; void *addr_tx_bbuf; struct completion xfer_completion; Loading Loading @@ -436,6 +440,11 @@ static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock) spin_unlock_irqrestore(&as->lock, as->flags); } static inline bool atmel_spi_is_vmalloc_xfer(struct spi_transfer *xfer) { return is_vmalloc_addr(xfer->tx_buf) || is_vmalloc_addr(xfer->rx_buf); } static inline bool atmel_spi_use_dma(struct atmel_spi *as, struct spi_transfer *xfer) { Loading @@ -448,7 +457,12 @@ static bool atmel_spi_can_dma(struct spi_master *master, { struct atmel_spi *as = spi_master_get_devdata(master); if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) return atmel_spi_use_dma(as, xfer) && !atmel_spi_is_vmalloc_xfer(xfer); else return atmel_spi_use_dma(as, xfer); } static int atmel_spi_dma_slave_config(struct atmel_spi *as, Loading Loading @@ -594,6 +608,11 @@ static void dma_callback(void *data) struct spi_master *master = data; struct atmel_spi *as = spi_master_get_devdata(master); if (is_vmalloc_addr(as->current_transfer->rx_buf) && IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { memcpy(as->current_transfer->rx_buf, as->addr_rx_bbuf, as->current_transfer->len); } complete(&as->xfer_completion); } Loading Loading @@ -744,17 +763,41 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, goto err_exit; /* Send both scatterlists */ if (atmel_spi_is_vmalloc_xfer(xfer) && IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { rxdesc = dmaengine_prep_slave_single(rxchan, as->dma_addr_rx_bbuf, xfer->len, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } else { rxdesc = dmaengine_prep_slave_sg(rxchan, xfer->rx_sg.sgl, xfer->rx_sg.nents, xfer->rx_sg.sgl, xfer->rx_sg.nents, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (!rxdesc) goto err_dma; if (atmel_spi_is_vmalloc_xfer(xfer) && IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { memcpy(as->addr_tx_bbuf, xfer->tx_buf, xfer->len); txdesc = dmaengine_prep_slave_single(txchan, as->dma_addr_tx_bbuf, xfer->len, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } else { txdesc = dmaengine_prep_slave_sg(txchan, xfer->tx_sg.sgl, xfer->tx_sg.nents, xfer->tx_sg.sgl, xfer->tx_sg.nents, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_PREP_INTERRUPT | DMA_CTRL_ACK); } if (!txdesc) goto err_dma; Loading Loading @@ -1426,27 +1469,7 @@ static void atmel_get_caps(struct atmel_spi *as) as->caps.is_spi2 = version > 0x121; as->caps.has_wdrbt = version >= 0x210; #ifdef CONFIG_SOC_SAM_V4_V5 /* * Atmel SoCs based on ARM9 (SAM9x) cores should not use spi_map_buf() * since this later function tries to map buffers with dma_map_sg() * even if they have not been allocated inside DMA-safe areas. * On SoCs based on Cortex A5 (SAMA5Dx), it works anyway because for * those ARM cores, the data cache follows the PIPT model. * Also the L2 cache controller of SAMA5D2 uses the PIPT model too. * In case of PIPT caches, there cannot be cache aliases. * However on ARM9 cores, the data cache follows the VIVT model, hence * the cache aliases issue can occur when buffers are allocated from * DMA-unsafe areas, by vmalloc() for instance, where cache coherency is * not taken into account or at least not handled completely (cache * lines of aliases are not invalidated). * This is not a theorical issue: it was reproduced when trying to mount * a UBI file-system on a at91sam9g35ek board. */ as->caps.has_dma_support = false; #else as->caps.has_dma_support = version >= 0x212; #endif as->caps.has_pdc_support = version < 0x212; } Loading Loading @@ -1592,6 +1615,30 @@ static int atmel_spi_probe(struct platform_device *pdev) as->use_pdc = true; } if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { as->addr_rx_bbuf = dma_alloc_coherent(&pdev->dev, SPI_MAX_DMA_XFER, &as->dma_addr_rx_bbuf, GFP_KERNEL | GFP_DMA); if (!as->addr_rx_bbuf) { as->use_dma = false; } else { as->addr_tx_bbuf = dma_alloc_coherent(&pdev->dev, SPI_MAX_DMA_XFER, &as->dma_addr_tx_bbuf, GFP_KERNEL | GFP_DMA); if (!as->addr_tx_bbuf) { as->use_dma = false; dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, as->addr_rx_bbuf, as->dma_addr_rx_bbuf); } } if (!as->use_dma) dev_info(master->dev.parent, " can not allocate dma coherent memory\n"); } if (as->caps.has_dma_support && !as->use_dma) dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n"); Loading Loading @@ -1664,6 +1711,14 @@ static int atmel_spi_remove(struct platform_device *pdev) if (as->use_dma) { atmel_spi_stop_dma(master); atmel_spi_release_dma(master); if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, as->addr_tx_bbuf, as->dma_addr_tx_bbuf); dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, as->addr_rx_bbuf, as->dma_addr_rx_bbuf); } } spin_lock_irq(&as->lock); Loading
drivers/spi/spi-bcm53xx.c +10 −16 Original line number Diff line number Diff line Loading @@ -27,8 +27,6 @@ struct bcm53xxspi { struct bcma_device *core; struct spi_master *master; void __iomem *mmio_base; size_t read_offset; bool bspi; /* Boot SPI mode with memory mapping */ }; Loading Loading @@ -172,8 +170,6 @@ static void bcm53xxspi_buf_write(struct bcm53xxspi *b53spi, u8 *w_buf, if (!cont) bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); b53spi->read_offset = len; } static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, Loading @@ -182,10 +178,10 @@ static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, u32 tmp; int i; for (i = 0; i < b53spi->read_offset + len; i++) { for (i = 0; i < len; i++) { tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | B53SPI_CDRAM_PCS_DSCK; if (!cont && i == b53spi->read_offset + len - 1) if (!cont && i == len - 1) tmp &= ~B53SPI_CDRAM_CONT; tmp &= ~0x1; /* Command Register File */ Loading @@ -194,8 +190,7 @@ static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, /* Set queue pointers */ bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, b53spi->read_offset + len - 1); bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); if (cont) bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); Loading @@ -214,13 +209,11 @@ static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); for (i = 0; i < len; ++i) { int offset = b53spi->read_offset + i; u16 reg = B53SPI_MSPI_RXRAM + 4 * (1 + i * 2); /* Data stored in the transmit register file LSB */ r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); r_buf[i] = (u8)bcm53xxspi_read(b53spi, reg); } b53spi->read_offset = 0; } static int bcm53xxspi_transfer_one(struct spi_master *master, Loading @@ -238,7 +231,8 @@ static int bcm53xxspi_transfer_one(struct spi_master *master, left = t->len; while (left) { size_t to_write = min_t(size_t, 16, left); bool cont = left - to_write > 0; bool cont = !spi_transfer_is_last(master, t) || left - to_write > 0; bcm53xxspi_buf_write(b53spi, buf, to_write, cont); left -= to_write; Loading @@ -250,9 +244,9 @@ static int bcm53xxspi_transfer_one(struct spi_master *master, buf = (u8 *)t->rx_buf; left = t->len; while (left) { size_t to_read = min_t(size_t, 16 - b53spi->read_offset, left); bool cont = left - to_read > 0; size_t to_read = min_t(size_t, 16, left); bool cont = !spi_transfer_is_last(master, t) || left - to_read > 0; bcm53xxspi_buf_read(b53spi, buf, to_read, cont); left -= to_read; Loading
drivers/spi/spi-davinci.c +2 −2 Original line number Diff line number Diff line Loading @@ -945,6 +945,8 @@ static int davinci_spi_probe(struct platform_device *pdev) goto free_master; } init_completion(&dspi->done); ret = platform_get_irq(pdev, 0); if (ret == 0) ret = -EINVAL; Loading Loading @@ -1021,8 +1023,6 @@ static int davinci_spi_probe(struct platform_device *pdev) 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); Loading
drivers/spi/spi-dw.c +0 −2 Original line number Diff line number Diff line Loading @@ -30,13 +30,11 @@ /* Slave spi_dev related */ struct chip_data { u8 cs; /* chip select pin */ u8 tmode; /* TR/TO/RO/EEPROM */ u8 type; /* SPI/SSP/MicroWire */ u8 poll_mode; /* 1 means use poll mode */ u8 enable_dma; u16 clk_div; /* baud rate divider */ u32 speed_hz; /* baud rate */ void (*cs_control)(u32 command); Loading