1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // Copyright (c) 2011-2014 Samsung Electronics Co., Ltd 4 // http://www.samsung.com 5 6 #include <linux/device.h> 7 #include <linux/interrupt.h> 8 #include <linux/irq.h> 9 #include <linux/module.h> 10 #include <linux/regmap.h> 11 12 #include <linux/mfd/samsung/core.h> 13 #include <linux/mfd/samsung/irq.h> 14 #include <linux/mfd/samsung/s2mps11.h> 15 #include <linux/mfd/samsung/s2mps14.h> 16 #include <linux/mfd/samsung/s2mpu02.h> 17 #include <linux/mfd/samsung/s5m8763.h> 18 #include <linux/mfd/samsung/s5m8767.h> 19 20 static const struct regmap_irq s2mps11_irqs[] = { 21 [S2MPS11_IRQ_PWRONF] = { 22 .reg_offset = 0, 23 .mask = S2MPS11_IRQ_PWRONF_MASK, 24 }, 25 [S2MPS11_IRQ_PWRONR] = { 26 .reg_offset = 0, 27 .mask = S2MPS11_IRQ_PWRONR_MASK, 28 }, 29 [S2MPS11_IRQ_JIGONBF] = { 30 .reg_offset = 0, 31 .mask = S2MPS11_IRQ_JIGONBF_MASK, 32 }, 33 [S2MPS11_IRQ_JIGONBR] = { 34 .reg_offset = 0, 35 .mask = S2MPS11_IRQ_JIGONBR_MASK, 36 }, 37 [S2MPS11_IRQ_ACOKBF] = { 38 .reg_offset = 0, 39 .mask = S2MPS11_IRQ_ACOKBF_MASK, 40 }, 41 [S2MPS11_IRQ_ACOKBR] = { 42 .reg_offset = 0, 43 .mask = S2MPS11_IRQ_ACOKBR_MASK, 44 }, 45 [S2MPS11_IRQ_PWRON1S] = { 46 .reg_offset = 0, 47 .mask = S2MPS11_IRQ_PWRON1S_MASK, 48 }, 49 [S2MPS11_IRQ_MRB] = { 50 .reg_offset = 0, 51 .mask = S2MPS11_IRQ_MRB_MASK, 52 }, 53 [S2MPS11_IRQ_RTC60S] = { 54 .reg_offset = 1, 55 .mask = S2MPS11_IRQ_RTC60S_MASK, 56 }, 57 [S2MPS11_IRQ_RTCA1] = { 58 .reg_offset = 1, 59 .mask = S2MPS11_IRQ_RTCA1_MASK, 60 }, 61 [S2MPS11_IRQ_RTCA0] = { 62 .reg_offset = 1, 63 .mask = S2MPS11_IRQ_RTCA0_MASK, 64 }, 65 [S2MPS11_IRQ_SMPL] = { 66 .reg_offset = 1, 67 .mask = S2MPS11_IRQ_SMPL_MASK, 68 }, 69 [S2MPS11_IRQ_RTC1S] = { 70 .reg_offset = 1, 71 .mask = S2MPS11_IRQ_RTC1S_MASK, 72 }, 73 [S2MPS11_IRQ_WTSR] = { 74 .reg_offset = 1, 75 .mask = S2MPS11_IRQ_WTSR_MASK, 76 }, 77 [S2MPS11_IRQ_INT120C] = { 78 .reg_offset = 2, 79 .mask = S2MPS11_IRQ_INT120C_MASK, 80 }, 81 [S2MPS11_IRQ_INT140C] = { 82 .reg_offset = 2, 83 .mask = S2MPS11_IRQ_INT140C_MASK, 84 }, 85 }; 86 87 static const struct regmap_irq s2mps14_irqs[] = { 88 [S2MPS14_IRQ_PWRONF] = { 89 .reg_offset = 0, 90 .mask = S2MPS11_IRQ_PWRONF_MASK, 91 }, 92 [S2MPS14_IRQ_PWRONR] = { 93 .reg_offset = 0, 94 .mask = S2MPS11_IRQ_PWRONR_MASK, 95 }, 96 [S2MPS14_IRQ_JIGONBF] = { 97 .reg_offset = 0, 98 .mask = S2MPS11_IRQ_JIGONBF_MASK, 99 }, 100 [S2MPS14_IRQ_JIGONBR] = { 101 .reg_offset = 0, 102 .mask = S2MPS11_IRQ_JIGONBR_MASK, 103 }, 104 [S2MPS14_IRQ_ACOKBF] = { 105 .reg_offset = 0, 106 .mask = S2MPS11_IRQ_ACOKBF_MASK, 107 }, 108 [S2MPS14_IRQ_ACOKBR] = { 109 .reg_offset = 0, 110 .mask = S2MPS11_IRQ_ACOKBR_MASK, 111 }, 112 [S2MPS14_IRQ_PWRON1S] = { 113 .reg_offset = 0, 114 .mask = S2MPS11_IRQ_PWRON1S_MASK, 115 }, 116 [S2MPS14_IRQ_MRB] = { 117 .reg_offset = 0, 118 .mask = S2MPS11_IRQ_MRB_MASK, 119 }, 120 [S2MPS14_IRQ_RTC60S] = { 121 .reg_offset = 1, 122 .mask = S2MPS11_IRQ_RTC60S_MASK, 123 }, 124 [S2MPS14_IRQ_RTCA1] = { 125 .reg_offset = 1, 126 .mask = S2MPS11_IRQ_RTCA1_MASK, 127 }, 128 [S2MPS14_IRQ_RTCA0] = { 129 .reg_offset = 1, 130 .mask = S2MPS11_IRQ_RTCA0_MASK, 131 }, 132 [S2MPS14_IRQ_SMPL] = { 133 .reg_offset = 1, 134 .mask = S2MPS11_IRQ_SMPL_MASK, 135 }, 136 [S2MPS14_IRQ_RTC1S] = { 137 .reg_offset = 1, 138 .mask = S2MPS11_IRQ_RTC1S_MASK, 139 }, 140 [S2MPS14_IRQ_WTSR] = { 141 .reg_offset = 1, 142 .mask = S2MPS11_IRQ_WTSR_MASK, 143 }, 144 [S2MPS14_IRQ_INT120C] = { 145 .reg_offset = 2, 146 .mask = S2MPS11_IRQ_INT120C_MASK, 147 }, 148 [S2MPS14_IRQ_INT140C] = { 149 .reg_offset = 2, 150 .mask = S2MPS11_IRQ_INT140C_MASK, 151 }, 152 [S2MPS14_IRQ_TSD] = { 153 .reg_offset = 2, 154 .mask = S2MPS14_IRQ_TSD_MASK, 155 }, 156 }; 157 158 static const struct regmap_irq s2mpu02_irqs[] = { 159 [S2MPU02_IRQ_PWRONF] = { 160 .reg_offset = 0, 161 .mask = S2MPS11_IRQ_PWRONF_MASK, 162 }, 163 [S2MPU02_IRQ_PWRONR] = { 164 .reg_offset = 0, 165 .mask = S2MPS11_IRQ_PWRONR_MASK, 166 }, 167 [S2MPU02_IRQ_JIGONBF] = { 168 .reg_offset = 0, 169 .mask = S2MPS11_IRQ_JIGONBF_MASK, 170 }, 171 [S2MPU02_IRQ_JIGONBR] = { 172 .reg_offset = 0, 173 .mask = S2MPS11_IRQ_JIGONBR_MASK, 174 }, 175 [S2MPU02_IRQ_ACOKBF] = { 176 .reg_offset = 0, 177 .mask = S2MPS11_IRQ_ACOKBF_MASK, 178 }, 179 [S2MPU02_IRQ_ACOKBR] = { 180 .reg_offset = 0, 181 .mask = S2MPS11_IRQ_ACOKBR_MASK, 182 }, 183 [S2MPU02_IRQ_PWRON1S] = { 184 .reg_offset = 0, 185 .mask = S2MPS11_IRQ_PWRON1S_MASK, 186 }, 187 [S2MPU02_IRQ_MRB] = { 188 .reg_offset = 0, 189 .mask = S2MPS11_IRQ_MRB_MASK, 190 }, 191 [S2MPU02_IRQ_RTC60S] = { 192 .reg_offset = 1, 193 .mask = S2MPS11_IRQ_RTC60S_MASK, 194 }, 195 [S2MPU02_IRQ_RTCA1] = { 196 .reg_offset = 1, 197 .mask = S2MPS11_IRQ_RTCA1_MASK, 198 }, 199 [S2MPU02_IRQ_RTCA0] = { 200 .reg_offset = 1, 201 .mask = S2MPS11_IRQ_RTCA0_MASK, 202 }, 203 [S2MPU02_IRQ_SMPL] = { 204 .reg_offset = 1, 205 .mask = S2MPS11_IRQ_SMPL_MASK, 206 }, 207 [S2MPU02_IRQ_RTC1S] = { 208 .reg_offset = 1, 209 .mask = S2MPS11_IRQ_RTC1S_MASK, 210 }, 211 [S2MPU02_IRQ_WTSR] = { 212 .reg_offset = 1, 213 .mask = S2MPS11_IRQ_WTSR_MASK, 214 }, 215 [S2MPU02_IRQ_INT120C] = { 216 .reg_offset = 2, 217 .mask = S2MPS11_IRQ_INT120C_MASK, 218 }, 219 [S2MPU02_IRQ_INT140C] = { 220 .reg_offset = 2, 221 .mask = S2MPS11_IRQ_INT140C_MASK, 222 }, 223 [S2MPU02_IRQ_TSD] = { 224 .reg_offset = 2, 225 .mask = S2MPS14_IRQ_TSD_MASK, 226 }, 227 }; 228 229 static const struct regmap_irq s5m8767_irqs[] = { 230 [S5M8767_IRQ_PWRR] = { 231 .reg_offset = 0, 232 .mask = S5M8767_IRQ_PWRR_MASK, 233 }, 234 [S5M8767_IRQ_PWRF] = { 235 .reg_offset = 0, 236 .mask = S5M8767_IRQ_PWRF_MASK, 237 }, 238 [S5M8767_IRQ_PWR1S] = { 239 .reg_offset = 0, 240 .mask = S5M8767_IRQ_PWR1S_MASK, 241 }, 242 [S5M8767_IRQ_JIGR] = { 243 .reg_offset = 0, 244 .mask = S5M8767_IRQ_JIGR_MASK, 245 }, 246 [S5M8767_IRQ_JIGF] = { 247 .reg_offset = 0, 248 .mask = S5M8767_IRQ_JIGF_MASK, 249 }, 250 [S5M8767_IRQ_LOWBAT2] = { 251 .reg_offset = 0, 252 .mask = S5M8767_IRQ_LOWBAT2_MASK, 253 }, 254 [S5M8767_IRQ_LOWBAT1] = { 255 .reg_offset = 0, 256 .mask = S5M8767_IRQ_LOWBAT1_MASK, 257 }, 258 [S5M8767_IRQ_MRB] = { 259 .reg_offset = 1, 260 .mask = S5M8767_IRQ_MRB_MASK, 261 }, 262 [S5M8767_IRQ_DVSOK2] = { 263 .reg_offset = 1, 264 .mask = S5M8767_IRQ_DVSOK2_MASK, 265 }, 266 [S5M8767_IRQ_DVSOK3] = { 267 .reg_offset = 1, 268 .mask = S5M8767_IRQ_DVSOK3_MASK, 269 }, 270 [S5M8767_IRQ_DVSOK4] = { 271 .reg_offset = 1, 272 .mask = S5M8767_IRQ_DVSOK4_MASK, 273 }, 274 [S5M8767_IRQ_RTC60S] = { 275 .reg_offset = 2, 276 .mask = S5M8767_IRQ_RTC60S_MASK, 277 }, 278 [S5M8767_IRQ_RTCA1] = { 279 .reg_offset = 2, 280 .mask = S5M8767_IRQ_RTCA1_MASK, 281 }, 282 [S5M8767_IRQ_RTCA2] = { 283 .reg_offset = 2, 284 .mask = S5M8767_IRQ_RTCA2_MASK, 285 }, 286 [S5M8767_IRQ_SMPL] = { 287 .reg_offset = 2, 288 .mask = S5M8767_IRQ_SMPL_MASK, 289 }, 290 [S5M8767_IRQ_RTC1S] = { 291 .reg_offset = 2, 292 .mask = S5M8767_IRQ_RTC1S_MASK, 293 }, 294 [S5M8767_IRQ_WTSR] = { 295 .reg_offset = 2, 296 .mask = S5M8767_IRQ_WTSR_MASK, 297 }, 298 }; 299 300 static const struct regmap_irq s5m8763_irqs[] = { 301 [S5M8763_IRQ_DCINF] = { 302 .reg_offset = 0, 303 .mask = S5M8763_IRQ_DCINF_MASK, 304 }, 305 [S5M8763_IRQ_DCINR] = { 306 .reg_offset = 0, 307 .mask = S5M8763_IRQ_DCINR_MASK, 308 }, 309 [S5M8763_IRQ_JIGF] = { 310 .reg_offset = 0, 311 .mask = S5M8763_IRQ_JIGF_MASK, 312 }, 313 [S5M8763_IRQ_JIGR] = { 314 .reg_offset = 0, 315 .mask = S5M8763_IRQ_JIGR_MASK, 316 }, 317 [S5M8763_IRQ_PWRONF] = { 318 .reg_offset = 0, 319 .mask = S5M8763_IRQ_PWRONF_MASK, 320 }, 321 [S5M8763_IRQ_PWRONR] = { 322 .reg_offset = 0, 323 .mask = S5M8763_IRQ_PWRONR_MASK, 324 }, 325 [S5M8763_IRQ_WTSREVNT] = { 326 .reg_offset = 1, 327 .mask = S5M8763_IRQ_WTSREVNT_MASK, 328 }, 329 [S5M8763_IRQ_SMPLEVNT] = { 330 .reg_offset = 1, 331 .mask = S5M8763_IRQ_SMPLEVNT_MASK, 332 }, 333 [S5M8763_IRQ_ALARM1] = { 334 .reg_offset = 1, 335 .mask = S5M8763_IRQ_ALARM1_MASK, 336 }, 337 [S5M8763_IRQ_ALARM0] = { 338 .reg_offset = 1, 339 .mask = S5M8763_IRQ_ALARM0_MASK, 340 }, 341 [S5M8763_IRQ_ONKEY1S] = { 342 .reg_offset = 2, 343 .mask = S5M8763_IRQ_ONKEY1S_MASK, 344 }, 345 [S5M8763_IRQ_TOPOFFR] = { 346 .reg_offset = 2, 347 .mask = S5M8763_IRQ_TOPOFFR_MASK, 348 }, 349 [S5M8763_IRQ_DCINOVPR] = { 350 .reg_offset = 2, 351 .mask = S5M8763_IRQ_DCINOVPR_MASK, 352 }, 353 [S5M8763_IRQ_CHGRSTF] = { 354 .reg_offset = 2, 355 .mask = S5M8763_IRQ_CHGRSTF_MASK, 356 }, 357 [S5M8763_IRQ_DONER] = { 358 .reg_offset = 2, 359 .mask = S5M8763_IRQ_DONER_MASK, 360 }, 361 [S5M8763_IRQ_CHGFAULT] = { 362 .reg_offset = 2, 363 .mask = S5M8763_IRQ_CHGFAULT_MASK, 364 }, 365 [S5M8763_IRQ_LOBAT1] = { 366 .reg_offset = 3, 367 .mask = S5M8763_IRQ_LOBAT1_MASK, 368 }, 369 [S5M8763_IRQ_LOBAT2] = { 370 .reg_offset = 3, 371 .mask = S5M8763_IRQ_LOBAT2_MASK, 372 }, 373 }; 374 375 static const struct regmap_irq_chip s2mps11_irq_chip = { 376 .name = "s2mps11", 377 .irqs = s2mps11_irqs, 378 .num_irqs = ARRAY_SIZE(s2mps11_irqs), 379 .num_regs = 3, 380 .status_base = S2MPS11_REG_INT1, 381 .mask_base = S2MPS11_REG_INT1M, 382 .ack_base = S2MPS11_REG_INT1, 383 }; 384 385 #define S2MPS1X_IRQ_CHIP_COMMON_DATA \ 386 .irqs = s2mps14_irqs, \ 387 .num_irqs = ARRAY_SIZE(s2mps14_irqs), \ 388 .num_regs = 3, \ 389 .status_base = S2MPS14_REG_INT1, \ 390 .mask_base = S2MPS14_REG_INT1M, \ 391 .ack_base = S2MPS14_REG_INT1 \ 392 393 static const struct regmap_irq_chip s2mps13_irq_chip = { 394 .name = "s2mps13", 395 S2MPS1X_IRQ_CHIP_COMMON_DATA, 396 }; 397 398 static const struct regmap_irq_chip s2mps14_irq_chip = { 399 .name = "s2mps14", 400 S2MPS1X_IRQ_CHIP_COMMON_DATA, 401 }; 402 403 static const struct regmap_irq_chip s2mps15_irq_chip = { 404 .name = "s2mps15", 405 S2MPS1X_IRQ_CHIP_COMMON_DATA, 406 }; 407 408 static const struct regmap_irq_chip s2mpu02_irq_chip = { 409 .name = "s2mpu02", 410 .irqs = s2mpu02_irqs, 411 .num_irqs = ARRAY_SIZE(s2mpu02_irqs), 412 .num_regs = 3, 413 .status_base = S2MPU02_REG_INT1, 414 .mask_base = S2MPU02_REG_INT1M, 415 .ack_base = S2MPU02_REG_INT1, 416 }; 417 418 static const struct regmap_irq_chip s5m8767_irq_chip = { 419 .name = "s5m8767", 420 .irqs = s5m8767_irqs, 421 .num_irqs = ARRAY_SIZE(s5m8767_irqs), 422 .num_regs = 3, 423 .status_base = S5M8767_REG_INT1, 424 .mask_base = S5M8767_REG_INT1M, 425 .ack_base = S5M8767_REG_INT1, 426 }; 427 428 static const struct regmap_irq_chip s5m8763_irq_chip = { 429 .name = "s5m8763", 430 .irqs = s5m8763_irqs, 431 .num_irqs = ARRAY_SIZE(s5m8763_irqs), 432 .num_regs = 4, 433 .status_base = S5M8763_REG_IRQ1, 434 .mask_base = S5M8763_REG_IRQM1, 435 .ack_base = S5M8763_REG_IRQ1, 436 }; 437 438 int sec_irq_init(struct sec_pmic_dev *sec_pmic) 439 { 440 int ret = 0; 441 int type = sec_pmic->device_type; 442 const struct regmap_irq_chip *sec_irq_chip; 443 444 if (!sec_pmic->irq) { 445 dev_warn(sec_pmic->dev, 446 "No interrupt specified, no interrupts\n"); 447 return 0; 448 } 449 450 switch (type) { 451 case S5M8763X: 452 sec_irq_chip = &s5m8763_irq_chip; 453 break; 454 case S5M8767X: 455 sec_irq_chip = &s5m8767_irq_chip; 456 break; 457 case S2MPA01: 458 sec_irq_chip = &s2mps14_irq_chip; 459 break; 460 case S2MPS11X: 461 sec_irq_chip = &s2mps11_irq_chip; 462 break; 463 case S2MPS13X: 464 sec_irq_chip = &s2mps13_irq_chip; 465 break; 466 case S2MPS14X: 467 sec_irq_chip = &s2mps14_irq_chip; 468 break; 469 case S2MPS15X: 470 sec_irq_chip = &s2mps15_irq_chip; 471 break; 472 case S2MPU02: 473 sec_irq_chip = &s2mpu02_irq_chip; 474 break; 475 default: 476 dev_err(sec_pmic->dev, "Unknown device type %lu\n", 477 sec_pmic->device_type); 478 return -EINVAL; 479 } 480 481 ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, 482 sec_pmic->irq, 483 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 484 0, sec_irq_chip, &sec_pmic->irq_data); 485 if (ret != 0) { 486 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); 487 return ret; 488 } 489 490 /* 491 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11 492 * so the interrupt number must be consistent. 493 */ 494 BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0); 495 496 return 0; 497 } 498 EXPORT_SYMBOL_GPL(sec_irq_init); 499 500 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 501 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); 502 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); 503 MODULE_DESCRIPTION("Interrupt support for the S5M MFD"); 504 MODULE_LICENSE("GPL"); 505