arm64: dts: rockchip: enable pcie_phy for Sapphire board
[firefly-linux-kernel-4.4.55.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 = AIC3262_LEFT_DAC_OVERFLOW_INT | AIC3262_RIGHT_DAC_OVERFLOW_INT
43                         | AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT | AIC3262_LEFT_ADC_OVERFLOW_INT
44                         | AIC3262_RIGHT_ADC_OVERFLOW_INT | AIC3262_MINIDSP_D_BARREL_SHIFT_OVERFLOW_INT,
45         },
46         {
47                 .mask = AIC3262_SPK_OVERCURRENT_MASK,
48                 .status = AIC3262_SPK_OVER_CURRENT_INT,
49         },
50
51 };
52
53 struct aic3262_gpio_data {
54
55 };
56
57 static inline struct aic3262_irq_data *irq_to_aic3262_irq(struct aic3262 *aic3262,
58                 int irq)
59 {
60         return &aic3262_irqs[irq - aic3262->irq_base];
61 }
62
63 static void aic3262_irq_lock(struct irq_data *data)
64 {
65         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
66
67         mutex_lock(&aic3262->irq_lock);
68 }
69
70 static void aic3262_irq_sync_unlock(struct irq_data *data)
71 {
72         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
73
74         /* write back to hardware any change in irq mask */
75         if (aic3262->irq_masks_cur != aic3262->irq_masks_cache) {
76                 aic3262->irq_masks_cache = aic3262->irq_masks_cur;
77                 aic3262_reg_write(aic3262, AIC3262_INT1_CNTL,
78                                 aic3262->irq_masks_cur);
79         }
80
81         mutex_unlock(&aic3262->irq_lock);
82 }
83
84 static void aic3262_irq_unmask(struct irq_data *data)
85 {
86         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
87         struct aic3262_irq_data *irq_data = irq_to_aic3262_irq(aic3262, data->irq);
88
89         aic3262->irq_masks_cur |= irq_data->mask;
90 }
91
92 static void aic3262_irq_mask(struct irq_data *data)
93 {
94         struct aic3262 *aic3262 = irq_data_get_irq_chip_data(data);
95         struct aic3262_irq_data *irq_data = irq_to_aic3262_irq(aic3262, data->irq);
96
97         aic3262->irq_masks_cur &= ~irq_data->mask;
98 }
99
100 static struct irq_chip aic3262_irq_chip = {
101         .name = "tlv320aic3262",
102         .irq_bus_lock = aic3262_irq_lock,
103         .irq_bus_sync_unlock = aic3262_irq_sync_unlock,
104         .irq_mask = aic3262_irq_mask,
105         .irq_unmask = aic3262_irq_unmask,
106 };
107
108 static irqreturn_t aic3262_irq_thread(int irq, void *data)
109 {
110         struct aic3262 *aic3262 = data;
111         u8 status[4]; 
112         int i=0;
113         // Reading the sticky bit registers acknowledges the interrupt to the device */
114         aic3262_bulk_read(aic3262, AIC3262_INT_STICKY_FLAG1, 4, status);
115         
116         /* report  */
117         if(status[2] & aic3262_irqs[AIC3262_IRQ_HEADSET_DETECT].status) // 0    
118         {
119                         handle_nested_irq(aic3262->irq_base);
120                         
121         }
122         if(status[2] & aic3262_irqs[AIC3262_IRQ_BUTTON_PRESS].status)   // 1            
123                         handle_nested_irq(aic3262->irq_base + 1);
124         if(status[2] & aic3262_irqs[AIC3262_IRQ_DAC_DRC].status)        // 2            
125                         handle_nested_irq(aic3262->irq_base + 2);
126         if(status[3] & aic3262_irqs[AIC3262_IRQ_AGC_NOISE].status)      // 3            
127                         handle_nested_irq(aic3262->irq_base + 3);
128         if(status[2] & aic3262_irqs[AIC3262_IRQ_OVER_CURRENT].status)   // 4            
129                         handle_nested_irq(aic3262->irq_base + 4);
130         if(status[0] & aic3262_irqs[AIC3262_IRQ_OVERFLOW_EVENT].status) // 5            
131                         handle_nested_irq(aic3262->irq_base + 5);
132         if(status[3] & aic3262_irqs[AIC3262_IRQ_SPEAKER_OVER_TEMP].status)      // 6            
133                         handle_nested_irq(aic3262->irq_base + 6);
134
135         /* ack unmasked irqs */
136         /* No need to acknowledge the interrupt on AIC3262 */
137
138         return IRQ_HANDLED;
139 }
140
141
142
143 int aic3262_irq_init(struct aic3262 *aic3262)
144 {
145         int cur_irq, ret;
146
147         mutex_init(&aic3262->irq_lock);
148
149         /* mask the individual interrupt sources */
150         aic3262->irq_masks_cur = 0x0; 
151         aic3262->irq_masks_cache = 0x0;
152         aic3262_reg_write(aic3262, AIC3262_INT1_CNTL, 0x0);
153
154         if (!aic3262->irq) {
155                 dev_warn(aic3262->dev,
156                                 "no interrupt specified, no interrupts\n");
157                 aic3262->irq_base = 0;
158                 return 0;
159         }
160
161         if (!aic3262->irq_base) {
162                 dev_err(aic3262->dev,
163                                 "no interrupt base specified, no interrupts\n");
164                 return 0;
165         }
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);