Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 114793
b: refs/heads/master
c: f1f640a
h: refs/heads/master
i:
  114791: 1174212
v: v3
  • Loading branch information
Vernon Sauder authored and Linus Torvalds committed Oct 16, 2008
1 parent ca84660 commit 1e520c7
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 65a00a20655f4929c4991017e230175f61c8f052
refs/heads/master: f1f640a9c1d97a1a131879ab1efe3766443904d7
34 changes: 23 additions & 11 deletions trunk/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 trunk/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 1e520c7

Please sign in to comment.