0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/delay.h>
0011 #include <linux/gpio.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/irq.h>
0014 #include <linux/irqdomain.h>
0015 #include <linux/module.h>
0016 #include <linux/pm_runtime.h>
0017 #include <linux/regmap.h>
0018 #include <linux/regulator/consumer.h>
0019 #include <linux/slab.h>
0020
0021 #include <linux/mfd/arizona/core.h>
0022 #include <linux/mfd/arizona/registers.h>
0023
0024 #include "arizona.h"
0025
0026 #define ARIZONA_AOD_IRQ_INDEX 0
0027 #define ARIZONA_MAIN_IRQ_INDEX 1
0028
0029 static int arizona_map_irq(struct arizona *arizona, int irq)
0030 {
0031 int ret;
0032
0033 if (arizona->aod_irq_chip) {
0034 ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq);
0035 if (ret >= 0)
0036 return ret;
0037 }
0038
0039 return regmap_irq_get_virq(arizona->irq_chip, irq);
0040 }
0041
0042 int arizona_request_irq(struct arizona *arizona, int irq, char *name,
0043 irq_handler_t handler, void *data)
0044 {
0045 irq = arizona_map_irq(arizona, irq);
0046 if (irq < 0)
0047 return irq;
0048
0049 return request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT,
0050 name, data);
0051 }
0052 EXPORT_SYMBOL_GPL(arizona_request_irq);
0053
0054 void arizona_free_irq(struct arizona *arizona, int irq, void *data)
0055 {
0056 irq = arizona_map_irq(arizona, irq);
0057 if (irq < 0)
0058 return;
0059
0060 free_irq(irq, data);
0061 }
0062 EXPORT_SYMBOL_GPL(arizona_free_irq);
0063
0064 int arizona_set_irq_wake(struct arizona *arizona, int irq, int on)
0065 {
0066 irq = arizona_map_irq(arizona, irq);
0067 if (irq < 0)
0068 return irq;
0069
0070 return irq_set_irq_wake(irq, on);
0071 }
0072 EXPORT_SYMBOL_GPL(arizona_set_irq_wake);
0073
0074 static irqreturn_t arizona_boot_done(int irq, void *data)
0075 {
0076 struct arizona *arizona = data;
0077
0078 dev_dbg(arizona->dev, "Boot done\n");
0079
0080 return IRQ_HANDLED;
0081 }
0082
0083 static irqreturn_t arizona_ctrlif_err(int irq, void *data)
0084 {
0085 struct arizona *arizona = data;
0086
0087
0088
0089
0090
0091 dev_err(arizona->dev, "Control interface error\n");
0092
0093 return IRQ_HANDLED;
0094 }
0095
0096 static irqreturn_t arizona_irq_thread(int irq, void *data)
0097 {
0098 struct arizona *arizona = data;
0099 bool poll;
0100 unsigned int val;
0101 int ret;
0102
0103 ret = pm_runtime_resume_and_get(arizona->dev);
0104 if (ret < 0) {
0105 dev_err(arizona->dev, "Failed to resume device: %d\n", ret);
0106 return IRQ_NONE;
0107 }
0108
0109 do {
0110 poll = false;
0111
0112 if (arizona->aod_irq_chip) {
0113
0114
0115
0116
0117 ret = regmap_read(arizona->regmap,
0118 ARIZONA_AOD_IRQ1, &val);
0119 if (ret)
0120 dev_warn(arizona->dev,
0121 "Failed to read AOD IRQ1 %d\n", ret);
0122 else if (val)
0123 handle_nested_irq(
0124 irq_find_mapping(arizona->virq, 0));
0125 }
0126
0127
0128
0129
0130
0131 ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS,
0132 &val);
0133 if (ret == 0 && val & ARIZONA_IRQ1_STS) {
0134 handle_nested_irq(irq_find_mapping(arizona->virq, 1));
0135 } else if (ret != 0) {
0136 dev_err(arizona->dev,
0137 "Failed to read main IRQ status: %d\n", ret);
0138 }
0139
0140
0141
0142
0143
0144 if (!arizona->pdata.irq_gpio) {
0145 break;
0146 } else if (arizona->pdata.irq_flags & IRQF_TRIGGER_RISING &&
0147 gpio_get_value_cansleep(arizona->pdata.irq_gpio)) {
0148 poll = true;
0149 } else if (arizona->pdata.irq_flags & IRQF_TRIGGER_FALLING &&
0150 !gpio_get_value_cansleep(arizona->pdata.irq_gpio)) {
0151 poll = true;
0152 }
0153 } while (poll);
0154
0155 pm_runtime_mark_last_busy(arizona->dev);
0156 pm_runtime_put_autosuspend(arizona->dev);
0157
0158 return IRQ_HANDLED;
0159 }
0160
0161 static void arizona_irq_enable(struct irq_data *data)
0162 {
0163 }
0164
0165 static void arizona_irq_disable(struct irq_data *data)
0166 {
0167 }
0168
0169 static int arizona_irq_set_wake(struct irq_data *data, unsigned int on)
0170 {
0171 struct arizona *arizona = irq_data_get_irq_chip_data(data);
0172
0173 return irq_set_irq_wake(arizona->irq, on);
0174 }
0175
0176 static struct irq_chip arizona_irq_chip = {
0177 .name = "arizona",
0178 .irq_disable = arizona_irq_disable,
0179 .irq_enable = arizona_irq_enable,
0180 .irq_set_wake = arizona_irq_set_wake,
0181 };
0182
0183 static struct lock_class_key arizona_irq_lock_class;
0184 static struct lock_class_key arizona_irq_request_class;
0185
0186 static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
0187 irq_hw_number_t hw)
0188 {
0189 struct arizona *data = h->host_data;
0190
0191 irq_set_chip_data(virq, data);
0192 irq_set_lockdep_class(virq, &arizona_irq_lock_class,
0193 &arizona_irq_request_class);
0194 irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_simple_irq);
0195 irq_set_nested_thread(virq, 1);
0196 irq_set_noprobe(virq);
0197
0198 return 0;
0199 }
0200
0201 static const struct irq_domain_ops arizona_domain_ops = {
0202 .map = arizona_irq_map,
0203 .xlate = irq_domain_xlate_twocell,
0204 };
0205
0206 int arizona_irq_init(struct arizona *arizona)
0207 {
0208 int flags = IRQF_ONESHOT;
0209 int ret;
0210 const struct regmap_irq_chip *aod, *irq;
0211 struct irq_data *irq_data;
0212 unsigned int virq;
0213
0214 arizona->ctrlif_error = true;
0215
0216 switch (arizona->type) {
0217 #ifdef CONFIG_MFD_WM5102
0218 case WM5102:
0219 aod = &wm5102_aod;
0220 irq = &wm5102_irq;
0221
0222 arizona->ctrlif_error = false;
0223 break;
0224 #endif
0225 #ifdef CONFIG_MFD_WM5110
0226 case WM5110:
0227 case WM8280:
0228 aod = &wm5110_aod;
0229
0230 switch (arizona->rev) {
0231 case 0 ... 2:
0232 irq = &wm5110_irq;
0233 break;
0234 default:
0235 irq = &wm5110_revd_irq;
0236 break;
0237 }
0238
0239 arizona->ctrlif_error = false;
0240 break;
0241 #endif
0242 #ifdef CONFIG_MFD_CS47L24
0243 case WM1831:
0244 case CS47L24:
0245 aod = NULL;
0246 irq = &cs47l24_irq;
0247
0248 arizona->ctrlif_error = false;
0249 break;
0250 #endif
0251 #ifdef CONFIG_MFD_WM8997
0252 case WM8997:
0253 aod = &wm8997_aod;
0254 irq = &wm8997_irq;
0255
0256 arizona->ctrlif_error = false;
0257 break;
0258 #endif
0259 #ifdef CONFIG_MFD_WM8998
0260 case WM8998:
0261 case WM1814:
0262 aod = &wm8998_aod;
0263 irq = &wm8998_irq;
0264
0265 arizona->ctrlif_error = false;
0266 break;
0267 #endif
0268 default:
0269 BUG_ON("Unknown Arizona class device" == NULL);
0270 return -EINVAL;
0271 }
0272
0273
0274 regmap_write(arizona->regmap, ARIZONA_WAKE_CONTROL, 0);
0275
0276
0277 if (!arizona->pdata.irq_flags) {
0278 irq_data = irq_get_irq_data(arizona->irq);
0279 if (!irq_data) {
0280 dev_err(arizona->dev, "Invalid IRQ: %d\n",
0281 arizona->irq);
0282 return -EINVAL;
0283 }
0284
0285 arizona->pdata.irq_flags = irqd_get_trigger_type(irq_data);
0286 switch (arizona->pdata.irq_flags) {
0287 case IRQF_TRIGGER_LOW:
0288 case IRQF_TRIGGER_HIGH:
0289 case IRQF_TRIGGER_RISING:
0290 case IRQF_TRIGGER_FALLING:
0291 break;
0292
0293 case IRQ_TYPE_NONE:
0294 default:
0295
0296 arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
0297 break;
0298 }
0299 }
0300
0301 if (arizona->pdata.irq_flags & (IRQF_TRIGGER_HIGH |
0302 IRQF_TRIGGER_RISING)) {
0303 ret = regmap_update_bits(arizona->regmap, ARIZONA_IRQ_CTRL_1,
0304 ARIZONA_IRQ_POL, 0);
0305 if (ret != 0) {
0306 dev_err(arizona->dev, "Couldn't set IRQ polarity: %d\n",
0307 ret);
0308 goto err;
0309 }
0310 }
0311
0312 flags |= arizona->pdata.irq_flags;
0313
0314
0315 arizona->virq = irq_domain_add_linear(NULL, 2, &arizona_domain_ops,
0316 arizona);
0317 if (!arizona->virq) {
0318 dev_err(arizona->dev, "Failed to add core IRQ domain\n");
0319 ret = -EINVAL;
0320 goto err;
0321 }
0322
0323 if (aod) {
0324 virq = irq_create_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
0325 if (!virq) {
0326 dev_err(arizona->dev, "Failed to map AOD IRQs\n");
0327 ret = -EINVAL;
0328 goto err_domain;
0329 }
0330
0331 ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
0332 0, aod, &arizona->aod_irq_chip);
0333 if (ret != 0) {
0334 dev_err(arizona->dev,
0335 "Failed to add AOD IRQs: %d\n", ret);
0336 goto err_map_aod;
0337 }
0338 }
0339
0340 virq = irq_create_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
0341 if (!virq) {
0342 dev_err(arizona->dev, "Failed to map main IRQs\n");
0343 ret = -EINVAL;
0344 goto err_aod;
0345 }
0346
0347 ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
0348 0, irq, &arizona->irq_chip);
0349 if (ret != 0) {
0350 dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret);
0351 goto err_map_main_irq;
0352 }
0353
0354
0355 if (arizona->pdata.irq_gpio) {
0356 if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) {
0357 dev_warn(arizona->dev, "IRQ %d is not GPIO %d (%d)\n",
0358 arizona->irq, arizona->pdata.irq_gpio,
0359 gpio_to_irq(arizona->pdata.irq_gpio));
0360 arizona->irq = gpio_to_irq(arizona->pdata.irq_gpio);
0361 }
0362
0363 ret = devm_gpio_request_one(arizona->dev,
0364 arizona->pdata.irq_gpio,
0365 GPIOF_IN, "arizona IRQ");
0366 if (ret != 0) {
0367 dev_err(arizona->dev,
0368 "Failed to request IRQ GPIO %d:: %d\n",
0369 arizona->pdata.irq_gpio, ret);
0370 arizona->pdata.irq_gpio = 0;
0371 }
0372 }
0373
0374 ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,
0375 flags, "arizona", arizona);
0376
0377 if (ret != 0) {
0378 dev_err(arizona->dev, "Failed to request primary IRQ %d: %d\n",
0379 arizona->irq, ret);
0380 goto err_main_irq;
0381 }
0382
0383
0384 ret = arizona_request_irq(arizona, ARIZONA_IRQ_BOOT_DONE, "Boot done",
0385 arizona_boot_done, arizona);
0386 if (ret != 0) {
0387 dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
0388 arizona->irq, ret);
0389 goto err_boot_done;
0390 }
0391
0392
0393 if (arizona->ctrlif_error) {
0394 ret = arizona_request_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR,
0395 "Control interface error",
0396 arizona_ctrlif_err, arizona);
0397 if (ret != 0) {
0398 dev_err(arizona->dev,
0399 "Failed to request CTRLIF_ERR %d: %d\n",
0400 arizona->irq, ret);
0401 goto err_ctrlif;
0402 }
0403 }
0404
0405 return 0;
0406
0407 err_ctrlif:
0408 arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
0409 err_boot_done:
0410 free_irq(arizona->irq, arizona);
0411 err_main_irq:
0412 regmap_del_irq_chip(irq_find_mapping(arizona->virq,
0413 ARIZONA_MAIN_IRQ_INDEX),
0414 arizona->irq_chip);
0415 err_map_main_irq:
0416 irq_dispose_mapping(irq_find_mapping(arizona->virq,
0417 ARIZONA_MAIN_IRQ_INDEX));
0418 err_aod:
0419 regmap_del_irq_chip(irq_find_mapping(arizona->virq,
0420 ARIZONA_AOD_IRQ_INDEX),
0421 arizona->aod_irq_chip);
0422 err_map_aod:
0423 irq_dispose_mapping(irq_find_mapping(arizona->virq,
0424 ARIZONA_AOD_IRQ_INDEX));
0425 err_domain:
0426 irq_domain_remove(arizona->virq);
0427 err:
0428 return ret;
0429 }
0430
0431 int arizona_irq_exit(struct arizona *arizona)
0432 {
0433 unsigned int virq;
0434
0435 if (arizona->ctrlif_error)
0436 arizona_free_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR, arizona);
0437 arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
0438
0439 virq = irq_find_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
0440 regmap_del_irq_chip(virq, arizona->irq_chip);
0441 irq_dispose_mapping(virq);
0442
0443 virq = irq_find_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
0444 regmap_del_irq_chip(virq, arizona->aod_irq_chip);
0445 irq_dispose_mapping(virq);
0446
0447 irq_domain_remove(arizona->virq);
0448
0449 free_irq(arizona->irq, arizona);
0450
0451 return 0;
0452 }