Commit 8d94cc50 authored by Stephen Street's avatar Stephen Street Committed by Linus Torvalds

[PATCH] spi: stabilize PIO mode transfers on PXA2xx systems

Stabilize PIO mode transfers against a range of word sizes and FIFO
thresholds and fixes word size setup/override issues.

1) 16 and 32 bit DMA/PIO transfers broken due to timing differences.
2) Potential for bad transfer counts due to transfer size assumptions.
3) Setup function broken is multiple ways.
4) Per transfer bit_per_word changes break DMA setup in pump_tranfers.
5) False positive timeout are not errors.
6) Changes in pxa2xx_spi_chip not effective in calls to setup.
7) Timeout scaling wrong for PXA255 NSSP.
8) Driver leaks memory while busy during unloading.

Known issues:

SPI_CS_HIGH and SPI_LSB_FIRST settings in struct spi_device are not handled.

Testing:

This patch has been test against the "random length, random bits/word,
random data (verified on loopback) and stepped baud rate by octaves
(3.6MHz to 115kHz)" test.  It is robust in PIO mode, using any
combination of tx and rx thresholds, and also in DMA mode (which
internally computes the thresholds).

Much thanks to Ned Forrester for exhaustive reviews, fixes and testing.
The driver is substantially better for his efforts.
Signed-off-by: default avatarStephen Street <stephen@streetfiresound.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6451956a
...@@ -102,7 +102,7 @@ struct pxa2xx_spi_chip { ...@@ -102,7 +102,7 @@ struct pxa2xx_spi_chip {
u8 tx_threshold; u8 tx_threshold;
u8 rx_threshold; u8 rx_threshold;
u8 dma_burst_size; u8 dma_burst_size;
u32 timeout_microsecs; u32 timeout;
u8 enable_loopback; u8 enable_loopback;
void (*cs_control)(u32 command); void (*cs_control)(u32 command);
}; };
...@@ -121,7 +121,7 @@ the PXA2xx "Developer Manual" sections on the DMA controller and SSP Controllers ...@@ -121,7 +121,7 @@ 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 "pxa2xx_spi_chip.timeout_microsecs" 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
dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific dependent on the SPI bus speed ("spi_board_info.max_speed_hz") and the specific
slave device. Please note that the PXA2xx SSP 1 does not support trailing byte slave device. Please note that the PXA2xx SSP 1 does not support trailing byte
...@@ -162,18 +162,18 @@ static void cs8405a_cs_control(u32 command) ...@@ -162,18 +162,18 @@ static void cs8405a_cs_control(u32 command)
} }
static struct pxa2xx_spi_chip cs8415a_chip_info = { static struct pxa2xx_spi_chip cs8415a_chip_info = {
.tx_threshold = 12, /* SSP hardward FIFO threshold */ .tx_threshold = 8, /* SSP hardward FIFO threshold */
.rx_threshold = 4, /* SSP hardward FIFO threshold */ .rx_threshold = 8, /* SSP hardward FIFO threshold */
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
.timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */ .timeout = 235, /* See Intel documentation */
.cs_control = cs8415a_cs_control, /* Use external chip select */ .cs_control = cs8415a_cs_control, /* Use external chip select */
}; };
static struct pxa2xx_spi_chip cs8405a_chip_info = { static struct pxa2xx_spi_chip cs8405a_chip_info = {
.tx_threshold = 12, /* SSP hardward FIFO threshold */ .tx_threshold = 8, /* SSP hardward FIFO threshold */
.rx_threshold = 4, /* SSP hardward FIFO threshold */ .rx_threshold = 8, /* SSP hardward FIFO threshold */
.dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */ .dma_burst_size = 8, /* Byte wide transfers used so 8 byte bursts */
.timeout_microsecs = 64, /* Wait at least 64usec to handle trailing */ .timeout = 235, /* See Intel documentation */
.cs_control = cs8405a_cs_control, /* Use external chip select */ .cs_control = cs8405a_cs_control, /* Use external chip select */
}; };
......
This diff is collapsed.
...@@ -27,16 +27,13 @@ ...@@ -27,16 +27,13 @@
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00) #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00)
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP_TIMEOUT_SCALE (2712)
#elif defined(CONFIG_PXA27x) #elif defined(CONFIG_PXA27x)
#define CLOCK_SPEED_HZ 13000000 #define CLOCK_SPEED_HZ 13000000
#define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00)
#define SSP_TIMEOUT_SCALE (769)
#endif #endif
#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE)
#define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1))))) #define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1)))))
#define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2))))) #define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2)))))
#define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3))))) #define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3)))))
...@@ -63,7 +60,7 @@ struct pxa2xx_spi_chip { ...@@ -63,7 +60,7 @@ struct pxa2xx_spi_chip {
u8 tx_threshold; u8 tx_threshold;
u8 rx_threshold; u8 rx_threshold;
u8 dma_burst_size; u8 dma_burst_size;
u32 timeout_microsecs; u32 timeout;
u8 enable_loopback; u8 enable_loopback;
void (*cs_control)(u32 command); void (*cs_control)(u32 command);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment