166c9fbb9SSangbeom Kim /* 263063bfbSSangbeom Kim * sec-core.c 366c9fbb9SSangbeom Kim * 463063bfbSSangbeom Kim * Copyright (c) 2012 Samsung Electronics Co., Ltd 566c9fbb9SSangbeom Kim * http://www.samsung.com 666c9fbb9SSangbeom Kim * 766c9fbb9SSangbeom Kim * This program is free software; you can redistribute it and/or modify it 866c9fbb9SSangbeom Kim * under the terms of the GNU General Public License as published by the 966c9fbb9SSangbeom Kim * Free Software Foundation; either version 2 of the License, or (at your 1066c9fbb9SSangbeom Kim * option) any later version. 1166c9fbb9SSangbeom Kim * 1266c9fbb9SSangbeom Kim */ 1366c9fbb9SSangbeom Kim 1466c9fbb9SSangbeom Kim #include <linux/module.h> 1566c9fbb9SSangbeom Kim #include <linux/moduleparam.h> 1666c9fbb9SSangbeom Kim #include <linux/init.h> 1766c9fbb9SSangbeom Kim #include <linux/err.h> 1866c9fbb9SSangbeom Kim #include <linux/slab.h> 1966c9fbb9SSangbeom Kim #include <linux/i2c.h> 201c5a099bSSachin Kamat #include <linux/of.h> 2126aec009SAmit Daniel Kachhap #include <linux/of_irq.h> 2266c9fbb9SSangbeom Kim #include <linux/interrupt.h> 2366c9fbb9SSangbeom Kim #include <linux/pm_runtime.h> 2466c9fbb9SSangbeom Kim #include <linux/mutex.h> 2566c9fbb9SSangbeom Kim #include <linux/mfd/core.h> 2654227bcfSSangbeom Kim #include <linux/mfd/samsung/core.h> 2754227bcfSSangbeom Kim #include <linux/mfd/samsung/irq.h> 2854227bcfSSangbeom Kim #include <linux/mfd/samsung/rtc.h> 2925f311faSMark Brown #include <linux/mfd/samsung/s2mps11.h> 3025f311faSMark Brown #include <linux/mfd/samsung/s5m8763.h> 3125f311faSMark Brown #include <linux/mfd/samsung/s5m8767.h> 3266c9fbb9SSangbeom Kim #include <linux/regmap.h> 3366c9fbb9SSangbeom Kim 345ac98553SGeert Uytterhoeven static const struct mfd_cell s5m8751_devs[] = { 3566c9fbb9SSangbeom Kim { 3666c9fbb9SSangbeom Kim .name = "s5m8751-pmic", 3766c9fbb9SSangbeom Kim }, { 3866c9fbb9SSangbeom Kim .name = "s5m-charger", 3966c9fbb9SSangbeom Kim }, { 4066c9fbb9SSangbeom Kim .name = "s5m8751-codec", 4166c9fbb9SSangbeom Kim }, 4266c9fbb9SSangbeom Kim }; 4366c9fbb9SSangbeom Kim 445ac98553SGeert Uytterhoeven static const struct mfd_cell s5m8763_devs[] = { 4566c9fbb9SSangbeom Kim { 4666c9fbb9SSangbeom Kim .name = "s5m8763-pmic", 4766c9fbb9SSangbeom Kim }, { 4866c9fbb9SSangbeom Kim .name = "s5m-rtc", 4966c9fbb9SSangbeom Kim }, { 5066c9fbb9SSangbeom Kim .name = "s5m-charger", 5166c9fbb9SSangbeom Kim }, 5266c9fbb9SSangbeom Kim }; 5366c9fbb9SSangbeom Kim 545ac98553SGeert Uytterhoeven static const struct mfd_cell s5m8767_devs[] = { 5566c9fbb9SSangbeom Kim { 5666c9fbb9SSangbeom Kim .name = "s5m8767-pmic", 5766c9fbb9SSangbeom Kim }, { 5866c9fbb9SSangbeom Kim .name = "s5m-rtc", 5939fed00fSTushar Behera }, { 6039fed00fSTushar Behera .name = "s5m8767-clk", 6139fed00fSTushar Behera } 6266c9fbb9SSangbeom Kim }; 6366c9fbb9SSangbeom Kim 645ac98553SGeert Uytterhoeven static const struct mfd_cell s2mps11_devs[] = { 659b6d1343SSangbeom Kim { 669b6d1343SSangbeom Kim .name = "s2mps11-pmic", 673134bcaeSYadwinder Singh Brar }, { 683134bcaeSYadwinder Singh Brar .name = "s2mps11-clk", 693134bcaeSYadwinder Singh Brar } 709b6d1343SSangbeom Kim }; 719b6d1343SSangbeom Kim 7226aec009SAmit Daniel Kachhap #ifdef CONFIG_OF 7326aec009SAmit Daniel Kachhap static struct of_device_id sec_dt_match[] = { 7426aec009SAmit Daniel Kachhap { .compatible = "samsung,s5m8767-pmic", 7526aec009SAmit Daniel Kachhap .data = (void *)S5M8767X, 7626aec009SAmit Daniel Kachhap }, 77aa32acadSYadwinder Singh Brar { .compatible = "samsung,s2mps11-pmic", 78aa32acadSYadwinder Singh Brar .data = (void *)S2MPS11X, 79aa32acadSYadwinder Singh Brar }, 8026aec009SAmit Daniel Kachhap {}, 8126aec009SAmit Daniel Kachhap }; 8226aec009SAmit Daniel Kachhap #endif 8326aec009SAmit Daniel Kachhap 846b845ba9SMark Brown static bool s2mps11_volatile(struct device *dev, unsigned int reg) 856b845ba9SMark Brown { 866b845ba9SMark Brown switch (reg) { 876b845ba9SMark Brown case S2MPS11_REG_INT1M: 886b845ba9SMark Brown case S2MPS11_REG_INT2M: 896b845ba9SMark Brown case S2MPS11_REG_INT3M: 906b845ba9SMark Brown return false; 916b845ba9SMark Brown default: 926b845ba9SMark Brown return true; 936b845ba9SMark Brown } 946b845ba9SMark Brown } 956b845ba9SMark Brown 966b845ba9SMark Brown static bool s5m8763_volatile(struct device *dev, unsigned int reg) 976b845ba9SMark Brown { 986b845ba9SMark Brown switch (reg) { 996b845ba9SMark Brown case S5M8763_REG_IRQM1: 1006b845ba9SMark Brown case S5M8763_REG_IRQM2: 1016b845ba9SMark Brown case S5M8763_REG_IRQM3: 1026b845ba9SMark Brown case S5M8763_REG_IRQM4: 1036b845ba9SMark Brown return false; 1046b845ba9SMark Brown default: 1056b845ba9SMark Brown return true; 1066b845ba9SMark Brown } 1076b845ba9SMark Brown } 1086b845ba9SMark Brown 109a30fffb0SKrzysztof Kozlowski static const struct regmap_config sec_regmap_config = { 11066c9fbb9SSangbeom Kim .reg_bits = 8, 11166c9fbb9SSangbeom Kim .val_bits = 8, 11266c9fbb9SSangbeom Kim }; 11366c9fbb9SSangbeom Kim 114a30fffb0SKrzysztof Kozlowski static const struct regmap_config s2mps11_regmap_config = { 11525f311faSMark Brown .reg_bits = 8, 11625f311faSMark Brown .val_bits = 8, 11725f311faSMark Brown 11825f311faSMark Brown .max_register = S2MPS11_REG_L38CTRL, 1196b845ba9SMark Brown .volatile_reg = s2mps11_volatile, 1206b845ba9SMark Brown .cache_type = REGCACHE_FLAT, 12125f311faSMark Brown }; 12225f311faSMark Brown 123a30fffb0SKrzysztof Kozlowski static const struct regmap_config s5m8763_regmap_config = { 12425f311faSMark Brown .reg_bits = 8, 12525f311faSMark Brown .val_bits = 8, 12625f311faSMark Brown 12725f311faSMark Brown .max_register = S5M8763_REG_LBCNFG2, 1286b845ba9SMark Brown .volatile_reg = s5m8763_volatile, 1296b845ba9SMark Brown .cache_type = REGCACHE_FLAT, 13025f311faSMark Brown }; 13125f311faSMark Brown 132a30fffb0SKrzysztof Kozlowski static const struct regmap_config s5m8767_regmap_config = { 13325f311faSMark Brown .reg_bits = 8, 13425f311faSMark Brown .val_bits = 8, 13525f311faSMark Brown 13625f311faSMark Brown .max_register = S5M8767_REG_LDO28CTRL, 1376b845ba9SMark Brown .volatile_reg = s2mps11_volatile, 1386b845ba9SMark Brown .cache_type = REGCACHE_FLAT, 13925f311faSMark Brown }; 14026aec009SAmit Daniel Kachhap 1413e1e4a5fSKrzysztof Kozlowski static const struct regmap_config sec_rtc_regmap_config = { 1423e1e4a5fSKrzysztof Kozlowski .reg_bits = 8, 1433e1e4a5fSKrzysztof Kozlowski .val_bits = 8, 144b07e2b70SKrzysztof Kozlowski 145b07e2b70SKrzysztof Kozlowski .max_register = SEC_RTC_REG_MAX, 1463e1e4a5fSKrzysztof Kozlowski }; 1473e1e4a5fSKrzysztof Kozlowski 14826aec009SAmit Daniel Kachhap #ifdef CONFIG_OF 14926aec009SAmit Daniel Kachhap /* 15026aec009SAmit Daniel Kachhap * Only the common platform data elements for s5m8767 are parsed here from the 15126aec009SAmit Daniel Kachhap * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and 15226aec009SAmit Daniel Kachhap * others have to parse their own platform data elements from device tree. 15326aec009SAmit Daniel Kachhap * 15426aec009SAmit Daniel Kachhap * The s5m8767 platform data structure is instantiated here and the drivers for 15526aec009SAmit Daniel Kachhap * the sub-modules need not instantiate another instance while parsing their 15626aec009SAmit Daniel Kachhap * platform data. 15726aec009SAmit Daniel Kachhap */ 15826aec009SAmit Daniel Kachhap static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( 15926aec009SAmit Daniel Kachhap struct device *dev) 16026aec009SAmit Daniel Kachhap { 16126aec009SAmit Daniel Kachhap struct sec_platform_data *pd; 16226aec009SAmit Daniel Kachhap 16326aec009SAmit Daniel Kachhap pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); 16426aec009SAmit Daniel Kachhap if (!pd) { 16526aec009SAmit Daniel Kachhap dev_err(dev, "could not allocate memory for pdata\n"); 16626aec009SAmit Daniel Kachhap return ERR_PTR(-ENOMEM); 16726aec009SAmit Daniel Kachhap } 16826aec009SAmit Daniel Kachhap 16926aec009SAmit Daniel Kachhap /* 17026aec009SAmit Daniel Kachhap * ToDo: the 'wakeup' member in the platform data is more of a linux 17126aec009SAmit Daniel Kachhap * specfic information. Hence, there is no binding for that yet and 17226aec009SAmit Daniel Kachhap * not parsed here. 17326aec009SAmit Daniel Kachhap */ 17426aec009SAmit Daniel Kachhap 17526aec009SAmit Daniel Kachhap return pd; 17626aec009SAmit Daniel Kachhap } 17726aec009SAmit Daniel Kachhap #else 178197bf856SMark Brown static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( 17926aec009SAmit Daniel Kachhap struct device *dev) 18026aec009SAmit Daniel Kachhap { 181005718c0SWei Yongjun return NULL; 18226aec009SAmit Daniel Kachhap } 18326aec009SAmit Daniel Kachhap #endif 18426aec009SAmit Daniel Kachhap 18526aec009SAmit Daniel Kachhap static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, 18626aec009SAmit Daniel Kachhap const struct i2c_device_id *id) 18726aec009SAmit Daniel Kachhap { 18826aec009SAmit Daniel Kachhap #ifdef CONFIG_OF 18926aec009SAmit Daniel Kachhap if (i2c->dev.of_node) { 19026aec009SAmit Daniel Kachhap const struct of_device_id *match; 19126aec009SAmit Daniel Kachhap match = of_match_node(sec_dt_match, i2c->dev.of_node); 19226aec009SAmit Daniel Kachhap return (int)match->data; 19326aec009SAmit Daniel Kachhap } 19426aec009SAmit Daniel Kachhap #endif 19526aec009SAmit Daniel Kachhap return (int)id->driver_data; 19626aec009SAmit Daniel Kachhap } 19726aec009SAmit Daniel Kachhap 19863063bfbSSangbeom Kim static int sec_pmic_probe(struct i2c_client *i2c, 19966c9fbb9SSangbeom Kim const struct i2c_device_id *id) 20066c9fbb9SSangbeom Kim { 201334a41ceSJingoo Han struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); 2023e5a45f7SKrzysztof Kozlowski const struct regmap_config *regmap, *regmap_rtc; 20363063bfbSSangbeom Kim struct sec_pmic_dev *sec_pmic; 20466c9fbb9SSangbeom Kim int ret; 20566c9fbb9SSangbeom Kim 20663063bfbSSangbeom Kim sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev), 20766c9fbb9SSangbeom Kim GFP_KERNEL); 20863063bfbSSangbeom Kim if (sec_pmic == NULL) 20966c9fbb9SSangbeom Kim return -ENOMEM; 21066c9fbb9SSangbeom Kim 21163063bfbSSangbeom Kim i2c_set_clientdata(i2c, sec_pmic); 21263063bfbSSangbeom Kim sec_pmic->dev = &i2c->dev; 21363063bfbSSangbeom Kim sec_pmic->i2c = i2c; 21463063bfbSSangbeom Kim sec_pmic->irq = i2c->irq; 21526aec009SAmit Daniel Kachhap sec_pmic->type = sec_i2c_get_driver_data(i2c, id); 21666c9fbb9SSangbeom Kim 21726aec009SAmit Daniel Kachhap if (sec_pmic->dev->of_node) { 21826aec009SAmit Daniel Kachhap pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); 21926aec009SAmit Daniel Kachhap if (IS_ERR(pdata)) { 22026aec009SAmit Daniel Kachhap ret = PTR_ERR(pdata); 22126aec009SAmit Daniel Kachhap return ret; 22226aec009SAmit Daniel Kachhap } 22326aec009SAmit Daniel Kachhap pdata->device_type = sec_pmic->type; 22426aec009SAmit Daniel Kachhap } 22566c9fbb9SSangbeom Kim if (pdata) { 22663063bfbSSangbeom Kim sec_pmic->device_type = pdata->device_type; 22763063bfbSSangbeom Kim sec_pmic->ono = pdata->ono; 22863063bfbSSangbeom Kim sec_pmic->irq_base = pdata->irq_base; 22963063bfbSSangbeom Kim sec_pmic->wakeup = pdata->wakeup; 23026aec009SAmit Daniel Kachhap sec_pmic->pdata = pdata; 23166c9fbb9SSangbeom Kim } 23266c9fbb9SSangbeom Kim 23325f311faSMark Brown switch (sec_pmic->device_type) { 23425f311faSMark Brown case S2MPS11X: 23525f311faSMark Brown regmap = &s2mps11_regmap_config; 2363e5a45f7SKrzysztof Kozlowski /* 2373e5a45f7SKrzysztof Kozlowski * The rtc-s5m driver does not support S2MPS11 and there 2383e5a45f7SKrzysztof Kozlowski * is no mfd_cell for S2MPS11 RTC device. 2393e5a45f7SKrzysztof Kozlowski * However we must pass something to devm_regmap_init_i2c() 2403e5a45f7SKrzysztof Kozlowski * so use S5M-like regmap config even though it wouldn't work. 2413e5a45f7SKrzysztof Kozlowski */ 2423e5a45f7SKrzysztof Kozlowski regmap_rtc = &sec_rtc_regmap_config; 24325f311faSMark Brown break; 24425f311faSMark Brown case S5M8763X: 24525f311faSMark Brown regmap = &s5m8763_regmap_config; 2463e5a45f7SKrzysztof Kozlowski regmap_rtc = &sec_rtc_regmap_config; 24725f311faSMark Brown break; 24825f311faSMark Brown case S5M8767X: 24925f311faSMark Brown regmap = &s5m8767_regmap_config; 2503e5a45f7SKrzysztof Kozlowski regmap_rtc = &sec_rtc_regmap_config; 25125f311faSMark Brown break; 25225f311faSMark Brown default: 25325f311faSMark Brown regmap = &sec_regmap_config; 2543e5a45f7SKrzysztof Kozlowski regmap_rtc = &sec_rtc_regmap_config; 25525f311faSMark Brown break; 25625f311faSMark Brown } 25725f311faSMark Brown 2583e1e4a5fSKrzysztof Kozlowski sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap); 2593e1e4a5fSKrzysztof Kozlowski if (IS_ERR(sec_pmic->regmap_pmic)) { 2603e1e4a5fSKrzysztof Kozlowski ret = PTR_ERR(sec_pmic->regmap_pmic); 26166c9fbb9SSangbeom Kim dev_err(&i2c->dev, "Failed to allocate register map: %d\n", 26266c9fbb9SSangbeom Kim ret); 26366c9fbb9SSangbeom Kim return ret; 26466c9fbb9SSangbeom Kim } 26566c9fbb9SSangbeom Kim 26663063bfbSSangbeom Kim sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); 26763063bfbSSangbeom Kim i2c_set_clientdata(sec_pmic->rtc, sec_pmic); 26866c9fbb9SSangbeom Kim 2693e5a45f7SKrzysztof Kozlowski sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc); 2703e1e4a5fSKrzysztof Kozlowski if (IS_ERR(sec_pmic->regmap_rtc)) { 2713e1e4a5fSKrzysztof Kozlowski ret = PTR_ERR(sec_pmic->regmap_rtc); 2723e1e4a5fSKrzysztof Kozlowski dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", 2733e1e4a5fSKrzysztof Kozlowski ret); 2743e1e4a5fSKrzysztof Kozlowski return ret; 2753e1e4a5fSKrzysztof Kozlowski } 2763e1e4a5fSKrzysztof Kozlowski 27766c9fbb9SSangbeom Kim if (pdata && pdata->cfg_pmic_irq) 27866c9fbb9SSangbeom Kim pdata->cfg_pmic_irq(); 27966c9fbb9SSangbeom Kim 28063063bfbSSangbeom Kim sec_irq_init(sec_pmic); 28166c9fbb9SSangbeom Kim 28263063bfbSSangbeom Kim pm_runtime_set_active(sec_pmic->dev); 28366c9fbb9SSangbeom Kim 28463063bfbSSangbeom Kim switch (sec_pmic->device_type) { 28566c9fbb9SSangbeom Kim case S5M8751X: 28663063bfbSSangbeom Kim ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs, 2870848c94fSMark Brown ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL); 28866c9fbb9SSangbeom Kim break; 28966c9fbb9SSangbeom Kim case S5M8763X: 29063063bfbSSangbeom Kim ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs, 2910848c94fSMark Brown ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL); 29266c9fbb9SSangbeom Kim break; 29366c9fbb9SSangbeom Kim case S5M8767X: 29463063bfbSSangbeom Kim ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, 2950848c94fSMark Brown ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); 29666c9fbb9SSangbeom Kim break; 2979b6d1343SSangbeom Kim case S2MPS11X: 2989b6d1343SSangbeom Kim ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, 2990848c94fSMark Brown ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); 3009b6d1343SSangbeom Kim break; 30166c9fbb9SSangbeom Kim default: 30266c9fbb9SSangbeom Kim /* If this happens the probe function is problem */ 30366c9fbb9SSangbeom Kim BUG(); 30466c9fbb9SSangbeom Kim } 30566c9fbb9SSangbeom Kim 30615447a46SLeon Romanovsky if (ret) 30766c9fbb9SSangbeom Kim goto err; 30866c9fbb9SSangbeom Kim 309f6d6daafSKrzysztof Kozlowski device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup); 310f6d6daafSKrzysztof Kozlowski 31166c9fbb9SSangbeom Kim return ret; 31266c9fbb9SSangbeom Kim 31366c9fbb9SSangbeom Kim err: 31463063bfbSSangbeom Kim sec_irq_exit(sec_pmic); 31563063bfbSSangbeom Kim i2c_unregister_device(sec_pmic->rtc); 31666c9fbb9SSangbeom Kim return ret; 31766c9fbb9SSangbeom Kim } 31866c9fbb9SSangbeom Kim 31963063bfbSSangbeom Kim static int sec_pmic_remove(struct i2c_client *i2c) 32066c9fbb9SSangbeom Kim { 32163063bfbSSangbeom Kim struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); 32266c9fbb9SSangbeom Kim 32363063bfbSSangbeom Kim mfd_remove_devices(sec_pmic->dev); 32463063bfbSSangbeom Kim sec_irq_exit(sec_pmic); 32563063bfbSSangbeom Kim i2c_unregister_device(sec_pmic->rtc); 32666c9fbb9SSangbeom Kim return 0; 32766c9fbb9SSangbeom Kim } 32866c9fbb9SSangbeom Kim 3298321bbf8SGeert Uytterhoeven #ifdef CONFIG_PM_SLEEP 330f6d6daafSKrzysztof Kozlowski static int sec_pmic_suspend(struct device *dev) 331f6d6daafSKrzysztof Kozlowski { 332f6d6daafSKrzysztof Kozlowski struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); 333f6d6daafSKrzysztof Kozlowski struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); 334f6d6daafSKrzysztof Kozlowski 335f6d6daafSKrzysztof Kozlowski if (device_may_wakeup(dev)) { 336f6d6daafSKrzysztof Kozlowski enable_irq_wake(sec_pmic->irq); 337f6d6daafSKrzysztof Kozlowski /* 338f6d6daafSKrzysztof Kozlowski * PMIC IRQ must be disabled during suspend for RTC alarm 339f6d6daafSKrzysztof Kozlowski * to work properly. 340f6d6daafSKrzysztof Kozlowski * When device is woken up from suspend by RTC Alarm, an 341f6d6daafSKrzysztof Kozlowski * interrupt occurs before resuming I2C bus controller. 342f6d6daafSKrzysztof Kozlowski * The interrupt is handled by regmap_irq_thread which tries 343f6d6daafSKrzysztof Kozlowski * to read RTC registers. This read fails (I2C is still 344f6d6daafSKrzysztof Kozlowski * suspended) and RTC Alarm interrupt is disabled. 345f6d6daafSKrzysztof Kozlowski */ 346f6d6daafSKrzysztof Kozlowski disable_irq(sec_pmic->irq); 347f6d6daafSKrzysztof Kozlowski } 348f6d6daafSKrzysztof Kozlowski 349f6d6daafSKrzysztof Kozlowski return 0; 350f6d6daafSKrzysztof Kozlowski } 351f6d6daafSKrzysztof Kozlowski 352f6d6daafSKrzysztof Kozlowski static int sec_pmic_resume(struct device *dev) 353f6d6daafSKrzysztof Kozlowski { 354f6d6daafSKrzysztof Kozlowski struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); 355f6d6daafSKrzysztof Kozlowski struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c); 356f6d6daafSKrzysztof Kozlowski 357f6d6daafSKrzysztof Kozlowski if (device_may_wakeup(dev)) { 358f6d6daafSKrzysztof Kozlowski disable_irq_wake(sec_pmic->irq); 359f6d6daafSKrzysztof Kozlowski enable_irq(sec_pmic->irq); 360f6d6daafSKrzysztof Kozlowski } 361f6d6daafSKrzysztof Kozlowski 362f6d6daafSKrzysztof Kozlowski return 0; 363f6d6daafSKrzysztof Kozlowski } 3648321bbf8SGeert Uytterhoeven #endif /* CONFIG_PM_SLEEP */ 365f6d6daafSKrzysztof Kozlowski 366f6d6daafSKrzysztof Kozlowski static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume); 367f6d6daafSKrzysztof Kozlowski 36863063bfbSSangbeom Kim static const struct i2c_device_id sec_pmic_id[] = { 36963063bfbSSangbeom Kim { "sec_pmic", 0 }, 37066c9fbb9SSangbeom Kim { } 37166c9fbb9SSangbeom Kim }; 37263063bfbSSangbeom Kim MODULE_DEVICE_TABLE(i2c, sec_pmic_id); 37366c9fbb9SSangbeom Kim 37463063bfbSSangbeom Kim static struct i2c_driver sec_pmic_driver = { 37566c9fbb9SSangbeom Kim .driver = { 37663063bfbSSangbeom Kim .name = "sec_pmic", 37766c9fbb9SSangbeom Kim .owner = THIS_MODULE, 378f6d6daafSKrzysztof Kozlowski .pm = &sec_pmic_pm_ops, 37926aec009SAmit Daniel Kachhap .of_match_table = of_match_ptr(sec_dt_match), 38066c9fbb9SSangbeom Kim }, 38163063bfbSSangbeom Kim .probe = sec_pmic_probe, 38263063bfbSSangbeom Kim .remove = sec_pmic_remove, 38363063bfbSSangbeom Kim .id_table = sec_pmic_id, 38466c9fbb9SSangbeom Kim }; 38566c9fbb9SSangbeom Kim 38663063bfbSSangbeom Kim static int __init sec_pmic_init(void) 38766c9fbb9SSangbeom Kim { 38863063bfbSSangbeom Kim return i2c_add_driver(&sec_pmic_driver); 38966c9fbb9SSangbeom Kim } 39066c9fbb9SSangbeom Kim 39163063bfbSSangbeom Kim subsys_initcall(sec_pmic_init); 39266c9fbb9SSangbeom Kim 39363063bfbSSangbeom Kim static void __exit sec_pmic_exit(void) 39466c9fbb9SSangbeom Kim { 39563063bfbSSangbeom Kim i2c_del_driver(&sec_pmic_driver); 39666c9fbb9SSangbeom Kim } 39763063bfbSSangbeom Kim module_exit(sec_pmic_exit); 39866c9fbb9SSangbeom Kim 39966c9fbb9SSangbeom Kim MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>"); 40066c9fbb9SSangbeom Kim MODULE_DESCRIPTION("Core support for the S5M MFD"); 40166c9fbb9SSangbeom Kim MODULE_LICENSE("GPL"); 402