Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: sec-core: Add support for S2MPU02 device

Add support for Samsung S2MPU02 PMIC device to the MFD sec-core driver.
The S2MPU02 device includes PMIC/RTC/Clock devices.

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Reviewed-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Chanwoo Choi and committed by
Lee Jones
54e8827d 10f9edae

+352 -30
+32 -14
drivers/mfd/sec-core.c
··· 89 89 }, 90 90 }; 91 91 92 + static const struct mfd_cell s2mpu02_devs[] = { 93 + { .name = "s2mpu02-pmic", }, 94 + { .name = "s2mpu02-rtc", }, 95 + { 96 + .name = "s2mpu02-clk", 97 + .of_compatible = "samsung,s2mpu02-clk", 98 + } 99 + }; 100 + 92 101 #ifdef CONFIG_OF 93 102 static const struct of_device_id sec_dt_match[] = { 94 103 { .compatible = "samsung,s5m8767-pmic", ··· 111 102 }, { 112 103 .compatible = "samsung,s2mpa01-pmic", 113 104 .data = (void *)S2MPA01, 105 + }, { 106 + .compatible = "samsung,s2mpu02-pmic", 107 + .data = (void *)S2MPU02, 114 108 }, { 115 109 /* Sentinel */ 116 110 }, ··· 262 250 { 263 251 struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); 264 252 const struct regmap_config *regmap; 253 + const struct mfd_cell *sec_devs; 265 254 struct sec_pmic_dev *sec_pmic; 266 255 unsigned long device_type; 267 - int ret; 256 + int ret, num_sec_devs; 268 257 269 258 sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev), 270 259 GFP_KERNEL); ··· 332 319 333 320 switch (sec_pmic->device_type) { 334 321 case S5M8751X: 335 - ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, 336 - ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); 322 + sec_devs = s5m8751_devs; 323 + num_sec_devs = ARRAY_SIZE(s5m8751_devs); 337 324 break; 338 325 case S5M8763X: 339 - ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, 340 - ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); 326 + sec_devs = s5m8763_devs; 327 + num_sec_devs = ARRAY_SIZE(s5m8763_devs); 341 328 break; 342 329 case S5M8767X: 343 - ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, 344 - ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); 330 + sec_devs = s5m8767_devs; 331 + num_sec_devs = ARRAY_SIZE(s5m8767_devs); 345 332 break; 346 333 case S2MPA01: 347 - ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs, 348 - ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL); 334 + sec_devs = s2mpa01_devs; 335 + num_sec_devs = ARRAY_SIZE(s2mpa01_devs); 349 336 break; 350 337 case S2MPS11X: 351 - ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, 352 - ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); 338 + sec_devs = s2mps11_devs; 339 + num_sec_devs = ARRAY_SIZE(s2mps11_devs); 353 340 break; 354 341 case S2MPS14X: 355 - ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs, 356 - ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL); 342 + sec_devs = s2mps14_devs; 343 + num_sec_devs = ARRAY_SIZE(s2mps14_devs); 344 + break; 345 + case S2MPU02: 346 + sec_devs = s2mpu02_devs; 347 + num_sec_devs = ARRAY_SIZE(s2mpu02_devs); 357 348 break; 358 349 default: 359 350 /* If this happens the probe function is problem */ 360 351 BUG(); 361 352 } 362 - 353 + ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL, 354 + 0, NULL); 363 355 if (ret) 364 356 goto err_mfd; 365 357
+94 -16
drivers/mfd/sec-irq.c
··· 20 20 #include <linux/mfd/samsung/irq.h> 21 21 #include <linux/mfd/samsung/s2mps11.h> 22 22 #include <linux/mfd/samsung/s2mps14.h> 23 + #include <linux/mfd/samsung/s2mpu02.h> 23 24 #include <linux/mfd/samsung/s5m8763.h> 24 25 #include <linux/mfd/samsung/s5m8767.h> 25 26 ··· 157 156 .mask = S2MPS11_IRQ_INT140C_MASK, 158 157 }, 159 158 [S2MPS14_IRQ_TSD] = { 159 + .reg_offset = 2, 160 + .mask = S2MPS14_IRQ_TSD_MASK, 161 + }, 162 + }; 163 + 164 + static const struct regmap_irq s2mpu02_irqs[] = { 165 + [S2MPU02_IRQ_PWRONF] = { 166 + .reg_offset = 0, 167 + .mask = S2MPS11_IRQ_PWRONF_MASK, 168 + }, 169 + [S2MPU02_IRQ_PWRONR] = { 170 + .reg_offset = 0, 171 + .mask = S2MPS11_IRQ_PWRONR_MASK, 172 + }, 173 + [S2MPU02_IRQ_JIGONBF] = { 174 + .reg_offset = 0, 175 + .mask = S2MPS11_IRQ_JIGONBF_MASK, 176 + }, 177 + [S2MPU02_IRQ_JIGONBR] = { 178 + .reg_offset = 0, 179 + .mask = S2MPS11_IRQ_JIGONBR_MASK, 180 + }, 181 + [S2MPU02_IRQ_ACOKBF] = { 182 + .reg_offset = 0, 183 + .mask = S2MPS11_IRQ_ACOKBF_MASK, 184 + }, 185 + [S2MPU02_IRQ_ACOKBR] = { 186 + .reg_offset = 0, 187 + .mask = S2MPS11_IRQ_ACOKBR_MASK, 188 + }, 189 + [S2MPU02_IRQ_PWRON1S] = { 190 + .reg_offset = 0, 191 + .mask = S2MPS11_IRQ_PWRON1S_MASK, 192 + }, 193 + [S2MPU02_IRQ_MRB] = { 194 + .reg_offset = 0, 195 + .mask = S2MPS11_IRQ_MRB_MASK, 196 + }, 197 + [S2MPU02_IRQ_RTC60S] = { 198 + .reg_offset = 1, 199 + .mask = S2MPS11_IRQ_RTC60S_MASK, 200 + }, 201 + [S2MPU02_IRQ_RTCA1] = { 202 + .reg_offset = 1, 203 + .mask = S2MPS11_IRQ_RTCA1_MASK, 204 + }, 205 + [S2MPU02_IRQ_RTCA0] = { 206 + .reg_offset = 1, 207 + .mask = S2MPS11_IRQ_RTCA0_MASK, 208 + }, 209 + [S2MPU02_IRQ_SMPL] = { 210 + .reg_offset = 1, 211 + .mask = S2MPS11_IRQ_SMPL_MASK, 212 + }, 213 + [S2MPU02_IRQ_RTC1S] = { 214 + .reg_offset = 1, 215 + .mask = S2MPS11_IRQ_RTC1S_MASK, 216 + }, 217 + [S2MPU02_IRQ_WTSR] = { 218 + .reg_offset = 1, 219 + .mask = S2MPS11_IRQ_WTSR_MASK, 220 + }, 221 + [S2MPU02_IRQ_INT120C] = { 222 + .reg_offset = 2, 223 + .mask = S2MPS11_IRQ_INT120C_MASK, 224 + }, 225 + [S2MPU02_IRQ_INT140C] = { 226 + .reg_offset = 2, 227 + .mask = S2MPS11_IRQ_INT140C_MASK, 228 + }, 229 + [S2MPU02_IRQ_TSD] = { 160 230 .reg_offset = 2, 161 231 .mask = S2MPS14_IRQ_TSD_MASK, 162 232 }, ··· 399 327 .ack_base = S2MPS14_REG_INT1, 400 328 }; 401 329 330 + static const struct regmap_irq_chip s2mpu02_irq_chip = { 331 + .name = "s2mpu02", 332 + .irqs = s2mpu02_irqs, 333 + .num_irqs = ARRAY_SIZE(s2mpu02_irqs), 334 + .num_regs = 3, 335 + .status_base = S2MPU02_REG_INT1, 336 + .mask_base = S2MPU02_REG_INT1M, 337 + .ack_base = S2MPU02_REG_INT1, 338 + }; 339 + 402 340 static const struct regmap_irq_chip s5m8767_irq_chip = { 403 341 .name = "s5m8767", 404 342 .irqs = s5m8767_irqs, ··· 433 351 { 434 352 int ret = 0; 435 353 int type = sec_pmic->device_type; 354 + const struct regmap_irq_chip *sec_irq_chip; 436 355 437 356 if (!sec_pmic->irq) { 438 357 dev_warn(sec_pmic->dev, ··· 444 361 445 362 switch (type) { 446 363 case S5M8763X: 447 - ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 448 - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 449 - sec_pmic->irq_base, &s5m8763_irq_chip, 450 - &sec_pmic->irq_data); 364 + sec_irq_chip = &s5m8763_irq_chip; 451 365 break; 452 366 case S5M8767X: 453 - ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 454 - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 455 - sec_pmic->irq_base, &s5m8767_irq_chip, 456 - &sec_pmic->irq_data); 367 + sec_irq_chip = &s5m8767_irq_chip; 457 368 break; 458 369 case S2MPS11X: 459 - ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 460 - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 461 - sec_pmic->irq_base, &s2mps11_irq_chip, 462 - &sec_pmic->irq_data); 370 + sec_irq_chip = &s2mps11_irq_chip; 463 371 break; 464 372 case S2MPS14X: 465 - ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 466 - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 467 - sec_pmic->irq_base, &s2mps14_irq_chip, 468 - &sec_pmic->irq_data); 373 + sec_irq_chip = &s2mps14_irq_chip; 374 + break; 375 + case S2MPU02: 376 + sec_irq_chip = &s2mpu02_irq_chip; 469 377 break; 470 378 default: 471 379 dev_err(sec_pmic->dev, "Unknown device type %lu\n", ··· 464 390 return -EINVAL; 465 391 } 466 392 393 + ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq, 394 + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 395 + sec_pmic->irq_base, sec_irq_chip, 396 + &sec_pmic->irq_data); 467 397 if (ret != 0) { 468 398 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret); 469 399 return ret;
+1
include/linux/mfd/samsung/core.h
··· 21 21 S2MPA01, 22 22 S2MPS11X, 23 23 S2MPS14X, 24 + S2MPU02, 24 25 }; 25 26 26 27 /**
+24
include/linux/mfd/samsung/irq.h
··· 129 129 S2MPS14_IRQ_NR, 130 130 }; 131 131 132 + enum s2mpu02_irq { 133 + S2MPU02_IRQ_PWRONF, 134 + S2MPU02_IRQ_PWRONR, 135 + S2MPU02_IRQ_JIGONBF, 136 + S2MPU02_IRQ_JIGONBR, 137 + S2MPU02_IRQ_ACOKBF, 138 + S2MPU02_IRQ_ACOKBR, 139 + S2MPU02_IRQ_PWRON1S, 140 + S2MPU02_IRQ_MRB, 141 + 142 + S2MPU02_IRQ_RTC60S, 143 + S2MPU02_IRQ_RTCA1, 144 + S2MPU02_IRQ_RTCA0, 145 + S2MPU02_IRQ_SMPL, 146 + S2MPU02_IRQ_RTC1S, 147 + S2MPU02_IRQ_WTSR, 148 + 149 + S2MPU02_IRQ_INT120C, 150 + S2MPU02_IRQ_INT140C, 151 + S2MPU02_IRQ_TSD, 152 + 153 + S2MPU02_IRQ_NR, 154 + }; 155 + 132 156 /* Masks for interrupts are the same as in s2mps11 */ 133 157 #define S2MPS14_IRQ_TSD_MASK (1 << 2) 134 158
+201
include/linux/mfd/samsung/s2mpu02.h
··· 1 + /* 2 + * s2mpu02.h 3 + * 4 + * Copyright (c) 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 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 + * GNU General Public License for more details. 16 + * 17 + */ 18 + 19 + #ifndef __LINUX_MFD_S2MPU02_H 20 + #define __LINUX_MFD_S2MPU02_H 21 + 22 + /* S2MPU02 registers */ 23 + enum S2MPU02_reg { 24 + S2MPU02_REG_ID, 25 + S2MPU02_REG_INT1, 26 + S2MPU02_REG_INT2, 27 + S2MPU02_REG_INT3, 28 + S2MPU02_REG_INT1M, 29 + S2MPU02_REG_INT2M, 30 + S2MPU02_REG_INT3M, 31 + S2MPU02_REG_ST1, 32 + S2MPU02_REG_ST2, 33 + S2MPU02_REG_PWRONSRC, 34 + S2MPU02_REG_OFFSRC, 35 + S2MPU02_REG_BU_CHG, 36 + S2MPU02_REG_RTCCTRL, 37 + S2MPU02_REG_PMCTRL1, 38 + S2MPU02_REG_RSVD1, 39 + S2MPU02_REG_RSVD2, 40 + S2MPU02_REG_RSVD3, 41 + S2MPU02_REG_RSVD4, 42 + S2MPU02_REG_RSVD5, 43 + S2MPU02_REG_RSVD6, 44 + S2MPU02_REG_RSVD7, 45 + S2MPU02_REG_WRSTEN, 46 + S2MPU02_REG_RSVD8, 47 + S2MPU02_REG_RSVD9, 48 + S2MPU02_REG_RSVD10, 49 + S2MPU02_REG_B1CTRL1, 50 + S2MPU02_REG_B1CTRL2, 51 + S2MPU02_REG_B2CTRL1, 52 + S2MPU02_REG_B2CTRL2, 53 + S2MPU02_REG_B3CTRL1, 54 + S2MPU02_REG_B3CTRL2, 55 + S2MPU02_REG_B4CTRL1, 56 + S2MPU02_REG_B4CTRL2, 57 + S2MPU02_REG_B5CTRL1, 58 + S2MPU02_REG_B5CTRL2, 59 + S2MPU02_REG_B5CTRL3, 60 + S2MPU02_REG_B5CTRL4, 61 + S2MPU02_REG_B5CTRL5, 62 + S2MPU02_REG_B6CTRL1, 63 + S2MPU02_REG_B6CTRL2, 64 + S2MPU02_REG_B7CTRL1, 65 + S2MPU02_REG_B7CTRL2, 66 + S2MPU02_REG_RAMP1, 67 + S2MPU02_REG_RAMP2, 68 + S2MPU02_REG_L1CTRL, 69 + S2MPU02_REG_L2CTRL1, 70 + S2MPU02_REG_L2CTRL2, 71 + S2MPU02_REG_L2CTRL3, 72 + S2MPU02_REG_L2CTRL4, 73 + S2MPU02_REG_L3CTRL, 74 + S2MPU02_REG_L4CTRL, 75 + S2MPU02_REG_L5CTRL, 76 + S2MPU02_REG_L6CTRL, 77 + S2MPU02_REG_L7CTRL, 78 + S2MPU02_REG_L8CTRL, 79 + S2MPU02_REG_L9CTRL, 80 + S2MPU02_REG_L10CTRL, 81 + S2MPU02_REG_L11CTRL, 82 + S2MPU02_REG_L12CTRL, 83 + S2MPU02_REG_L13CTRL, 84 + S2MPU02_REG_L14CTRL, 85 + S2MPU02_REG_L15CTRL, 86 + S2MPU02_REG_L16CTRL, 87 + S2MPU02_REG_L17CTRL, 88 + S2MPU02_REG_L18CTRL, 89 + S2MPU02_REG_L19CTRL, 90 + S2MPU02_REG_L20CTRL, 91 + S2MPU02_REG_L21CTRL, 92 + S2MPU02_REG_L22CTRL, 93 + S2MPU02_REG_L23CTRL, 94 + S2MPU02_REG_L24CTRL, 95 + S2MPU02_REG_L25CTRL, 96 + S2MPU02_REG_L26CTRL, 97 + S2MPU02_REG_L27CTRL, 98 + S2MPU02_REG_L28CTRL, 99 + S2MPU02_REG_LDODSCH1, 100 + S2MPU02_REG_LDODSCH2, 101 + S2MPU02_REG_LDODSCH3, 102 + S2MPU02_REG_LDODSCH4, 103 + S2MPU02_REG_SELMIF, 104 + S2MPU02_REG_RSVD11, 105 + S2MPU02_REG_RSVD12, 106 + S2MPU02_REG_RSVD13, 107 + S2MPU02_REG_DVSSEL, 108 + S2MPU02_REG_DVSPTR, 109 + S2MPU02_REG_DVSDATA, 110 + }; 111 + 112 + /* S2MPU02 regulator ids */ 113 + enum S2MPU02_regulators { 114 + S2MPU02_LDO1, 115 + S2MPU02_LDO2, 116 + S2MPU02_LDO3, 117 + S2MPU02_LDO4, 118 + S2MPU02_LDO5, 119 + S2MPU02_LDO6, 120 + S2MPU02_LDO7, 121 + S2MPU02_LDO8, 122 + S2MPU02_LDO9, 123 + S2MPU02_LDO10, 124 + S2MPU02_LDO11, 125 + S2MPU02_LDO12, 126 + S2MPU02_LDO13, 127 + S2MPU02_LDO14, 128 + S2MPU02_LDO15, 129 + S2MPU02_LDO16, 130 + S2MPU02_LDO17, 131 + S2MPU02_LDO18, 132 + S2MPU02_LDO19, 133 + S2MPU02_LDO20, 134 + S2MPU02_LDO21, 135 + S2MPU02_LDO22, 136 + S2MPU02_LDO23, 137 + S2MPU02_LDO24, 138 + S2MPU02_LDO25, 139 + S2MPU02_LDO26, 140 + S2MPU02_LDO27, 141 + S2MPU02_LDO28, 142 + S2MPU02_BUCK1, 143 + S2MPU02_BUCK2, 144 + S2MPU02_BUCK3, 145 + S2MPU02_BUCK4, 146 + S2MPU02_BUCK5, 147 + S2MPU02_BUCK6, 148 + S2MPU02_BUCK7, 149 + 150 + S2MPU02_REGULATOR_MAX, 151 + }; 152 + 153 + /* Regulator constraints for BUCKx */ 154 + #define S2MPU02_BUCK1234_MIN_600MV 600000 155 + #define S2MPU02_BUCK5_MIN_1081_25MV 1081250 156 + #define S2MPU02_BUCK6_MIN_1700MV 1700000 157 + #define S2MPU02_BUCK7_MIN_900MV 900000 158 + 159 + #define S2MPU02_BUCK1234_STEP_6_25MV 6250 160 + #define S2MPU02_BUCK5_STEP_6_25MV 6250 161 + #define S2MPU02_BUCK6_STEP_2_50MV 2500 162 + #define S2MPU02_BUCK7_STEP_6_25MV 6250 163 + 164 + #define S2MPU02_BUCK1234_START_SEL 0x00 165 + #define S2MPU02_BUCK5_START_SEL 0x4D 166 + #define S2MPU02_BUCK6_START_SEL 0x28 167 + #define S2MPU02_BUCK7_START_SEL 0x30 168 + 169 + #define S2MPU02_BUCK_RAMP_DELAY 12500 170 + 171 + /* Regulator constraints for different types of LDOx */ 172 + #define S2MPU02_LDO_MIN_900MV 900000 173 + #define S2MPU02_LDO_MIN_1050MV 1050000 174 + #define S2MPU02_LDO_MIN_1600MV 1600000 175 + #define S2MPU02_LDO_STEP_12_5MV 12500 176 + #define S2MPU02_LDO_STEP_25MV 25000 177 + #define S2MPU02_LDO_STEP_50MV 50000 178 + 179 + #define S2MPU02_LDO_GROUP1_START_SEL 0x8 180 + #define S2MPU02_LDO_GROUP2_START_SEL 0xA 181 + #define S2MPU02_LDO_GROUP3_START_SEL 0x10 182 + 183 + #define S2MPU02_LDO_VSEL_MASK 0x3F 184 + #define S2MPU02_BUCK_VSEL_MASK 0xFF 185 + #define S2MPU02_ENABLE_MASK (0x03 << S2MPU02_ENABLE_SHIFT) 186 + #define S2MPU02_ENABLE_SHIFT 6 187 + 188 + /* On/Off controlled by PWREN */ 189 + #define S2MPU02_ENABLE_SUSPEND (0x01 << S2MPU02_ENABLE_SHIFT) 190 + #define S2MPU02_DISABLE_SUSPEND (0x11 << S2MPU02_ENABLE_SHIFT) 191 + #define S2MPU02_LDO_N_VOLTAGES (S2MPU02_LDO_VSEL_MASK + 1) 192 + #define S2MPU02_BUCK_N_VOLTAGES (S2MPU02_BUCK_VSEL_MASK + 1) 193 + 194 + /* RAMP delay for BUCK1234*/ 195 + #define S2MPU02_BUCK1_RAMP_SHIFT 6 196 + #define S2MPU02_BUCK2_RAMP_SHIFT 4 197 + #define S2MPU02_BUCK3_RAMP_SHIFT 2 198 + #define S2MPU02_BUCK4_RAMP_SHIFT 0 199 + #define S2MPU02_BUCK1234_RAMP_MASK 0x3 200 + 201 + #endif /* __LINUX_MFD_S2MPU02_H */