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