Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v3.15-rc1 493 lines 12 kB view raw
1/* 2 * sec-core.c 3 * 4 * Copyright (c) 2012 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/module.h> 15#include <linux/moduleparam.h> 16#include <linux/init.h> 17#include <linux/err.h> 18#include <linux/slab.h> 19#include <linux/i2c.h> 20#include <linux/of.h> 21#include <linux/of_irq.h> 22#include <linux/interrupt.h> 23#include <linux/pm_runtime.h> 24#include <linux/mutex.h> 25#include <linux/mfd/core.h> 26#include <linux/mfd/samsung/core.h> 27#include <linux/mfd/samsung/irq.h> 28#include <linux/mfd/samsung/rtc.h> 29#include <linux/mfd/samsung/s2mpa01.h> 30#include <linux/mfd/samsung/s2mps11.h> 31#include <linux/mfd/samsung/s2mps14.h> 32#include <linux/mfd/samsung/s5m8763.h> 33#include <linux/mfd/samsung/s5m8767.h> 34#include <linux/regmap.h> 35 36static const struct mfd_cell s5m8751_devs[] = { 37 { 38 .name = "s5m8751-pmic", 39 }, { 40 .name = "s5m-charger", 41 }, { 42 .name = "s5m8751-codec", 43 }, 44}; 45 46static const struct mfd_cell s5m8763_devs[] = { 47 { 48 .name = "s5m8763-pmic", 49 }, { 50 .name = "s5m-rtc", 51 }, { 52 .name = "s5m-charger", 53 }, 54}; 55 56static const struct mfd_cell s5m8767_devs[] = { 57 { 58 .name = "s5m8767-pmic", 59 }, { 60 .name = "s5m-rtc", 61 }, { 62 .name = "s5m8767-clk", 63 .of_compatible = "samsung,s5m8767-clk", 64 } 65}; 66 67static const struct mfd_cell s2mps11_devs[] = { 68 { 69 .name = "s2mps11-pmic", 70 }, { 71 .name = "s2mps11-clk", 72 .of_compatible = "samsung,s2mps11-clk", 73 } 74}; 75 76static const struct mfd_cell s2mps14_devs[] = { 77 { 78 .name = "s2mps14-pmic", 79 }, { 80 .name = "s2mps14-rtc", 81 }, { 82 .name = "s2mps14-clk", 83 .of_compatible = "samsung,s2mps14-clk", 84 } 85}; 86 87static const struct mfd_cell s2mpa01_devs[] = { 88 { 89 .name = "s2mpa01-pmic", 90 }, 91}; 92 93#ifdef CONFIG_OF 94static struct of_device_id sec_dt_match[] = { 95 { .compatible = "samsung,s5m8767-pmic", 96 .data = (void *)S5M8767X, 97 }, { 98 .compatible = "samsung,s2mps11-pmic", 99 .data = (void *)S2MPS11X, 100 }, { 101 .compatible = "samsung,s2mps14-pmic", 102 .data = (void *)S2MPS14X, 103 }, { 104 .compatible = "samsung,s2mpa01-pmic", 105 .data = (void *)S2MPA01, 106 }, { 107 /* Sentinel */ 108 }, 109}; 110#endif 111 112static bool s2mpa01_volatile(struct device *dev, unsigned int reg) 113{ 114 switch (reg) { 115 case S2MPA01_REG_INT1M: 116 case S2MPA01_REG_INT2M: 117 case S2MPA01_REG_INT3M: 118 return false; 119 default: 120 return true; 121 } 122} 123 124static bool s2mps11_volatile(struct device *dev, unsigned int reg) 125{ 126 switch (reg) { 127 case S2MPS11_REG_INT1M: 128 case S2MPS11_REG_INT2M: 129 case S2MPS11_REG_INT3M: 130 return false; 131 default: 132 return true; 133 } 134} 135 136static bool s5m8763_volatile(struct device *dev, unsigned int reg) 137{ 138 switch (reg) { 139 case S5M8763_REG_IRQM1: 140 case S5M8763_REG_IRQM2: 141 case S5M8763_REG_IRQM3: 142 case S5M8763_REG_IRQM4: 143 return false; 144 default: 145 return true; 146 } 147} 148 149static const struct regmap_config sec_regmap_config = { 150 .reg_bits = 8, 151 .val_bits = 8, 152}; 153 154static const struct regmap_config s2mpa01_regmap_config = { 155 .reg_bits = 8, 156 .val_bits = 8, 157 158 .max_register = S2MPA01_REG_LDO_OVCB4, 159 .volatile_reg = s2mpa01_volatile, 160 .cache_type = REGCACHE_FLAT, 161}; 162 163static const struct regmap_config s2mps11_regmap_config = { 164 .reg_bits = 8, 165 .val_bits = 8, 166 167 .max_register = S2MPS11_REG_L38CTRL, 168 .volatile_reg = s2mps11_volatile, 169 .cache_type = REGCACHE_FLAT, 170}; 171 172static const struct regmap_config s2mps14_regmap_config = { 173 .reg_bits = 8, 174 .val_bits = 8, 175 176 .max_register = S2MPS14_REG_LDODSCH3, 177 .volatile_reg = s2mps11_volatile, 178 .cache_type = REGCACHE_FLAT, 179}; 180 181static const struct regmap_config s5m8763_regmap_config = { 182 .reg_bits = 8, 183 .val_bits = 8, 184 185 .max_register = S5M8763_REG_LBCNFG2, 186 .volatile_reg = s5m8763_volatile, 187 .cache_type = REGCACHE_FLAT, 188}; 189 190static const struct regmap_config s5m8767_regmap_config = { 191 .reg_bits = 8, 192 .val_bits = 8, 193 194 .max_register = S5M8767_REG_LDO28CTRL, 195 .volatile_reg = s2mps11_volatile, 196 .cache_type = REGCACHE_FLAT, 197}; 198 199static const struct regmap_config s5m_rtc_regmap_config = { 200 .reg_bits = 8, 201 .val_bits = 8, 202 203 .max_register = SEC_RTC_REG_MAX, 204}; 205 206static const struct regmap_config s2mps14_rtc_regmap_config = { 207 .reg_bits = 8, 208 .val_bits = 8, 209 210 .max_register = S2MPS_RTC_REG_MAX, 211}; 212 213#ifdef CONFIG_OF 214/* 215 * Only the common platform data elements for s5m8767 are parsed here from the 216 * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and 217 * others have to parse their own platform data elements from device tree. 218 * 219 * The s5m8767 platform data structure is instantiated here and the drivers for 220 * the sub-modules need not instantiate another instance while parsing their 221 * platform data. 222 */ 223static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( 224 struct device *dev) 225{ 226 struct sec_platform_data *pd; 227 228 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 229 if (!pd) { 230 dev_err(dev, "could not allocate memory for pdata\n"); 231 return ERR_PTR(-ENOMEM); 232 } 233 234 /* 235 * ToDo: the 'wakeup' member in the platform data is more of a linux 236 * specfic information. Hence, there is no binding for that yet and 237 * not parsed here. 238 */ 239 240 return pd; 241} 242#else 243static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( 244 struct device *dev) 245{ 246 return NULL; 247} 248#endif 249 250static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c, 251 const struct i2c_device_id *id) 252{ 253#ifdef CONFIG_OF 254 if (i2c->dev.of_node) { 255 const struct of_device_id *match; 256 match = of_match_node(sec_dt_match, i2c->dev.of_node); 257 return (unsigned long)match->data; 258 } 259#endif 260 return id->driver_data; 261} 262 263static int sec_pmic_probe(struct i2c_client *i2c, 264 const struct i2c_device_id *id) 265{ 266 struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); 267 const struct regmap_config *regmap, *regmap_rtc; 268 struct sec_pmic_dev *sec_pmic; 269 int ret; 270 271 sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev), 272 GFP_KERNEL); 273 if (sec_pmic == NULL) 274 return -ENOMEM; 275 276 i2c_set_clientdata(i2c, sec_pmic); 277 sec_pmic->dev = &i2c->dev; 278 sec_pmic->i2c = i2c; 279 sec_pmic->irq = i2c->irq; 280 sec_pmic->type = sec_i2c_get_driver_data(i2c, id); 281 282 if (sec_pmic->dev->of_node) { 283 pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); 284 if (IS_ERR(pdata)) { 285 ret = PTR_ERR(pdata); 286 return ret; 287 } 288 pdata->device_type = sec_pmic->type; 289 } 290 if (pdata) { 291 sec_pmic->device_type = pdata->device_type; 292 sec_pmic->ono = pdata->ono; 293 sec_pmic->irq_base = pdata->irq_base; 294 sec_pmic->wakeup = pdata->wakeup; 295 sec_pmic->pdata = pdata; 296 } 297 298 switch (sec_pmic->device_type) { 299 case S2MPA01: 300 regmap = &s2mpa01_regmap_config; 301 /* 302 * The rtc-s5m driver does not support S2MPA01 and there 303 * is no mfd_cell for S2MPA01 RTC device. 304 * However we must pass something to devm_regmap_init_i2c() 305 * so use S5M-like regmap config even though it wouldn't work. 306 */ 307 regmap_rtc = &s5m_rtc_regmap_config; 308 break; 309 case S2MPS11X: 310 regmap = &s2mps11_regmap_config; 311 /* 312 * The rtc-s5m driver does not support S2MPS11 and there 313 * is no mfd_cell for S2MPS11 RTC device. 314 * However we must pass something to devm_regmap_init_i2c() 315 * so use S5M-like regmap config even though it wouldn't work. 316 */ 317 regmap_rtc = &s5m_rtc_regmap_config; 318 break; 319 case S2MPS14X: 320 regmap = &s2mps14_regmap_config; 321 regmap_rtc = &s2mps14_rtc_regmap_config; 322 break; 323 case S5M8763X: 324 regmap = &s5m8763_regmap_config; 325 regmap_rtc = &s5m_rtc_regmap_config; 326 break; 327 case S5M8767X: 328 regmap = &s5m8767_regmap_config; 329 regmap_rtc = &s5m_rtc_regmap_config; 330 break; 331 default: 332 regmap = &sec_regmap_config; 333 regmap_rtc = &s5m_rtc_regmap_config; 334 break; 335 } 336 337 sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap); 338 if (IS_ERR(sec_pmic->regmap_pmic)) { 339 ret = PTR_ERR(sec_pmic->regmap_pmic); 340 dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 341 ret); 342 return ret; 343 } 344 345 sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); 346 if (!sec_pmic->rtc) { 347 dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n"); 348 return -ENODEV; 349 } 350 i2c_set_clientdata(sec_pmic->rtc, sec_pmic); 351 352 sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc); 353 if (IS_ERR(sec_pmic->regmap_rtc)) { 354 ret = PTR_ERR(sec_pmic->regmap_rtc); 355 dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", 356 ret); 357 goto err_regmap_rtc; 358 } 359 360 if (pdata && pdata->cfg_pmic_irq) 361 pdata->cfg_pmic_irq(); 362 363 sec_irq_init(sec_pmic); 364 365 pm_runtime_set_active(sec_pmic->dev); 366 367 switch (sec_pmic->device_type) { 368 case S5M8751X: 369 ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, 370 ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); 371 break; 372 case S5M8763X: 373 ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, 374 ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); 375 break; 376 case S5M8767X: 377 ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, 378 ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); 379 break; 380 case S2MPA01: 381 ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs, 382 ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL); 383 break; 384 case S2MPS11X: 385 ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, 386 ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); 387 break; 388 case S2MPS14X: 389 ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs, 390 ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL); 391 break; 392 default: 393 /* If this happens the probe function is problem */ 394 BUG(); 395 } 396 397 if (ret) 398 goto err_mfd; 399 400 device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); 401 402 return ret; 403 404err_mfd: 405 sec_irq_exit(sec_pmic); 406err_regmap_rtc: 407 i2c_unregister_device(sec_pmic->rtc); 408 return ret; 409} 410 411static int sec_pmic_remove(struct i2c_client *i2c) 412{ 413 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); 414 415 mfd_remove_devices(sec_pmic->dev); 416 sec_irq_exit(sec_pmic); 417 i2c_unregister_device(sec_pmic->rtc); 418 return 0; 419} 420 421#ifdef CONFIG_PM_SLEEP 422static int sec_pmic_suspend(struct device *dev) 423{ 424 struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); 425 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); 426 427 if (device_may_wakeup(dev)) { 428 enable_irq_wake(sec_pmic->irq); 429 /* 430 * PMIC IRQ must be disabled during suspend for RTC alarm 431 * to work properly. 432 * When device is woken up from suspend by RTC Alarm, an 433 * interrupt occurs before resuming I2C bus controller. 434 * The interrupt is handled by regmap_irq_thread which tries 435 * to read RTC registers. This read fails (I2C is still 436 * suspended) and RTC Alarm interrupt is disabled. 437 */ 438 disable_irq(sec_pmic->irq); 439 } 440 441 return 0; 442} 443 444static int sec_pmic_resume(struct device *dev) 445{ 446 struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); 447 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); 448 449 if (device_may_wakeup(dev)) { 450 disable_irq_wake(sec_pmic->irq); 451 enable_irq(sec_pmic->irq); 452 } 453 454 return 0; 455} 456#endif /* CONFIG_PM_SLEEP */ 457 458static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); 459 460static const struct i2c_device_id sec_pmic_id[] = { 461 { "sec_pmic", 0 }, 462 { } 463}; 464MODULE_DEVICE_TABLE(i2c, sec_pmic_id); 465 466static struct i2c_driver sec_pmic_driver = { 467 .driver = { 468 .name = "sec_pmic", 469 .owner = THIS_MODULE, 470 .pm = &sec_pmic_pm_ops, 471 .of_match_table = of_match_ptr(sec_dt_match), 472 }, 473 .probe = sec_pmic_probe, 474 .remove = sec_pmic_remove, 475 .id_table = sec_pmic_id, 476}; 477 478static int __init sec_pmic_init(void) 479{ 480 return i2c_add_driver(&sec_pmic_driver); 481} 482 483subsys_initcall(sec_pmic_init); 484 485static void __exit sec_pmic_exit(void) 486{ 487 i2c_del_driver(&sec_pmic_driver); 488} 489module_exit(sec_pmic_exit); 490 491MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 492MODULE_DESCRIPTION("Core support for the S5M MFD"); 493MODULE_LICENSE("GPL");