1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2966cdc96SMark Brown /*
3966cdc96SMark Brown * Arizona interrupt support
4966cdc96SMark Brown *
5966cdc96SMark Brown * Copyright 2012 Wolfson Microelectronics plc
6966cdc96SMark Brown *
7966cdc96SMark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8966cdc96SMark Brown */
9966cdc96SMark Brown
10966cdc96SMark Brown #include <linux/delay.h>
11966cdc96SMark Brown #include <linux/gpio.h>
12966cdc96SMark Brown #include <linux/interrupt.h>
13966cdc96SMark Brown #include <linux/irq.h>
14966cdc96SMark Brown #include <linux/irqdomain.h>
15966cdc96SMark Brown #include <linux/module.h>
16966cdc96SMark Brown #include <linux/pm_runtime.h>
17966cdc96SMark Brown #include <linux/regmap.h>
18966cdc96SMark Brown #include <linux/regulator/consumer.h>
19966cdc96SMark Brown #include <linux/slab.h>
20966cdc96SMark Brown
21966cdc96SMark Brown #include <linux/mfd/arizona/core.h>
22966cdc96SMark Brown #include <linux/mfd/arizona/registers.h>
23966cdc96SMark Brown
24966cdc96SMark Brown #include "arizona.h"
25966cdc96SMark Brown
261a86dcb3SCharles Keepax #define ARIZONA_AOD_IRQ_INDEX 0
271a86dcb3SCharles Keepax #define ARIZONA_MAIN_IRQ_INDEX 1
281a86dcb3SCharles Keepax
arizona_map_irq(struct arizona * arizona,int irq)29966cdc96SMark Brown static int arizona_map_irq(struct arizona *arizona, int irq)
30966cdc96SMark Brown {
31966cdc96SMark Brown int ret;
32966cdc96SMark Brown
33ea1f3339SRichard Fitzgerald if (arizona->aod_irq_chip) {
34966cdc96SMark Brown ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq);
35ea1f3339SRichard Fitzgerald if (ret >= 0)
36966cdc96SMark Brown return ret;
37966cdc96SMark Brown }
38966cdc96SMark Brown
39ea1f3339SRichard Fitzgerald return regmap_irq_get_virq(arizona->irq_chip, irq);
40ea1f3339SRichard Fitzgerald }
41ea1f3339SRichard Fitzgerald
arizona_request_irq(struct arizona * arizona,int irq,char * name,irq_handler_t handler,void * data)42966cdc96SMark Brown int arizona_request_irq(struct arizona *arizona, int irq, char *name,
43966cdc96SMark Brown irq_handler_t handler, void *data)
44966cdc96SMark Brown {
45966cdc96SMark Brown irq = arizona_map_irq(arizona, irq);
46966cdc96SMark Brown if (irq < 0)
47966cdc96SMark Brown return irq;
48966cdc96SMark Brown
49966cdc96SMark Brown return request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT,
50966cdc96SMark Brown name, data);
51966cdc96SMark Brown }
52966cdc96SMark Brown EXPORT_SYMBOL_GPL(arizona_request_irq);
53966cdc96SMark Brown
arizona_free_irq(struct arizona * arizona,int irq,void * data)54966cdc96SMark Brown void arizona_free_irq(struct arizona *arizona, int irq, void *data)
55966cdc96SMark Brown {
56966cdc96SMark Brown irq = arizona_map_irq(arizona, irq);
57966cdc96SMark Brown if (irq < 0)
58966cdc96SMark Brown return;
59966cdc96SMark Brown
60966cdc96SMark Brown free_irq(irq, data);
61966cdc96SMark Brown }
62966cdc96SMark Brown EXPORT_SYMBOL_GPL(arizona_free_irq);
63966cdc96SMark Brown
arizona_set_irq_wake(struct arizona * arizona,int irq,int on)64966cdc96SMark Brown int arizona_set_irq_wake(struct arizona *arizona, int irq, int on)
65966cdc96SMark Brown {
66966cdc96SMark Brown irq = arizona_map_irq(arizona, irq);
67966cdc96SMark Brown if (irq < 0)
68966cdc96SMark Brown return irq;
69966cdc96SMark Brown
70966cdc96SMark Brown return irq_set_irq_wake(irq, on);
71966cdc96SMark Brown }
72966cdc96SMark Brown EXPORT_SYMBOL_GPL(arizona_set_irq_wake);
73966cdc96SMark Brown
arizona_boot_done(int irq,void * data)74966cdc96SMark Brown static irqreturn_t arizona_boot_done(int irq, void *data)
75966cdc96SMark Brown {
76966cdc96SMark Brown struct arizona *arizona = data;
77966cdc96SMark Brown
78966cdc96SMark Brown dev_dbg(arizona->dev, "Boot done\n");
79966cdc96SMark Brown
80966cdc96SMark Brown return IRQ_HANDLED;
81966cdc96SMark Brown }
82966cdc96SMark Brown
arizona_ctrlif_err(int irq,void * data)83966cdc96SMark Brown static irqreturn_t arizona_ctrlif_err(int irq, void *data)
84966cdc96SMark Brown {
85966cdc96SMark Brown struct arizona *arizona = data;
86966cdc96SMark Brown
87966cdc96SMark Brown /*
88966cdc96SMark Brown * For pretty much all potential sources a register cache sync
89966cdc96SMark Brown * won't help, we've just got a software bug somewhere.
90966cdc96SMark Brown */
91966cdc96SMark Brown dev_err(arizona->dev, "Control interface error\n");
92966cdc96SMark Brown
93966cdc96SMark Brown return IRQ_HANDLED;
94966cdc96SMark Brown }
95966cdc96SMark Brown
arizona_irq_thread(int irq,void * data)96966cdc96SMark Brown static irqreturn_t arizona_irq_thread(int irq, void *data)
97966cdc96SMark Brown {
98966cdc96SMark Brown struct arizona *arizona = data;
993092f805SMark Brown bool poll;
1003080de4eSMark Brown unsigned int val;
101cdabc1c8SMark Brown int ret;
102966cdc96SMark Brown
103*fe6df2b4SDinghao Liu ret = pm_runtime_resume_and_get(arizona->dev);
104966cdc96SMark Brown if (ret < 0) {
105966cdc96SMark Brown dev_err(arizona->dev, "Failed to resume device: %d\n", ret);
106966cdc96SMark Brown return IRQ_NONE;
107966cdc96SMark Brown }
108966cdc96SMark Brown
1093092f805SMark Brown do {
1103092f805SMark Brown poll = false;
1113092f805SMark Brown
1121f2c3972SRichard Fitzgerald if (arizona->aod_irq_chip) {
1131f2c3972SRichard Fitzgerald /*
1141f2c3972SRichard Fitzgerald * Check the AOD status register to determine whether
1151f2c3972SRichard Fitzgerald * the nested IRQ handler should be called.
1161f2c3972SRichard Fitzgerald */
1171f2c3972SRichard Fitzgerald ret = regmap_read(arizona->regmap,
1181f2c3972SRichard Fitzgerald ARIZONA_AOD_IRQ1, &val);
1191f2c3972SRichard Fitzgerald if (ret)
1201f2c3972SRichard Fitzgerald dev_warn(arizona->dev,
1211f2c3972SRichard Fitzgerald "Failed to read AOD IRQ1 %d\n", ret);
1221f2c3972SRichard Fitzgerald else if (val)
1231f2c3972SRichard Fitzgerald handle_nested_irq(
1241f2c3972SRichard Fitzgerald irq_find_mapping(arizona->virq, 0));
1251f2c3972SRichard Fitzgerald }
1263080de4eSMark Brown
1273080de4eSMark Brown /*
1283080de4eSMark Brown * Check if one of the main interrupts is asserted and only
1293080de4eSMark Brown * check that domain if it is.
1303080de4eSMark Brown */
1313092f805SMark Brown ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS,
1323092f805SMark Brown &val);
1333080de4eSMark Brown if (ret == 0 && val & ARIZONA_IRQ1_STS) {
1343080de4eSMark Brown handle_nested_irq(irq_find_mapping(arizona->virq, 1));
1353080de4eSMark Brown } else if (ret != 0) {
1363092f805SMark Brown dev_err(arizona->dev,
1373092f805SMark Brown "Failed to read main IRQ status: %d\n", ret);
1383080de4eSMark Brown }
139966cdc96SMark Brown
1403092f805SMark Brown /*
1413092f805SMark Brown * Poll the IRQ pin status to see if we're really done
1423092f805SMark Brown * if the interrupt controller can't do it for us.
1433092f805SMark Brown */
1443092f805SMark Brown if (!arizona->pdata.irq_gpio) {
1453092f805SMark Brown break;
1463092f805SMark Brown } else if (arizona->pdata.irq_flags & IRQF_TRIGGER_RISING &&
1473092f805SMark Brown gpio_get_value_cansleep(arizona->pdata.irq_gpio)) {
1483092f805SMark Brown poll = true;
1493092f805SMark Brown } else if (arizona->pdata.irq_flags & IRQF_TRIGGER_FALLING &&
1503092f805SMark Brown !gpio_get_value_cansleep(arizona->pdata.irq_gpio)) {
1513092f805SMark Brown poll = true;
1523092f805SMark Brown }
1533092f805SMark Brown } while (poll);
1543092f805SMark Brown
155966cdc96SMark Brown pm_runtime_mark_last_busy(arizona->dev);
156966cdc96SMark Brown pm_runtime_put_autosuspend(arizona->dev);
157966cdc96SMark Brown
158966cdc96SMark Brown return IRQ_HANDLED;
159966cdc96SMark Brown }
160966cdc96SMark Brown
arizona_irq_enable(struct irq_data * data)161966cdc96SMark Brown static void arizona_irq_enable(struct irq_data *data)
162966cdc96SMark Brown {
163966cdc96SMark Brown }
164966cdc96SMark Brown
arizona_irq_disable(struct irq_data * data)165966cdc96SMark Brown static void arizona_irq_disable(struct irq_data *data)
166966cdc96SMark Brown {
167966cdc96SMark Brown }
168966cdc96SMark Brown
arizona_irq_set_wake(struct irq_data * data,unsigned int on)169c38715feSCharles Keepax static int arizona_irq_set_wake(struct irq_data *data, unsigned int on)
170c38715feSCharles Keepax {
171c38715feSCharles Keepax struct arizona *arizona = irq_data_get_irq_chip_data(data);
172c38715feSCharles Keepax
173c38715feSCharles Keepax return irq_set_irq_wake(arizona->irq, on);
174c38715feSCharles Keepax }
175c38715feSCharles Keepax
176966cdc96SMark Brown static struct irq_chip arizona_irq_chip = {
177966cdc96SMark Brown .name = "arizona",
178966cdc96SMark Brown .irq_disable = arizona_irq_disable,
179966cdc96SMark Brown .irq_enable = arizona_irq_enable,
180c38715feSCharles Keepax .irq_set_wake = arizona_irq_set_wake,
181966cdc96SMark Brown };
182966cdc96SMark Brown
183dedf24a2SCharles Keepax static struct lock_class_key arizona_irq_lock_class;
18439c3fd58SAndrew Lunn static struct lock_class_key arizona_irq_request_class;
185dedf24a2SCharles Keepax
arizona_irq_map(struct irq_domain * h,unsigned int virq,irq_hw_number_t hw)186966cdc96SMark Brown static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
187966cdc96SMark Brown irq_hw_number_t hw)
188966cdc96SMark Brown {
1890a464dfdSCharles Keepax struct arizona *data = h->host_data;
190966cdc96SMark Brown
191966cdc96SMark Brown irq_set_chip_data(virq, data);
19239c3fd58SAndrew Lunn irq_set_lockdep_class(virq, &arizona_irq_lock_class,
19339c3fd58SAndrew Lunn &arizona_irq_request_class);
194cfeb35daSCharles Keepax irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq);
195966cdc96SMark Brown irq_set_nested_thread(virq, 1);
196966cdc96SMark Brown irq_set_noprobe(virq);
197966cdc96SMark Brown
198966cdc96SMark Brown return 0;
199966cdc96SMark Brown }
200966cdc96SMark Brown
2017ce7b26fSKrzysztof Kozlowski static const struct irq_domain_ops arizona_domain_ops = {
202966cdc96SMark Brown .map = arizona_irq_map,
203966cdc96SMark Brown .xlate = irq_domain_xlate_twocell,
204966cdc96SMark Brown };
205966cdc96SMark Brown
arizona_irq_init(struct arizona * arizona)206966cdc96SMark Brown int arizona_irq_init(struct arizona *arizona)
207966cdc96SMark Brown {
208966cdc96SMark Brown int flags = IRQF_ONESHOT;
209003db34eSCharles Keepax int ret;
210966cdc96SMark Brown const struct regmap_irq_chip *aod, *irq;
21122c75fe7SMark Brown struct irq_data *irq_data;
2123dfaff27SCharles Keepax unsigned int virq;
213966cdc96SMark Brown
21430a2af3aSCharles Keepax arizona->ctrlif_error = true;
21530a2af3aSCharles Keepax
216966cdc96SMark Brown switch (arizona->type) {
217863df8d5SMark Brown #ifdef CONFIG_MFD_WM5102
218966cdc96SMark Brown case WM5102:
219966cdc96SMark Brown aod = &wm5102_aod;
220966cdc96SMark Brown irq = &wm5102_irq;
22192d80139SMark Brown
22230a2af3aSCharles Keepax arizona->ctrlif_error = false;
22392d80139SMark Brown break;
224863df8d5SMark Brown #endif
225e102befeSMark Brown #ifdef CONFIG_MFD_WM5110
226e102befeSMark Brown case WM5110:
227e5d4ef0dSRichard Fitzgerald case WM8280:
228e102befeSMark Brown aod = &wm5110_aod;
2293215501fSCharles Keepax
2303215501fSCharles Keepax switch (arizona->rev) {
2313215501fSCharles Keepax case 0 ... 2:
232e102befeSMark Brown irq = &wm5110_irq;
2333215501fSCharles Keepax break;
2343215501fSCharles Keepax default:
2353215501fSCharles Keepax irq = &wm5110_revd_irq;
2363215501fSCharles Keepax break;
2373215501fSCharles Keepax }
23892d80139SMark Brown
23930a2af3aSCharles Keepax arizona->ctrlif_error = false;
24092d80139SMark Brown break;
241e102befeSMark Brown #endif
242ea1f3339SRichard Fitzgerald #ifdef CONFIG_MFD_CS47L24
243ea1f3339SRichard Fitzgerald case WM1831:
244ea1f3339SRichard Fitzgerald case CS47L24:
245ea1f3339SRichard Fitzgerald aod = NULL;
246ea1f3339SRichard Fitzgerald irq = &cs47l24_irq;
247ea1f3339SRichard Fitzgerald
248ea1f3339SRichard Fitzgerald arizona->ctrlif_error = false;
249ea1f3339SRichard Fitzgerald break;
250ea1f3339SRichard Fitzgerald #endif
251dc7d4863SCharles Keepax #ifdef CONFIG_MFD_WM8997
252dc7d4863SCharles Keepax case WM8997:
253dc7d4863SCharles Keepax aod = &wm8997_aod;
254dc7d4863SCharles Keepax irq = &wm8997_irq;
255dc7d4863SCharles Keepax
25630a2af3aSCharles Keepax arizona->ctrlif_error = false;
257dc7d4863SCharles Keepax break;
258dc7d4863SCharles Keepax #endif
2596887b042SRichard Fitzgerald #ifdef CONFIG_MFD_WM8998
2606887b042SRichard Fitzgerald case WM8998:
2616887b042SRichard Fitzgerald case WM1814:
2626887b042SRichard Fitzgerald aod = &wm8998_aod;
2636887b042SRichard Fitzgerald irq = &wm8998_irq;
2646887b042SRichard Fitzgerald
2656887b042SRichard Fitzgerald arizona->ctrlif_error = false;
2666887b042SRichard Fitzgerald break;
2676887b042SRichard Fitzgerald #endif
268966cdc96SMark Brown default:
269966cdc96SMark Brown BUG_ON("Unknown Arizona class device" == NULL);
270966cdc96SMark Brown return -EINVAL;
271966cdc96SMark Brown }
272966cdc96SMark Brown
2731816cb34SMark Brown /* Disable all wake sources by default */
2741816cb34SMark Brown regmap_write(arizona->regmap, ARIZONA_WAKE_CONTROL, 0);
2751816cb34SMark Brown
27622c75fe7SMark Brown /* Read the flags from the interrupt controller if not specified */
27722c75fe7SMark Brown if (!arizona->pdata.irq_flags) {
27822c75fe7SMark Brown irq_data = irq_get_irq_data(arizona->irq);
27922c75fe7SMark Brown if (!irq_data) {
28022c75fe7SMark Brown dev_err(arizona->dev, "Invalid IRQ: %d\n",
28122c75fe7SMark Brown arizona->irq);
28222c75fe7SMark Brown return -EINVAL;
28322c75fe7SMark Brown }
28422c75fe7SMark Brown
28522c75fe7SMark Brown arizona->pdata.irq_flags = irqd_get_trigger_type(irq_data);
28622c75fe7SMark Brown switch (arizona->pdata.irq_flags) {
28722c75fe7SMark Brown case IRQF_TRIGGER_LOW:
28822c75fe7SMark Brown case IRQF_TRIGGER_HIGH:
28922c75fe7SMark Brown case IRQF_TRIGGER_RISING:
29022c75fe7SMark Brown case IRQF_TRIGGER_FALLING:
29122c75fe7SMark Brown break;
29222c75fe7SMark Brown
29322c75fe7SMark Brown case IRQ_TYPE_NONE:
29422c75fe7SMark Brown default:
29522c75fe7SMark Brown /* Device default */
296f8a0941fSMark Brown arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
29722c75fe7SMark Brown break;
29822c75fe7SMark Brown }
29922c75fe7SMark Brown }
300f8a0941fSMark Brown
301f8a0941fSMark Brown if (arizona->pdata.irq_flags & (IRQF_TRIGGER_HIGH |
302f8a0941fSMark Brown IRQF_TRIGGER_RISING)) {
303966cdc96SMark Brown ret = regmap_update_bits(arizona->regmap, ARIZONA_IRQ_CTRL_1,
304966cdc96SMark Brown ARIZONA_IRQ_POL, 0);
305966cdc96SMark Brown if (ret != 0) {
306966cdc96SMark Brown dev_err(arizona->dev, "Couldn't set IRQ polarity: %d\n",
307966cdc96SMark Brown ret);
308966cdc96SMark Brown goto err;
309966cdc96SMark Brown }
310966cdc96SMark Brown }
311966cdc96SMark Brown
312f8a0941fSMark Brown flags |= arizona->pdata.irq_flags;
313f8a0941fSMark Brown
314966cdc96SMark Brown /* Allocate a virtual IRQ domain to distribute to the regmap domains */
315966cdc96SMark Brown arizona->virq = irq_domain_add_linear(NULL, 2, &arizona_domain_ops,
316966cdc96SMark Brown arizona);
317966cdc96SMark Brown if (!arizona->virq) {
318b7dea5dcSMark Brown dev_err(arizona->dev, "Failed to add core IRQ domain\n");
319966cdc96SMark Brown ret = -EINVAL;
320966cdc96SMark Brown goto err;
321966cdc96SMark Brown }
322966cdc96SMark Brown
323ea1f3339SRichard Fitzgerald if (aod) {
3243dfaff27SCharles Keepax virq = irq_create_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
3253dfaff27SCharles Keepax if (!virq) {
3263dfaff27SCharles Keepax dev_err(arizona->dev, "Failed to map AOD IRQs\n");
3273dfaff27SCharles Keepax ret = -EINVAL;
3283dfaff27SCharles Keepax goto err_domain;
3293dfaff27SCharles Keepax }
3303dfaff27SCharles Keepax
3313dfaff27SCharles Keepax ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
3323dfaff27SCharles Keepax 0, aod, &arizona->aod_irq_chip);
333966cdc96SMark Brown if (ret != 0) {
334ea1f3339SRichard Fitzgerald dev_err(arizona->dev,
335ea1f3339SRichard Fitzgerald "Failed to add AOD IRQs: %d\n", ret);
3363dfaff27SCharles Keepax goto err_map_aod;
337966cdc96SMark Brown }
338ea1f3339SRichard Fitzgerald }
339966cdc96SMark Brown
3403dfaff27SCharles Keepax virq = irq_create_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
3413dfaff27SCharles Keepax if (!virq) {
3423dfaff27SCharles Keepax dev_err(arizona->dev, "Failed to map main IRQs\n");
3433dfaff27SCharles Keepax ret = -EINVAL;
3443dfaff27SCharles Keepax goto err_aod;
3453dfaff27SCharles Keepax }
3463dfaff27SCharles Keepax
3473dfaff27SCharles Keepax ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
3483dfaff27SCharles Keepax 0, irq, &arizona->irq_chip);
349966cdc96SMark Brown if (ret != 0) {
350d1cb4cc9SCharles Keepax dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret);
3513dfaff27SCharles Keepax goto err_map_main_irq;
352966cdc96SMark Brown }
353966cdc96SMark Brown
3543092f805SMark Brown /* Used to emulate edge trigger and to work around broken pinmux */
3553092f805SMark Brown if (arizona->pdata.irq_gpio) {
3563092f805SMark Brown if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) {
3573092f805SMark Brown dev_warn(arizona->dev, "IRQ %d is not GPIO %d (%d)\n",
3583092f805SMark Brown arizona->irq, arizona->pdata.irq_gpio,
3593092f805SMark Brown gpio_to_irq(arizona->pdata.irq_gpio));
3603092f805SMark Brown arizona->irq = gpio_to_irq(arizona->pdata.irq_gpio);
3613092f805SMark Brown }
3623092f805SMark Brown
3633092f805SMark Brown ret = devm_gpio_request_one(arizona->dev,
3643092f805SMark Brown arizona->pdata.irq_gpio,
3653092f805SMark Brown GPIOF_IN, "arizona IRQ");
3663092f805SMark Brown if (ret != 0) {
3673092f805SMark Brown dev_err(arizona->dev,
3683092f805SMark Brown "Failed to request IRQ GPIO %d:: %d\n",
3693092f805SMark Brown arizona->pdata.irq_gpio, ret);
3703092f805SMark Brown arizona->pdata.irq_gpio = 0;
3713092f805SMark Brown }
3723092f805SMark Brown }
3733092f805SMark Brown
374966cdc96SMark Brown ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,
375966cdc96SMark Brown flags, "arizona", arizona);
376966cdc96SMark Brown
377966cdc96SMark Brown if (ret != 0) {
3787994c664SMark Brown dev_err(arizona->dev, "Failed to request primary IRQ %d: %d\n",
379966cdc96SMark Brown arizona->irq, ret);
380966cdc96SMark Brown goto err_main_irq;
381966cdc96SMark Brown }
382966cdc96SMark Brown
3836c006b1bSCharles Keepax /* Make sure the boot done IRQ is unmasked for resumes */
384003db34eSCharles Keepax ret = arizona_request_irq(arizona, ARIZONA_IRQ_BOOT_DONE, "Boot done",
385003db34eSCharles Keepax arizona_boot_done, arizona);
3866c006b1bSCharles Keepax if (ret != 0) {
3876c006b1bSCharles Keepax dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
3886c006b1bSCharles Keepax arizona->irq, ret);
3896c006b1bSCharles Keepax goto err_boot_done;
3906c006b1bSCharles Keepax }
3916c006b1bSCharles Keepax
3926c006b1bSCharles Keepax /* Handle control interface errors in the core */
3936c006b1bSCharles Keepax if (arizona->ctrlif_error) {
394003db34eSCharles Keepax ret = arizona_request_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR,
395003db34eSCharles Keepax "Control interface error",
396003db34eSCharles Keepax arizona_ctrlif_err, arizona);
3976c006b1bSCharles Keepax if (ret != 0) {
3986c006b1bSCharles Keepax dev_err(arizona->dev,
3996c006b1bSCharles Keepax "Failed to request CTRLIF_ERR %d: %d\n",
4006c006b1bSCharles Keepax arizona->irq, ret);
4016c006b1bSCharles Keepax goto err_ctrlif;
4026c006b1bSCharles Keepax }
4036c006b1bSCharles Keepax }
4046c006b1bSCharles Keepax
405966cdc96SMark Brown return 0;
406966cdc96SMark Brown
407966cdc96SMark Brown err_ctrlif:
408003db34eSCharles Keepax arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
409966cdc96SMark Brown err_boot_done:
4106c006b1bSCharles Keepax free_irq(arizona->irq, arizona);
4116c006b1bSCharles Keepax err_main_irq:
4121a86dcb3SCharles Keepax regmap_del_irq_chip(irq_find_mapping(arizona->virq,
4131a86dcb3SCharles Keepax ARIZONA_MAIN_IRQ_INDEX),
414966cdc96SMark Brown arizona->irq_chip);
4153dfaff27SCharles Keepax err_map_main_irq:
4163dfaff27SCharles Keepax irq_dispose_mapping(irq_find_mapping(arizona->virq,
4173dfaff27SCharles Keepax ARIZONA_MAIN_IRQ_INDEX));
418966cdc96SMark Brown err_aod:
4191a86dcb3SCharles Keepax regmap_del_irq_chip(irq_find_mapping(arizona->virq,
4201a86dcb3SCharles Keepax ARIZONA_AOD_IRQ_INDEX),
421966cdc96SMark Brown arizona->aod_irq_chip);
4223dfaff27SCharles Keepax err_map_aod:
4233dfaff27SCharles Keepax irq_dispose_mapping(irq_find_mapping(arizona->virq,
4243dfaff27SCharles Keepax ARIZONA_AOD_IRQ_INDEX));
4253dfaff27SCharles Keepax err_domain:
4263dfaff27SCharles Keepax irq_domain_remove(arizona->virq);
427966cdc96SMark Brown err:
428966cdc96SMark Brown return ret;
429966cdc96SMark Brown }
430966cdc96SMark Brown
arizona_irq_exit(struct arizona * arizona)431966cdc96SMark Brown int arizona_irq_exit(struct arizona *arizona)
432966cdc96SMark Brown {
4333dfaff27SCharles Keepax unsigned int virq;
4343dfaff27SCharles Keepax
43530a2af3aSCharles Keepax if (arizona->ctrlif_error)
436003db34eSCharles Keepax arizona_free_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR, arizona);
437003db34eSCharles Keepax arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
438003db34eSCharles Keepax
4393dfaff27SCharles Keepax virq = irq_find_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
4403dfaff27SCharles Keepax regmap_del_irq_chip(virq, arizona->irq_chip);
4413dfaff27SCharles Keepax irq_dispose_mapping(virq);
4423dfaff27SCharles Keepax
4433dfaff27SCharles Keepax virq = irq_find_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
4443dfaff27SCharles Keepax regmap_del_irq_chip(virq, arizona->aod_irq_chip);
4453dfaff27SCharles Keepax irq_dispose_mapping(virq);
4463dfaff27SCharles Keepax
4473dfaff27SCharles Keepax irq_domain_remove(arizona->virq);
4483dfaff27SCharles Keepax
449966cdc96SMark Brown free_irq(arizona->irq, arizona);
450966cdc96SMark Brown
451966cdc96SMark Brown return 0;
452966cdc96SMark Brown }
453