diff options
Diffstat (limited to 'drivers/spi/pxa2xx_spi.c')
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 78 |
1 files changed, 43 insertions, 35 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index d47d3636227f..cf12f2d84be2 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -47,6 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi"); #define MAX_BUSES 3 +#define RX_THRESH_DFLT 8 +#define TX_THRESH_DFLT 8 +#define TIMOUT_DFLT 1000 + #define DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR) #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) #define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0) @@ -348,21 +352,21 @@ static int map_dma_buffers(struct driver_data *drv_data) } else drv_data->tx_map_len = drv_data->len; - /* 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)) - return 0; - - /* Stream map the tx buffer */ + /* 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); + drv_data->tx_map_len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, drv_data->tx_dma)) + return 0; - if (dma_mapping_error(dev, drv_data->tx_dma)) { - dma_unmap_single(dev, drv_data->rx_dma, + /* 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; } @@ -1171,6 +1175,8 @@ static int setup(struct spi_device *spi) struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct ssp_device *ssp = drv_data->ssp; unsigned int clk_div; + uint tx_thres = TX_THRESH_DFLT; + uint rx_thres = RX_THRESH_DFLT; if (!spi->bits_per_word) spi->bits_per_word = 8; @@ -1209,8 +1215,7 @@ static int setup(struct spi_device *spi) chip->cs_control = null_cs_control; chip->enable_dma = 0; - chip->timeout = 1000; - chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); + chip->timeout = TIMOUT_DFLT; chip->dma_burst_size = drv_data->master_info->enable_dma ? DCMD_BURST8 : 0; } @@ -1224,22 +1229,21 @@ static int setup(struct spi_device *spi) if (chip_info) { if (chip_info->cs_control) chip->cs_control = chip_info->cs_control; - - chip->timeout = chip_info->timeout; - - chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) & - SSCR1_RFT) | - (SSCR1_TxTresh(chip_info->tx_threshold) & - SSCR1_TFT); - - chip->enable_dma = chip_info->dma_burst_size != 0 - && drv_data->master_info->enable_dma; + if (chip_info->timeout) + chip->timeout = chip_info->timeout; + if (chip_info->tx_threshold) + tx_thres = chip_info->tx_threshold; + if (chip_info->rx_threshold) + rx_thres = chip_info->rx_threshold; + chip->enable_dma = drv_data->master_info->enable_dma; chip->dma_threshold = 0; - if (chip_info->enable_loopback) chip->cr1 = SSCR1_LBM; } + chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | + (SSCR1_TxTresh(tx_thres) & SSCR1_TFT); + /* set dma burst and threshold outside of chip_info path so that if * chip_info goes away after setting chip->enable_dma, the * burst and threshold can still respond to changes in bits_per_word */ @@ -1268,17 +1272,19 @@ static int setup(struct spi_device *spi) /* NOTE: PXA25x_SSP _could_ use external clocking ... */ if (drv_data->ssp_type != PXA25x_SSP) - dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n", + dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n", spi->bits_per_word, clk_get_rate(ssp->clk) / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), - spi->mode & 0x3); + spi->mode & 0x3, + chip->enable_dma ? "DMA" : "PIO"); else - dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n", + dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d, %s\n", spi->bits_per_word, - clk_get_rate(ssp->clk) + clk_get_rate(ssp->clk) / 2 / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), - spi->mode & 0x3); + spi->mode & 0x3, + chip->enable_dma ? "DMA" : "PIO"); if (spi->bits_per_word <= 8) { chip->n_bytes = 1; @@ -1407,9 +1413,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct pxa2xx_spi_master *platform_info; struct spi_master *master; - struct driver_data *drv_data = NULL; + struct driver_data *drv_data; struct ssp_device *ssp; - int status = 0; + int status; platform_info = dev->platform_data; @@ -1422,7 +1428,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) /* Allocate master with space for drv_data and null dma buffer */ master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); if (!master) { - dev_err(&pdev->dev, "can not alloc spi_master\n"); + dev_err(&pdev->dev, "cannot alloc spi_master\n"); ssp_free(ssp); return -ENOMEM; } @@ -1458,7 +1464,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data); if (status < 0) { - dev_err(&pdev->dev, "can not get IRQ\n"); + dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); goto out_error_master_alloc; } @@ -1498,7 +1504,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) /* Load default SSP configuration */ write_SSCR0(0, drv_data->ioaddr); - write_SSCR1(SSCR1_RxTresh(4) | SSCR1_TxTresh(12), drv_data->ioaddr); + write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | + SSCR1_TxTresh(TX_THRESH_DFLT), + drv_data->ioaddr); write_SSCR0(SSCR0_SerClkDiv(2) | SSCR0_Motorola | SSCR0_DataSize(8), |