1 /* 2 * sec-irq.c 3 * 4 * Copyright (c) 2011-2014 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/s2mps14.h> 23 #include <linux/mfd/samsung/s5m8763.h> 24 #include <linux/mfd/samsung/s5m8767.h> 25 26 static const struct regmap_irq s2mps11_irqs[] = { 27 [S2MPS11_IRQ_PWRONF] = { 28 .reg_offset = 0, 29 .mask = S2MPS11_IRQ_PWRONF_MASK, 30 }, 31 [S2MPS11_IRQ_PWRONR] = { 32 .reg_offset = 0, 33 .mask = S2MPS11_IRQ_PWRONR_MASK, 34 }, 35 [S2MPS11_IRQ_JIGONBF] = { 36 .reg_offset = 0, 37 .mask = S2MPS11_IRQ_JIGONBF_MASK, 38 }, 39 [S2MPS11_IRQ_JIGONBR] = { 40 .reg_offset = 0, 41 .mask = S2MPS11_IRQ_JIGONBR_MASK, 42 }, 43 [S2MPS11_IRQ_ACOKBF] = { 44 .reg_offset = 0, 45 .mask = S2MPS11_IRQ_ACOKBF_MASK, 46 }, 47 [S2MPS11_IRQ_ACOKBR] = { 48 .reg_offset = 0, 49 .mask = S2MPS11_IRQ_ACOKBR_MASK, 50 }, 51 [S2MPS11_IRQ_PWRON1S] = { 52 .reg_offset = 0, 53 .mask = S2MPS11_IRQ_PWRON1S_MASK, 54 }, 55 [S2MPS11_IRQ_MRB] = { 56 .reg_offset = 0, 57 .mask = S2MPS11_IRQ_MRB_MASK, 58 }, 59 [S2MPS11_IRQ_RTC60S] = { 60 .reg_offset = 1, 61 .mask = S2MPS11_IRQ_RTC60S_MASK, 62 }, 63 [S2MPS11_IRQ_RTCA0] = { 64 .reg_offset = 1, 65 .mask = S2MPS11_IRQ_RTCA0_MASK, 66 }, 67 [S2MPS11_IRQ_RTCA1] = { 68 .reg_offset = 1, 69 .mask = S2MPS11_IRQ_RTCA1_MASK, 70 }, 71 [S2MPS11_IRQ_SMPL] = { 72 .reg_offset = 1, 73 .mask = S2MPS11_IRQ_SMPL_MASK, 74 }, 75 [S2MPS11_IRQ_RTC1S] = { 76 .reg_offset = 1, 77 .mask = S2MPS11_IRQ_RTC1S_MASK, 78 }, 79 [S2MPS11_IRQ_WTSR] = { 80 .reg_offset = 1, 81 .mask = S2MPS11_IRQ_WTSR_MASK, 82 }, 83 [S2MPS11_IRQ_INT120C] = { 84 .reg_offset = 2, 85 .mask = S2MPS11_IRQ_INT120C_MASK, 86 }, 87 [S2MPS11_IRQ_INT140C] = { 88 .reg_offset = 2, 89 .mask = S2MPS11_IRQ_INT140C_MASK, 90 }, 91 }; 92 93 static const struct regmap_irq s2mps14_irqs[] = { 94 [S2MPS14_IRQ_PWRONF] = { 95 .reg_offset = 0, 96 .mask = S2MPS11_IRQ_PWRONF_MASK, 97 }, 98 [S2MPS14_IRQ_PWRONR] = { 99 .reg_offset = 0, 100 .mask = S2MPS11_IRQ_PWRONR_MASK, 101 }, 102 [S2MPS14_IRQ_JIGONBF] = { 103 .reg_offset = 0, 104 .mask = S2MPS11_IRQ_JIGONBF_MASK, 105 }, 106 [S2MPS14_IRQ_JIGONBR] = { 107 .reg_offset = 0, 108 .mask = S2MPS11_IRQ_JIGONBR_MASK, 109 }, 110 [S2MPS14_IRQ_ACOKBF] = { 111 .reg_offset = 0, 112 .mask = S2MPS11_IRQ_ACOKBF_MASK, 113 }, 114 [S2MPS14_IRQ_ACOKBR] = { 115 .reg_offset = 0, 116 .mask = S2MPS11_IRQ_ACOKBR_MASK, 117 }, 118 [S2MPS14_IRQ_PWRON1S] = { 119 .reg_offset = 0, 120 .mask = S2MPS11_IRQ_PWRON1S_MASK, 121 }, 122 [S2MPS14_IRQ_MRB] = { 123 .reg_offset = 0, 124 .mask = S2MPS11_IRQ_MRB_MASK, 125 }, 126 [S2MPS14_IRQ_RTC60S] = { 127 .reg_offset = 1, 128 .mask = S2MPS11_IRQ_RTC60S_MASK, 129 }, 130 [S2MPS14_IRQ_RTCA1] = { 131 .reg_offset = 1, 132 .mask = S2MPS11_IRQ_RTCA1_MASK, 133 }, 134 [S2MPS14_IRQ_RTCA0] = { 135 .reg_offset = 1, 136 .mask = S2MPS11_IRQ_RTCA0_MASK, 137 }, 138 [S2MPS14_IRQ_SMPL] = { 139 .reg_offset = 1, 140 .mask = S2MPS11_IRQ_SMPL_MASK, 141 }, 142 [S2MPS14_IRQ_RTC1S] = { 143 .reg_offset = 1, 144 .mask = S2MPS11_IRQ_RTC1S_MASK, 145 }, 146 [S2MPS14_IRQ_WTSR] = { 147 .reg_offset = 1, 148 .mask = S2MPS11_IRQ_WTSR_MASK, 149 }, 150 [S2MPS14_IRQ_INT120C] = { 151 .reg_offset = 2, 152 .mask = S2MPS11_IRQ_INT120C_MASK, 153 }, 154 [S2MPS14_IRQ_INT140C] = { 155 .reg_offset = 2, 156 .mask = S2MPS11_IRQ_INT140C_MASK, 157 }, 158 [S2MPS14_IRQ_TSD] = { 159 .reg_offset = 2, 160 .mask = S2MPS14_IRQ_TSD_MASK, 161 }, 162 }; 163 164 static const struct regmap_irq s5m8767_irqs[] = { 165 [S5M8767_IRQ_PWRR] = { 166 .reg_offset = 0, 167 .mask = S5M8767_IRQ_PWRR_MASK, 168 }, 169 [S5M8767_IRQ_PWRF] = { 170 .reg_offset = 0, 171 .mask = S5M8767_IRQ_PWRF_MASK, 172 }, 173 [S5M8767_IRQ_PWR1S] = { 174 .reg_offset = 0, 175 .mask = S5M8767_IRQ_PWR1S_MASK, 176 }, 177 [S5M8767_IRQ_JIGR] = { 178 .reg_offset = 0, 179 .mask = S5M8767_IRQ_JIGR_MASK, 180 }, 181 [S5M8767_IRQ_JIGF] = { 182 .reg_offset = 0, 183 .mask = S5M8767_IRQ_JIGF_MASK, 184 }, 185 [S5M8767_IRQ_LOWBAT2] = { 186 .reg_offset = 0, 187 .mask = S5M8767_IRQ_LOWBAT2_MASK, 188 }, 189 [S5M8767_IRQ_LOWBAT1] = { 190 .reg_offset = 0, 191 .mask = S5M8767_IRQ_LOWBAT1_MASK, 192 }, 193 [S5M8767_IRQ_MRB] = { 194 .reg_offset = 1, 195 .mask = S5M8767_IRQ_MRB_MASK, 196 }, 197 [S5M8767_IRQ_DVSOK2] = { 198 .reg_offset = 1, 199 .mask = S5M8767_IRQ_DVSOK2_MASK, 200 }, 201 [S5M8767_IRQ_DVSOK3] = { 202 .reg_offset = 1, 203 .mask = S5M8767_IRQ_DVSOK3_MASK, 204 }, 205 [S5M8767_IRQ_DVSOK4] = { 206 .reg_offset = 1, 207 .mask = S5M8767_IRQ_DVSOK4_MASK, 208 }, 209 [S5M8767_IRQ_RTC60S] = { 210 .reg_offset = 2, 211 .mask = S5M8767_IRQ_RTC60S_MASK, 212 }, 213 [S5M8767_IRQ_RTCA1] = { 214 .reg_offset = 2, 215 .mask = S5M8767_IRQ_RTCA1_MASK, 216 }, 217 [S5M8767_IRQ_RTCA2] = { 218 .reg_offset = 2, 219 .mask = S5M8767_IRQ_RTCA2_MASK, 220 }, 221 [S5M8767_IRQ_SMPL] = { 222 .reg_offset = 2, 223 .mask = S5M8767_IRQ_SMPL_MASK, 224 }, 225 [S5M8767_IRQ_RTC1S] = { 226 .reg_offset = 2, 227 .mask = S5M8767_IRQ_RTC1S_MASK, 228 }, 229 [S5M8767_IRQ_WTSR] = { 230 .reg_offset = 2, 231 .mask = S5M8767_IRQ_WTSR_MASK, 232 }, 233 }; 234 235 static const struct regmap_irq s5m8763_irqs[] = { 236 [S5M8763_IRQ_DCINF] = { 237 .reg_offset = 0, 238 .mask = S5M8763_IRQ_DCINF_MASK, 239 }, 240 [S5M8763_IRQ_DCINR] = { 241 .reg_offset = 0, 242 .mask = S5M8763_IRQ_DCINR_MASK, 243 }, 244 [S5M8763_IRQ_JIGF] = { 245 .reg_offset = 0, 246 .mask = S5M8763_IRQ_JIGF_MASK, 247 }, 248 [S5M8763_IRQ_JIGR] = { 249 .reg_offset = 0, 250 .mask = S5M8763_IRQ_JIGR_MASK, 251 }, 252 [S5M8763_IRQ_PWRONF] = { 253 .reg_offset = 0, 254 .mask = S5M8763_IRQ_PWRONF_MASK, 255 }, 256 [S5M8763_IRQ_PWRONR] = { 257 .reg_offset = 0, 258 .mask = S5M8763_IRQ_PWRONR_MASK, 259 }, 260 [S5M8763_IRQ_WTSREVNT] = { 261 .reg_offset = 1, 262 .mask = S5M8763_IRQ_WTSREVNT_MASK, 263 }, 264 [S5M8763_IRQ_SMPLEVNT] = { 265 .reg_offset = 1, 266 .mask = S5M8763_IRQ_SMPLEVNT_MASK, 267 }, 268 [S5M8763_IRQ_ALARM1] = { 269 .reg_offset = 1, 270 .mask = S5M8763_IRQ_ALARM1_MASK, 271 }, 272 [S5M8763_IRQ_ALARM0] = { 273 .reg_offset = 1, 274 .mask = S5M8763_IRQ_ALARM0_MASK, 275 }, 276 [S5M8763_IRQ_ONKEY1S] = { 277 .reg_offset = 2, 278 .mask = S5M8763_IRQ_ONKEY1S_MASK, 279 }, 280 [S5M8763_IRQ_TOPOFFR] = { 281 .reg_offset = 2, 282 .mask = S5M8763_IRQ_TOPOFFR_MASK, 283 }, 284 [S5M8763_IRQ_DCINOVPR] = { 285 .reg_offset = 2, 286 .mask = S5M8763_IRQ_DCINOVPR_MASK, 287 }, 288 [S5M8763_IRQ_CHGRSTF] = { 289 .reg_offset = 2, 290 .mask = S5M8763_IRQ_CHGRSTF_MASK, 291 }, 292 [S5M8763_IRQ_DONER] = { 293 .reg_offset = 2, 294 .mask = S5M8763_IRQ_DONER_MASK, 295 }, 296 [S5M8763_IRQ_CHGFAULT] = { 297 .reg_offset = 2, 298 .mask = S5M8763_IRQ_CHGFAULT_MASK, 299 }, 300 [S5M8763_IRQ_LOBAT1] = { 301 .reg_offset = 3, 302 .mask = S5M8763_IRQ_LOBAT1_MASK, 303 }, 304 [S5M8763_IRQ_LOBAT2] = { 305 .reg_offset = 3, 306 .mask = S5M8763_IRQ_LOBAT2_MASK, 307 }, 308 }; 309 310 static const struct regmap_irq_chip s2mps11_irq_chip = { 311 .name = "s2mps11", 312 .irqs = s2mps11_irqs, 313 .num_irqs = ARRAY_SIZE(s2mps11_irqs), 314 .num_regs = 3, 315 .status_base = S2MPS11_REG_INT1, 316 .mask_base = S2MPS11_REG_INT1M, 317 .ack_base = S2MPS11_REG_INT1, 318 }; 319 320 static const struct regmap_irq_chip s2mps14_irq_chip = { 321 .name = "s2mps14", 322 .irqs = s2mps14_irqs, 323 .num_irqs = ARRAY_SIZE(s2mps14_irqs), 324 .num_regs = 3, 325 .status_base = S2MPS14_REG_INT1, 326 .mask_base = S2MPS14_REG_INT1M, 327 .ack_base = S2MPS14_REG_INT1, 328 }; 329 330 static const struct regmap_irq_chip s5m8767_irq_chip = { 331 .name = "s5m8767", 332 .irqs = s5m8767_irqs, 333 .num_irqs = ARRAY_SIZE(s5m8767_irqs), 334 .num_regs = 3, 335 .status_base = S5M8767_REG_INT1, 336 .mask_base = S5M8767_REG_INT1M, 337 .ack_base = S5M8767_REG_INT1, 338 }; 339 340 static const struct regmap_irq_chip s5m8763_irq_chip = { 341 .name = "s5m8763", 342 .irqs = s5m8763_irqs, 343 .num_irqs = ARRAY_SIZE(s5m8763_irqs), 344 .num_regs = 4, 345 .status_base = S5M8763_REG_IRQ1, 346 .mask_base = S5M8763_REG_IRQM1, 347 .ack_base = S5M8763_REG_IRQ1, 348 }; 349 350 int sec_irq_init(struct sec_pmic_dev *sec_pmic) 351 { 352 int ret = 0; 353 int type = sec_pmic->device_type; 354 355 if (!sec_pmic->irq) { 356 dev_warn(sec_pmic->dev, 357 "No interrupt specified, no interrupts\n"); 358 sec_pmic->irq_base = 0; 359 return 0; 360 } 361 362 switch (type) { 363 case S5M8763X: 364 ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 365 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 366 sec_pmic->irq_base, &s5m8763_irq_chip, 367 &sec_pmic->irq_data); 368 break; 369 case S5M8767X: 370 ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 371 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 372 sec_pmic->irq_base, &s5m8767_irq_chip, 373 &sec_pmic->irq_data); 374 break; 375 case S2MPS11X: 376 ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 377 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 378 sec_pmic->irq_base, &s2mps11_irq_chip, 379 &sec_pmic->irq_data); 380 break; 381 case S2MPS14X: 382 ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 383 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 384 sec_pmic->irq_base, &s2mps14_irq_chip, 385 &sec_pmic->irq_data); 386 break; 387 default: 388 dev_err(sec_pmic->dev, "Unknown device type %d\n", 389 sec_pmic->device_type); 390 return -EINVAL; 391 } 392 393 if (ret != 0) { 394 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); 395 return ret; 396 } 397 398 return 0; 399 } 400 401 void sec_irq_exit(struct sec_pmic_dev *sec_pmic) 402 { 403 regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data); 404 } 405