0001
0002
0003
0004
0005
0006 #include <linux/device.h>
0007 #include <linux/interrupt.h>
0008 #include <linux/irq.h>
0009 #include <linux/module.h>
0010 #include <linux/regmap.h>
0011
0012 #include <linux/mfd/samsung/core.h>
0013 #include <linux/mfd/samsung/irq.h>
0014 #include <linux/mfd/samsung/s2mps11.h>
0015 #include <linux/mfd/samsung/s2mps14.h>
0016 #include <linux/mfd/samsung/s2mpu02.h>
0017 #include <linux/mfd/samsung/s5m8763.h>
0018 #include <linux/mfd/samsung/s5m8767.h>
0019
0020 static const struct regmap_irq s2mps11_irqs[] = {
0021 [S2MPS11_IRQ_PWRONF] = {
0022 .reg_offset = 0,
0023 .mask = S2MPS11_IRQ_PWRONF_MASK,
0024 },
0025 [S2MPS11_IRQ_PWRONR] = {
0026 .reg_offset = 0,
0027 .mask = S2MPS11_IRQ_PWRONR_MASK,
0028 },
0029 [S2MPS11_IRQ_JIGONBF] = {
0030 .reg_offset = 0,
0031 .mask = S2MPS11_IRQ_JIGONBF_MASK,
0032 },
0033 [S2MPS11_IRQ_JIGONBR] = {
0034 .reg_offset = 0,
0035 .mask = S2MPS11_IRQ_JIGONBR_MASK,
0036 },
0037 [S2MPS11_IRQ_ACOKBF] = {
0038 .reg_offset = 0,
0039 .mask = S2MPS11_IRQ_ACOKBF_MASK,
0040 },
0041 [S2MPS11_IRQ_ACOKBR] = {
0042 .reg_offset = 0,
0043 .mask = S2MPS11_IRQ_ACOKBR_MASK,
0044 },
0045 [S2MPS11_IRQ_PWRON1S] = {
0046 .reg_offset = 0,
0047 .mask = S2MPS11_IRQ_PWRON1S_MASK,
0048 },
0049 [S2MPS11_IRQ_MRB] = {
0050 .reg_offset = 0,
0051 .mask = S2MPS11_IRQ_MRB_MASK,
0052 },
0053 [S2MPS11_IRQ_RTC60S] = {
0054 .reg_offset = 1,
0055 .mask = S2MPS11_IRQ_RTC60S_MASK,
0056 },
0057 [S2MPS11_IRQ_RTCA1] = {
0058 .reg_offset = 1,
0059 .mask = S2MPS11_IRQ_RTCA1_MASK,
0060 },
0061 [S2MPS11_IRQ_RTCA0] = {
0062 .reg_offset = 1,
0063 .mask = S2MPS11_IRQ_RTCA0_MASK,
0064 },
0065 [S2MPS11_IRQ_SMPL] = {
0066 .reg_offset = 1,
0067 .mask = S2MPS11_IRQ_SMPL_MASK,
0068 },
0069 [S2MPS11_IRQ_RTC1S] = {
0070 .reg_offset = 1,
0071 .mask = S2MPS11_IRQ_RTC1S_MASK,
0072 },
0073 [S2MPS11_IRQ_WTSR] = {
0074 .reg_offset = 1,
0075 .mask = S2MPS11_IRQ_WTSR_MASK,
0076 },
0077 [S2MPS11_IRQ_INT120C] = {
0078 .reg_offset = 2,
0079 .mask = S2MPS11_IRQ_INT120C_MASK,
0080 },
0081 [S2MPS11_IRQ_INT140C] = {
0082 .reg_offset = 2,
0083 .mask = S2MPS11_IRQ_INT140C_MASK,
0084 },
0085 };
0086
0087 static const struct regmap_irq s2mps14_irqs[] = {
0088 [S2MPS14_IRQ_PWRONF] = {
0089 .reg_offset = 0,
0090 .mask = S2MPS11_IRQ_PWRONF_MASK,
0091 },
0092 [S2MPS14_IRQ_PWRONR] = {
0093 .reg_offset = 0,
0094 .mask = S2MPS11_IRQ_PWRONR_MASK,
0095 },
0096 [S2MPS14_IRQ_JIGONBF] = {
0097 .reg_offset = 0,
0098 .mask = S2MPS11_IRQ_JIGONBF_MASK,
0099 },
0100 [S2MPS14_IRQ_JIGONBR] = {
0101 .reg_offset = 0,
0102 .mask = S2MPS11_IRQ_JIGONBR_MASK,
0103 },
0104 [S2MPS14_IRQ_ACOKBF] = {
0105 .reg_offset = 0,
0106 .mask = S2MPS11_IRQ_ACOKBF_MASK,
0107 },
0108 [S2MPS14_IRQ_ACOKBR] = {
0109 .reg_offset = 0,
0110 .mask = S2MPS11_IRQ_ACOKBR_MASK,
0111 },
0112 [S2MPS14_IRQ_PWRON1S] = {
0113 .reg_offset = 0,
0114 .mask = S2MPS11_IRQ_PWRON1S_MASK,
0115 },
0116 [S2MPS14_IRQ_MRB] = {
0117 .reg_offset = 0,
0118 .mask = S2MPS11_IRQ_MRB_MASK,
0119 },
0120 [S2MPS14_IRQ_RTC60S] = {
0121 .reg_offset = 1,
0122 .mask = S2MPS11_IRQ_RTC60S_MASK,
0123 },
0124 [S2MPS14_IRQ_RTCA1] = {
0125 .reg_offset = 1,
0126 .mask = S2MPS11_IRQ_RTCA1_MASK,
0127 },
0128 [S2MPS14_IRQ_RTCA0] = {
0129 .reg_offset = 1,
0130 .mask = S2MPS11_IRQ_RTCA0_MASK,
0131 },
0132 [S2MPS14_IRQ_SMPL] = {
0133 .reg_offset = 1,
0134 .mask = S2MPS11_IRQ_SMPL_MASK,
0135 },
0136 [S2MPS14_IRQ_RTC1S] = {
0137 .reg_offset = 1,
0138 .mask = S2MPS11_IRQ_RTC1S_MASK,
0139 },
0140 [S2MPS14_IRQ_WTSR] = {
0141 .reg_offset = 1,
0142 .mask = S2MPS11_IRQ_WTSR_MASK,
0143 },
0144 [S2MPS14_IRQ_INT120C] = {
0145 .reg_offset = 2,
0146 .mask = S2MPS11_IRQ_INT120C_MASK,
0147 },
0148 [S2MPS14_IRQ_INT140C] = {
0149 .reg_offset = 2,
0150 .mask = S2MPS11_IRQ_INT140C_MASK,
0151 },
0152 [S2MPS14_IRQ_TSD] = {
0153 .reg_offset = 2,
0154 .mask = S2MPS14_IRQ_TSD_MASK,
0155 },
0156 };
0157
0158 static const struct regmap_irq s2mpu02_irqs[] = {
0159 [S2MPU02_IRQ_PWRONF] = {
0160 .reg_offset = 0,
0161 .mask = S2MPS11_IRQ_PWRONF_MASK,
0162 },
0163 [S2MPU02_IRQ_PWRONR] = {
0164 .reg_offset = 0,
0165 .mask = S2MPS11_IRQ_PWRONR_MASK,
0166 },
0167 [S2MPU02_IRQ_JIGONBF] = {
0168 .reg_offset = 0,
0169 .mask = S2MPS11_IRQ_JIGONBF_MASK,
0170 },
0171 [S2MPU02_IRQ_JIGONBR] = {
0172 .reg_offset = 0,
0173 .mask = S2MPS11_IRQ_JIGONBR_MASK,
0174 },
0175 [S2MPU02_IRQ_ACOKBF] = {
0176 .reg_offset = 0,
0177 .mask = S2MPS11_IRQ_ACOKBF_MASK,
0178 },
0179 [S2MPU02_IRQ_ACOKBR] = {
0180 .reg_offset = 0,
0181 .mask = S2MPS11_IRQ_ACOKBR_MASK,
0182 },
0183 [S2MPU02_IRQ_PWRON1S] = {
0184 .reg_offset = 0,
0185 .mask = S2MPS11_IRQ_PWRON1S_MASK,
0186 },
0187 [S2MPU02_IRQ_MRB] = {
0188 .reg_offset = 0,
0189 .mask = S2MPS11_IRQ_MRB_MASK,
0190 },
0191 [S2MPU02_IRQ_RTC60S] = {
0192 .reg_offset = 1,
0193 .mask = S2MPS11_IRQ_RTC60S_MASK,
0194 },
0195 [S2MPU02_IRQ_RTCA1] = {
0196 .reg_offset = 1,
0197 .mask = S2MPS11_IRQ_RTCA1_MASK,
0198 },
0199 [S2MPU02_IRQ_RTCA0] = {
0200 .reg_offset = 1,
0201 .mask = S2MPS11_IRQ_RTCA0_MASK,
0202 },
0203 [S2MPU02_IRQ_SMPL] = {
0204 .reg_offset = 1,
0205 .mask = S2MPS11_IRQ_SMPL_MASK,
0206 },
0207 [S2MPU02_IRQ_RTC1S] = {
0208 .reg_offset = 1,
0209 .mask = S2MPS11_IRQ_RTC1S_MASK,
0210 },
0211 [S2MPU02_IRQ_WTSR] = {
0212 .reg_offset = 1,
0213 .mask = S2MPS11_IRQ_WTSR_MASK,
0214 },
0215 [S2MPU02_IRQ_INT120C] = {
0216 .reg_offset = 2,
0217 .mask = S2MPS11_IRQ_INT120C_MASK,
0218 },
0219 [S2MPU02_IRQ_INT140C] = {
0220 .reg_offset = 2,
0221 .mask = S2MPS11_IRQ_INT140C_MASK,
0222 },
0223 [S2MPU02_IRQ_TSD] = {
0224 .reg_offset = 2,
0225 .mask = S2MPS14_IRQ_TSD_MASK,
0226 },
0227 };
0228
0229 static const struct regmap_irq s5m8767_irqs[] = {
0230 [S5M8767_IRQ_PWRR] = {
0231 .reg_offset = 0,
0232 .mask = S5M8767_IRQ_PWRR_MASK,
0233 },
0234 [S5M8767_IRQ_PWRF] = {
0235 .reg_offset = 0,
0236 .mask = S5M8767_IRQ_PWRF_MASK,
0237 },
0238 [S5M8767_IRQ_PWR1S] = {
0239 .reg_offset = 0,
0240 .mask = S5M8767_IRQ_PWR1S_MASK,
0241 },
0242 [S5M8767_IRQ_JIGR] = {
0243 .reg_offset = 0,
0244 .mask = S5M8767_IRQ_JIGR_MASK,
0245 },
0246 [S5M8767_IRQ_JIGF] = {
0247 .reg_offset = 0,
0248 .mask = S5M8767_IRQ_JIGF_MASK,
0249 },
0250 [S5M8767_IRQ_LOWBAT2] = {
0251 .reg_offset = 0,
0252 .mask = S5M8767_IRQ_LOWBAT2_MASK,
0253 },
0254 [S5M8767_IRQ_LOWBAT1] = {
0255 .reg_offset = 0,
0256 .mask = S5M8767_IRQ_LOWBAT1_MASK,
0257 },
0258 [S5M8767_IRQ_MRB] = {
0259 .reg_offset = 1,
0260 .mask = S5M8767_IRQ_MRB_MASK,
0261 },
0262 [S5M8767_IRQ_DVSOK2] = {
0263 .reg_offset = 1,
0264 .mask = S5M8767_IRQ_DVSOK2_MASK,
0265 },
0266 [S5M8767_IRQ_DVSOK3] = {
0267 .reg_offset = 1,
0268 .mask = S5M8767_IRQ_DVSOK3_MASK,
0269 },
0270 [S5M8767_IRQ_DVSOK4] = {
0271 .reg_offset = 1,
0272 .mask = S5M8767_IRQ_DVSOK4_MASK,
0273 },
0274 [S5M8767_IRQ_RTC60S] = {
0275 .reg_offset = 2,
0276 .mask = S5M8767_IRQ_RTC60S_MASK,
0277 },
0278 [S5M8767_IRQ_RTCA1] = {
0279 .reg_offset = 2,
0280 .mask = S5M8767_IRQ_RTCA1_MASK,
0281 },
0282 [S5M8767_IRQ_RTCA2] = {
0283 .reg_offset = 2,
0284 .mask = S5M8767_IRQ_RTCA2_MASK,
0285 },
0286 [S5M8767_IRQ_SMPL] = {
0287 .reg_offset = 2,
0288 .mask = S5M8767_IRQ_SMPL_MASK,
0289 },
0290 [S5M8767_IRQ_RTC1S] = {
0291 .reg_offset = 2,
0292 .mask = S5M8767_IRQ_RTC1S_MASK,
0293 },
0294 [S5M8767_IRQ_WTSR] = {
0295 .reg_offset = 2,
0296 .mask = S5M8767_IRQ_WTSR_MASK,
0297 },
0298 };
0299
0300 static const struct regmap_irq s5m8763_irqs[] = {
0301 [S5M8763_IRQ_DCINF] = {
0302 .reg_offset = 0,
0303 .mask = S5M8763_IRQ_DCINF_MASK,
0304 },
0305 [S5M8763_IRQ_DCINR] = {
0306 .reg_offset = 0,
0307 .mask = S5M8763_IRQ_DCINR_MASK,
0308 },
0309 [S5M8763_IRQ_JIGF] = {
0310 .reg_offset = 0,
0311 .mask = S5M8763_IRQ_JIGF_MASK,
0312 },
0313 [S5M8763_IRQ_JIGR] = {
0314 .reg_offset = 0,
0315 .mask = S5M8763_IRQ_JIGR_MASK,
0316 },
0317 [S5M8763_IRQ_PWRONF] = {
0318 .reg_offset = 0,
0319 .mask = S5M8763_IRQ_PWRONF_MASK,
0320 },
0321 [S5M8763_IRQ_PWRONR] = {
0322 .reg_offset = 0,
0323 .mask = S5M8763_IRQ_PWRONR_MASK,
0324 },
0325 [S5M8763_IRQ_WTSREVNT] = {
0326 .reg_offset = 1,
0327 .mask = S5M8763_IRQ_WTSREVNT_MASK,
0328 },
0329 [S5M8763_IRQ_SMPLEVNT] = {
0330 .reg_offset = 1,
0331 .mask = S5M8763_IRQ_SMPLEVNT_MASK,
0332 },
0333 [S5M8763_IRQ_ALARM1] = {
0334 .reg_offset = 1,
0335 .mask = S5M8763_IRQ_ALARM1_MASK,
0336 },
0337 [S5M8763_IRQ_ALARM0] = {
0338 .reg_offset = 1,
0339 .mask = S5M8763_IRQ_ALARM0_MASK,
0340 },
0341 [S5M8763_IRQ_ONKEY1S] = {
0342 .reg_offset = 2,
0343 .mask = S5M8763_IRQ_ONKEY1S_MASK,
0344 },
0345 [S5M8763_IRQ_TOPOFFR] = {
0346 .reg_offset = 2,
0347 .mask = S5M8763_IRQ_TOPOFFR_MASK,
0348 },
0349 [S5M8763_IRQ_DCINOVPR] = {
0350 .reg_offset = 2,
0351 .mask = S5M8763_IRQ_DCINOVPR_MASK,
0352 },
0353 [S5M8763_IRQ_CHGRSTF] = {
0354 .reg_offset = 2,
0355 .mask = S5M8763_IRQ_CHGRSTF_MASK,
0356 },
0357 [S5M8763_IRQ_DONER] = {
0358 .reg_offset = 2,
0359 .mask = S5M8763_IRQ_DONER_MASK,
0360 },
0361 [S5M8763_IRQ_CHGFAULT] = {
0362 .reg_offset = 2,
0363 .mask = S5M8763_IRQ_CHGFAULT_MASK,
0364 },
0365 [S5M8763_IRQ_LOBAT1] = {
0366 .reg_offset = 3,
0367 .mask = S5M8763_IRQ_LOBAT1_MASK,
0368 },
0369 [S5M8763_IRQ_LOBAT2] = {
0370 .reg_offset = 3,
0371 .mask = S5M8763_IRQ_LOBAT2_MASK,
0372 },
0373 };
0374
0375 static const struct regmap_irq_chip s2mps11_irq_chip = {
0376 .name = "s2mps11",
0377 .irqs = s2mps11_irqs,
0378 .num_irqs = ARRAY_SIZE(s2mps11_irqs),
0379 .num_regs = 3,
0380 .status_base = S2MPS11_REG_INT1,
0381 .mask_base = S2MPS11_REG_INT1M,
0382 .ack_base = S2MPS11_REG_INT1,
0383 };
0384
0385 #define S2MPS1X_IRQ_CHIP_COMMON_DATA \
0386 .irqs = s2mps14_irqs, \
0387 .num_irqs = ARRAY_SIZE(s2mps14_irqs), \
0388 .num_regs = 3, \
0389 .status_base = S2MPS14_REG_INT1, \
0390 .mask_base = S2MPS14_REG_INT1M, \
0391 .ack_base = S2MPS14_REG_INT1 \
0392
0393 static const struct regmap_irq_chip s2mps13_irq_chip = {
0394 .name = "s2mps13",
0395 S2MPS1X_IRQ_CHIP_COMMON_DATA,
0396 };
0397
0398 static const struct regmap_irq_chip s2mps14_irq_chip = {
0399 .name = "s2mps14",
0400 S2MPS1X_IRQ_CHIP_COMMON_DATA,
0401 };
0402
0403 static const struct regmap_irq_chip s2mps15_irq_chip = {
0404 .name = "s2mps15",
0405 S2MPS1X_IRQ_CHIP_COMMON_DATA,
0406 };
0407
0408 static const struct regmap_irq_chip s2mpu02_irq_chip = {
0409 .name = "s2mpu02",
0410 .irqs = s2mpu02_irqs,
0411 .num_irqs = ARRAY_SIZE(s2mpu02_irqs),
0412 .num_regs = 3,
0413 .status_base = S2MPU02_REG_INT1,
0414 .mask_base = S2MPU02_REG_INT1M,
0415 .ack_base = S2MPU02_REG_INT1,
0416 };
0417
0418 static const struct regmap_irq_chip s5m8767_irq_chip = {
0419 .name = "s5m8767",
0420 .irqs = s5m8767_irqs,
0421 .num_irqs = ARRAY_SIZE(s5m8767_irqs),
0422 .num_regs = 3,
0423 .status_base = S5M8767_REG_INT1,
0424 .mask_base = S5M8767_REG_INT1M,
0425 .ack_base = S5M8767_REG_INT1,
0426 };
0427
0428 static const struct regmap_irq_chip s5m8763_irq_chip = {
0429 .name = "s5m8763",
0430 .irqs = s5m8763_irqs,
0431 .num_irqs = ARRAY_SIZE(s5m8763_irqs),
0432 .num_regs = 4,
0433 .status_base = S5M8763_REG_IRQ1,
0434 .mask_base = S5M8763_REG_IRQM1,
0435 .ack_base = S5M8763_REG_IRQ1,
0436 };
0437
0438 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
0439 {
0440 int ret = 0;
0441 int type = sec_pmic->device_type;
0442 const struct regmap_irq_chip *sec_irq_chip;
0443
0444 if (!sec_pmic->irq) {
0445 dev_warn(sec_pmic->dev,
0446 "No interrupt specified, no interrupts\n");
0447 return 0;
0448 }
0449
0450 switch (type) {
0451 case S5M8763X:
0452 sec_irq_chip = &s5m8763_irq_chip;
0453 break;
0454 case S5M8767X:
0455 sec_irq_chip = &s5m8767_irq_chip;
0456 break;
0457 case S2MPA01:
0458 sec_irq_chip = &s2mps14_irq_chip;
0459 break;
0460 case S2MPS11X:
0461 sec_irq_chip = &s2mps11_irq_chip;
0462 break;
0463 case S2MPS13X:
0464 sec_irq_chip = &s2mps13_irq_chip;
0465 break;
0466 case S2MPS14X:
0467 sec_irq_chip = &s2mps14_irq_chip;
0468 break;
0469 case S2MPS15X:
0470 sec_irq_chip = &s2mps15_irq_chip;
0471 break;
0472 case S2MPU02:
0473 sec_irq_chip = &s2mpu02_irq_chip;
0474 break;
0475 default:
0476 dev_err(sec_pmic->dev, "Unknown device type %lu\n",
0477 sec_pmic->device_type);
0478 return -EINVAL;
0479 }
0480
0481 ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
0482 sec_pmic->irq, IRQF_ONESHOT,
0483 0, sec_irq_chip, &sec_pmic->irq_data);
0484 if (ret != 0) {
0485 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
0486 return ret;
0487 }
0488
0489
0490
0491
0492
0493 BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
0494
0495 return 0;
0496 }
0497 EXPORT_SYMBOL_GPL(sec_irq_init);
0498
0499 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
0500 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
0501 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
0502 MODULE_DESCRIPTION("Interrupt support for the S5M MFD");
0503 MODULE_LICENSE("GPL");