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 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 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 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 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 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 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 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 103966cdc96SMark Brown ret = pm_runtime_get_sync(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 161966cdc96SMark Brown static void arizona_irq_enable(struct irq_data *data) 162966cdc96SMark Brown { 163966cdc96SMark Brown } 164966cdc96SMark Brown 165966cdc96SMark Brown static void arizona_irq_disable(struct irq_data *data) 166966cdc96SMark Brown { 167966cdc96SMark Brown } 168966cdc96SMark Brown 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 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 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 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