Blame view
drivers/mfd/wm8994-irq.c
5.81 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
c9fbf7e07 mfd: Add WM8994 i... |
2 3 4 5 6 7 |
/* * wm8994-irq.c -- Interrupt controller support for Wolfson WM8994 * * Copyright 2010 Wolfson Microelectronics PLC. * * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
c9fbf7e07 mfd: Add WM8994 i... |
8 9 10 11 |
*/ #include <linux/kernel.h> #include <linux/module.h> |
7c8844481 mfd: wm8994: Emul... |
12 |
#include <linux/gpio.h> |
c9fbf7e07 mfd: Add WM8994 i... |
13 14 15 16 |
#include <linux/i2c.h> #include <linux/irq.h> #include <linux/mfd/core.h> #include <linux/interrupt.h> |
7c8844481 mfd: wm8994: Emul... |
17 |
#include <linux/irqdomain.h> |
8ab306918 mfd: Convert wm89... |
18 |
#include <linux/regmap.h> |
c9fbf7e07 mfd: Add WM8994 i... |
19 20 |
#include <linux/mfd/wm8994/core.h> |
b0ab907d3 mfd: Support for ... |
21 |
#include <linux/mfd/wm8994/pdata.h> |
c9fbf7e07 mfd: Add WM8994 i... |
22 23 24 |
#include <linux/mfd/wm8994/registers.h> #include <linux/delay.h> |
7ce7b26f8 mfd: Constify reg... |
25 |
static const struct regmap_irq wm8994_irqs[] = { |
c9fbf7e07 mfd: Add WM8994 i... |
26 |
[WM8994_IRQ_TEMP_SHUT] = { |
8ab306918 mfd: Convert wm89... |
27 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
28 29 30 |
.mask = WM8994_TEMP_SHUT_EINT, }, [WM8994_IRQ_MIC1_DET] = { |
8ab306918 mfd: Convert wm89... |
31 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
32 33 34 |
.mask = WM8994_MIC1_DET_EINT, }, [WM8994_IRQ_MIC1_SHRT] = { |
8ab306918 mfd: Convert wm89... |
35 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
36 37 38 |
.mask = WM8994_MIC1_SHRT_EINT, }, [WM8994_IRQ_MIC2_DET] = { |
8ab306918 mfd: Convert wm89... |
39 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
40 41 42 |
.mask = WM8994_MIC2_DET_EINT, }, [WM8994_IRQ_MIC2_SHRT] = { |
8ab306918 mfd: Convert wm89... |
43 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
44 45 46 |
.mask = WM8994_MIC2_SHRT_EINT, }, [WM8994_IRQ_FLL1_LOCK] = { |
8ab306918 mfd: Convert wm89... |
47 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
48 49 50 |
.mask = WM8994_FLL1_LOCK_EINT, }, [WM8994_IRQ_FLL2_LOCK] = { |
8ab306918 mfd: Convert wm89... |
51 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
52 53 54 |
.mask = WM8994_FLL2_LOCK_EINT, }, [WM8994_IRQ_SRC1_LOCK] = { |
8ab306918 mfd: Convert wm89... |
55 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
56 57 58 |
.mask = WM8994_SRC1_LOCK_EINT, }, [WM8994_IRQ_SRC2_LOCK] = { |
8ab306918 mfd: Convert wm89... |
59 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
60 61 62 |
.mask = WM8994_SRC2_LOCK_EINT, }, [WM8994_IRQ_AIF1DRC1_SIG_DET] = { |
8ab306918 mfd: Convert wm89... |
63 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
64 65 66 |
.mask = WM8994_AIF1DRC1_SIG_DET, }, [WM8994_IRQ_AIF1DRC2_SIG_DET] = { |
8ab306918 mfd: Convert wm89... |
67 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
68 69 70 |
.mask = WM8994_AIF1DRC2_SIG_DET_EINT, }, [WM8994_IRQ_AIF2DRC_SIG_DET] = { |
8ab306918 mfd: Convert wm89... |
71 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
72 73 74 |
.mask = WM8994_AIF2DRC_SIG_DET_EINT, }, [WM8994_IRQ_FIFOS_ERR] = { |
8ab306918 mfd: Convert wm89... |
75 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
76 77 78 |
.mask = WM8994_FIFOS_ERR_EINT, }, [WM8994_IRQ_WSEQ_DONE] = { |
8ab306918 mfd: Convert wm89... |
79 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
80 81 82 |
.mask = WM8994_WSEQ_DONE_EINT, }, [WM8994_IRQ_DCS_DONE] = { |
8ab306918 mfd: Convert wm89... |
83 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
84 85 86 |
.mask = WM8994_DCS_DONE_EINT, }, [WM8994_IRQ_TEMP_WARN] = { |
8ab306918 mfd: Convert wm89... |
87 |
.reg_offset = 1, |
c9fbf7e07 mfd: Add WM8994 i... |
88 89 90 |
.mask = WM8994_TEMP_WARN_EINT, }, [WM8994_IRQ_GPIO(1)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
91 92 93 |
.mask = WM8994_GP1_EINT, }, [WM8994_IRQ_GPIO(2)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
94 95 96 |
.mask = WM8994_GP2_EINT, }, [WM8994_IRQ_GPIO(3)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
97 98 99 |
.mask = WM8994_GP3_EINT, }, [WM8994_IRQ_GPIO(4)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
100 101 102 |
.mask = WM8994_GP4_EINT, }, [WM8994_IRQ_GPIO(5)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
103 104 105 |
.mask = WM8994_GP5_EINT, }, [WM8994_IRQ_GPIO(6)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
106 107 108 |
.mask = WM8994_GP6_EINT, }, [WM8994_IRQ_GPIO(7)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
109 110 111 |
.mask = WM8994_GP7_EINT, }, [WM8994_IRQ_GPIO(8)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
112 113 114 |
.mask = WM8994_GP8_EINT, }, [WM8994_IRQ_GPIO(9)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
115 116 117 |
.mask = WM8994_GP8_EINT, }, [WM8994_IRQ_GPIO(10)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
118 119 120 |
.mask = WM8994_GP10_EINT, }, [WM8994_IRQ_GPIO(11)] = { |
c9fbf7e07 mfd: Add WM8994 i... |
121 122 123 |
.mask = WM8994_GP11_EINT, }, }; |
7ce7b26f8 mfd: Constify reg... |
124 |
static const struct regmap_irq_chip wm8994_irq_chip = { |
8ab306918 mfd: Convert wm89... |
125 126 127 |
.name = "wm8994", .irqs = wm8994_irqs, .num_irqs = ARRAY_SIZE(wm8994_irqs), |
c9fbf7e07 mfd: Add WM8994 i... |
128 |
|
8ab306918 mfd: Convert wm89... |
129 130 131 132 |
.num_regs = 2, .status_base = WM8994_INTERRUPT_STATUS_1, .mask_base = WM8994_INTERRUPT_STATUS_1_MASK, .ack_base = WM8994_INTERRUPT_STATUS_1, |
7a9763798 mfd: wm8994: Flag... |
133 |
.runtime_pm = true, |
c9fbf7e07 mfd: Add WM8994 i... |
134 |
}; |
7c8844481 mfd: wm8994: Emul... |
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
static void wm8994_edge_irq_enable(struct irq_data *data) { } static void wm8994_edge_irq_disable(struct irq_data *data) { } static struct irq_chip wm8994_edge_irq_chip = { .name = "wm8994_edge", .irq_disable = wm8994_edge_irq_disable, .irq_enable = wm8994_edge_irq_enable, }; static irqreturn_t wm8994_edge_irq(int irq, void *data) { struct wm8994 *wm8994 = data; while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio)) handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0)); return IRQ_HANDLED; } static int wm8994_edge_irq_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw) { struct wm8994 *wm8994 = h->host_data; irq_set_chip_data(virq, wm8994); irq_set_chip_and_handler(virq, &wm8994_edge_irq_chip, handle_edge_irq); irq_set_nested_thread(virq, 1); |
7c8844481 mfd: wm8994: Emul... |
167 |
irq_set_noprobe(virq); |
7c8844481 mfd: wm8994: Emul... |
168 169 170 |
return 0; } |
7ce7b26f8 mfd: Constify reg... |
171 |
static const struct irq_domain_ops wm8994_edge_irq_ops = { |
7c8844481 mfd: wm8994: Emul... |
172 173 174 |
.map = wm8994_edge_irq_map, .xlate = irq_domain_xlate_twocell, }; |
c9fbf7e07 mfd: Add WM8994 i... |
175 176 |
int wm8994_irq_init(struct wm8994 *wm8994) { |
8ab306918 mfd: Convert wm89... |
177 |
int ret; |
b0ab907d3 mfd: Support for ... |
178 |
unsigned long irqflags; |
dd30acc88 mfd: wm8994: Fix ... |
179 |
struct wm8994_pdata *pdata = &wm8994->pdata; |
c9fbf7e07 mfd: Add WM8994 i... |
180 181 182 183 184 185 186 187 |
if (!wm8994->irq) { dev_warn(wm8994->dev, "No interrupt specified, no interrupts "); wm8994->irq_base = 0; return 0; } |
b0ab907d3 mfd: Support for ... |
188 189 190 191 |
/* select user or default irq flags */ irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; if (pdata->irq_flags) irqflags = pdata->irq_flags; |
7c8844481 mfd: wm8994: Emul... |
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
/* use a GPIO for edge triggered controllers */ if (irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { if (gpio_to_irq(pdata->irq_gpio) != wm8994->irq) { dev_warn(wm8994->dev, "IRQ %d is not GPIO %d (%d) ", wm8994->irq, pdata->irq_gpio, gpio_to_irq(pdata->irq_gpio)); wm8994->irq = gpio_to_irq(pdata->irq_gpio); } ret = devm_gpio_request_one(wm8994->dev, pdata->irq_gpio, GPIOF_IN, "WM8994 IRQ"); if (ret != 0) { dev_err(wm8994->dev, "Failed to get IRQ GPIO: %d ", ret); return ret; } wm8994->edge_irq = irq_domain_add_linear(NULL, 1, &wm8994_edge_irq_ops, wm8994); ret = regmap_add_irq_chip(wm8994->regmap, irq_create_mapping(wm8994->edge_irq, 0), IRQF_ONESHOT, wm8994->irq_base, &wm8994_irq_chip, &wm8994->irq_data); if (ret != 0) { dev_err(wm8994->dev, "Failed to get IRQ: %d ", ret); return ret; } ret = request_threaded_irq(wm8994->irq, NULL, wm8994_edge_irq, irqflags, "WM8994 edge", wm8994); } else { ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq, irqflags, wm8994->irq_base, &wm8994_irq_chip, &wm8994->irq_data); } |
c9fbf7e07 mfd: Add WM8994 i... |
239 |
if (ret != 0) { |
8ab306918 mfd: Convert wm89... |
240 241 |
dev_err(wm8994->dev, "Failed to register IRQ chip: %d ", ret); |
c9fbf7e07 mfd: Add WM8994 i... |
242 243 244 245 246 247 248 249 |
return ret; } /* Enable top level interrupt if it was masked */ wm8994_reg_write(wm8994, WM8994_INTERRUPT_CONTROL, 0); return 0; } |
7821d9b24 mfd: wm8994: Expo... |
250 |
EXPORT_SYMBOL(wm8994_irq_init); |
c9fbf7e07 mfd: Add WM8994 i... |
251 252 253 |
void wm8994_irq_exit(struct wm8994 *wm8994) { |
8ab306918 mfd: Convert wm89... |
254 |
regmap_del_irq_chip(wm8994->irq, wm8994->irq_data); |
c9fbf7e07 mfd: Add WM8994 i... |
255 |
} |
7821d9b24 mfd: wm8994: Expo... |
256 |
EXPORT_SYMBOL(wm8994_irq_exit); |