aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/pxa2xx_spi.c
diff options
context:
space:
mode:
authorNed Forrester <nforrester@whoi.edu>2008-02-23 18:23:40 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-23 20:12:14 -0500
commitb97c74bddce4e2c6fef6b3b58910b4fd9eb7f3b8 (patch)
tree36e48f2687ba0c54350f740da796f321c7d2500c /drivers/spi/pxa2xx_spi.c
parentf6febccd7f86fbe94858a4a32d9384cc014c9f40 (diff)
spi: pxa2xx_spi clock polarity fix
Fixes a sequencing bug in spi driver pxa2xx_spi.c in which the chip select for a transfer may be asserted before the clock polarity is set on the interface. As a result of this bug, the clock signal may have the wrong polarity at transfer start, so it may need to make an extra half transition before the intended clock/data signals begin. (This probably means all transfers are one bit out of sequence.) This only occurs on the first transfer following a change in clock polarity in systems using more than one more than one such polarity. The fix assures that the clock mode is properly set 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 Signed-off-by: Ned Forrester <nforrester@whoi.edu> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Russell King <rmk@arm.linux.org.uk> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/spi/pxa2xx_spi.c')
-rw-r--r--drivers/spi/pxa2xx_spi.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 365e0e355aea..59deed79e0ab 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -51,13 +51,19 @@ MODULE_LICENSE("GPL");
51#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK) 51#define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
52#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0) 52#define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
53 53
54/* for testing SSCR1 changes that require SSP restart, basically 54/*
55 * everything except the service and interrupt enables */ 55 * for testing SSCR1 changes that require SSP restart, basically
56#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \ 56 * everything except the service and interrupt enables, the pxa270 developer
57 * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
58 * list, but the PXA255 dev man says all bits without really meaning the
59 * service and interrupt enables
60 */
61#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
57 | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \ 62 | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
58 | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \ 63 | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
59 | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \ 64 | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
60 | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM) 65 | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
66 | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
61 67
62#define DEFINE_SSP_REG(reg, off) \ 68#define DEFINE_SSP_REG(reg, off) \
63static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \ 69static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
@@ -973,9 +979,6 @@ static void pump_transfers(unsigned long data)
973 if (drv_data->ssp_type == PXA25x_SSP) 979 if (drv_data->ssp_type == PXA25x_SSP)
974 DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN; 980 DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
975 981
976 /* Fix me, need to handle cs polarity */
977 drv_data->cs_control(PXA2XX_CS_ASSERT);
978
979 /* Clear status and start DMA engine */ 982 /* Clear status and start DMA engine */
980 cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1; 983 cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
981 write_SSSR(drv_data->clear_sr, reg); 984 write_SSSR(drv_data->clear_sr, reg);
@@ -985,9 +988,6 @@ static void pump_transfers(unsigned long data)
985 /* Ensure we have the correct interrupt handler */ 988 /* Ensure we have the correct interrupt handler */
986 drv_data->transfer_handler = interrupt_transfer; 989 drv_data->transfer_handler = interrupt_transfer;
987 990
988 /* Fix me, need to handle cs polarity */
989 drv_data->cs_control(PXA2XX_CS_ASSERT);
990
991 /* Clear status */ 991 /* Clear status */
992 cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1; 992 cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
993 write_SSSR(drv_data->clear_sr, reg); 993 write_SSSR(drv_data->clear_sr, reg);
@@ -998,16 +998,29 @@ static void pump_transfers(unsigned long data)
998 || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) != 998 || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
999 (cr1 & SSCR1_CHANGE_MASK)) { 999 (cr1 & SSCR1_CHANGE_MASK)) {
1000 1000
1001 /* stop the SSP, and update the other bits */
1001 write_SSCR0(cr0 & ~SSCR0_SSE, reg); 1002 write_SSCR0(cr0 & ~SSCR0_SSE, reg);
1002 if (drv_data->ssp_type != PXA25x_SSP) 1003 if (drv_data->ssp_type != PXA25x_SSP)
1003 write_SSTO(chip->timeout, reg); 1004 write_SSTO(chip->timeout, reg);
1004 write_SSCR1(cr1, reg); 1005 /* first set CR1 without interrupt and service enables */
1006 write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
1007 /* restart the SSP */
1005 write_SSCR0(cr0, reg); 1008 write_SSCR0(cr0, reg);
1009
1006 } else { 1010 } else {
1007 if (drv_data->ssp_type != PXA25x_SSP) 1011 if (drv_data->ssp_type != PXA25x_SSP)
1008 write_SSTO(chip->timeout, reg); 1012 write_SSTO(chip->timeout, reg);
1009 write_SSCR1(cr1, reg);
1010 } 1013 }
1014
1015 /* FIXME, need to handle cs polarity,
1016 * this driver uses struct pxa2xx_spi_chip.cs_control to
1017 * specify a CS handling function, and it ignores most
1018 * struct spi_device.mode[s], including SPI_CS_HIGH */
1019 drv_data->cs_control(PXA2XX_CS_ASSERT);
1020
1021 /* after chip select, release the data by enabling service
1022 * requests and interrupts, without changing any mode bits */
1023 write_SSCR1(cr1, reg);
1011} 1024}
1012 1025
1013static void pump_messages(struct work_struct *work) 1026static void pump_messages(struct work_struct *work)