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