Skip to content

Commit

Permalink
pxa2xx_spi: fix chip_info defaults and documentation.
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Ned Forrester <[email protected]>
Signed-off-by: David Brownell <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Vernon Sauder authored and torvalds committed Oct 16, 2008
1 parent 65a00a2 commit f1f640a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 30 deletions.
34 changes: 23 additions & 11 deletions Documentation/spi/pxa2xx
Original file line number Diff line number Diff line change
Expand Up @@ -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
"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
device.
device. All fields are optional.

struct pxa2xx_spi_chip {
u8 tx_threshold;
Expand All @@ -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
fifo overruns (especially in PIO mode transfers). Good default values are

.tx_threshold = 12,
.rx_threshold = 4,
.tx_threshold = 8,
.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
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
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
trailing bytes in the SSP receiver fifo. The correct value for this field is
Expand All @@ -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
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
"spi_board_info.controller_data" field. Below is a sample configuration using
Expand Down Expand Up @@ -206,18 +215,21 @@ static void __init streetracer_init(void)

DMA and PIO I/O Support
-----------------------
The pxa2xx_spi driver support both DMA and interrupt driven PIO message
transfers. The driver defaults to PIO mode and DMA transfers must enabled by
setting the "enable_dma" flag in the "pxa2xx_spi_master" structure and
ensuring that the "pxa2xx_spi_chip.dma_burst_size" field is non-zero. The DMA
mode support both coherent and stream based DMA mappings.
The pxa2xx_spi driver supports both DMA and interrupt driven PIO message
transfers. The driver defaults to PIO mode and DMA transfers must be enabled
by setting the "enable_dma" flag in the "pxa2xx_spi_master" structure. The DMA
mode supports both coherent and stream based DMA mappings.

The following logic is used to determine the type of I/O to be used on
a per "spi_transfer" basis:

if !enable_dma or dma_burst_size == 0 then
if !enable_dma then
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
use coherent DMA mode

Expand Down
46 changes: 27 additions & 19 deletions drivers/spi/pxa2xx_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit f1f640a

Please sign in to comment.