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/s5m8767.h> 18 19 static const struct regmap_irq s2mps11_irqs[] = { 20 [S2MPS11_IRQ_PWRONF] = { 21 .reg_offset = 0, 22 .mask = S2MPS11_IRQ_PWRONF_MASK, 23 }, 24 [S2MPS11_IRQ_PWRONR] = { 25 .reg_offset = 0, 26 .mask = S2MPS11_IRQ_PWRONR_MASK, 27 }, 28 [S2MPS11_IRQ_JIGONBF] = { 29 .reg_offset = 0, 30 .mask = S2MPS11_IRQ_JIGONBF_MASK, 31 }, 32 [S2MPS11_IRQ_JIGONBR] = { 33 .reg_offset = 0, 34 .mask = S2MPS11_IRQ_JIGONBR_MASK, 35 }, 36 [S2MPS11_IRQ_ACOKBF] = { 37 .reg_offset = 0, 38 .mask = S2MPS11_IRQ_ACOKBF_MASK, 39 }, 40 [S2MPS11_IRQ_ACOKBR] = { 41 .reg_offset = 0, 42 .mask = S2MPS11_IRQ_ACOKBR_MASK, 43 }, 44 [S2MPS11_IRQ_PWRON1S] = { 45 .reg_offset = 0, 46 .mask = S2MPS11_IRQ_PWRON1S_MASK, 47 }, 48 [S2MPS11_IRQ_MRB] = { 49 .reg_offset = 0, 50 .mask = S2MPS11_IRQ_MRB_MASK, 51 }, 52 [S2MPS11_IRQ_RTC60S] = { 53 .reg_offset = 1, 54 .mask = S2MPS11_IRQ_RTC60S_MASK, 55 }, 56 [S2MPS11_IRQ_RTCA1] = { 57 .reg_offset = 1, 58 .mask = S2MPS11_IRQ_RTCA1_MASK, 59 }, 60 [S2MPS11_IRQ_RTCA0] = { 61 .reg_offset = 1, 62 .mask = S2MPS11_IRQ_RTCA0_MASK, 63 }, 64 [S2MPS11_IRQ_SMPL] = { 65 .reg_offset = 1, 66 .mask = S2MPS11_IRQ_SMPL_MASK, 67 }, 68 [S2MPS11_IRQ_RTC1S] = { 69 .reg_offset = 1, 70 .mask = S2MPS11_IRQ_RTC1S_MASK, 71 }, 72 [S2MPS11_IRQ_WTSR] = { 73 .reg_offset = 1, 74 .mask = S2MPS11_IRQ_WTSR_MASK, 75 }, 76 [S2MPS11_IRQ_INT120C] = { 77 .reg_offset = 2, 78 .mask = S2MPS11_IRQ_INT120C_MASK, 79 }, 80 [S2MPS11_IRQ_INT140C] = { 81 .reg_offset = 2, 82 .mask = S2MPS11_IRQ_INT140C_MASK, 83 }, 84 }; 85 86 static const struct regmap_irq s2mps14_irqs[] = { 87 [S2MPS14_IRQ_PWRONF] = { 88 .reg_offset = 0, 89 .mask = S2MPS11_IRQ_PWRONF_MASK, 90 }, 91 [S2MPS14_IRQ_PWRONR] = { 92 .reg_offset = 0, 93 .mask = S2MPS11_IRQ_PWRONR_MASK, 94 }, 95 [S2MPS14_IRQ_JIGONBF] = { 96 .reg_offset = 0, 97 .mask = S2MPS11_IRQ_JIGONBF_MASK, 98 }, 99 [S2MPS14_IRQ_JIGONBR] = { 100 .reg_offset = 0, 101 .mask = S2MPS11_IRQ_JIGONBR_MASK, 102 }, 103 [S2MPS14_IRQ_ACOKBF] = { 104 .reg_offset = 0, 105 .mask = S2MPS11_IRQ_ACOKBF_MASK, 106 }, 107 [S2MPS14_IRQ_ACOKBR] = { 108 .reg_offset = 0, 109 .mask = S2MPS11_IRQ_ACOKBR_MASK, 110 }, 111 [S2MPS14_IRQ_PWRON1S] = { 112 .reg_offset = 0, 113 .mask = S2MPS11_IRQ_PWRON1S_MASK, 114 }, 115 [S2MPS14_IRQ_MRB] = { 116 .reg_offset = 0, 117 .mask = S2MPS11_IRQ_MRB_MASK, 118 }, 119 [S2MPS14_IRQ_RTC60S] = { 120 .reg_offset = 1, 121 .mask = S2MPS11_IRQ_RTC60S_MASK, 122 }, 123 [S2MPS14_IRQ_RTCA1] = { 124 .reg_offset = 1, 125 .mask = S2MPS11_IRQ_RTCA1_MASK, 126 }, 127 [S2MPS14_IRQ_RTCA0] = { 128 .reg_offset = 1, 129 .mask = S2MPS11_IRQ_RTCA0_MASK, 130 }, 131 [S2MPS14_IRQ_SMPL] = { 132 .reg_offset = 1, 133 .mask = S2MPS11_IRQ_SMPL_MASK, 134 }, 135 [S2MPS14_IRQ_RTC1S] = { 136 .reg_offset = 1, 137 .mask = S2MPS11_IRQ_RTC1S_MASK, 138 }, 139 [S2MPS14_IRQ_WTSR] = { 140 .reg_offset = 1, 141 .mask = S2MPS11_IRQ_WTSR_MASK, 142 }, 143 [S2MPS14_IRQ_INT120C] = { 144 .reg_offset = 2, 145 .mask = S2MPS11_IRQ_INT120C_MASK, 146 }, 147 [S2MPS14_IRQ_INT140C] = { 148 .reg_offset = 2, 149 .mask = S2MPS11_IRQ_INT140C_MASK, 150 }, 151 [S2MPS14_IRQ_TSD] = { 152 .reg_offset = 2, 153 .mask = S2MPS14_IRQ_TSD_MASK, 154 }, 155 }; 156 157 static const struct regmap_irq s2mpu02_irqs[] = { 158 [S2MPU02_IRQ_PWRONF] = { 159 .reg_offset = 0, 160 .mask = S2MPS11_IRQ_PWRONF_MASK, 161 }, 162 [S2MPU02_IRQ_PWRONR] = { 163 .reg_offset = 0, 164 .mask = S2MPS11_IRQ_PWRONR_MASK, 165 }, 166 [S2MPU02_IRQ_JIGONBF] = { 167 .reg_offset = 0, 168 .mask = S2MPS11_IRQ_JIGONBF_MASK, 169 }, 170 [S2MPU02_IRQ_JIGONBR] = { 171 .reg_offset = 0, 172 .mask = S2MPS11_IRQ_JIGONBR_MASK, 173 }, 174 [S2MPU02_IRQ_ACOKBF] = { 175 .reg_offset = 0, 176 .mask = S2MPS11_IRQ_ACOKBF_MASK, 177 }, 178 [S2MPU02_IRQ_ACOKBR] = { 179 .reg_offset = 0, 180 .mask = S2MPS11_IRQ_ACOKBR_MASK, 181 }, 182 [S2MPU02_IRQ_PWRON1S] = { 183 .reg_offset = 0, 184 .mask = S2MPS11_IRQ_PWRON1S_MASK, 185 }, 186 [S2MPU02_IRQ_MRB] = { 187 .reg_offset = 0, 188 .mask = S2MPS11_IRQ_MRB_MASK, 189 }, 190 [S2MPU02_IRQ_RTC60S] = { 191 .reg_offset = 1, 192 .mask = S2MPS11_IRQ_RTC60S_MASK, 193 }, 194 [S2MPU02_IRQ_RTCA1] = { 195 .reg_offset = 1, 196 .mask = S2MPS11_IRQ_RTCA1_MASK, 197 }, 198 [S2MPU02_IRQ_RTCA0] = { 199 .reg_offset = 1, 200 .mask = S2MPS11_IRQ_RTCA0_MASK, 201 }, 202 [S2MPU02_IRQ_SMPL] = { 203 .reg_offset = 1, 204 .mask = S2MPS11_IRQ_SMPL_MASK, 205 }, 206 [S2MPU02_IRQ_RTC1S] = { 207 .reg_offset = 1, 208 .mask = S2MPS11_IRQ_RTC1S_MASK, 209 }, 210 [S2MPU02_IRQ_WTSR] = { 211 .reg_offset = 1, 212 .mask = S2MPS11_IRQ_WTSR_MASK, 213 }, 214 [S2MPU02_IRQ_INT120C] = { 215 .reg_offset = 2, 216 .mask = S2MPS11_IRQ_INT120C_MASK, 217 }, 218 [S2MPU02_IRQ_INT140C] = { 219 .reg_offset = 2, 220 .mask = S2MPS11_IRQ_INT140C_MASK, 221 }, 222 [S2MPU02_IRQ_TSD] = { 223 .reg_offset = 2, 224 .mask = S2MPS14_IRQ_TSD_MASK, 225 }, 226 }; 227 228 static const struct regmap_irq s5m8767_irqs[] = { 229 [S5M8767_IRQ_PWRR] = { 230 .reg_offset = 0, 231 .mask = S5M8767_IRQ_PWRR_MASK, 232 }, 233 [S5M8767_IRQ_PWRF] = { 234 .reg_offset = 0, 235 .mask = S5M8767_IRQ_PWRF_MASK, 236 }, 237 [S5M8767_IRQ_PWR1S] = { 238 .reg_offset = 0, 239 .mask = S5M8767_IRQ_PWR1S_MASK, 240 }, 241 [S5M8767_IRQ_JIGR] = { 242 .reg_offset = 0, 243 .mask = S5M8767_IRQ_JIGR_MASK, 244 }, 245 [S5M8767_IRQ_JIGF] = { 246 .reg_offset = 0, 247 .mask = S5M8767_IRQ_JIGF_MASK, 248 }, 249 [S5M8767_IRQ_LOWBAT2] = { 250 .reg_offset = 0, 251 .mask = S5M8767_IRQ_LOWBAT2_MASK, 252 }, 253 [S5M8767_IRQ_LOWBAT1] = { 254 .reg_offset = 0, 255 .mask = S5M8767_IRQ_LOWBAT1_MASK, 256 }, 257 [S5M8767_IRQ_MRB] = { 258 .reg_offset = 1, 259 .mask = S5M8767_IRQ_MRB_MASK, 260 }, 261 [S5M8767_IRQ_DVSOK2] = { 262 .reg_offset = 1, 263 .mask = S5M8767_IRQ_DVSOK2_MASK, 264 }, 265 [S5M8767_IRQ_DVSOK3] = { 266 .reg_offset = 1, 267 .mask = S5M8767_IRQ_DVSOK3_MASK, 268 }, 269 [S5M8767_IRQ_DVSOK4] = { 270 .reg_offset = 1, 271 .mask = S5M8767_IRQ_DVSOK4_MASK, 272 }, 273 [S5M8767_IRQ_RTC60S] = { 274 .reg_offset = 2, 275 .mask = S5M8767_IRQ_RTC60S_MASK, 276 }, 277 [S5M8767_IRQ_RTCA1] = { 278 .reg_offset = 2, 279 .mask = S5M8767_IRQ_RTCA1_MASK, 280 }, 281 [S5M8767_IRQ_RTCA2] = { 282 .reg_offset = 2, 283 .mask = S5M8767_IRQ_RTCA2_MASK, 284 }, 285 [S5M8767_IRQ_SMPL] = { 286 .reg_offset = 2, 287 .mask = S5M8767_IRQ_SMPL_MASK, 288 }, 289 [S5M8767_IRQ_RTC1S] = { 290 .reg_offset = 2, 291 .mask = S5M8767_IRQ_RTC1S_MASK, 292 }, 293 [S5M8767_IRQ_WTSR] = { 294 .reg_offset = 2, 295 .mask = S5M8767_IRQ_WTSR_MASK, 296 }, 297 }; 298 299 static const struct regmap_irq_chip s2mps11_irq_chip = { 300 .name = "s2mps11", 301 .irqs = s2mps11_irqs, 302 .num_irqs = ARRAY_SIZE(s2mps11_irqs), 303 .num_regs = 3, 304 .status_base = S2MPS11_REG_INT1, 305 .mask_base = S2MPS11_REG_INT1M, 306 .ack_base = S2MPS11_REG_INT1, 307 }; 308 309 #define S2MPS1X_IRQ_CHIP_COMMON_DATA \ 310 .irqs = s2mps14_irqs, \ 311 .num_irqs = ARRAY_SIZE(s2mps14_irqs), \ 312 .num_regs = 3, \ 313 .status_base = S2MPS14_REG_INT1, \ 314 .mask_base = S2MPS14_REG_INT1M, \ 315 .ack_base = S2MPS14_REG_INT1 \ 316 317 static const struct regmap_irq_chip s2mps13_irq_chip = { 318 .name = "s2mps13", 319 S2MPS1X_IRQ_CHIP_COMMON_DATA, 320 }; 321 322 static const struct regmap_irq_chip s2mps14_irq_chip = { 323 .name = "s2mps14", 324 S2MPS1X_IRQ_CHIP_COMMON_DATA, 325 }; 326 327 static const struct regmap_irq_chip s2mps15_irq_chip = { 328 .name = "s2mps15", 329 S2MPS1X_IRQ_CHIP_COMMON_DATA, 330 }; 331 332 static const struct regmap_irq_chip s2mpu02_irq_chip = { 333 .name = "s2mpu02", 334 .irqs = s2mpu02_irqs, 335 .num_irqs = ARRAY_SIZE(s2mpu02_irqs), 336 .num_regs = 3, 337 .status_base = S2MPU02_REG_INT1, 338 .mask_base = S2MPU02_REG_INT1M, 339 .ack_base = S2MPU02_REG_INT1, 340 }; 341 342 static const struct regmap_irq_chip s5m8767_irq_chip = { 343 .name = "s5m8767", 344 .irqs = s5m8767_irqs, 345 .num_irqs = ARRAY_SIZE(s5m8767_irqs), 346 .num_regs = 3, 347 .status_base = S5M8767_REG_INT1, 348 .mask_base = S5M8767_REG_INT1M, 349 .ack_base = S5M8767_REG_INT1, 350 }; 351 352 int sec_irq_init(struct sec_pmic_dev *sec_pmic) 353 { 354 int ret = 0; 355 int type = sec_pmic->device_type; 356 const struct regmap_irq_chip *sec_irq_chip; 357 358 if (!sec_pmic->irq) { 359 dev_warn(sec_pmic->dev, 360 "No interrupt specified, no interrupts\n"); 361 return 0; 362 } 363 364 switch (type) { 365 case S5M8767X: 366 sec_irq_chip = &s5m8767_irq_chip; 367 break; 368 case S2MPA01: 369 sec_irq_chip = &s2mps14_irq_chip; 370 break; 371 case S2MPS11X: 372 sec_irq_chip = &s2mps11_irq_chip; 373 break; 374 case S2MPS13X: 375 sec_irq_chip = &s2mps13_irq_chip; 376 break; 377 case S2MPS14X: 378 sec_irq_chip = &s2mps14_irq_chip; 379 break; 380 case S2MPS15X: 381 sec_irq_chip = &s2mps15_irq_chip; 382 break; 383 case S2MPU02: 384 sec_irq_chip = &s2mpu02_irq_chip; 385 break; 386 default: 387 dev_err(sec_pmic->dev, "Unknown device type %lu\n", 388 sec_pmic->device_type); 389 return -EINVAL; 390 } 391 392 ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic, 393 sec_pmic->irq, IRQF_ONESHOT, 394 0, sec_irq_chip, &sec_pmic->irq_data); 395 if (ret != 0) { 396 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); 397 return ret; 398 } 399 400 /* 401 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11 402 * so the interrupt number must be consistent. 403 */ 404 BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0); 405 406 return 0; 407 } 408 EXPORT_SYMBOL_GPL(sec_irq_init); 409 410 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 411 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); 412 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); 413 MODULE_DESCRIPTION("Interrupt support for the S5M MFD"); 414 MODULE_LICENSE("GPL"); 415