[ARM] 3760/1: This patch adds timeouts while working with SSP registers. Such timeouts were en

Patch from Paul Sokolovsky

This patch adds timeouts while working with SSP registers. Such
timeouts were envisioned by docstrings in ssp.c, but were not
implemented. There were actual lockups while accessing
touchscreen for iPaqs h1910, h4000 due to lack of the timeouts.
This is updated version of previously submitted patch: 3738/1.

Signed-off-by: Paul Sokolovsky <pmiscml@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by Paul Sokolovsky and committed by Russell King 8f1bf874 b53a2b41

+84 -29
+12 -8
arch/arm/mach-pxa/corgi_ssp.c
··· 47 */ 48 unsigned long corgi_ssp_ads7846_putget(ulong data) 49 { 50 - unsigned long ret,flag; 51 52 spin_lock_irqsave(&corgi_ssp_lock, flag); 53 if (ssp_machinfo->cs_ads7846 >= 0) 54 GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); 55 56 ssp_write_word(&corgi_ssp_dev,data); 57 - ret = ssp_read_word(&corgi_ssp_dev); 58 59 if (ssp_machinfo->cs_ads7846 >= 0) 60 GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); ··· 89 90 unsigned long corgi_ssp_ads7846_get(void) 91 { 92 - return ssp_read_word(&corgi_ssp_dev); 93 } 94 95 EXPORT_SYMBOL(corgi_ssp_ads7846_putget); ··· 107 unsigned long corgi_ssp_dac_put(ulong data) 108 { 109 unsigned long flag, sscr1 = SSCR1_SPH; 110 111 spin_lock_irqsave(&corgi_ssp_lock, flag); 112 ··· 122 GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); 123 ssp_write_word(&corgi_ssp_dev,data); 124 /* Read null data back from device to prevent SSP overflow */ 125 - ssp_read_word(&corgi_ssp_dev); 126 if (ssp_machinfo->cs_lcdcon >= 0) 127 GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); 128 ··· 154 int corgi_ssp_max1111_get(ulong data) 155 { 156 unsigned long flag; 157 - int voltage,voltage1,voltage2; 158 159 spin_lock_irqsave(&corgi_ssp_lock, flag); 160 if (ssp_machinfo->cs_max1111 >= 0) ··· 167 168 /* TB1/RB1 */ 169 ssp_write_word(&corgi_ssp_dev,data); 170 - ssp_read_word(&corgi_ssp_dev); /* null read */ 171 172 /* TB12/RB2 */ 173 ssp_write_word(&corgi_ssp_dev,0); 174 - voltage1=ssp_read_word(&corgi_ssp_dev); 175 176 /* TB13/RB3*/ 177 ssp_write_word(&corgi_ssp_dev,0); 178 - voltage2=ssp_read_word(&corgi_ssp_dev); 179 180 ssp_disable(&corgi_ssp_dev); 181 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
··· 47 */ 48 unsigned long corgi_ssp_ads7846_putget(ulong data) 49 { 50 + unsigned long flag; 51 + u32 ret = 0; 52 53 spin_lock_irqsave(&corgi_ssp_lock, flag); 54 if (ssp_machinfo->cs_ads7846 >= 0) 55 GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); 56 57 ssp_write_word(&corgi_ssp_dev,data); 58 + ssp_read_word(&corgi_ssp_dev, &ret); 59 60 if (ssp_machinfo->cs_ads7846 >= 0) 61 GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); ··· 88 89 unsigned long corgi_ssp_ads7846_get(void) 90 { 91 + u32 ret = 0; 92 + ssp_read_word(&corgi_ssp_dev, &ret); 93 + return ret; 94 } 95 96 EXPORT_SYMBOL(corgi_ssp_ads7846_putget); ··· 104 unsigned long corgi_ssp_dac_put(ulong data) 105 { 106 unsigned long flag, sscr1 = SSCR1_SPH; 107 + u32 tmp; 108 109 spin_lock_irqsave(&corgi_ssp_lock, flag); 110 ··· 118 GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); 119 ssp_write_word(&corgi_ssp_dev,data); 120 /* Read null data back from device to prevent SSP overflow */ 121 + ssp_read_word(&corgi_ssp_dev, &tmp); 122 if (ssp_machinfo->cs_lcdcon >= 0) 123 GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); 124 ··· 150 int corgi_ssp_max1111_get(ulong data) 151 { 152 unsigned long flag; 153 + long voltage = 0, voltage1 = 0, voltage2 = 0; 154 155 spin_lock_irqsave(&corgi_ssp_lock, flag); 156 if (ssp_machinfo->cs_max1111 >= 0) ··· 163 164 /* TB1/RB1 */ 165 ssp_write_word(&corgi_ssp_dev,data); 166 + ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */ 167 168 /* TB12/RB2 */ 169 ssp_write_word(&corgi_ssp_dev,0); 170 + ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); 171 172 /* TB13/RB3*/ 173 ssp_write_word(&corgi_ssp_dev,0); 174 + ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2); 175 176 ssp_disable(&corgi_ssp_dev); 177 ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
+29 -8
arch/arm/mach-pxa/ssp.c
··· 40 41 #define PXA_SSP_PORTS 3 42 43 struct ssp_info_ { 44 int irq; 45 u32 clock; ··· 94 * The caller is expected to perform the necessary locking. 95 * 96 * Returns: 97 - * %-ETIMEDOUT timeout occurred (for future) 98 * 0 success 99 */ 100 int ssp_write_word(struct ssp_dev *dev, u32 data) 101 { 102 - while (!(SSSR_P(dev->port) & SSSR_TNF)) 103 cpu_relax(); 104 105 SSDR_P(dev->port) = data; 106 ··· 124 * The caller is expected to perform the necessary locking. 125 * 126 * Returns: 127 - * %-ETIMEDOUT timeout occurred (for future) 128 * 32-bit data success 129 */ 130 - int ssp_read_word(struct ssp_dev *dev) 131 { 132 - while (!(SSSR_P(dev->port) & SSSR_RNE)) 133 - cpu_relax(); 134 135 - return SSDR_P(dev->port); 136 } 137 138 /** ··· 149 * 150 * The caller is expected to perform the necessary locking. 151 */ 152 - void ssp_flush(struct ssp_dev *dev) 153 { 154 do { 155 while (SSSR_P(dev->port) & SSSR_RNE) { 156 (void) SSDR_P(dev->port); 157 } 158 } while (SSSR_P(dev->port) & SSSR_BSY); 159 } 160 161 /**
··· 40 41 #define PXA_SSP_PORTS 3 42 43 + #define TIMEOUT 100000 44 + 45 struct ssp_info_ { 46 int irq; 47 u32 clock; ··· 92 * The caller is expected to perform the necessary locking. 93 * 94 * Returns: 95 + * %-ETIMEDOUT timeout occurred 96 * 0 success 97 */ 98 int ssp_write_word(struct ssp_dev *dev, u32 data) 99 { 100 + int timeout = TIMEOUT; 101 + 102 + while (!(SSSR_P(dev->port) & SSSR_TNF)) { 103 + if (!--timeout) 104 + return -ETIMEDOUT; 105 cpu_relax(); 106 + } 107 108 SSDR_P(dev->port) = data; 109 ··· 117 * The caller is expected to perform the necessary locking. 118 * 119 * Returns: 120 + * %-ETIMEDOUT timeout occurred 121 * 32-bit data success 122 */ 123 + int ssp_read_word(struct ssp_dev *dev, u32 *data) 124 { 125 + int timeout = TIMEOUT; 126 127 + while (!(SSSR_P(dev->port) & SSSR_RNE)) { 128 + if (!--timeout) 129 + return -ETIMEDOUT; 130 + cpu_relax(); 131 + } 132 + 133 + *data = SSDR_P(dev->port); 134 + return 0; 135 } 136 137 /** ··· 136 * 137 * The caller is expected to perform the necessary locking. 138 */ 139 + int ssp_flush(struct ssp_dev *dev) 140 { 141 + int timeout = TIMEOUT * 2; 142 + 143 do { 144 while (SSSR_P(dev->port) & SSSR_RNE) { 145 + if (!--timeout) 146 + return -ETIMEDOUT; 147 (void) SSDR_P(dev->port); 148 } 149 + if (!--timeout) 150 + return -ETIMEDOUT; 151 } while (SSSR_P(dev->port) & SSSR_BSY); 152 + 153 + return 0; 154 } 155 156 /**
+39 -9
arch/arm/mach-sa1100/ssp.c
··· 23 #include <asm/hardware.h> 24 #include <asm/hardware/ssp.h> 25 26 static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) 27 { 28 unsigned int status = Ser4SSSR; ··· 49 * The caller is expected to perform the necessary locking. 50 * 51 * Returns: 52 - * %-ETIMEDOUT timeout occurred (for future) 53 * 0 success 54 */ 55 int ssp_write_word(u16 data) 56 { 57 - while (!(Ser4SSSR & SSSR_TNF)) 58 cpu_relax(); 59 60 Ser4SSDR = data; 61 62 - while (!(Ser4SSSR & SSSR_BSY)) 63 cpu_relax(); 64 65 return 0; 66 } ··· 86 * The caller is expected to perform the necessary locking. 87 * 88 * Returns: 89 - * %-ETIMEDOUT timeout occurred (for future) 90 * 16-bit data success 91 */ 92 - int ssp_read_word(void) 93 { 94 - while (!(Ser4SSSR & SSSR_RNE)) 95 - cpu_relax(); 96 97 - return Ser4SSDR; 98 } 99 100 /** ··· 111 * is empty. 112 * 113 * The caller is expected to perform the necessary locking. 114 */ 115 - void ssp_flush(void) 116 { 117 do { 118 while (Ser4SSSR & SSSR_RNE) { 119 (void) Ser4SSDR; 120 } 121 } while (Ser4SSSR & SSSR_BSY); 122 } 123 124 /**
··· 23 #include <asm/hardware.h> 24 #include <asm/hardware/ssp.h> 25 26 + #define TIMEOUT 100000 27 + 28 static irqreturn_t ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) 29 { 30 unsigned int status = Ser4SSSR; ··· 47 * The caller is expected to perform the necessary locking. 48 * 49 * Returns: 50 + * %-ETIMEDOUT timeout occurred 51 * 0 success 52 */ 53 int ssp_write_word(u16 data) 54 { 55 + int timeout = TIMEOUT; 56 + 57 + while (!(Ser4SSSR & SSSR_TNF)) { 58 + if (!--timeout) 59 + return -ETIMEDOUT; 60 cpu_relax(); 61 + } 62 63 Ser4SSDR = data; 64 65 + timeout = TIMEOUT; 66 + while (!(Ser4SSSR & SSSR_BSY)) { 67 + if (!--timeout) 68 + return -ETIMEDOUT; 69 cpu_relax(); 70 + } 71 72 return 0; 73 } ··· 75 * The caller is expected to perform the necessary locking. 76 * 77 * Returns: 78 + * %-ETIMEDOUT timeout occurred 79 * 16-bit data success 80 */ 81 + int ssp_read_word(u16 *data) 82 { 83 + int timeout = TIMEOUT; 84 85 + while (!(Ser4SSSR & SSSR_RNE)) { 86 + if (!--timeout) 87 + return -ETIMEDOUT; 88 + cpu_relax(); 89 + } 90 + 91 + *data = (u16)Ser4SSDR; 92 + 93 + return 0; 94 } 95 96 /** ··· 93 * is empty. 94 * 95 * The caller is expected to perform the necessary locking. 96 + * 97 + * Returns: 98 + * %-ETIMEDOUT timeout occurred 99 + * 0 success 100 */ 101 + int ssp_flush(void) 102 { 103 + int timeout = TIMEOUT * 2; 104 + 105 do { 106 while (Ser4SSSR & SSSR_RNE) { 107 + if (!--timeout) 108 + return -ETIMEDOUT; 109 (void) Ser4SSDR; 110 } 111 + if (!--timeout) 112 + return -ETIMEDOUT; 113 } while (Ser4SSSR & SSSR_BSY); 114 + 115 + return 0; 116 } 117 118 /**
+2 -2
include/asm-arm/arch-pxa/ssp.h
··· 40 }; 41 42 int ssp_write_word(struct ssp_dev *dev, u32 data); 43 - int ssp_read_word(struct ssp_dev *dev); 44 - void ssp_flush(struct ssp_dev *dev); 45 void ssp_enable(struct ssp_dev *dev); 46 void ssp_disable(struct ssp_dev *dev); 47 void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
··· 40 }; 41 42 int ssp_write_word(struct ssp_dev *dev, u32 data); 43 + int ssp_read_word(struct ssp_dev *dev, u32 *data); 44 + int ssp_flush(struct ssp_dev *dev); 45 void ssp_enable(struct ssp_dev *dev); 46 void ssp_disable(struct ssp_dev *dev); 47 void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
+2 -2
include/asm-arm/hardware/ssp.h
··· 16 }; 17 18 int ssp_write_word(u16 data); 19 - int ssp_read_word(void); 20 - void ssp_flush(void); 21 void ssp_enable(void); 22 void ssp_disable(void); 23 void ssp_save_state(struct ssp_state *ssp);
··· 16 }; 17 18 int ssp_write_word(u16 data); 19 + int ssp_read_word(u16 *data); 20 + int ssp_flush(void); 21 void ssp_enable(void); 22 void ssp_disable(void); 23 void ssp_save_state(struct ssp_state *ssp);