config: tegra3: enable /dev mount with ACL
[linux-2.6.git] / drivers / mfd / tlv320aic3262-irq.c
1
2 #include <linux/kernel.h>
3 #include <linux/module.h>
4 #include <linux/i2c.h>
5 #include <linux/irq.h>
6 #include <linux/mfd/core.h>
7 #include <linux/interrupt.h>
8
9 #include <linux/mfd/tlv320aic3262-core.h>
10 #include <linux/mfd/tlv320aic3262-registers.h>
11
12 #include <linux/delay.h>
13 struct aic3262_irq_data {
14         int mask;
15         int status;
16 };
17
18 static struct aic3262_irq_data aic3262_irqs[] = {
19         {
20          .mask = AIC3262_HEADSET_IN_MASK,
21          .status = AIC3262_HEADSET_PLUG_UNPLUG_INT,
22          },
23         {
24          .mask = AIC3262_BUTTON_PRESS_MASK,
25          .status = AIC3262_BUTTON_PRESS_INT,
26          },
27         {
28          .mask = AIC3262_DAC_DRC_THRES_MASK,
29          .status = AIC3262_LEFT_DRC_THRES_INT | AIC3262_RIGHT_DRC_THRES_INT,
30          },
31         {
32          .mask = AIC3262_AGC_NOISE_MASK,
33          .status = AIC3262_LEFT_AGC_NOISE_INT | AIC3262_RIGHT_AGC_NOISE_INT,
34          },
35         {
36          .mask = AIC3262_OVER_CURRENT_MASK,
37          .status = AIC3262_LEFT_OUTPUT_DRIVER_OVERCURRENT_INT
38          | AIC3262_RIGHT_OUTPUT_DRIVER_OVERCURRENT_INT,
39          },
40         {
41          .mask = AIC3262_OVERFLOW_MASK,
42          .status =
43          AIC3262_LEFT_DAC_OVERFLOW_INT | AIC3262_RIGHT_DAC_OVERFLOW_INT |
44          AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT |
45          AIC3262_LEFT_ADC_OVERFLOW_INT | AIC3262_RIGHT_ADC_OVERFLOW_INT |
46          AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT,
47          },
48         {
49          .mask = AIC3262_SPK_OVERCURRENT_MASK,
50          .status = AIC3262_SPK_OVER_CURRENT_INT,
51          },
52
53 };
54
55 struct aic3262_gpio_data {
56
57 };
58
59 static inline struct aic3262_irq_data *irq_to_aic3262_irq(struct aic3262
60                                                           *aic3262, int irq)
61 {
62         return &aic3262_irqs[irq - aic3262->irq_base];
63 }
64
65 static void aic3262_irq_lock(struct irq_data *data)
66 {
67         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
68
69         mutex_lock(&aic3262->irq_lock);
70 }
71
72 static void aic3262_irq_sync_unlock(struct irq_data *data)
73 {
74         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
75
76         /* write back to hardware any change in irq mask */
77         if (aic3262->irq_masks_cur != aic3262->irq_masks_cache) {
78                 aic3262->irq_masks_cache = aic3262->irq_masks_cur;
79                 aic3262_reg_write(aic3262, AIC3262_INT1_CNTL,
80                                   aic3262->irq_masks_cur);
81         }
82
83         mutex_unlock(&aic3262->irq_lock);
84 }
85
86 static void aic3262_irq_unmask(struct irq_data *data)
87 {
88         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
89         struct aic3262_irq_data *irq_data =
90             irq_to_aic3262_irq(aic3262, data->irq);
91
92         aic3262->irq_masks_cur |= irq_data->mask;
93 }
94
95 static void aic3262_irq_mask(struct irq_data *data)
96 {
97         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
98         struct aic3262_irq_data *irq_data =
99             irq_to_aic3262_irq(aic3262, data->irq);
100
101         aic3262->irq_masks_cur &= ~irq_data->mask;
102 }
103
104 static struct irq_chip aic3262_irq_chip = {
105         .name = "tlv320aic3262",
106         .irq_bus_lock = aic3262_irq_lock,
107         .irq_bus_sync_unlock = aic3262_irq_sync_unlock,
108         .irq_mask = aic3262_irq_mask,
109         .irq_unmask = aic3262_irq_unmask,
110 };
111
112 static irqreturn_t aic3262_irq_thread(int irq, void *data)
113 {
114         struct aic3262 *aic3262 = data;
115         u8 status[4];
116         int i = 0;
117         /* Reading the sticky bit registers acknowledges
118         the interrupt to the device */
119         aic3262_bulk_read(aic3262, AIC3262_INT_STICKY_FLAG1, 4, status);
120
121         /* report  */
122         if (status[2] & aic3262_irqs[AIC3262_IRQ_HEADSET_DETECT].status)
123                 handle_nested_irq(aic3262->irq_base);
124
125         if (status[2] & aic3262_irqs[AIC3262_IRQ_BUTTON_PRESS].status)
126                 handle_nested_irq(aic3262->irq_base + 1);
127         if (status[2] & aic3262_irqs[AIC3262_IRQ_DAC_DRC].status)
128                 handle_nested_irq(aic3262->irq_base + 2);
129         if (status[3] & aic3262_irqs[AIC3262_IRQ_AGC_NOISE].status)
130                 handle_nested_irq(aic3262->irq_base + 3);
131         if (status[2] & aic3262_irqs[AIC3262_IRQ_OVER_CURRENT].status)
132                 handle_nested_irq(aic3262->irq_base + 4);
133         if (status[0] & aic3262_irqs[AIC3262_IRQ_OVERFLOW_EVENT].status)
134                 handle_nested_irq(aic3262->irq_base + 5);
135         if (status[3] & aic3262_irqs[AIC3262_IRQ_SPEAKER_OVER_TEMP].status)
136                 handle_nested_irq(aic3262->irq_base + 6);
137
138         /* ack unmasked irqs */
139         /* No need to acknowledge the interrupt on AIC3262 */
140
141         return IRQ_HANDLED;
142 }
143
144 int aic3262_irq_init(struct aic3262 *aic3262)
145 {
146         int cur_irq, ret;
147
148         mutex_init(&aic3262->irq_lock);
149
150         /* mask the individual interrupt sources */
151         aic3262->irq_masks_cur = 0x0;
152         aic3262->irq_masks_cache = 0x0;
153         aic3262_reg_write(aic3262, AIC3262_INT1_CNTL, 0x0);
154
155         if (!aic3262->irq) {
156                 dev_warn(aic3262->dev,
157                          "no interrupt specified, no interrupts\n");
158                 aic3262->irq_base = 0;
159                 return 0;
160         }
161
162         if (!aic3262->irq_base) {
163                 dev_err(aic3262->dev,
164                         "no interrupt base specified, no interrupts\n");
165                 return 0;
166         }
167
168         /* Register them with genirq */
169         for (cur_irq = aic3262->irq_base;
170              cur_irq < aic3262->irq_base + ARRAY_SIZE(aic3262_irqs);
171              cur_irq++) {
172                 irq_set_chip_data(cur_irq, aic3262);
173                 irq_set_chip_and_handler(cur_irq, &aic3262_irq_chip,
174                                          handle_edge_irq);
175                 irq_set_nested_thread(cur_irq, 1);
176
177                 /* ARM needs us to explicitly flag the IRQ as valid
178                  * and will set them noprobe when we do so. */
179 #ifdef CONFIG_ARM
180                 set_irq_flags(cur_irq, IRQF_VALID);
181 #else
182                 set_irq_noprobe(cur_irq);
183 #endif
184         }
185
186         ret = request_threaded_irq(aic3262->irq, NULL, aic3262_irq_thread,
187                                    IRQF_TRIGGER_RISING,
188                                    "tlv320aic3262", aic3262);
189         if (ret) {
190                 dev_err(aic3262->dev, "failed to request IRQ %d: %d\n",
191                         aic3262->irq, ret);
192                 return ret;
193         }
194
195         return 0;
196 }
197 EXPORT_SYMBOL(aic3262_irq_init);
198
199 void aic3262_irq_exit(struct aic3262 *aic3262)
200 {
201         if (aic3262->irq)
202                 free_irq(aic3262->irq, aic3262);
203 }
204 EXPORT_SYMBOL(aic3262_irq_exit);