2 * Copyright (C) 2009 - 2010, Motorola, All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 #include <linux/gpio.h>
20 #include <linux/input.h>
21 #include <linux/interrupt.h>
22 #include <linux/irq.h>
23 #include <linux/mutex.h>
24 #include <linux/workqueue.h>
25 #include <linux/wakelock.h>
27 #include <linux/spi/cpcap.h>
28 #include <linux/spi/spi.h>
29 #include <linux/debugfs.h>
30 #include <linux/seq_file.h>
32 #define NUM_INT_REGS 5
33 #define NUM_INTS_PER_REG 16
35 #define CPCAP_INT1_VALID_BITS 0xFFFB
36 #define CPCAP_INT2_VALID_BITS 0xFFFF
37 #define CPCAP_INT3_VALID_BITS 0xFFFF
38 #define CPCAP_INT4_VALID_BITS 0x03FF
39 #define CPCAP_INT5_VALID_BITS 0xFFFF
41 struct cpcap_event_handler {
42 void (*func)(enum cpcap_irqs, void *);
46 struct cpcap_irq_info {
52 struct cpcap_irqdata {
54 struct work_struct work;
55 struct workqueue_struct *workqueue;
56 struct cpcap_device *cpcap;
57 struct cpcap_event_handler event_handler[CPCAP_IRQ__NUM];
58 struct cpcap_irq_info irq_info[CPCAP_IRQ__NUM];
59 struct wake_lock wake_lock;
62 #define EVENT_MASK(event) (1 << ((event) % NUM_INTS_PER_REG))
65 PWRKEY_RELEASE, /* Power key released state. */
66 PWRKEY_PRESS, /* Power key pressed state. */
67 PWRKEY_UNKNOWN, /* Unknown power key state. */
70 static irqreturn_t event_isr(int irq, void *data)
72 struct cpcap_irqdata *irq_data = data;
73 disable_irq_nosync(irq);
74 wake_lock(&irq_data->wake_lock);
75 queue_work(irq_data->workqueue, &irq_data->work);
80 static unsigned short get_int_reg(enum cpcap_irqs event)
84 if ((event) >= CPCAP_IRQ_INT5_INDEX)
86 else if ((event) >= CPCAP_IRQ_INT4_INDEX)
88 else if ((event) >= CPCAP_IRQ_INT3_INDEX)
90 else if ((event) >= CPCAP_IRQ_INT2_INDEX)
98 static unsigned short get_mask_reg(enum cpcap_irqs event)
102 if (event >= CPCAP_IRQ_INT5_INDEX)
103 ret = CPCAP_REG_MIM1;
104 else if (event >= CPCAP_IRQ_INT4_INDEX)
105 ret = CPCAP_REG_INTM4;
106 else if (event >= CPCAP_IRQ_INT3_INDEX)
107 ret = CPCAP_REG_INTM3;
108 else if (event >= CPCAP_IRQ_INT2_INDEX)
109 ret = CPCAP_REG_INTM2;
111 ret = CPCAP_REG_INTM1;
116 static unsigned short get_sense_reg(enum cpcap_irqs event)
120 if (event >= CPCAP_IRQ_INT5_INDEX)
122 else if (event >= CPCAP_IRQ_INT4_INDEX)
123 ret = CPCAP_REG_INTS4;
124 else if (event >= CPCAP_IRQ_INT3_INDEX)
125 ret = CPCAP_REG_INTS3;
126 else if (event >= CPCAP_IRQ_INT2_INDEX)
127 ret = CPCAP_REG_INTS2;
129 ret = CPCAP_REG_INTS1;
134 void cpcap_irq_mask_all(struct cpcap_device *cpcap)
138 static const struct {
139 unsigned short mask_reg;
140 unsigned short valid;
141 } int_reg[NUM_INT_REGS] = {
142 {CPCAP_REG_INTM1, CPCAP_INT1_VALID_BITS},
143 {CPCAP_REG_INTM2, CPCAP_INT2_VALID_BITS},
144 {CPCAP_REG_INTM3, CPCAP_INT3_VALID_BITS},
145 {CPCAP_REG_INTM4, CPCAP_INT4_VALID_BITS},
146 {CPCAP_REG_MIM1, CPCAP_INT5_VALID_BITS}
149 for (i = 0; i < NUM_INT_REGS; i++) {
150 cpcap_regacc_write(cpcap, int_reg[i].mask_reg,
157 struct cpcap_device *cpcap;
158 enum pwrkey_states state;
159 struct wake_lock wake_lock;
162 static void pwrkey_handler(enum cpcap_irqs irq, void *data)
164 struct pwrkey_data *pwrkey_data = data;
165 enum pwrkey_states new_state, last_state = pwrkey_data->state;
166 struct cpcap_device *cpcap = pwrkey_data->cpcap;
168 new_state = (enum pwrkey_states) cpcap_irq_sense(cpcap, irq, 0);
171 if ((new_state < PWRKEY_UNKNOWN) && (new_state != last_state)) {
172 wake_lock_timeout(&pwrkey_data->wake_lock, 20);
173 cpcap_broadcast_key_event(cpcap, KEY_END, new_state);
174 pwrkey_data->state = new_state;
175 } else if ((last_state == PWRKEY_RELEASE) &&
176 (new_state == PWRKEY_RELEASE)) {
177 /* Key must have been released before press was handled. Send
178 * both the press and the release. */
179 wake_lock_timeout(&pwrkey_data->wake_lock, 20);
180 cpcap_broadcast_key_event(cpcap, KEY_END, PWRKEY_PRESS);
181 cpcap_broadcast_key_event(cpcap, KEY_END, PWRKEY_RELEASE);
183 cpcap_irq_unmask(cpcap, CPCAP_IRQ_ON);
186 static int pwrkey_init(struct cpcap_device *cpcap)
188 struct pwrkey_data *data = kmalloc(sizeof(struct pwrkey_data),
195 data->state = PWRKEY_RELEASE;
196 retval = cpcap_irq_register(cpcap, CPCAP_IRQ_ON, pwrkey_handler, data);
199 wake_lock_init(&data->wake_lock, WAKE_LOCK_SUSPEND, "pwrkey");
203 static void pwrkey_remove(struct cpcap_device *cpcap)
205 struct pwrkey_data *data;
207 cpcap_irq_get_data(cpcap, CPCAP_IRQ_ON, (void **)&data);
210 cpcap_irq_free(cpcap, CPCAP_IRQ_ON);
211 wake_lock_destroy(&data->wake_lock);
215 static int int_read_and_clear(struct cpcap_device *cpcap,
216 unsigned short status_reg,
217 unsigned short mask_reg,
218 unsigned short valid_mask,
221 unsigned short ireg_val, mreg_val;
223 ret = cpcap_regacc_read(cpcap, status_reg, &ireg_val);
226 ret = cpcap_regacc_read(cpcap, mask_reg, &mreg_val);
229 *en |= ireg_val & ~mreg_val;
231 ret = cpcap_regacc_write(cpcap, mask_reg, *en, *en);
234 ret = cpcap_regacc_write(cpcap, status_reg, *en, *en);
241 static void irq_work_func(struct work_struct *work)
244 unsigned short en_ints[NUM_INT_REGS];
246 struct cpcap_irqdata *data;
247 struct cpcap_device *cpcap;
248 struct spi_device *spi;
250 static const struct {
251 unsigned short status_reg;
252 unsigned short mask_reg;
253 unsigned short valid;
254 } int_reg[NUM_INT_REGS] = {
255 {CPCAP_REG_INT1, CPCAP_REG_INTM1, CPCAP_INT1_VALID_BITS},
256 {CPCAP_REG_INT2, CPCAP_REG_INTM2, CPCAP_INT2_VALID_BITS},
257 {CPCAP_REG_INT3, CPCAP_REG_INTM3, CPCAP_INT3_VALID_BITS},
258 {CPCAP_REG_INT4, CPCAP_REG_INTM4, CPCAP_INT4_VALID_BITS},
259 {CPCAP_REG_MI1, CPCAP_REG_MIM1, CPCAP_INT5_VALID_BITS}
262 for (i = 0; i < NUM_INT_REGS; ++i)
265 data = container_of(work, struct cpcap_irqdata, work);
269 for (i = 0; i < NUM_INT_REGS; ++i) {
270 retval = int_read_and_clear(cpcap,
271 int_reg[i].status_reg,
276 dev_err(&spi->dev, "Error reading interrupts\n");
280 enable_irq(spi->irq);
282 /* lock protects event handlers and data */
283 mutex_lock(&data->lock);
284 for (i = 0; i < NUM_INT_REGS; ++i) {
287 while (en_ints[i] > 0) {
288 struct cpcap_event_handler *event_handler;
290 /* find the first set bit */
291 index = (unsigned char)(ffs(en_ints[i]) - 1);
292 if (index >= CPCAP_IRQ__NUM)
295 en_ints[i] &= ~(1 << index);
296 /* find the event that occurred */
297 index += CPCAP_IRQ__START + (i * NUM_INTS_PER_REG);
298 event_handler = &data->event_handler[index];
300 if (event_handler->func)
301 event_handler->func(index, event_handler->data);
303 data->irq_info[index].count++;
307 mutex_unlock(&data->lock);
308 wake_unlock(&data->wake_lock);
311 #ifdef CONFIG_DEBUG_FS
312 static int cpcap_dbg_irq_show(struct seq_file *s, void *data)
314 static const char *irq_name[] = {
315 [CPCAP_IRQ_HSCLK] = "HSCLK",
316 [CPCAP_IRQ_PRIMAC] = "PRIMAC",
317 [CPCAP_IRQ_SECMAC] = "SECMAC",
318 [CPCAP_IRQ_LOWBPL] = "LOWBPL",
319 [CPCAP_IRQ_SEC2PRI] = "SEC2PRI",
320 [CPCAP_IRQ_LOWBPH] = "LOWBPH",
321 [CPCAP_IRQ_EOL] = "EOL",
322 [CPCAP_IRQ_TS] = "TS",
323 [CPCAP_IRQ_ADCDONE] = "ADCDONE",
324 [CPCAP_IRQ_HS] = "HS",
325 [CPCAP_IRQ_MB2] = "MB2",
326 [CPCAP_IRQ_VBUSOV] = "VBUSOV",
327 [CPCAP_IRQ_RVRS_CHRG] = "RVRS_CHRG",
328 [CPCAP_IRQ_CHRG_DET] = "CHRG_DET",
329 [CPCAP_IRQ_IDFLOAT] = "IDFLOAT",
330 [CPCAP_IRQ_IDGND] = "IDGND",
332 [CPCAP_IRQ_SE1] = "SE1",
333 [CPCAP_IRQ_SESSEND] = "SESSEND",
334 [CPCAP_IRQ_SESSVLD] = "SESSVLD",
335 [CPCAP_IRQ_VBUSVLD] = "VBUSVLD",
336 [CPCAP_IRQ_CHRG_CURR1] = "CHRG_CURR1",
337 [CPCAP_IRQ_CHRG_CURR2] = "CHRG_CURR2",
338 [CPCAP_IRQ_RVRS_MODE] = "RVRS_MODE",
339 [CPCAP_IRQ_ON] = "ON",
340 [CPCAP_IRQ_ON2] = "ON2",
341 [CPCAP_IRQ_CLK] = "CLK",
342 [CPCAP_IRQ_1HZ] = "1HZ",
343 [CPCAP_IRQ_PTT] = "PTT",
344 [CPCAP_IRQ_SE0CONN] = "SE0CONN",
345 [CPCAP_IRQ_CHRG_SE1B] = "CHRG_SE1B",
346 [CPCAP_IRQ_UART_ECHO_OVERRUN] = "UART_ECHO_OVERRUN",
347 [CPCAP_IRQ_EXTMEMHD] = "EXTMEMHD",
349 [CPCAP_IRQ_WARM] = "WARM",
350 [CPCAP_IRQ_SYSRSTR] = "SYSRSTR",
351 [CPCAP_IRQ_SOFTRST] = "SOFTRST",
352 [CPCAP_IRQ_DIEPWRDWN] = "DIEPWRDWN",
353 [CPCAP_IRQ_DIETEMPH] = "DIETEMPH",
354 [CPCAP_IRQ_PC] = "PC",
355 [CPCAP_IRQ_OFLOWSW] = "OFLOWSW",
356 [CPCAP_IRQ_TODA] = "TODA",
357 [CPCAP_IRQ_OPT_SEL_DTCH] = "OPT_SEL_DTCH",
358 [CPCAP_IRQ_OPT_SEL_STATE] = "OPT_SEL_STATE",
359 [CPCAP_IRQ_ONEWIRE1] = "ONEWIRE1",
360 [CPCAP_IRQ_ONEWIRE2] = "ONEWIRE2",
361 [CPCAP_IRQ_ONEWIRE3] = "ONEWIRE3",
362 [CPCAP_IRQ_UCRESET] = "UCRESET",
363 [CPCAP_IRQ_PWRGOOD] = "PWRGOOD",
364 [CPCAP_IRQ_USBDPLLCLK] = "USBDPLLCLK",
366 [CPCAP_IRQ_DPI] = "DPI",
367 [CPCAP_IRQ_DMI] = "DMI",
368 [CPCAP_IRQ_UCBUSY] = "UCBUSY",
369 [CPCAP_IRQ_GCAI_CURR1] = "GCAI_CURR1",
370 [CPCAP_IRQ_GCAI_CURR2] = "GCAI_CURR2",
371 [CPCAP_IRQ_SB_MAX_RETRANSMIT_ERR] = "SB_MAX_RETRANSMIT_ERR",
372 [CPCAP_IRQ_BATTDETB] = "BATTDETB",
373 [CPCAP_IRQ_PRIHALT] = "PRIHALT",
374 [CPCAP_IRQ_SECHALT] = "SECHALT",
375 [CPCAP_IRQ_CC_CAL] = "CC_CAL",
377 [CPCAP_IRQ_UC_PRIROMR] = "UC_PRIROMR",
378 [CPCAP_IRQ_UC_PRIRAMW] = "UC_PRIRAMW",
379 [CPCAP_IRQ_UC_PRIRAMR] = "UC_PRIRAMR",
380 [CPCAP_IRQ_UC_USEROFF] = "UC_USEROFF",
381 [CPCAP_IRQ_UC_PRIMACRO_4] = "UC_PRIMACRO_4",
382 [CPCAP_IRQ_UC_PRIMACRO_5] = "UC_PRIMACRO_5",
383 [CPCAP_IRQ_UC_PRIMACRO_6] = "UC_PRIMACRO_6",
384 [CPCAP_IRQ_UC_PRIMACRO_7] = "UC_PRIMACRO_7",
385 [CPCAP_IRQ_UC_PRIMACRO_8] = "UC_PRIMACRO_8",
386 [CPCAP_IRQ_UC_PRIMACRO_9] = "UC_PRIMACRO_9",
387 [CPCAP_IRQ_UC_PRIMACRO_10] = "UC_PRIMACRO_10",
388 [CPCAP_IRQ_UC_PRIMACRO_11] = "UC_PRIMACRO_11",
389 [CPCAP_IRQ_UC_PRIMACRO_12] = "UC_PRIMACRO_12",
390 [CPCAP_IRQ_UC_PRIMACRO_13] = "UC_PRIMACRO_13",
391 [CPCAP_IRQ_UC_PRIMACRO_14] = "UC_PRIMACRO_14",
392 [CPCAP_IRQ_UC_PRIMACRO_15] = "UC_PRIMACRO_15",
395 struct cpcap_irqdata *irqdata = s->private;
397 seq_printf(s, "%21s%9s%12s%10s\n",
398 "CPCAP IRQ", "Enabled", "Registered", "Count");
400 for (i = 0; i < CPCAP_IRQ__NUM; i++) {
401 if ((i <= CPCAP_IRQ_CC_CAL) || (i >= CPCAP_IRQ_UC_PRIROMR)) {
402 seq_printf(s, "%21s%9d%12d%10d\n",
404 irqdata->irq_info[i].enabled,
405 irqdata->irq_info[i].registered,
406 irqdata->irq_info[i].count);
412 static int cpcap_dbg_irq_open(struct inode *inode, struct file *file)
414 return single_open(file, cpcap_dbg_irq_show, inode->i_private);
417 static const struct file_operations debug_fops = {
418 .open = cpcap_dbg_irq_open,
421 .release = single_release,
425 int cpcap_irq_init(struct cpcap_device *cpcap)
428 struct spi_device *spi = cpcap->spi;
429 struct cpcap_irqdata *data;
431 data = kzalloc(sizeof(struct cpcap_irqdata), GFP_KERNEL);
435 cpcap_irq_mask_all(cpcap);
437 data->workqueue = create_singlethread_workqueue("cpcap_irq");
438 INIT_WORK(&data->work, irq_work_func);
439 mutex_init(&data->lock);
440 wake_lock_init(&data->wake_lock, WAKE_LOCK_SUSPEND, "cpcap-irq");
443 retval = request_irq(spi->irq, event_isr, IRQF_DISABLED |
444 IRQF_TRIGGER_HIGH, "cpcap-irq", data);
446 printk(KERN_ERR "cpcap_irq: Failed requesting irq.\n");
450 enable_irq_wake(spi->irq);
452 cpcap->irqdata = data;
453 retval = pwrkey_init(cpcap);
455 printk(KERN_ERR "cpcap_irq: Failed initializing pwrkey.\n");
458 #ifdef CONFIG_DEBUG_FS
459 (void)debugfs_create_file("cpcap-irq", S_IRUGO, NULL, data,
465 free_irq(spi->irq, data);
467 printk(KERN_ERR "cpcap_irq: Error registering cpcap irq.\n");
471 void cpcap_irq_shutdown(struct cpcap_device *cpcap)
473 struct spi_device *spi = cpcap->spi;
474 struct cpcap_irqdata *data = cpcap->irqdata;
476 pwrkey_remove(cpcap);
477 cancel_work_sync(&data->work);
478 destroy_workqueue(data->workqueue);
479 free_irq(spi->irq, data);
483 int cpcap_irq_register(struct cpcap_device *cpcap,
485 void (*cb_func) (enum cpcap_irqs, void *),
488 struct cpcap_irqdata *irqdata = cpcap->irqdata;
491 if ((irq >= CPCAP_IRQ__NUM) || (!cb_func))
494 mutex_lock(&irqdata->lock);
496 if (irqdata->event_handler[irq].func == NULL) {
497 irqdata->irq_info[irq].registered = 1;
498 cpcap_irq_unmask(cpcap, irq);
499 irqdata->event_handler[irq].func = cb_func;
500 irqdata->event_handler[irq].data = data;
504 mutex_unlock(&irqdata->lock);
508 EXPORT_SYMBOL_GPL(cpcap_irq_register);
510 int cpcap_irq_free(struct cpcap_device *cpcap, enum cpcap_irqs irq)
512 struct cpcap_irqdata *data = cpcap->irqdata;
515 if (irq >= CPCAP_IRQ__NUM)
518 mutex_lock(&data->lock);
519 retval = cpcap_irq_mask(cpcap, irq);
520 data->event_handler[irq].func = NULL;
521 data->event_handler[irq].data = NULL;
522 data->irq_info[irq].registered = 0;
523 mutex_unlock(&data->lock);
527 EXPORT_SYMBOL_GPL(cpcap_irq_free);
529 int cpcap_irq_get_data(struct cpcap_device *cpcap,
533 struct cpcap_irqdata *irqdata = cpcap->irqdata;
535 if (irq >= CPCAP_IRQ__NUM)
538 mutex_lock(&irqdata->lock);
539 *data = irqdata->event_handler[irq].data;
540 mutex_unlock(&irqdata->lock);
544 EXPORT_SYMBOL_GPL(cpcap_irq_get_data);
546 int cpcap_irq_clear(struct cpcap_device *cpcap,
549 int retval = -EINVAL;
551 if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC)) {
552 retval = cpcap_regacc_write(cpcap,
560 EXPORT_SYMBOL_GPL(cpcap_irq_clear);
562 int cpcap_irq_mask(struct cpcap_device *cpcap,
565 struct cpcap_irqdata *data = cpcap->irqdata;
566 int retval = -EINVAL;
568 if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC)) {
569 data->irq_info[irq].enabled = 0;
570 retval = cpcap_regacc_write(cpcap,
578 EXPORT_SYMBOL_GPL(cpcap_irq_mask);
580 int cpcap_irq_unmask(struct cpcap_device *cpcap,
583 struct cpcap_irqdata *data = cpcap->irqdata;
584 int retval = -EINVAL;
586 if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC)) {
587 data->irq_info[irq].enabled = 1;
588 retval = cpcap_regacc_write(cpcap,
596 EXPORT_SYMBOL_GPL(cpcap_irq_unmask);
598 int cpcap_irq_mask_get(struct cpcap_device *cpcap,
601 struct cpcap_irqdata *data = cpcap->irqdata;
602 int retval = -EINVAL;
604 if ((irq < CPCAP_IRQ__NUM) && (irq != CPCAP_IRQ_SECMAC))
605 return data->irq_info[irq].enabled;
609 EXPORT_SYMBOL_GPL(cpcap_irq_mask_get);
611 int cpcap_irq_sense(struct cpcap_device *cpcap,
618 if (irq >= CPCAP_IRQ__NUM)
621 retval = cpcap_regacc_read(cpcap, get_sense_reg(irq), &val);
626 retval = cpcap_irq_clear(cpcap, irq);
630 return ((val & EVENT_MASK(irq)) != 0) ? 1 : 0;
632 EXPORT_SYMBOL_GPL(cpcap_irq_sense);
635 int cpcap_irq_suspend(struct cpcap_device *cpcap)
637 struct spi_device *spi = cpcap->spi;
638 struct cpcap_irqdata *data = cpcap->irqdata;
640 disable_irq(spi->irq);
641 flush_work(&data->work);
645 int cpcap_irq_resume(struct cpcap_device *cpcap)
647 struct spi_device *spi = cpcap->spi;
649 enable_irq(spi->irq);