459 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// Copyright (c) 2012 Samsung Electronics Co., Ltd4// http://www.samsung.com5 6#include <linux/module.h>7#include <linux/moduleparam.h>8#include <linux/init.h>9#include <linux/err.h>10#include <linux/slab.h>11#include <linux/i2c.h>12#include <linux/of.h>13#include <linux/interrupt.h>14#include <linux/pm_runtime.h>15#include <linux/mutex.h>16#include <linux/mfd/core.h>17#include <linux/mfd/samsung/core.h>18#include <linux/mfd/samsung/irq.h>19#include <linux/mfd/samsung/s2mpa01.h>20#include <linux/mfd/samsung/s2mps11.h>21#include <linux/mfd/samsung/s2mps13.h>22#include <linux/mfd/samsung/s2mps14.h>23#include <linux/mfd/samsung/s2mps15.h>24#include <linux/mfd/samsung/s2mpu02.h>25#include <linux/mfd/samsung/s5m8767.h>26#include <linux/regmap.h>27 28static const struct mfd_cell s5m8767_devs[] = {29 { .name = "s5m8767-pmic", },30 { .name = "s5m-rtc", },31 {32 .name = "s5m8767-clk",33 .of_compatible = "samsung,s5m8767-clk",34 },35};36 37static const struct mfd_cell s2mps11_devs[] = {38 { .name = "s2mps11-regulator", },39 { .name = "s2mps14-rtc", },40 {41 .name = "s2mps11-clk",42 .of_compatible = "samsung,s2mps11-clk",43 },44};45 46static const struct mfd_cell s2mps13_devs[] = {47 { .name = "s2mps13-regulator", },48 { .name = "s2mps13-rtc", },49 {50 .name = "s2mps13-clk",51 .of_compatible = "samsung,s2mps13-clk",52 },53};54 55static const struct mfd_cell s2mps14_devs[] = {56 { .name = "s2mps14-regulator", },57 { .name = "s2mps14-rtc", },58 {59 .name = "s2mps14-clk",60 .of_compatible = "samsung,s2mps14-clk",61 },62};63 64static const struct mfd_cell s2mps15_devs[] = {65 { .name = "s2mps15-regulator", },66 { .name = "s2mps15-rtc", },67 {68 .name = "s2mps13-clk",69 .of_compatible = "samsung,s2mps13-clk",70 },71};72 73static const struct mfd_cell s2mpa01_devs[] = {74 { .name = "s2mpa01-pmic", },75 { .name = "s2mps14-rtc", },76};77 78static const struct mfd_cell s2mpu02_devs[] = {79 { .name = "s2mpu02-regulator", },80};81 82static const struct of_device_id sec_dt_match[] = {83 {84 .compatible = "samsung,s5m8767-pmic",85 .data = (void *)S5M8767X,86 }, {87 .compatible = "samsung,s2mps11-pmic",88 .data = (void *)S2MPS11X,89 }, {90 .compatible = "samsung,s2mps13-pmic",91 .data = (void *)S2MPS13X,92 }, {93 .compatible = "samsung,s2mps14-pmic",94 .data = (void *)S2MPS14X,95 }, {96 .compatible = "samsung,s2mps15-pmic",97 .data = (void *)S2MPS15X,98 }, {99 .compatible = "samsung,s2mpa01-pmic",100 .data = (void *)S2MPA01,101 }, {102 .compatible = "samsung,s2mpu02-pmic",103 .data = (void *)S2MPU02,104 }, {105 /* Sentinel */106 },107};108MODULE_DEVICE_TABLE(of, sec_dt_match);109 110static bool s2mpa01_volatile(struct device *dev, unsigned int reg)111{112 switch (reg) {113 case S2MPA01_REG_INT1M:114 case S2MPA01_REG_INT2M:115 case S2MPA01_REG_INT3M:116 return false;117 default:118 return true;119 }120}121 122static bool s2mps11_volatile(struct device *dev, unsigned int reg)123{124 switch (reg) {125 case S2MPS11_REG_INT1M:126 case S2MPS11_REG_INT2M:127 case S2MPS11_REG_INT3M:128 return false;129 default:130 return true;131 }132}133 134static bool s2mpu02_volatile(struct device *dev, unsigned int reg)135{136 switch (reg) {137 case S2MPU02_REG_INT1M:138 case S2MPU02_REG_INT2M:139 case S2MPU02_REG_INT3M:140 return false;141 default:142 return true;143 }144}145 146static const struct regmap_config sec_regmap_config = {147 .reg_bits = 8,148 .val_bits = 8,149};150 151static const struct regmap_config s2mpa01_regmap_config = {152 .reg_bits = 8,153 .val_bits = 8,154 155 .max_register = S2MPA01_REG_LDO_OVCB4,156 .volatile_reg = s2mpa01_volatile,157 .cache_type = REGCACHE_FLAT,158};159 160static const struct regmap_config s2mps11_regmap_config = {161 .reg_bits = 8,162 .val_bits = 8,163 164 .max_register = S2MPS11_REG_L38CTRL,165 .volatile_reg = s2mps11_volatile,166 .cache_type = REGCACHE_FLAT,167};168 169static const struct regmap_config s2mps13_regmap_config = {170 .reg_bits = 8,171 .val_bits = 8,172 173 .max_register = S2MPS13_REG_LDODSCH5,174 .volatile_reg = s2mps11_volatile,175 .cache_type = REGCACHE_FLAT,176};177 178static const struct regmap_config s2mps14_regmap_config = {179 .reg_bits = 8,180 .val_bits = 8,181 182 .max_register = S2MPS14_REG_LDODSCH3,183 .volatile_reg = s2mps11_volatile,184 .cache_type = REGCACHE_FLAT,185};186 187static const struct regmap_config s2mps15_regmap_config = {188 .reg_bits = 8,189 .val_bits = 8,190 191 .max_register = S2MPS15_REG_LDODSCH4,192 .volatile_reg = s2mps11_volatile,193 .cache_type = REGCACHE_FLAT,194};195 196static const struct regmap_config s2mpu02_regmap_config = {197 .reg_bits = 8,198 .val_bits = 8,199 200 .max_register = S2MPU02_REG_DVSDATA,201 .volatile_reg = s2mpu02_volatile,202 .cache_type = REGCACHE_FLAT,203};204 205static const struct regmap_config s5m8767_regmap_config = {206 .reg_bits = 8,207 .val_bits = 8,208 209 .max_register = S5M8767_REG_LDO28CTRL,210 .volatile_reg = s2mps11_volatile,211 .cache_type = REGCACHE_FLAT,212};213 214static void sec_pmic_dump_rev(struct sec_pmic_dev *sec_pmic)215{216 unsigned int val;217 218 /* For each device type, the REG_ID is always the first register */219 if (!regmap_read(sec_pmic->regmap_pmic, S2MPS11_REG_ID, &val))220 dev_dbg(sec_pmic->dev, "Revision: 0x%x\n", val);221}222 223static void sec_pmic_configure(struct sec_pmic_dev *sec_pmic)224{225 int err;226 227 if (sec_pmic->device_type != S2MPS13X)228 return;229 230 if (sec_pmic->pdata->disable_wrstbi) {231 /*232 * If WRSTBI pin is pulled down this feature must be disabled233 * because each Suspend to RAM will trigger buck voltage reset234 * to default values.235 */236 err = regmap_update_bits(sec_pmic->regmap_pmic,237 S2MPS13_REG_WRSTBI,238 S2MPS13_REG_WRSTBI_MASK, 0x0);239 if (err)240 dev_warn(sec_pmic->dev,241 "Cannot initialize WRSTBI config: %d\n",242 err);243 }244}245 246/*247 * Only the common platform data elements for s5m8767 are parsed here from the248 * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and249 * others have to parse their own platform data elements from device tree.250 *251 * The s5m8767 platform data structure is instantiated here and the drivers for252 * the sub-modules need not instantiate another instance while parsing their253 * platform data.254 */255static struct sec_platform_data *256sec_pmic_i2c_parse_dt_pdata(struct device *dev)257{258 struct sec_platform_data *pd;259 260 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);261 if (!pd)262 return ERR_PTR(-ENOMEM);263 264 pd->manual_poweroff = of_property_read_bool(dev->of_node,265 "samsung,s2mps11-acokb-ground");266 pd->disable_wrstbi = of_property_read_bool(dev->of_node,267 "samsung,s2mps11-wrstbi-ground");268 return pd;269}270 271static int sec_pmic_probe(struct i2c_client *i2c)272{273 const struct regmap_config *regmap;274 struct sec_platform_data *pdata;275 const struct mfd_cell *sec_devs;276 struct sec_pmic_dev *sec_pmic;277 int ret, num_sec_devs;278 279 sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),280 GFP_KERNEL);281 if (sec_pmic == NULL)282 return -ENOMEM;283 284 i2c_set_clientdata(i2c, sec_pmic);285 sec_pmic->dev = &i2c->dev;286 sec_pmic->i2c = i2c;287 sec_pmic->irq = i2c->irq;288 289 pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev);290 if (IS_ERR(pdata)) {291 ret = PTR_ERR(pdata);292 return ret;293 }294 295 sec_pmic->device_type = (unsigned long)of_device_get_match_data(sec_pmic->dev);296 sec_pmic->pdata = pdata;297 298 switch (sec_pmic->device_type) {299 case S2MPA01:300 regmap = &s2mpa01_regmap_config;301 break;302 case S2MPS11X:303 regmap = &s2mps11_regmap_config;304 break;305 case S2MPS13X:306 regmap = &s2mps13_regmap_config;307 break;308 case S2MPS14X:309 regmap = &s2mps14_regmap_config;310 break;311 case S2MPS15X:312 regmap = &s2mps15_regmap_config;313 break;314 case S5M8767X:315 regmap = &s5m8767_regmap_config;316 break;317 case S2MPU02:318 regmap = &s2mpu02_regmap_config;319 break;320 default:321 regmap = &sec_regmap_config;322 break;323 }324 325 sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);326 if (IS_ERR(sec_pmic->regmap_pmic)) {327 ret = PTR_ERR(sec_pmic->regmap_pmic);328 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",329 ret);330 return ret;331 }332 333 sec_irq_init(sec_pmic);334 335 pm_runtime_set_active(sec_pmic->dev);336 337 switch (sec_pmic->device_type) {338 case S5M8767X:339 sec_devs = s5m8767_devs;340 num_sec_devs = ARRAY_SIZE(s5m8767_devs);341 break;342 case S2MPA01:343 sec_devs = s2mpa01_devs;344 num_sec_devs = ARRAY_SIZE(s2mpa01_devs);345 break;346 case S2MPS11X:347 sec_devs = s2mps11_devs;348 num_sec_devs = ARRAY_SIZE(s2mps11_devs);349 break;350 case S2MPS13X:351 sec_devs = s2mps13_devs;352 num_sec_devs = ARRAY_SIZE(s2mps13_devs);353 break;354 case S2MPS14X:355 sec_devs = s2mps14_devs;356 num_sec_devs = ARRAY_SIZE(s2mps14_devs);357 break;358 case S2MPS15X:359 sec_devs = s2mps15_devs;360 num_sec_devs = ARRAY_SIZE(s2mps15_devs);361 break;362 case S2MPU02:363 sec_devs = s2mpu02_devs;364 num_sec_devs = ARRAY_SIZE(s2mpu02_devs);365 break;366 default:367 dev_err(&i2c->dev, "Unsupported device type (%lu)\n",368 sec_pmic->device_type);369 return -ENODEV;370 }371 ret = devm_mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs,372 NULL, 0, NULL);373 if (ret)374 return ret;375 376 sec_pmic_configure(sec_pmic);377 sec_pmic_dump_rev(sec_pmic);378 379 return ret;380}381 382static void sec_pmic_shutdown(struct i2c_client *i2c)383{384 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);385 unsigned int reg, mask;386 387 if (!sec_pmic->pdata->manual_poweroff)388 return;389 390 switch (sec_pmic->device_type) {391 case S2MPS11X:392 reg = S2MPS11_REG_CTRL1;393 mask = S2MPS11_CTRL1_PWRHOLD_MASK;394 break;395 default:396 /*397 * Currently only one board with S2MPS11 needs this, so just398 * ignore the rest.399 */400 dev_warn(sec_pmic->dev,401 "Unsupported device %lu for manual power off\n",402 sec_pmic->device_type);403 return;404 }405 406 regmap_update_bits(sec_pmic->regmap_pmic, reg, mask, 0);407}408 409static int sec_pmic_suspend(struct device *dev)410{411 struct i2c_client *i2c = to_i2c_client(dev);412 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);413 414 if (device_may_wakeup(dev))415 enable_irq_wake(sec_pmic->irq);416 /*417 * PMIC IRQ must be disabled during suspend for RTC alarm418 * to work properly.419 * When device is woken up from suspend, an420 * interrupt occurs before resuming I2C bus controller.421 * The interrupt is handled by regmap_irq_thread which tries422 * to read RTC registers. This read fails (I2C is still423 * suspended) and RTC Alarm interrupt is disabled.424 */425 disable_irq(sec_pmic->irq);426 427 return 0;428}429 430static int sec_pmic_resume(struct device *dev)431{432 struct i2c_client *i2c = to_i2c_client(dev);433 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);434 435 if (device_may_wakeup(dev))436 disable_irq_wake(sec_pmic->irq);437 enable_irq(sec_pmic->irq);438 439 return 0;440}441 442static DEFINE_SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops,443 sec_pmic_suspend, sec_pmic_resume);444 445static struct i2c_driver sec_pmic_driver = {446 .driver = {447 .name = "sec_pmic",448 .pm = pm_sleep_ptr(&sec_pmic_pm_ops),449 .of_match_table = sec_dt_match,450 },451 .probe = sec_pmic_probe,452 .shutdown = sec_pmic_shutdown,453};454module_i2c_driver(sec_pmic_driver);455 456MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");457MODULE_DESCRIPTION("Core support for the S5M MFD");458MODULE_LICENSE("GPL");459