spi: Fix pxa2xx_spi.c chip select sequence error
PATCH 1/1 spi: Fix pxa2xx_spi.c chip select sequence error
From: Ned Forrester <nforrester-/[email protected]>
Applies to kernel 2.6.25-rc1
Fixes a sequencing bug in spi driver pxa2xx_spi.c in which the chip select for a transfer may be asserted before the transmission mode is set on the interface. As a result of this bug, the pins of the interface can make extra transitions after chip select is set and before the intended clock/data signals begin. This only occurs on the first transfer following a change in transmission mode. The fix assures that all modes are set on the interface before asserting chip select.
This bug was introduced in a patch merged on 2006/12/10, kernel 2.6.20.
The patch defines an additional bit in:include/asm-arm/arch-pxa/regs-ssp.h
for 2.6.25 and newer kernels
but this addition must be made in:include/asm-arm/arch-pxa/pxa-regs.h
for kernels between 2.6.20 and 2.6.24, inclusive
---
drivers/spi/pxa2xx_spi.c | 41 +++++++++++++++++--------- include/asm-arm/arch-pxa/regs-ssp.h | 1 2 files changed, 28 insertions(+), 14 deletions(-)
drivers/spi/pxa2xx_spi.c +27 -14
@@ -51,13 +51,19 @@ MODULE_LICENSE("GPL");#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)#define IS_DMA_ALIGNED (x) (((u32)(x)&0x07)==0) -/* for testing SSCR1 changes that require SSP restart, basically -* everything except the service and interrupt enables */ -#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \ +/* +* for testing SSCR1 changes that require SSP restart, basically +* everything except the service and interrupt enables, the pxa270 developer +* manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this +* list, but the PXA255 dev man says all bits without really meaning the +* service and interrupt enables +*/ +#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \ | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \ - | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \ - | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \ - | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) + | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \ + | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \ + | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \ + | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)#define DEFINE_SSP_REG (reg, off) \ static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
@@ -973,9 +979,6 @@ static void pump_transfers(unsigned longif (drv_data->ssp_type == PXA25x_SSP)DCMD (drv_data->tx_channel) |=DCMD_ENDIRQEN ; -/* Fix me, need to handle cs polarity */ - drv_data->cs_control (PXA2XX_CS_ASSERT ); -/* Clear status and start DMA engine */ cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;write_SSSR (drv_data->clear_sr, reg);
@@ -985,9 +988,6 @@ static void pump_transfers(unsigned long/* Ensure we have the correct interrupt handler */ drv_data->transfer_handler = interrupt_transfer; -/* Fix me, need to handle cs polarity */ - drv_data->cs_control (PXA2XX_CS_ASSERT ); -/* Clear status */ cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;write_SSSR (drv_data->clear_sr, reg);
@@ -998,16 +998,29 @@ static void pump_transfers(unsigned long || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) != (cr1 & SSCR1_CHANGE_MASK)) { +/* stop the SSP, and update the other bits */ write_SSCR0 (cr0 & ~SSCR0_SSE , reg);if (drv_data->ssp_type != PXA25x_SSP)write_SSTO (chip->timeout, reg); - write_SSCR1(cr1, reg); +/* first set CR1 without interrupt and service enables */ +write_SSCR1 (cr1 &SSCR1_CHANGE_MASK , reg); +/* restart the SSP */ write_SSCR0 (cr0, reg); + } else {if (drv_data->ssp_type != PXA25x_SSP)write_SSTO (chip->timeout, reg); -write_SSCR1 (cr1, reg); } + +/* FIXME, need to handle cs polarity, +* this driver uses struct pxa2xx_spi_chip.cs_control to +* specify a CS handling function, and it ignores most +* struct spi_device.mode[s], including SPI_CS_HIGH */ + drv_data->cs_control (PXA2XX_CS_ASSERT ); + +/* after chip select, release the data by enabling service +* requests and interrupts, without changing any mode bits */ +write_SSCR1 (cr1, reg); }static void pump_messages (struct work_struct *work)
include/asm-arm/arch-pxa/regs-ssp.h +1 -0
@@ -85,6 +85,7 @@#define SSCR1_RSRE (1 << 20)/* Receive Service Request Enable */ #define SSCR1_TINTE (1 << 19)/* Receiver Time-out Interrupt enable */ #define SSCR1_PINTE (1 << 18)/* Peripheral Trailing Byte Interupt Enable */ +#define SSCR1_IFS (1 << 16)/* Invert Frame Signal */ #define SSCR1_STRF (1 << 15)/* Select FIFO or EFWR */ #define SSCR1_EFWR (1 << 14)/* Enable FIFO Write/Read */
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/