aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/hp_sdc_mlc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/serio/hp_sdc_mlc.c')
-rw-r--r--drivers/input/serio/hp_sdc_mlc.c227
1 files changed, 110 insertions, 117 deletions
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
index aa4a8a4ccfdb..c45ea74d53e4 100644
--- a/drivers/input/serio/hp_sdc_mlc.c
+++ b/drivers/input/serio/hp_sdc_mlc.c
@@ -58,12 +58,13 @@ struct hp_sdc_mlc_priv_s {
58} hp_sdc_mlc_priv; 58} hp_sdc_mlc_priv;
59 59
60/************************* Interrupt context ******************************/ 60/************************* Interrupt context ******************************/
61static void hp_sdc_mlc_isr (int irq, void *dev_id, 61static void hp_sdc_mlc_isr (int irq, void *dev_id,
62 uint8_t status, uint8_t data) { 62 uint8_t status, uint8_t data)
63 int idx; 63{
64 int idx;
64 hil_mlc *mlc = &hp_sdc_mlc; 65 hil_mlc *mlc = &hp_sdc_mlc;
65 66
66 write_lock(&(mlc->lock)); 67 write_lock(&mlc->lock);
67 if (mlc->icount < 0) { 68 if (mlc->icount < 0) {
68 printk(KERN_WARNING PREFIX "HIL Overflow!\n"); 69 printk(KERN_WARNING PREFIX "HIL Overflow!\n");
69 up(&mlc->isem); 70 up(&mlc->isem);
@@ -73,239 +74,232 @@ static void hp_sdc_mlc_isr (int irq, void *dev_id,
73 if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) { 74 if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
74 mlc->ipacket[idx] |= data | HIL_ERR_INT; 75 mlc->ipacket[idx] |= data | HIL_ERR_INT;
75 mlc->icount--; 76 mlc->icount--;
76 if (hp_sdc_mlc_priv.got5x) goto check; 77 if (hp_sdc_mlc_priv.got5x || !idx)
77 if (!idx) goto check; 78 goto check;
78 if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) != 79 if ((mlc->ipacket[idx - 1] & HIL_PKT_ADDR_MASK) !=
79 (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) { 80 (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
80 mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK; 81 mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
81 mlc->ipacket[idx] |= (mlc->ipacket[idx-1] 82 mlc->ipacket[idx] |= (mlc->ipacket[idx - 1]
82 & HIL_PKT_ADDR_MASK); 83 & HIL_PKT_ADDR_MASK);
83 } 84 }
84 goto check; 85 goto check;
85 } 86 }
86 /* We know status is 5X */ 87 /* We know status is 5X */
87 if (data & HP_SDC_HIL_ISERR) goto err; 88 if (data & HP_SDC_HIL_ISERR)
88 mlc->ipacket[idx] = 89 goto err;
90 mlc->ipacket[idx] =
89 (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT; 91 (data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
90 hp_sdc_mlc_priv.got5x = 1; 92 hp_sdc_mlc_priv.got5x = 1;
91 goto out; 93 goto out;
92 94
93 check: 95 check:
94 hp_sdc_mlc_priv.got5x = 0; 96 hp_sdc_mlc_priv.got5x = 0;
95 if (mlc->imatch == 0) goto done; 97 if (mlc->imatch == 0)
96 if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 98 goto done;
97 && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done; 99 if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL))
98 if (mlc->ipacket[idx] == mlc->imatch) goto done; 100 && (mlc->ipacket[idx] == (mlc->imatch | idx)))
101 goto done;
102 if (mlc->ipacket[idx] == mlc->imatch)
103 goto done;
99 goto out; 104 goto out;
100 105
101 err: 106 err:
102 printk(KERN_DEBUG PREFIX "err code %x\n", data); 107 printk(KERN_DEBUG PREFIX "err code %x\n", data);
108
103 switch (data) { 109 switch (data) {
104 case HP_SDC_HIL_RC_DONE: 110 case HP_SDC_HIL_RC_DONE:
105 printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n"); 111 printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
106 break; 112 break;
113
107 case HP_SDC_HIL_ERR: 114 case HP_SDC_HIL_ERR:
108 mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 115 mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR |
109 HIL_ERR_FERR | HIL_ERR_FOF; 116 HIL_ERR_FERR | HIL_ERR_FOF;
110 break; 117 break;
118
111 case HP_SDC_HIL_TO: 119 case HP_SDC_HIL_TO:
112 mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR; 120 mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
113 break; 121 break;
122
114 case HP_SDC_HIL_RC: 123 case HP_SDC_HIL_RC:
115 printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n"); 124 printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
116 break; 125 break;
126
117 default: 127 default:
118 printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data); 128 printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
119 break; 129 break;
120 } 130 }
131
121 /* No more data will be coming due to an error. */ 132 /* No more data will be coming due to an error. */
122 done: 133 done:
123 tasklet_schedule(mlc->tasklet); 134 tasklet_schedule(mlc->tasklet);
124 up(&(mlc->isem)); 135 up(&mlc->isem);
125 out: 136 out:
126 write_unlock(&(mlc->lock)); 137 write_unlock(&mlc->lock);
127} 138}
128 139
129 140
130/******************** Tasklet or userspace context functions ****************/ 141/******************** Tasklet or userspace context functions ****************/
131 142
132static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) { 143static int hp_sdc_mlc_in(hil_mlc *mlc, suseconds_t timeout)
133 unsigned long flags; 144{
134 struct hp_sdc_mlc_priv_s *priv; 145 struct hp_sdc_mlc_priv_s *priv;
135 int rc = 2; 146 int rc = 2;
136 147
137 priv = mlc->priv; 148 priv = mlc->priv;
138 149
139 write_lock_irqsave(&(mlc->lock), flags);
140
141 /* Try to down the semaphore */ 150 /* Try to down the semaphore */
142 if (down_trylock(&(mlc->isem))) { 151 if (down_trylock(&mlc->isem)) {
143 struct timeval tv; 152 struct timeval tv;
144 if (priv->emtestmode) { 153 if (priv->emtestmode) {
145 mlc->ipacket[0] = 154 mlc->ipacket[0] =
146 HIL_ERR_INT | (mlc->opacket & 155 HIL_ERR_INT | (mlc->opacket &
147 (HIL_PKT_CMD | 156 (HIL_PKT_CMD |
148 HIL_PKT_ADDR_MASK | 157 HIL_PKT_ADDR_MASK |
149 HIL_PKT_DATA_MASK)); 158 HIL_PKT_DATA_MASK));
150 mlc->icount = 14; 159 mlc->icount = 14;
151 /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */ 160 /* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
152 goto wasup; 161 goto wasup;
153 } 162 }
154 do_gettimeofday(&tv); 163 do_gettimeofday(&tv);
155 tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec); 164 tv.tv_usec += USEC_PER_SEC * (tv.tv_sec - mlc->instart.tv_sec);
156 if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) { 165 if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
157 /* printk("!%i %i", 166 /* printk("!%i %i",
158 tv.tv_usec - mlc->instart.tv_usec, 167 tv.tv_usec - mlc->instart.tv_usec,
159 mlc->intimeout); 168 mlc->intimeout);
160 */ 169 */
161 rc = 1; 170 rc = 1;
162 up(&(mlc->isem)); 171 up(&mlc->isem);
163 } 172 }
164 goto done; 173 goto done;
165 } 174 }
166 wasup: 175 wasup:
167 up(&(mlc->isem)); 176 up(&mlc->isem);
168 rc = 0; 177 rc = 0;
169 goto done;
170 done: 178 done:
171 write_unlock_irqrestore(&(mlc->lock), flags);
172 return rc; 179 return rc;
173} 180}
174 181
175static int hp_sdc_mlc_cts (hil_mlc *mlc) { 182static int hp_sdc_mlc_cts(hil_mlc *mlc)
183{
176 struct hp_sdc_mlc_priv_s *priv; 184 struct hp_sdc_mlc_priv_s *priv;
177 unsigned long flags;
178 185
179 priv = mlc->priv; 186 priv = mlc->priv;
180
181 write_lock_irqsave(&(mlc->lock), flags);
182 187
183 /* Try to down the semaphores -- they should be up. */ 188 /* Try to down the semaphores -- they should be up. */
184 if (down_trylock(&(mlc->isem))) { 189 BUG_ON(down_trylock(&mlc->isem));
185 BUG(); 190 BUG_ON(down_trylock(&mlc->osem));
186 goto busy; 191
187 } 192 up(&mlc->isem);
188 if (down_trylock(&(mlc->osem))) { 193 up(&mlc->osem);
189 BUG();
190 up(&(mlc->isem));
191 goto busy;
192 }
193 up(&(mlc->isem));
194 up(&(mlc->osem));
195 194
196 if (down_trylock(&(mlc->csem))) { 195 if (down_trylock(&mlc->csem)) {
197 if (priv->trans.act.semaphore != &(mlc->csem)) goto poll; 196 if (priv->trans.act.semaphore != &mlc->csem)
198 goto busy; 197 goto poll;
198 else
199 goto busy;
199 } 200 }
200 if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done; 201
202 if (!(priv->tseq[4] & HP_SDC_USE_LOOP))
203 goto done;
201 204
202 poll: 205 poll:
203 priv->trans.act.semaphore = &(mlc->csem); 206 priv->trans.act.semaphore = &mlc->csem;
204 priv->trans.actidx = 0; 207 priv->trans.actidx = 0;
205 priv->trans.idx = 1; 208 priv->trans.idx = 1;
206 priv->trans.endidx = 5; 209 priv->trans.endidx = 5;
207 priv->tseq[0] = 210 priv->tseq[0] =
208 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE; 211 HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
209 priv->tseq[1] = HP_SDC_CMD_READ_USE; 212 priv->tseq[1] = HP_SDC_CMD_READ_USE;
210 priv->tseq[2] = 1; 213 priv->tseq[2] = 1;
211 priv->tseq[3] = 0; 214 priv->tseq[3] = 0;
212 priv->tseq[4] = 0; 215 priv->tseq[4] = 0;
213 hp_sdc_enqueue_transaction(&(priv->trans)); 216 __hp_sdc_enqueue_transaction(&priv->trans);
214 busy: 217 busy:
215 write_unlock_irqrestore(&(mlc->lock), flags);
216 return 1; 218 return 1;
217 done: 219 done:
218 priv->trans.act.semaphore = &(mlc->osem); 220 priv->trans.act.semaphore = &mlc->osem;
219 up(&(mlc->csem)); 221 up(&mlc->csem);
220 write_unlock_irqrestore(&(mlc->lock), flags);
221 return 0; 222 return 0;
222} 223}
223 224
224static void hp_sdc_mlc_out (hil_mlc *mlc) { 225static void hp_sdc_mlc_out(hil_mlc *mlc)
226{
225 struct hp_sdc_mlc_priv_s *priv; 227 struct hp_sdc_mlc_priv_s *priv;
226 unsigned long flags;
227 228
228 priv = mlc->priv; 229 priv = mlc->priv;
229 230
230 write_lock_irqsave(&(mlc->lock), flags);
231
232 /* Try to down the semaphore -- it should be up. */ 231 /* Try to down the semaphore -- it should be up. */
233 if (down_trylock(&(mlc->osem))) { 232 BUG_ON(down_trylock(&mlc->osem));
234 BUG();
235 goto done;
236 }
237 233
238 if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control; 234 if (mlc->opacket & HIL_DO_ALTER_CTRL)
235 goto do_control;
239 236
240 do_data: 237 do_data:
241 if (priv->emtestmode) { 238 if (priv->emtestmode) {
242 up(&(mlc->osem)); 239 up(&mlc->osem);
243 goto done; 240 return;
244 } 241 }
245 /* Shouldn't be sending commands when loop may be busy */ 242 /* Shouldn't be sending commands when loop may be busy */
246 if (down_trylock(&(mlc->csem))) { 243 BUG_ON(down_trylock(&mlc->csem));
247 BUG(); 244 up(&mlc->csem);
248 goto done;
249 }
250 up(&(mlc->csem));
251 245
252 priv->trans.actidx = 0; 246 priv->trans.actidx = 0;
253 priv->trans.idx = 1; 247 priv->trans.idx = 1;
254 priv->trans.act.semaphore = &(mlc->osem); 248 priv->trans.act.semaphore = &mlc->osem;
255 priv->trans.endidx = 6; 249 priv->trans.endidx = 6;
256 priv->tseq[0] = 250 priv->tseq[0] =
257 HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE; 251 HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
258 priv->tseq[1] = 0x7; 252 priv->tseq[1] = 0x7;
259 priv->tseq[2] = 253 priv->tseq[2] =
260 (mlc->opacket & 254 (mlc->opacket &
261 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD)) 255 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
262 >> HIL_PKT_ADDR_SHIFT; 256 >> HIL_PKT_ADDR_SHIFT;
263 priv->tseq[3] = 257 priv->tseq[3] =
264 (mlc->opacket & HIL_PKT_DATA_MASK) 258 (mlc->opacket & HIL_PKT_DATA_MASK)
265 >> HIL_PKT_DATA_SHIFT; 259 >> HIL_PKT_DATA_SHIFT;
266 priv->tseq[4] = 0; /* No timeout */ 260 priv->tseq[4] = 0; /* No timeout */
267 if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1; 261 if (priv->tseq[3] == HIL_CMD_DHR)
262 priv->tseq[4] = 1;
268 priv->tseq[5] = HP_SDC_CMD_DO_HIL; 263 priv->tseq[5] = HP_SDC_CMD_DO_HIL;
269 goto enqueue; 264 goto enqueue;
270 265
271 do_control: 266 do_control:
272 priv->emtestmode = mlc->opacket & HIL_CTRL_TEST; 267 priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
273 268
274 /* we cannot emulate this, it should not be used. */ 269 /* we cannot emulate this, it should not be used. */
275 BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE); 270 BUG_ON((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE);
276 271
277 if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only; 272 if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY)
278 if (mlc->opacket & HIL_CTRL_APE) { 273 goto control_only;
279 BUG(); /* Should not send command/data after engaging APE */ 274
280 goto done; 275 /* Should not send command/data after engaging APE */
281 } 276 BUG_ON(mlc->opacket & HIL_CTRL_APE);
282 /* Disengaging APE this way would not be valid either since 277
278 /* Disengaging APE this way would not be valid either since
283 * the loop must be allowed to idle. 279 * the loop must be allowed to idle.
284 * 280 *
285 * So, it works out that we really never actually send control 281 * So, it works out that we really never actually send control
286 * and data when using SDC, we just send the data. 282 * and data when using SDC, we just send the data.
287 */ 283 */
288 goto do_data; 284 goto do_data;
289 285
290 control_only: 286 control_only:
291 priv->trans.actidx = 0; 287 priv->trans.actidx = 0;
292 priv->trans.idx = 1; 288 priv->trans.idx = 1;
293 priv->trans.act.semaphore = &(mlc->osem); 289 priv->trans.act.semaphore = &mlc->osem;
294 priv->trans.endidx = 4; 290 priv->trans.endidx = 4;
295 priv->tseq[0] = 291 priv->tseq[0] =
296 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE; 292 HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
297 priv->tseq[1] = HP_SDC_CMD_SET_LPC; 293 priv->tseq[1] = HP_SDC_CMD_SET_LPC;
298 priv->tseq[2] = 1; 294 priv->tseq[2] = 1;
299 // priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; 295 /* priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC; */
300 priv->tseq[3] = 0; 296 priv->tseq[3] = 0;
301 if (mlc->opacket & HIL_CTRL_APE) { 297 if (mlc->opacket & HIL_CTRL_APE) {
302 priv->tseq[3] |= HP_SDC_LPC_APE_IPF; 298 priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
303 down_trylock(&(mlc->csem)); 299 down_trylock(&mlc->csem);
304 } 300 }
305 enqueue: 301 enqueue:
306 hp_sdc_enqueue_transaction(&(priv->trans)); 302 hp_sdc_enqueue_transaction(&priv->trans);
307 done:
308 write_unlock_irqrestore(&(mlc->lock), flags);
309} 303}
310 304
311static int __init hp_sdc_mlc_init(void) 305static int __init hp_sdc_mlc_init(void)
@@ -316,18 +310,18 @@ static int __init hp_sdc_mlc_init(void)
316 310
317 hp_sdc_mlc_priv.emtestmode = 0; 311 hp_sdc_mlc_priv.emtestmode = 0;
318 hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq; 312 hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
319 hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem); 313 hp_sdc_mlc_priv.trans.act.semaphore = &mlc->osem;
320 hp_sdc_mlc_priv.got5x = 0; 314 hp_sdc_mlc_priv.got5x = 0;
321 315
322 mlc->cts = &hp_sdc_mlc_cts; 316 mlc->cts = &hp_sdc_mlc_cts;
323 mlc->in = &hp_sdc_mlc_in; 317 mlc->in = &hp_sdc_mlc_in;
324 mlc->out = &hp_sdc_mlc_out; 318 mlc->out = &hp_sdc_mlc_out;
319 mlc->priv = &hp_sdc_mlc_priv;
325 320
326 if (hil_mlc_register(mlc)) { 321 if (hil_mlc_register(mlc)) {
327 printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n"); 322 printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
328 goto err0; 323 goto err0;
329 } 324 }
330 mlc->priv = &hp_sdc_mlc_priv;
331 325
332 if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) { 326 if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
333 printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n"); 327 printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
@@ -335,10 +329,9 @@ static int __init hp_sdc_mlc_init(void)
335 } 329 }
336 return 0; 330 return 0;
337 err1: 331 err1:
338 if (hil_mlc_unregister(mlc)) { 332 if (hil_mlc_unregister(mlc))
339 printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" 333 printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
340 "This is bad. Could cause an oops.\n"); 334 "This is bad. Could cause an oops.\n");
341 }
342 err0: 335 err0:
343 return -EBUSY; 336 return -EBUSY;
344} 337}
@@ -346,14 +339,14 @@ static int __init hp_sdc_mlc_init(void)
346static void __exit hp_sdc_mlc_exit(void) 339static void __exit hp_sdc_mlc_exit(void)
347{ 340{
348 hil_mlc *mlc = &hp_sdc_mlc; 341 hil_mlc *mlc = &hp_sdc_mlc;
349 if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) { 342
343 if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr))
350 printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n" 344 printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
351 "This is bad. Could cause an oops.\n"); 345 "This is bad. Could cause an oops.\n");
352 } 346
353 if (hil_mlc_unregister(mlc)) { 347 if (hil_mlc_unregister(mlc))
354 printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n" 348 printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
355 "This is bad. Could cause an oops.\n"); 349 "This is bad. Could cause an oops.\n");
356 }
357} 350}
358 351
359module_init(hp_sdc_mlc_init); 352module_init(hp_sdc_mlc_init);