1 /* 2 * sec-irq.c 3 * 4 * Copyright (c) 2011 Samsung Electronics Co., Ltd 5 * http://www.samsung.com 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 */ 13 14 #include <linux/device.h> 15 #include <linux/interrupt.h> 16 #include <linux/irq.h> 17 #include <linux/regmap.h> 18 19 #include <linux/mfd/samsung/core.h> 20 #include <linux/mfd/samsung/irq.h> 21 #include <linux/mfd/samsung/s2mps11.h> 22 #include <linux/mfd/samsung/s5m8763.h> 23 #include <linux/mfd/samsung/s5m8767.h> 24 25 static struct regmap_irq s2mps11_irqs[] = { 26 [S2MPS11_IRQ_PWRONF] = { 27 .reg_offset = 0, 28 .mask = S2MPS11_IRQ_PWRONF_MASK, 29 }, 30 [S2MPS11_IRQ_PWRONR] = { 31 .reg_offset = 0, 32 .mask = S2MPS11_IRQ_PWRONR_MASK, 33 }, 34 [S2MPS11_IRQ_JIGONBF] = { 35 .reg_offset = 0, 36 .mask = S2MPS11_IRQ_JIGONBF_MASK, 37 }, 38 [S2MPS11_IRQ_JIGONBR] = { 39 .reg_offset = 0, 40 .mask = S2MPS11_IRQ_JIGONBR_MASK, 41 }, 42 [S2MPS11_IRQ_ACOKBF] = { 43 .reg_offset = 0, 44 .mask = S2MPS11_IRQ_ACOKBF_MASK, 45 }, 46 [S2MPS11_IRQ_ACOKBR] = { 47 .reg_offset = 0, 48 .mask = S2MPS11_IRQ_ACOKBR_MASK, 49 }, 50 [S2MPS11_IRQ_PWRON1S] = { 51 .reg_offset = 0, 52 .mask = S2MPS11_IRQ_PWRON1S_MASK, 53 }, 54 [S2MPS11_IRQ_MRB] = { 55 .reg_offset = 0, 56 .mask = S2MPS11_IRQ_MRB_MASK, 57 }, 58 [S2MPS11_IRQ_RTC60S] = { 59 .reg_offset = 1, 60 .mask = S2MPS11_IRQ_RTC60S_MASK, 61 }, 62 [S2MPS11_IRQ_RTCA1] = { 63 .reg_offset = 1, 64 .mask = S2MPS11_IRQ_RTCA1_MASK, 65 }, 66 [S2MPS11_IRQ_RTCA2] = { 67 .reg_offset = 1, 68 .mask = S2MPS11_IRQ_RTCA2_MASK, 69 }, 70 [S2MPS11_IRQ_SMPL] = { 71 .reg_offset = 1, 72 .mask = S2MPS11_IRQ_SMPL_MASK, 73 }, 74 [S2MPS11_IRQ_RTC1S] = { 75 .reg_offset = 1, 76 .mask = S2MPS11_IRQ_RTC1S_MASK, 77 }, 78 [S2MPS11_IRQ_WTSR] = { 79 .reg_offset = 1, 80 .mask = S2MPS11_IRQ_WTSR_MASK, 81 }, 82 [S2MPS11_IRQ_INT120C] = { 83 .reg_offset = 2, 84 .mask = S2MPS11_IRQ_INT120C_MASK, 85 }, 86 [S2MPS11_IRQ_INT140C] = { 87 .reg_offset = 2, 88 .mask = S2MPS11_IRQ_INT140C_MASK, 89 }, 90 }; 91 92 93 static struct regmap_irq s5m8767_irqs[] = { 94 [S5M8767_IRQ_PWRR] = { 95 .reg_offset = 0, 96 .mask = S5M8767_IRQ_PWRR_MASK, 97 }, 98 [S5M8767_IRQ_PWRF] = { 99 .reg_offset = 0, 100 .mask = S5M8767_IRQ_PWRF_MASK, 101 }, 102 [S5M8767_IRQ_PWR1S] = { 103 .reg_offset = 0, 104 .mask = S5M8767_IRQ_PWR1S_MASK, 105 }, 106 [S5M8767_IRQ_JIGR] = { 107 .reg_offset = 0, 108 .mask = S5M8767_IRQ_JIGR_MASK, 109 }, 110 [S5M8767_IRQ_JIGF] = { 111 .reg_offset = 0, 112 .mask = S5M8767_IRQ_JIGF_MASK, 113 }, 114 [S5M8767_IRQ_LOWBAT2] = { 115 .reg_offset = 0, 116 .mask = S5M8767_IRQ_LOWBAT2_MASK, 117 }, 118 [S5M8767_IRQ_LOWBAT1] = { 119 .reg_offset = 0, 120 .mask = S5M8767_IRQ_LOWBAT1_MASK, 121 }, 122 [S5M8767_IRQ_MRB] = { 123 .reg_offset = 1, 124 .mask = S5M8767_IRQ_MRB_MASK, 125 }, 126 [S5M8767_IRQ_DVSOK2] = { 127 .reg_offset = 1, 128 .mask = S5M8767_IRQ_DVSOK2_MASK, 129 }, 130 [S5M8767_IRQ_DVSOK3] = { 131 .reg_offset = 1, 132 .mask = S5M8767_IRQ_DVSOK3_MASK, 133 }, 134 [S5M8767_IRQ_DVSOK4] = { 135 .reg_offset = 1, 136 .mask = S5M8767_IRQ_DVSOK4_MASK, 137 }, 138 [S5M8767_IRQ_RTC60S] = { 139 .reg_offset = 2, 140 .mask = S5M8767_IRQ_RTC60S_MASK, 141 }, 142 [S5M8767_IRQ_RTCA1] = { 143 .reg_offset = 2, 144 .mask = S5M8767_IRQ_RTCA1_MASK, 145 }, 146 [S5M8767_IRQ_RTCA2] = { 147 .reg_offset = 2, 148 .mask = S5M8767_IRQ_RTCA2_MASK, 149 }, 150 [S5M8767_IRQ_SMPL] = { 151 .reg_offset = 2, 152 .mask = S5M8767_IRQ_SMPL_MASK, 153 }, 154 [S5M8767_IRQ_RTC1S] = { 155 .reg_offset = 2, 156 .mask = S5M8767_IRQ_RTC1S_MASK, 157 }, 158 [S5M8767_IRQ_WTSR] = { 159 .reg_offset = 2, 160 .mask = S5M8767_IRQ_WTSR_MASK, 161 }, 162 }; 163 164 static struct regmap_irq s5m8763_irqs[] = { 165 [S5M8763_IRQ_DCINF] = { 166 .reg_offset = 0, 167 .mask = S5M8763_IRQ_DCINF_MASK, 168 }, 169 [S5M8763_IRQ_DCINR] = { 170 .reg_offset = 0, 171 .mask = S5M8763_IRQ_DCINR_MASK, 172 }, 173 [S5M8763_IRQ_JIGF] = { 174 .reg_offset = 0, 175 .mask = S5M8763_IRQ_JIGF_MASK, 176 }, 177 [S5M8763_IRQ_JIGR] = { 178 .reg_offset = 0, 179 .mask = S5M8763_IRQ_JIGR_MASK, 180 }, 181 [S5M8763_IRQ_PWRONF] = { 182 .reg_offset = 0, 183 .mask = S5M8763_IRQ_PWRONF_MASK, 184 }, 185 [S5M8763_IRQ_PWRONR] = { 186 .reg_offset = 0, 187 .mask = S5M8763_IRQ_PWRONR_MASK, 188 }, 189 [S5M8763_IRQ_WTSREVNT] = { 190 .reg_offset = 1, 191 .mask = S5M8763_IRQ_WTSREVNT_MASK, 192 }, 193 [S5M8763_IRQ_SMPLEVNT] = { 194 .reg_offset = 1, 195 .mask = S5M8763_IRQ_SMPLEVNT_MASK, 196 }, 197 [S5M8763_IRQ_ALARM1] = { 198 .reg_offset = 1, 199 .mask = S5M8763_IRQ_ALARM1_MASK, 200 }, 201 [S5M8763_IRQ_ALARM0] = { 202 .reg_offset = 1, 203 .mask = S5M8763_IRQ_ALARM0_MASK, 204 }, 205 [S5M8763_IRQ_ONKEY1S] = { 206 .reg_offset = 2, 207 .mask = S5M8763_IRQ_ONKEY1S_MASK, 208 }, 209 [S5M8763_IRQ_TOPOFFR] = { 210 .reg_offset = 2, 211 .mask = S5M8763_IRQ_TOPOFFR_MASK, 212 }, 213 [S5M8763_IRQ_DCINOVPR] = { 214 .reg_offset = 2, 215 .mask = S5M8763_IRQ_DCINOVPR_MASK, 216 }, 217 [S5M8763_IRQ_CHGRSTF] = { 218 .reg_offset = 2, 219 .mask = S5M8763_IRQ_CHGRSTF_MASK, 220 }, 221 [S5M8763_IRQ_DONER] = { 222 .reg_offset = 2, 223 .mask = S5M8763_IRQ_DONER_MASK, 224 }, 225 [S5M8763_IRQ_CHGFAULT] = { 226 .reg_offset = 2, 227 .mask = S5M8763_IRQ_CHGFAULT_MASK, 228 }, 229 [S5M8763_IRQ_LOBAT1] = { 230 .reg_offset = 3, 231 .mask = S5M8763_IRQ_LOBAT1_MASK, 232 }, 233 [S5M8763_IRQ_LOBAT2] = { 234 .reg_offset = 3, 235 .mask = S5M8763_IRQ_LOBAT2_MASK, 236 }, 237 }; 238 239 static struct regmap_irq_chip s2mps11_irq_chip = { 240 .name = "s2mps11", 241 .irqs = s2mps11_irqs, 242 .num_irqs = ARRAY_SIZE(s2mps11_irqs), 243 .num_regs = 3, 244 .status_base = S2MPS11_REG_INT1, 245 .mask_base = S2MPS11_REG_INT1M, 246 .ack_base = S2MPS11_REG_INT1, 247 }; 248 249 static struct regmap_irq_chip s5m8767_irq_chip = { 250 .name = "s5m8767", 251 .irqs = s5m8767_irqs, 252 .num_irqs = ARRAY_SIZE(s5m8767_irqs), 253 .num_regs = 3, 254 .status_base = S5M8767_REG_INT1, 255 .mask_base = S5M8767_REG_INT1M, 256 .ack_base = S5M8767_REG_INT1, 257 }; 258 259 static struct regmap_irq_chip s5m8763_irq_chip = { 260 .name = "s5m8763", 261 .irqs = s5m8763_irqs, 262 .num_irqs = ARRAY_SIZE(s5m8763_irqs), 263 .num_regs = 4, 264 .status_base = S5M8763_REG_IRQ1, 265 .mask_base = S5M8763_REG_IRQM1, 266 .ack_base = S5M8763_REG_IRQ1, 267 }; 268 269 int sec_irq_init(struct sec_pmic_dev *sec_pmic) 270 { 271 int ret = 0; 272 int type = sec_pmic->device_type; 273 274 if (!sec_pmic->irq) { 275 dev_warn(sec_pmic->dev, 276 "No interrupt specified, no interrupts\n"); 277 sec_pmic->irq_base = 0; 278 return 0; 279 } 280 281 switch (type) { 282 case S5M8763X: 283 ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, 284 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 285 sec_pmic->irq_base, &s5m8763_irq_chip, 286 &sec_pmic->irq_data); 287 break; 288 case S5M8767X: 289 ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, 290 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 291 sec_pmic->irq_base, &s5m8767_irq_chip, 292 &sec_pmic->irq_data); 293 break; 294 case S2MPS11X: 295 ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq, 296 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 297 sec_pmic->irq_base, &s2mps11_irq_chip, 298 &sec_pmic->irq_data); 299 break; 300 default: 301 dev_err(sec_pmic->dev, "Unknown device type %d\n", 302 sec_pmic->device_type); 303 return -EINVAL; 304 } 305 306 if (ret != 0) { 307 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); 308 return ret; 309 } 310 311 return 0; 312 } 313 314 void sec_irq_exit(struct sec_pmic_dev *sec_pmic) 315 { 316 regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data); 317 } 318