pxa2xx_spi: fix chip_info defaults and documentation.

Make the chip info structure data optional by providing reasonable
defaults.  Improve corresponding documentation, and highlight the drawback
of not providing explicit chipselect control.

DMA can determine appropriate dma_burst_size and thresholds automatically
so use DMA even if dma_burst_size is not specified.

Signed-off-by: Vernon Sauder <VernonInHand@gmail.com>
Reviewed-by: Ned Forrester <nforrester@whoi.edu>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Vernon Sauder 2008-10-15 22:02:43 -07:00 committed by Linus Torvalds
parent 65a00a2065
commit f1f640a9c1
2 changed files with 50 additions and 30 deletions

View file

@ -96,7 +96,7 @@ Each slave device attached to the PXA must provide slave specific configuration
information via the structure "pxa2xx_spi_chip" found in information via the structure "pxa2xx_spi_chip" found in
"arch/arm/mach-pxa/include/mach/pxa2xx_spi.h". The pxa2xx_spi master controller driver "arch/arm/mach-pxa/include/mach/pxa2xx_spi.h". The pxa2xx_spi master controller driver
will uses the configuration whenever the driver communicates with the slave will uses the configuration whenever the driver communicates with the slave
device. device. All fields are optional.
struct pxa2xx_spi_chip { struct pxa2xx_spi_chip {
u8 tx_threshold; u8 tx_threshold;
@ -112,14 +112,17 @@ used to configure the SSP hardware fifo. These fields are critical to the
performance of pxa2xx_spi driver and misconfiguration will result in rx performance of pxa2xx_spi driver and misconfiguration will result in rx
fifo overruns (especially in PIO mode transfers). Good default values are fifo overruns (especially in PIO mode transfers). Good default values are
.tx_threshold = 12, .tx_threshold = 8,
.rx_threshold = 4, .rx_threshold = 8,
The range is 1 to 16 where zero indicates "use default".
The "pxa2xx_spi_chip.dma_burst_size" field is used to configure PXA2xx DMA The "pxa2xx_spi_chip.dma_burst_size" field is used to configure PXA2xx DMA
engine and is related the "spi_device.bits_per_word" field. Read and understand engine and is related the "spi_device.bits_per_word" field. Read and understand
the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers
to determine the correct value. An SSP configured for byte-wide transfers would to determine the correct value. An SSP configured for byte-wide transfers would
use a value of 8. use a value of 8. The driver will determine a reasonable default if
dma_burst_size == 0.
The "pxa2xx_spi_chip.timeout" fields is used to efficiently handle The "pxa2xx_spi_chip.timeout" fields is used to efficiently handle
trailing bytes in the SSP receiver fifo. The correct value for this field is trailing bytes in the SSP receiver fifo. The correct value for this field is
@ -137,7 +140,13 @@ function for asserting/deasserting a slave device chip select. If the field is
NULL, the pxa2xx_spi master controller driver assumes that the SSP port is NULL, the pxa2xx_spi master controller driver assumes that the SSP port is
configured to use SSPFRM instead. configured to use SSPFRM instead.
NSSP SALVE SAMPLE NOTE: the SPI driver cannot control the chip select if SSPFRM is used, so the
chipselect is dropped after each spi_transfer. Most devices need chip select
asserted around the complete message. Use SSPFRM as a GPIO (through cs_control)
to accomodate these chips.
NSSP SLAVE SAMPLE
----------------- -----------------
The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the The pxa2xx_spi_chip structure is passed to the pxa2xx_spi driver in the
"spi_board_info.controller_data" field. Below is a sample configuration using "spi_board_info.controller_data" field. Below is a sample configuration using
@ -206,18 +215,21 @@ static void __init streetracer_init(void)
DMA and PIO I/O Support DMA and PIO I/O Support
----------------------- -----------------------
The pxa2xx_spi driver support both DMA and interrupt driven PIO message The pxa2xx_spi driver supports both DMA and interrupt driven PIO message
transfers. The driver defaults to PIO mode and DMA transfers must enabled by transfers. The driver defaults to PIO mode and DMA transfers must be enabled
setting the "enable_dma" flag in the "pxa2xx_spi_master" structure and by setting the "enable_dma" flag in the "pxa2xx_spi_master" structure. The DMA
ensuring that the "pxa2xx_spi_chip.dma_burst_size" field is non-zero. The DMA mode supports both coherent and stream based DMA mappings.
mode support both coherent and stream based DMA mappings.
The following logic is used to determine the type of I/O to be used on The following logic is used to determine the type of I/O to be used on
a per "spi_transfer" basis: a per "spi_transfer" basis:
if !enable_dma or dma_burst_size == 0 then if !enable_dma then
always use PIO transfers always use PIO transfers
if spi_message.len > 8191 then
print "rate limited" warning
use PIO transfers
if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then if spi_message.is_dma_mapped and rx_dma_buf != 0 and tx_dma_buf != 0 then
use coherent DMA mode use coherent DMA mode

View file

@ -47,6 +47,10 @@ MODULE_ALIAS("platform:pxa2xx-spi");
#define MAX_BUSES 3 #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 DMA_INT_MASK (DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR)
#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
#define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0) #define IS_DMA_ALIGNED(x) ((((u32)(x)) & 0x07) == 0)
@ -1171,6 +1175,8 @@ static int setup(struct spi_device *spi)
struct driver_data *drv_data = spi_master_get_devdata(spi->master); struct driver_data *drv_data = spi_master_get_devdata(spi->master);
struct ssp_device *ssp = drv_data->ssp; struct ssp_device *ssp = drv_data->ssp;
unsigned int clk_div; unsigned int clk_div;
uint tx_thres = TX_THRESH_DFLT;
uint rx_thres = RX_THRESH_DFLT;
if (!spi->bits_per_word) if (!spi->bits_per_word)
spi->bits_per_word = 8; spi->bits_per_word = 8;
@ -1209,8 +1215,7 @@ static int setup(struct spi_device *spi)
chip->cs_control = null_cs_control; chip->cs_control = null_cs_control;
chip->enable_dma = 0; chip->enable_dma = 0;
chip->timeout = 1000; chip->timeout = TIMOUT_DFLT;
chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1);
chip->dma_burst_size = drv_data->master_info->enable_dma ? chip->dma_burst_size = drv_data->master_info->enable_dma ?
DCMD_BURST8 : 0; DCMD_BURST8 : 0;
} }
@ -1224,22 +1229,21 @@ static int setup(struct spi_device *spi)
if (chip_info) { if (chip_info) {
if (chip_info->cs_control) if (chip_info->cs_control)
chip->cs_control = chip_info->cs_control; chip->cs_control = chip_info->cs_control;
if (chip_info->timeout)
chip->timeout = chip_info->timeout; chip->timeout = chip_info->timeout;
if (chip_info->tx_threshold)
chip->threshold = (SSCR1_RxTresh(chip_info->rx_threshold) & tx_thres = chip_info->tx_threshold;
SSCR1_RFT) | if (chip_info->rx_threshold)
(SSCR1_TxTresh(chip_info->tx_threshold) & rx_thres = chip_info->rx_threshold;
SSCR1_TFT); chip->enable_dma = drv_data->master_info->enable_dma;
chip->enable_dma = chip_info->dma_burst_size != 0
&& drv_data->master_info->enable_dma;
chip->dma_threshold = 0; chip->dma_threshold = 0;
if (chip_info->enable_loopback) if (chip_info->enable_loopback)
chip->cr1 = SSCR1_LBM; 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 /* set dma burst and threshold outside of chip_info path so that if
* chip_info goes away after setting chip->enable_dma, the * chip_info goes away after setting chip->enable_dma, the
* burst and threshold can still respond to changes in bits_per_word */ * 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 ... */ /* NOTE: PXA25x_SSP _could_ use external clocking ... */
if (drv_data->ssp_type != PXA25x_SSP) 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, spi->bits_per_word,
clk_get_rate(ssp->clk) clk_get_rate(ssp->clk)
/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
spi->mode & 0x3); spi->mode & 0x3,
chip->enable_dma ? "DMA" : "PIO");
else 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, spi->bits_per_word,
clk_get_rate(ssp->clk) clk_get_rate(ssp->clk) / 2
/ (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)),
spi->mode & 0x3); spi->mode & 0x3,
chip->enable_dma ? "DMA" : "PIO");
if (spi->bits_per_word <= 8) { if (spi->bits_per_word <= 8) {
chip->n_bytes = 1; chip->n_bytes = 1;
@ -1498,7 +1504,9 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev)
/* Load default SSP configuration */ /* Load default SSP configuration */
write_SSCR0(0, drv_data->ioaddr); 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) write_SSCR0(SSCR0_SerClkDiv(2)
| SSCR0_Motorola | SSCR0_Motorola
| SSCR0_DataSize(8), | SSCR0_DataSize(8),