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/s2mpu05.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 s2mpu05_irqs[] = { 230 REGMAP_IRQ_REG(S2MPU05_IRQ_PWRONF, 0, S2MPU05_IRQ_PWRONF_MASK), 231 REGMAP_IRQ_REG(S2MPU05_IRQ_PWRONR, 0, S2MPU05_IRQ_PWRONR_MASK), 232 REGMAP_IRQ_REG(S2MPU05_IRQ_JIGONBF, 0, S2MPU05_IRQ_JIGONBF_MASK), 233 REGMAP_IRQ_REG(S2MPU05_IRQ_JIGONBR, 0, S2MPU05_IRQ_JIGONBR_MASK), 234 REGMAP_IRQ_REG(S2MPU05_IRQ_ACOKF, 0, S2MPU05_IRQ_ACOKF_MASK), 235 REGMAP_IRQ_REG(S2MPU05_IRQ_ACOKR, 0, S2MPU05_IRQ_ACOKR_MASK), 236 REGMAP_IRQ_REG(S2MPU05_IRQ_PWRON1S, 0, S2MPU05_IRQ_PWRON1S_MASK), 237 REGMAP_IRQ_REG(S2MPU05_IRQ_MRB, 0, S2MPU05_IRQ_MRB_MASK), 238 REGMAP_IRQ_REG(S2MPU05_IRQ_RTC60S, 1, S2MPU05_IRQ_RTC60S_MASK), 239 REGMAP_IRQ_REG(S2MPU05_IRQ_RTCA1, 1, S2MPU05_IRQ_RTCA1_MASK), 240 REGMAP_IRQ_REG(S2MPU05_IRQ_RTCA0, 1, S2MPU05_IRQ_RTCA0_MASK), 241 REGMAP_IRQ_REG(S2MPU05_IRQ_SMPL, 1, S2MPU05_IRQ_SMPL_MASK), 242 REGMAP_IRQ_REG(S2MPU05_IRQ_RTC1S, 1, S2MPU05_IRQ_RTC1S_MASK), 243 REGMAP_IRQ_REG(S2MPU05_IRQ_WTSR, 1, S2MPU05_IRQ_WTSR_MASK), 244 REGMAP_IRQ_REG(S2MPU05_IRQ_INT120C, 2, S2MPU05_IRQ_INT120C_MASK), 245 REGMAP_IRQ_REG(S2MPU05_IRQ_INT140C, 2, S2MPU05_IRQ_INT140C_MASK), 246 REGMAP_IRQ_REG(S2MPU05_IRQ_TSD, 2, S2MPU05_IRQ_TSD_MASK), 247 }; 248 249 static const struct regmap_irq s5m8767_irqs[] = { 250 [S5M8767_IRQ_PWRR] = { 251 .reg_offset = 0, 252 .mask = S5M8767_IRQ_PWRR_MASK, 253 }, 254 [S5M8767_IRQ_PWRF] = { 255 .reg_offset = 0, 256 .mask = S5M8767_IRQ_PWRF_MASK, 257 }, 258 [S5M8767_IRQ_PWR1S] = { 259 .reg_offset = 0, 260 .mask = S5M8767_IRQ_PWR1S_MASK, 261 }, 262 [S5M8767_IRQ_JIGR] = { 263 .reg_offset = 0, 264 .mask = S5M8767_IRQ_JIGR_MASK, 265 }, 266 [S5M8767_IRQ_JIGF] = { 267 .reg_offset = 0, 268 .mask = S5M8767_IRQ_JIGF_MASK, 269 }, 270 [S5M8767_IRQ_LOWBAT2] = { 271 .reg_offset = 0, 272 .mask = S5M8767_IRQ_LOWBAT2_MASK, 273 }, 274 [S5M8767_IRQ_LOWBAT1] = { 275 .reg_offset = 0, 276 .mask = S5M8767_IRQ_LOWBAT1_MASK, 277 }, 278 [S5M8767_IRQ_MRB] = { 279 .reg_offset = 1, 280 .mask = S5M8767_IRQ_MRB_MASK, 281 }, 282 [S5M8767_IRQ_DVSOK2] = { 283 .reg_offset = 1, 284 .mask = S5M8767_IRQ_DVSOK2_MASK, 285 }, 286 [S5M8767_IRQ_DVSOK3] = { 287 .reg_offset = 1, 288 .mask = S5M8767_IRQ_DVSOK3_MASK, 289 }, 290 [S5M8767_IRQ_DVSOK4] = { 291 .reg_offset = 1, 292 .mask = S5M8767_IRQ_DVSOK4_MASK, 293 }, 294 [S5M8767_IRQ_RTC60S] = { 295 .reg_offset = 2, 296 .mask = S5M8767_IRQ_RTC60S_MASK, 297 }, 298 [S5M8767_IRQ_RTCA1] = { 299 .reg_offset = 2, 300 .mask = S5M8767_IRQ_RTCA1_MASK, 301 }, 302 [S5M8767_IRQ_RTCA2] = { 303 .reg_offset = 2, 304 .mask = S5M8767_IRQ_RTCA2_MASK, 305 }, 306 [S5M8767_IRQ_SMPL] = { 307 .reg_offset = 2, 308 .mask = S5M8767_IRQ_SMPL_MASK, 309 }, 310 [S5M8767_IRQ_RTC1S] = { 311 .reg_offset = 2, 312 .mask = S5M8767_IRQ_RTC1S_MASK, 313 }, 314 [S5M8767_IRQ_WTSR] = { 315 .reg_offset = 2, 316 .mask = S5M8767_IRQ_WTSR_MASK, 317 }, 318 }; 319 320 static const struct regmap_irq_chip s2mps11_irq_chip = { 321 .name = "s2mps11", 322 .irqs = s2mps11_irqs, 323 .num_irqs = ARRAY_SIZE(s2mps11_irqs), 324 .num_regs = 3, 325 .status_base = S2MPS11_REG_INT1, 326 .mask_base = S2MPS11_REG_INT1M, 327 .ack_base = S2MPS11_REG_INT1, 328 }; 329 330 #define S2MPS1X_IRQ_CHIP_COMMON_DATA \ 331 .irqs = s2mps14_irqs, \ 332 .num_irqs = ARRAY_SIZE(s2mps14_irqs), \ 333 .num_regs = 3, \ 334 .status_base = S2MPS14_REG_INT1, \ 335 .mask_base = S2MPS14_REG_INT1M, \ 336 .ack_base = S2MPS14_REG_INT1 \ 337 338 static const struct regmap_irq_chip s2mps13_irq_chip = { 339 .name = "s2mps13", 340 S2MPS1X_IRQ_CHIP_COMMON_DATA, 341 }; 342 343 static const struct regmap_irq_chip s2mps14_irq_chip = { 344 .name = "s2mps14", 345 S2MPS1X_IRQ_CHIP_COMMON_DATA, 346 }; 347 348 static const struct regmap_irq_chip s2mps15_irq_chip = { 349 .name = "s2mps15", 350 S2MPS1X_IRQ_CHIP_COMMON_DATA, 351 }; 352 353 static const struct regmap_irq_chip s2mpu02_irq_chip = { 354 .name = "s2mpu02", 355 .irqs = s2mpu02_irqs, 356 .num_irqs = ARRAY_SIZE(s2mpu02_irqs), 357 .num_regs = 3, 358 .status_base = S2MPU02_REG_INT1, 359 .mask_base = S2MPU02_REG_INT1M, 360 .ack_base = S2MPU02_REG_INT1, 361 }; 362 363 static const struct regmap_irq_chip s2mpu05_irq_chip = { 364 .name = "s2mpu05", 365 .irqs = s2mpu05_irqs, 366 .num_irqs = ARRAY_SIZE(s2mpu05_irqs), 367 .num_regs = 3, 368 .status_base = S2MPU05_REG_INT1, 369 .mask_base = S2MPU05_REG_INT1M, 370 .ack_base = S2MPU05_REG_INT1, 371 }; 372 373 static const struct regmap_irq_chip s5m8767_irq_chip = { 374 .name = "s5m8767", 375 .irqs = s5m8767_irqs, 376 .num_irqs = ARRAY_SIZE(s5m8767_irqs), 377 .num_regs = 3, 378 .status_base = S5M8767_REG_INT1, 379 .mask_base = S5M8767_REG_INT1M, 380 .ack_base = S5M8767_REG_INT1, 381 }; 382 383 int sec_irq_init(struct sec_pmic_dev *sec_pmic) 384 { 385 int ret = 0; 386 int type = sec_pmic->device_type; 387 const struct regmap_irq_chip *sec_irq_chip; 388 389 if (!sec_pmic->irq) { 390 dev_warn(sec_pmic->dev, 391 "No interrupt specified, no interrupts\n"); 392 return 0; 393 } 394 395 switch (type) { 396 case S5M8767X: 397 sec_irq_chip = &s5m8767_irq_chip; 398 break; 399 case S2MPA01: 400 sec_irq_chip = &s2mps14_irq_chip; 401 break; 402 case S2MPS11X: 403 sec_irq_chip = &s2mps11_irq_chip; 404 break; 405 case S2MPS13X: 406 sec_irq_chip = &s2mps13_irq_chip; 407 break; 408 case S2MPS14X: 409 sec_irq_chip = &s2mps14_irq_chip; 410 break; 411 case S2MPS15X: 412 sec_irq_chip = &s2mps15_irq_chip; 413 break; 414 case S2MPU02: 415 sec_irq_chip = &s2mpu02_irq_chip; 416 break; 417 case S2MPU05: 418 sec_irq_chip = &s2mpu05_irq_chip; 419 break; 420 default: 421 dev_err(sec_pmic->dev, "Unknown device type %lu\n", 422 sec_pmic->device_type); 423 return -EINVAL; 424 } 425 426 ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, 427 sec_pmic->irq, IRQF_ONESHOT, 428 0, sec_irq_chip, &sec_pmic->irq_data); 429 if (ret != 0) { 430 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); 431 return ret; 432 } 433 434 /* 435 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11 436 * so the interrupt number must be consistent. 437 */ 438 BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0); 439 440 return 0; 441 } 442 EXPORT_SYMBOL_GPL(sec_irq_init); 443 444 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 445 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); 446 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); 447 MODULE_DESCRIPTION("Interrupt support for the S5M MFD"); 448 MODULE_LICENSE("GPL"); 449