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