aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/arizona-irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/arizona-irq.c')
-rw-r--r--drivers/mfd/arizona-irq.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 98ac345f468e..ef0f2d001df2 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -94,7 +94,8 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data)
94static irqreturn_t arizona_irq_thread(int irq, void *data) 94static irqreturn_t arizona_irq_thread(int irq, void *data)
95{ 95{
96 struct arizona *arizona = data; 96 struct arizona *arizona = data;
97 int i, ret; 97 unsigned int val;
98 int ret;
98 99
99 ret = pm_runtime_get_sync(arizona->dev); 100 ret = pm_runtime_get_sync(arizona->dev);
100 if (ret < 0) { 101 if (ret < 0) {
@@ -102,9 +103,20 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
102 return IRQ_NONE; 103 return IRQ_NONE;
103 } 104 }
104 105
105 /* Check both domains */ 106 /* Always handle the AoD domain */
106 for (i = 0; i < 2; i++) 107 handle_nested_irq(irq_find_mapping(arizona->virq, 0));
107 handle_nested_irq(irq_find_mapping(arizona->virq, i)); 108
109 /*
110 * Check if one of the main interrupts is asserted and only
111 * check that domain if it is.
112 */
113 ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS, &val);
114 if (ret == 0 && val & ARIZONA_IRQ1_STS) {
115 handle_nested_irq(irq_find_mapping(arizona->virq, 1));
116 } else if (ret != 0) {
117 dev_err(arizona->dev, "Failed to read main IRQ status: %d\n",
118 ret);
119 }
108 120
109 pm_runtime_mark_last_busy(arizona->dev); 121 pm_runtime_mark_last_busy(arizona->dev);
110 pm_runtime_put_autosuspend(arizona->dev); 122 pm_runtime_put_autosuspend(arizona->dev);
@@ -156,18 +168,36 @@ int arizona_irq_init(struct arizona *arizona)
156 int flags = IRQF_ONESHOT; 168 int flags = IRQF_ONESHOT;
157 int ret, i; 169 int ret, i;
158 const struct regmap_irq_chip *aod, *irq; 170 const struct regmap_irq_chip *aod, *irq;
171 bool ctrlif_error = true;
159 172
160 switch (arizona->type) { 173 switch (arizona->type) {
161#ifdef CONFIG_MFD_WM5102 174#ifdef CONFIG_MFD_WM5102
162 case WM5102: 175 case WM5102:
163 aod = &wm5102_aod; 176 aod = &wm5102_aod;
164 irq = &wm5102_irq; 177 irq = &wm5102_irq;
178
179 switch (arizona->rev) {
180 case 0:
181 ctrlif_error = false;
182 break;
183 default:
184 break;
185 }
165 break; 186 break;
166#endif 187#endif
167#ifdef CONFIG_MFD_WM5110 188#ifdef CONFIG_MFD_WM5110
168 case WM5110: 189 case WM5110:
169 aod = &wm5110_aod; 190 aod = &wm5110_aod;
170 irq = &wm5110_irq; 191 irq = &wm5110_irq;
192
193 switch (arizona->rev) {
194 case 0:
195 case 1:
196 ctrlif_error = false;
197 break;
198 default:
199 break;
200 }
171 break; 201 break;
172#endif 202#endif
173 default: 203 default:
@@ -226,13 +256,17 @@ int arizona_irq_init(struct arizona *arizona)
226 } 256 }
227 257
228 /* Handle control interface errors in the core */ 258 /* Handle control interface errors in the core */
229 i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR); 259 if (ctrlif_error) {
230 ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT, 260 i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
231 "Control interface error", arizona); 261 ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
232 if (ret != 0) { 262 IRQF_ONESHOT,
233 dev_err(arizona->dev, "Failed to request boot done %d: %d\n", 263 "Control interface error", arizona);
234 arizona->irq, ret); 264 if (ret != 0) {
235 goto err_ctrlif; 265 dev_err(arizona->dev,
266 "Failed to request CTRLIF_ERR %d: %d\n",
267 arizona->irq, ret);
268 goto err_ctrlif;
269 }
236 } 270 }
237 271
238 ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread, 272 ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,