blob: 2621328851ba1e18e8c52a45b7f2fe3969f1195b [file] [log] [blame]
Sangbeom Kim0f5f7072011-12-23 17:28:08 +09001/*
Sangbeom Kim63063bf2012-07-11 21:06:55 +09002 * sec-core.c
Sangbeom Kim0f5f7072011-12-23 17:28:08 +09003 *
Sangbeom Kim63063bf2012-07-11 21:06:55 +09004 * Copyright (c) 2012 Samsung Electronics Co., Ltd
Sangbeom Kim0f5f7072011-12-23 17:28:08 +09005 * 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>
Sachin Kamat1c5a0992013-10-16 14:26:52 +053020#include <linux/of.h>
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -080021#include <linux/of_irq.h>
Sangbeom Kim0f5f7072011-12-23 17:28:08 +090022#include <linux/interrupt.h>
23#include <linux/pm_runtime.h>
24#include <linux/mutex.h>
25#include <linux/mfd/core.h>
Sangbeom Kim54227bc2012-07-11 21:07:16 +090026#include <linux/mfd/samsung/core.h>
27#include <linux/mfd/samsung/irq.h>
Sachin Kamatce249912014-03-14 17:21:57 +053028#include <linux/mfd/samsung/s2mpa01.h>
Mark Brown25f311f2013-07-01 23:02:19 +010029#include <linux/mfd/samsung/s2mps11.h>
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +010030#include <linux/mfd/samsung/s2mps14.h>
Chanwoo Choi00e25732014-06-25 16:14:45 +090031#include <linux/mfd/samsung/s2mpu02.h>
Mark Brown25f311f2013-07-01 23:02:19 +010032#include <linux/mfd/samsung/s5m8763.h>
33#include <linux/mfd/samsung/s5m8767.h>
Sangbeom Kim0f5f7072011-12-23 17:28:08 +090034#include <linux/regmap.h>
35
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +010036static const struct mfd_cell s5m8751_devs[] = {
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +090037 {
38 .name = "s5m8751-pmic",
39 }, {
40 .name = "s5m-charger",
41 }, {
42 .name = "s5m8751-codec",
43 },
44};
45
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +010046static const struct mfd_cell s5m8763_devs[] = {
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +090047 {
48 .name = "s5m8763-pmic",
49 }, {
50 .name = "s5m-rtc",
51 }, {
52 .name = "s5m-charger",
53 },
54};
55
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +010056static const struct mfd_cell s5m8767_devs[] = {
Sangbeom Kim0f5f7072011-12-23 17:28:08 +090057 {
58 .name = "s5m8767-pmic",
59 }, {
60 .name = "s5m-rtc",
Tushar Behera39fed002013-12-26 15:49:00 +053061 }, {
62 .name = "s5m8767-clk",
Krzysztof Kozlowski53c31b32014-03-17 10:19:17 +010063 .of_compatible = "samsung,s5m8767-clk",
Tushar Behera39fed002013-12-26 15:49:00 +053064 }
Sangbeom Kim0f5f7072011-12-23 17:28:08 +090065};
66
Geert Uytterhoeven5ac98552013-11-18 14:33:06 +010067static const struct mfd_cell s2mps11_devs[] = {
Sangbeom Kim9b6d1342012-07-11 21:07:55 +090068 {
69 .name = "s2mps11-pmic",
Yadwinder Singh Brar3134bca2013-07-07 17:14:21 +053070 }, {
71 .name = "s2mps11-clk",
Krzysztof Kozlowski53c31b32014-03-17 10:19:17 +010072 .of_compatible = "samsung,s2mps11-clk",
Yadwinder Singh Brar3134bca2013-07-07 17:14:21 +053073 }
Sangbeom Kim9b6d1342012-07-11 21:07:55 +090074};
75
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +010076static const struct mfd_cell s2mps14_devs[] = {
77 {
78 .name = "s2mps14-pmic",
79 }, {
80 .name = "s2mps14-rtc",
81 }, {
82 .name = "s2mps14-clk",
Krzysztof Kozlowski53c31b32014-03-17 10:19:17 +010083 .of_compatible = "samsung,s2mps14-clk",
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +010084 }
85};
86
Sachin Kamatce249912014-03-14 17:21:57 +053087static const struct mfd_cell s2mpa01_devs[] = {
88 {
89 .name = "s2mpa01-pmic",
90 },
91};
92
Chanwoo Choi54e88272014-06-25 16:14:44 +090093static const struct mfd_cell s2mpu02_devs[] = {
94 { .name = "s2mpu02-pmic", },
95 { .name = "s2mpu02-rtc", },
96 {
97 .name = "s2mpu02-clk",
98 .of_compatible = "samsung,s2mpu02-clk",
99 }
100};
101
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800102#ifdef CONFIG_OF
Krzysztof Kozlowskidf20b7c2014-05-13 12:58:46 +0200103static const struct of_device_id sec_dt_match[] = {
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800104 { .compatible = "samsung,s5m8767-pmic",
105 .data = (void *)S5M8767X,
Sachin Kamatce249912014-03-14 17:21:57 +0530106 }, {
107 .compatible = "samsung,s2mps11-pmic",
Yadwinder Singh Braraa32aca2013-06-29 18:21:20 +0530108 .data = (void *)S2MPS11X,
Sachin Kamatce249912014-03-14 17:21:57 +0530109 }, {
110 .compatible = "samsung,s2mps14-pmic",
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +0100111 .data = (void *)S2MPS14X,
Sachin Kamatce249912014-03-14 17:21:57 +0530112 }, {
113 .compatible = "samsung,s2mpa01-pmic",
114 .data = (void *)S2MPA01,
115 }, {
Chanwoo Choi54e88272014-06-25 16:14:44 +0900116 .compatible = "samsung,s2mpu02-pmic",
117 .data = (void *)S2MPU02,
118 }, {
Sachin Kamatce249912014-03-14 17:21:57 +0530119 /* Sentinel */
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +0100120 },
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800121};
122#endif
123
Sachin Kamatce249912014-03-14 17:21:57 +0530124static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
125{
126 switch (reg) {
127 case S2MPA01_REG_INT1M:
128 case S2MPA01_REG_INT2M:
129 case S2MPA01_REG_INT3M:
130 return false;
131 default:
132 return true;
133 }
134}
135
Mark Brown6b845ba2013-07-02 18:51:16 +0100136static bool s2mps11_volatile(struct device *dev, unsigned int reg)
137{
138 switch (reg) {
139 case S2MPS11_REG_INT1M:
140 case S2MPS11_REG_INT2M:
141 case S2MPS11_REG_INT3M:
142 return false;
143 default:
144 return true;
145 }
146}
147
Chanwoo Choi00e25732014-06-25 16:14:45 +0900148static bool s2mpu02_volatile(struct device *dev, unsigned int reg)
149{
150 switch (reg) {
151 case S2MPU02_REG_INT1M:
152 case S2MPU02_REG_INT2M:
153 case S2MPU02_REG_INT3M:
154 return false;
155 default:
156 return true;
157 }
158}
159
Mark Brown6b845ba2013-07-02 18:51:16 +0100160static bool s5m8763_volatile(struct device *dev, unsigned int reg)
161{
162 switch (reg) {
163 case S5M8763_REG_IRQM1:
164 case S5M8763_REG_IRQM2:
165 case S5M8763_REG_IRQM3:
166 case S5M8763_REG_IRQM4:
167 return false;
168 default:
169 return true;
170 }
171}
172
Krzysztof Kozlowskia30fffb2013-11-28 09:09:43 +0100173static const struct regmap_config sec_regmap_config = {
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900174 .reg_bits = 8,
175 .val_bits = 8,
176};
177
Sachin Kamatce249912014-03-14 17:21:57 +0530178static const struct regmap_config s2mpa01_regmap_config = {
179 .reg_bits = 8,
180 .val_bits = 8,
181
182 .max_register = S2MPA01_REG_LDO_OVCB4,
183 .volatile_reg = s2mpa01_volatile,
184 .cache_type = REGCACHE_FLAT,
185};
186
Krzysztof Kozlowskia30fffb2013-11-28 09:09:43 +0100187static const struct regmap_config s2mps11_regmap_config = {
Mark Brown25f311f2013-07-01 23:02:19 +0100188 .reg_bits = 8,
189 .val_bits = 8,
190
191 .max_register = S2MPS11_REG_L38CTRL,
Mark Brown6b845ba2013-07-02 18:51:16 +0100192 .volatile_reg = s2mps11_volatile,
193 .cache_type = REGCACHE_FLAT,
Mark Brown25f311f2013-07-01 23:02:19 +0100194};
195
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +0100196static const struct regmap_config s2mps14_regmap_config = {
197 .reg_bits = 8,
198 .val_bits = 8,
199
200 .max_register = S2MPS14_REG_LDODSCH3,
201 .volatile_reg = s2mps11_volatile,
202 .cache_type = REGCACHE_FLAT,
203};
204
Chanwoo Choi00e25732014-06-25 16:14:45 +0900205static const struct regmap_config s2mpu02_regmap_config = {
206 .reg_bits = 8,
207 .val_bits = 8,
208
209 .max_register = S2MPU02_REG_DVSDATA,
210 .volatile_reg = s2mpu02_volatile,
211 .cache_type = REGCACHE_FLAT,
212};
213
Krzysztof Kozlowskia30fffb2013-11-28 09:09:43 +0100214static const struct regmap_config s5m8763_regmap_config = {
Mark Brown25f311f2013-07-01 23:02:19 +0100215 .reg_bits = 8,
216 .val_bits = 8,
217
218 .max_register = S5M8763_REG_LBCNFG2,
Mark Brown6b845ba2013-07-02 18:51:16 +0100219 .volatile_reg = s5m8763_volatile,
220 .cache_type = REGCACHE_FLAT,
Mark Brown25f311f2013-07-01 23:02:19 +0100221};
222
Krzysztof Kozlowskia30fffb2013-11-28 09:09:43 +0100223static const struct regmap_config s5m8767_regmap_config = {
Mark Brown25f311f2013-07-01 23:02:19 +0100224 .reg_bits = 8,
225 .val_bits = 8,
226
227 .max_register = S5M8767_REG_LDO28CTRL,
Mark Brown6b845ba2013-07-02 18:51:16 +0100228 .volatile_reg = s2mps11_volatile,
229 .cache_type = REGCACHE_FLAT,
Mark Brown25f311f2013-07-01 23:02:19 +0100230};
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800231
232#ifdef CONFIG_OF
233/*
234 * Only the common platform data elements for s5m8767 are parsed here from the
235 * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and
236 * others have to parse their own platform data elements from device tree.
237 *
238 * The s5m8767 platform data structure is instantiated here and the drivers for
239 * the sub-modules need not instantiate another instance while parsing their
240 * platform data.
241 */
242static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
243 struct device *dev)
244{
245 struct sec_platform_data *pd;
246
247 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
248 if (!pd) {
249 dev_err(dev, "could not allocate memory for pdata\n");
250 return ERR_PTR(-ENOMEM);
251 }
252
253 /*
254 * ToDo: the 'wakeup' member in the platform data is more of a linux
255 * specfic information. Hence, there is no binding for that yet and
256 * not parsed here.
257 */
258
259 return pd;
260}
261#else
Mark Brown197bf852013-02-04 18:31:25 +0000262static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800263 struct device *dev)
264{
Wei Yongjun005718c2013-12-07 14:02:15 +0800265 return NULL;
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800266}
267#endif
268
Pankaj Dubey8f695de2014-03-13 11:14:07 +0900269static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c,
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800270 const struct i2c_device_id *id)
271{
272#ifdef CONFIG_OF
273 if (i2c->dev.of_node) {
274 const struct of_device_id *match;
275 match = of_match_node(sec_dt_match, i2c->dev.of_node);
Pankaj Dubey8f695de2014-03-13 11:14:07 +0900276 return (unsigned long)match->data;
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800277 }
278#endif
Pankaj Dubey8f695de2014-03-13 11:14:07 +0900279 return id->driver_data;
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800280}
281
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900282static int sec_pmic_probe(struct i2c_client *i2c,
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900283 const struct i2c_device_id *id)
284{
Jingoo Han334a41ce2013-07-30 17:10:05 +0900285 struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
Krzysztof Kozlowskie349c912014-04-14 09:40:45 +0200286 const struct regmap_config *regmap;
Chanwoo Choi54e88272014-06-25 16:14:44 +0900287 const struct mfd_cell *sec_devs;
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900288 struct sec_pmic_dev *sec_pmic;
Krzysztof Kozlowski9549b5f2014-04-23 16:13:05 +0200289 unsigned long device_type;
Chanwoo Choi54e88272014-06-25 16:14:44 +0900290 int ret, num_sec_devs;
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900291
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900292 sec_pmic = devm_kzalloc(&i2c->dev, sizeof(struct sec_pmic_dev),
Sangbeom Kim621210e2012-01-20 16:09:11 +0900293 GFP_KERNEL);
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900294 if (sec_pmic == NULL)
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900295 return -ENOMEM;
296
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900297 i2c_set_clientdata(i2c, sec_pmic);
298 sec_pmic->dev = &i2c->dev;
299 sec_pmic->i2c = i2c;
300 sec_pmic->irq = i2c->irq;
Krzysztof Kozlowski9549b5f2014-04-23 16:13:05 +0200301 device_type = sec_i2c_get_driver_data(i2c, id);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900302
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800303 if (sec_pmic->dev->of_node) {
304 pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev);
305 if (IS_ERR(pdata)) {
306 ret = PTR_ERR(pdata);
307 return ret;
308 }
Krzysztof Kozlowski9549b5f2014-04-23 16:13:05 +0200309 pdata->device_type = device_type;
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800310 }
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900311 if (pdata) {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900312 sec_pmic->device_type = pdata->device_type;
313 sec_pmic->ono = pdata->ono;
314 sec_pmic->irq_base = pdata->irq_base;
315 sec_pmic->wakeup = pdata->wakeup;
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800316 sec_pmic->pdata = pdata;
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900317 }
318
Mark Brown25f311f2013-07-01 23:02:19 +0100319 switch (sec_pmic->device_type) {
Sachin Kamatce249912014-03-14 17:21:57 +0530320 case S2MPA01:
321 regmap = &s2mpa01_regmap_config;
322 break;
Mark Brown25f311f2013-07-01 23:02:19 +0100323 case S2MPS11X:
324 regmap = &s2mps11_regmap_config;
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +0100325 break;
326 case S2MPS14X:
327 regmap = &s2mps14_regmap_config;
Mark Brown25f311f2013-07-01 23:02:19 +0100328 break;
329 case S5M8763X:
330 regmap = &s5m8763_regmap_config;
331 break;
332 case S5M8767X:
333 regmap = &s5m8767_regmap_config;
334 break;
Chanwoo Choi00e25732014-06-25 16:14:45 +0900335 case S2MPU02:
336 regmap = &s2mpu02_regmap_config;
337 break;
Mark Brown25f311f2013-07-01 23:02:19 +0100338 default:
339 regmap = &sec_regmap_config;
340 break;
341 }
342
Krzysztof Kozlowski3e1e4a52013-12-12 17:12:31 -0800343 sec_pmic->regmap_pmic = devm_regmap_init_i2c(i2c, regmap);
344 if (IS_ERR(sec_pmic->regmap_pmic)) {
345 ret = PTR_ERR(sec_pmic->regmap_pmic);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900346 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
Axel Lin61a2af32012-02-28 14:23:55 +0800347 ret);
Axel Lin1092e1c2012-04-25 10:03:44 +0800348 return ret;
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900349 }
350
Jonghwan Choic3ebb302012-01-16 09:08:42 +0900351 if (pdata && pdata->cfg_pmic_irq)
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900352 pdata->cfg_pmic_irq();
353
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900354 sec_irq_init(sec_pmic);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900355
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900356 pm_runtime_set_active(sec_pmic->dev);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900357
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900358 switch (sec_pmic->device_type) {
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +0900359 case S5M8751X:
Chanwoo Choi54e88272014-06-25 16:14:44 +0900360 sec_devs = s5m8751_devs;
361 num_sec_devs = ARRAY_SIZE(s5m8751_devs);
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +0900362 break;
363 case S5M8763X:
Chanwoo Choi54e88272014-06-25 16:14:44 +0900364 sec_devs = s5m8763_devs;
365 num_sec_devs = ARRAY_SIZE(s5m8763_devs);
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +0900366 break;
367 case S5M8767X:
Chanwoo Choi54e88272014-06-25 16:14:44 +0900368 sec_devs = s5m8767_devs;
369 num_sec_devs = ARRAY_SIZE(s5m8767_devs);
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +0900370 break;
Sachin Kamatce249912014-03-14 17:21:57 +0530371 case S2MPA01:
Chanwoo Choi54e88272014-06-25 16:14:44 +0900372 sec_devs = s2mpa01_devs;
373 num_sec_devs = ARRAY_SIZE(s2mpa01_devs);
Sachin Kamatce249912014-03-14 17:21:57 +0530374 break;
Sangbeom Kim9b6d1342012-07-11 21:07:55 +0900375 case S2MPS11X:
Chanwoo Choi54e88272014-06-25 16:14:44 +0900376 sec_devs = s2mps11_devs;
377 num_sec_devs = ARRAY_SIZE(s2mps11_devs);
Sangbeom Kim9b6d1342012-07-11 21:07:55 +0900378 break;
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +0100379 case S2MPS14X:
Chanwoo Choi54e88272014-06-25 16:14:44 +0900380 sec_devs = s2mps14_devs;
381 num_sec_devs = ARRAY_SIZE(s2mps14_devs);
382 break;
383 case S2MPU02:
384 sec_devs = s2mpu02_devs;
385 num_sec_devs = ARRAY_SIZE(s2mpu02_devs);
Krzysztof Kozlowskidc691962014-02-28 11:41:44 +0100386 break;
Sangbeom Kim88a1cfd2012-01-20 16:09:12 +0900387 default:
388 /* If this happens the probe function is problem */
389 BUG();
390 }
Chanwoo Choi54e88272014-06-25 16:14:44 +0900391 ret = mfd_add_devices(sec_pmic->dev, -1, sec_devs, num_sec_devs, NULL,
392 0, NULL);
Leon Romanovsky15447a462013-05-15 18:00:48 +0300393 if (ret)
Krzysztof Kozlowski8c66eec2014-03-18 13:57:50 +0100394 goto err_mfd;
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900395
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100396 device_init_wakeup(sec_pmic->dev, sec_pmic->wakeup);
397
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900398 return ret;
399
Krzysztof Kozlowski8c66eec2014-03-18 13:57:50 +0100400err_mfd:
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900401 sec_irq_exit(sec_pmic);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900402 return ret;
403}
404
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900405static int sec_pmic_remove(struct i2c_client *i2c)
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900406{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900407 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900408
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900409 mfd_remove_devices(sec_pmic->dev);
410 sec_irq_exit(sec_pmic);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900411 return 0;
412}
413
Geert Uytterhoeven8321bbf2014-01-26 11:38:43 +0100414#ifdef CONFIG_PM_SLEEP
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100415static int sec_pmic_suspend(struct device *dev)
416{
417 struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
418 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
419
Krzysztof Kozlowski360d15d2014-04-22 16:00:25 +0200420 if (device_may_wakeup(dev))
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100421 enable_irq_wake(sec_pmic->irq);
Krzysztof Kozlowski360d15d2014-04-22 16:00:25 +0200422 /*
423 * PMIC IRQ must be disabled during suspend for RTC alarm
424 * to work properly.
425 * When device is woken up from suspend, an
426 * interrupt occurs before resuming I2C bus controller.
427 * The interrupt is handled by regmap_irq_thread which tries
428 * to read RTC registers. This read fails (I2C is still
429 * suspended) and RTC Alarm interrupt is disabled.
430 */
431 disable_irq(sec_pmic->irq);
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100432
433 return 0;
434}
435
436static int sec_pmic_resume(struct device *dev)
437{
438 struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
439 struct sec_pmic_dev *sec_pmic = i2c_get_clientdata(i2c);
440
Krzysztof Kozlowski360d15d2014-04-22 16:00:25 +0200441 if (device_may_wakeup(dev))
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100442 disable_irq_wake(sec_pmic->irq);
Krzysztof Kozlowski360d15d2014-04-22 16:00:25 +0200443 enable_irq(sec_pmic->irq);
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100444
445 return 0;
446}
Geert Uytterhoeven8321bbf2014-01-26 11:38:43 +0100447#endif /* CONFIG_PM_SLEEP */
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100448
449static SIMPLE_DEV_PM_OPS(sec_pmic_pm_ops, sec_pmic_suspend, sec_pmic_resume);
450
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900451static const struct i2c_device_id sec_pmic_id[] = {
452 { "sec_pmic", 0 },
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900453 { }
454};
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900455MODULE_DEVICE_TABLE(i2c, sec_pmic_id);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900456
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900457static struct i2c_driver sec_pmic_driver = {
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900458 .driver = {
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900459 .name = "sec_pmic",
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900460 .owner = THIS_MODULE,
Krzysztof Kozlowskif6d6daa2013-11-26 14:50:27 +0100461 .pm = &sec_pmic_pm_ops,
Amit Daniel Kachhap26aec0092013-02-03 15:49:47 -0800462 .of_match_table = of_match_ptr(sec_dt_match),
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900463 },
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900464 .probe = sec_pmic_probe,
465 .remove = sec_pmic_remove,
466 .id_table = sec_pmic_id,
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900467};
468
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900469static int __init sec_pmic_init(void)
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900470{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900471 return i2c_add_driver(&sec_pmic_driver);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900472}
473
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900474subsys_initcall(sec_pmic_init);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900475
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900476static void __exit sec_pmic_exit(void)
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900477{
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900478 i2c_del_driver(&sec_pmic_driver);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900479}
Sangbeom Kim63063bf2012-07-11 21:06:55 +0900480module_exit(sec_pmic_exit);
Sangbeom Kim0f5f7072011-12-23 17:28:08 +0900481
482MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
483MODULE_DESCRIPTION("Core support for the S5M MFD");
484MODULE_LICENSE("GPL");