| /* |
| * 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. |
| * |
| * 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., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/delay.h> |
| #include <linux/device.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/pxa2xx_ssp.h> |
| #include <linux/spi/spi.h> |
| #include <linux/spi/pxa2xx_spi.h> |
| |
| #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(void const __iomem *ioaddr) |
| { |
| unsigned long limit = loops_per_jiffy << 1; |
| |
| while ((read_SSSR(ioaddr) & 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) |
| { |
| void __iomem *reg = drv_data->ioaddr; |
| |
| /* 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); |
| write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); |
| if (!pxa25x_ssp_comp(drv_data)) |
| write_SSTO(0, reg); |
| pxa2xx_spi_flush(drv_data); |
| write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); |
| |
| 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) |
| { |
| void __iomem *reg = drv_data->ioaddr; |
| struct spi_message *msg = drv_data->cur_msg; |
| |
| /* Clear and disable interrupts on SSP and DMA channels*/ |
| write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); |
| 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->ioaddr) == 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; |
| void __iomem *reg = drv_data->ioaddr; |
| |
| irq_status = read_SSSR(reg) & 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)) { |
| write_SSSR(SSSR_TINT, reg); |
| 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)) |
| write_SSTO(0, reg); |
| |
| /* 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; |
| } |