1 /* da9063-irq.c: Interrupts support for Dialog DA9063 2 * 3 * Copyright 2012 Dialog Semiconductor Ltd. 4 * Copyright 2013 Philipp Zabel, Pengutronix 5 * 6 * Author: Michal Hajduk, Dialog Semiconductor 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/irq.h> 18 #include <linux/mfd/core.h> 19 #include <linux/interrupt.h> 20 #include <linux/regmap.h> 21 #include <linux/mfd/da9063/core.h> 22 #include <linux/mfd/da9063/pdata.h> 23 24 #define DA9063_REG_EVENT_A_OFFSET 0 25 #define DA9063_REG_EVENT_B_OFFSET 1 26 #define DA9063_REG_EVENT_C_OFFSET 2 27 #define DA9063_REG_EVENT_D_OFFSET 3 28 29 static const struct regmap_irq da9063_irqs[] = { 30 /* DA9063 event A register */ 31 REGMAP_IRQ_REG(DA9063_IRQ_ONKEY, 32 DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY), 33 REGMAP_IRQ_REG(DA9063_IRQ_ALARM, 34 DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM), 35 REGMAP_IRQ_REG(DA9063_IRQ_TICK, 36 DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK), 37 REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY, 38 DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY), 39 REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY, 40 DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY), 41 /* DA9063 event B register */ 42 REGMAP_IRQ_REG(DA9063_IRQ_WAKE, 43 DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE), 44 REGMAP_IRQ_REG(DA9063_IRQ_TEMP, 45 DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP), 46 REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2, 47 DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2), 48 REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM, 49 DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM), 50 REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV, 51 DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV), 52 REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY, 53 DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY), 54 REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON, 55 DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON), 56 REGMAP_IRQ_REG(DA9063_IRQ_WARN, 57 DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN), 58 /* DA9063 event C register */ 59 REGMAP_IRQ_REG(DA9063_IRQ_GPI0, 60 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0), 61 REGMAP_IRQ_REG(DA9063_IRQ_GPI1, 62 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1), 63 REGMAP_IRQ_REG(DA9063_IRQ_GPI2, 64 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2), 65 REGMAP_IRQ_REG(DA9063_IRQ_GPI3, 66 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3), 67 REGMAP_IRQ_REG(DA9063_IRQ_GPI4, 68 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4), 69 REGMAP_IRQ_REG(DA9063_IRQ_GPI5, 70 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5), 71 REGMAP_IRQ_REG(DA9063_IRQ_GPI6, 72 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6), 73 REGMAP_IRQ_REG(DA9063_IRQ_GPI7, 74 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7), 75 /* DA9063 event D register */ 76 REGMAP_IRQ_REG(DA9063_IRQ_GPI8, 77 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8), 78 REGMAP_IRQ_REG(DA9063_IRQ_GPI9, 79 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9), 80 REGMAP_IRQ_REG(DA9063_IRQ_GPI10, 81 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10), 82 REGMAP_IRQ_REG(DA9063_IRQ_GPI11, 83 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11), 84 REGMAP_IRQ_REG(DA9063_IRQ_GPI12, 85 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12), 86 REGMAP_IRQ_REG(DA9063_IRQ_GPI13, 87 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13), 88 REGMAP_IRQ_REG(DA9063_IRQ_GPI14, 89 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14), 90 REGMAP_IRQ_REG(DA9063_IRQ_GPI15, 91 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15), 92 }; 93 94 static const struct regmap_irq_chip da9063_irq_chip = { 95 .name = "da9063-irq", 96 .irqs = da9063_irqs, 97 .num_irqs = ARRAY_SIZE(da9063_irqs), 98 .num_regs = 4, 99 .status_base = DA9063_REG_EVENT_A, 100 .mask_base = DA9063_REG_IRQ_MASK_A, 101 .ack_base = DA9063_REG_EVENT_A, 102 .init_ack_masked = true, 103 }; 104 105 static const struct regmap_irq da9063l_irqs[] = { 106 /* DA9063 event A register */ 107 REGMAP_IRQ_REG(DA9063_IRQ_ONKEY, 108 DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY), 109 REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY, 110 DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY), 111 REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY, 112 DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY), 113 /* DA9063 event B register */ 114 REGMAP_IRQ_REG(DA9063_IRQ_WAKE, 115 DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE), 116 REGMAP_IRQ_REG(DA9063_IRQ_TEMP, 117 DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP), 118 REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2, 119 DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2), 120 REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM, 121 DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM), 122 REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV, 123 DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV), 124 REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY, 125 DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY), 126 REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON, 127 DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON), 128 REGMAP_IRQ_REG(DA9063_IRQ_WARN, 129 DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN), 130 /* DA9063 event C register */ 131 REGMAP_IRQ_REG(DA9063_IRQ_GPI0, 132 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0), 133 REGMAP_IRQ_REG(DA9063_IRQ_GPI1, 134 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1), 135 REGMAP_IRQ_REG(DA9063_IRQ_GPI2, 136 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2), 137 REGMAP_IRQ_REG(DA9063_IRQ_GPI3, 138 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3), 139 REGMAP_IRQ_REG(DA9063_IRQ_GPI4, 140 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4), 141 REGMAP_IRQ_REG(DA9063_IRQ_GPI5, 142 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5), 143 REGMAP_IRQ_REG(DA9063_IRQ_GPI6, 144 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6), 145 REGMAP_IRQ_REG(DA9063_IRQ_GPI7, 146 DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7), 147 /* DA9063 event D register */ 148 REGMAP_IRQ_REG(DA9063_IRQ_GPI8, 149 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8), 150 REGMAP_IRQ_REG(DA9063_IRQ_GPI9, 151 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9), 152 REGMAP_IRQ_REG(DA9063_IRQ_GPI10, 153 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10), 154 REGMAP_IRQ_REG(DA9063_IRQ_GPI11, 155 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11), 156 REGMAP_IRQ_REG(DA9063_IRQ_GPI12, 157 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12), 158 REGMAP_IRQ_REG(DA9063_IRQ_GPI13, 159 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13), 160 REGMAP_IRQ_REG(DA9063_IRQ_GPI14, 161 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14), 162 REGMAP_IRQ_REG(DA9063_IRQ_GPI15, 163 DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15), 164 }; 165 166 static const struct regmap_irq_chip da9063l_irq_chip = { 167 .name = "da9063l-irq", 168 .irqs = da9063l_irqs, 169 .num_irqs = ARRAY_SIZE(da9063l_irqs), 170 .num_regs = 4, 171 .status_base = DA9063_REG_EVENT_A, 172 .mask_base = DA9063_REG_IRQ_MASK_A, 173 .ack_base = DA9063_REG_EVENT_A, 174 .init_ack_masked = true, 175 }; 176 177 int da9063_irq_init(struct da9063 *da9063) 178 { 179 const struct regmap_irq_chip *irq_chip; 180 int ret; 181 182 if (!da9063->chip_irq) { 183 dev_err(da9063->dev, "No IRQ configured\n"); 184 return -EINVAL; 185 } 186 187 if (da9063->type == PMIC_TYPE_DA9063) 188 irq_chip = &da9063_irq_chip; 189 else 190 irq_chip = &da9063l_irq_chip; 191 192 ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap, 193 da9063->chip_irq, 194 IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, 195 da9063->irq_base, irq_chip, &da9063->regmap_irq); 196 if (ret) { 197 dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n", 198 da9063->chip_irq, ret); 199 return ret; 200 } 201 202 return 0; 203 } 204