2 * s2mpb02-core.c - mfd core driver for the Samsung s2mpb02
4 * Copyright (C) 2014 Samsung Electronics
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * This driver is based on max77804.c
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/i2c.h>
26 #include <linux/irq.h>
27 #include <linux/interrupt.h>
28 #include <linux/mutex.h>
29 #include <linux/mfd/core.h>
30 #include <linux/mfd/s2mpb02.h>
31 #include <linux/mfd/s2mpb02-regulator.h>
32 #include <linux/regulator/machine.h>
35 #include <linux/of_device.h>
36 #include <linux/of_gpio.h>
37 #endif /* CONFIG_OF */
39 static struct mfd_cell s2mpb02_devs
[] = {
40 #ifdef CONFIG_LEDS_S2MPB02
41 { .name
= "s2mpb02-led", },
42 #endif /* CONFIG_LEDS_S2MPB02 */
43 { .name
= "s2mpb02-regulator", },
46 int s2mpb02_read_reg(struct i2c_client
*i2c
, u8 reg
, u8
*dest
)
48 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
51 mutex_lock(&s2mpb02
->i2c_lock
);
52 ret
= i2c_smbus_read_byte_data(i2c
, reg
);
53 mutex_unlock(&s2mpb02
->i2c_lock
);
55 pr_info("%s:%s reg(0x%x), ret(%d)\n",
56 MFD_DEV_NAME
, __func__
, reg
, ret
);
64 EXPORT_SYMBOL_GPL(s2mpb02_read_reg
);
66 int s2mpb02_bulk_read(struct i2c_client
*i2c
, u8 reg
, int count
, u8
*buf
)
68 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
71 mutex_lock(&s2mpb02
->i2c_lock
);
72 ret
= i2c_smbus_read_i2c_block_data(i2c
, reg
, count
, buf
);
73 mutex_unlock(&s2mpb02
->i2c_lock
);
79 EXPORT_SYMBOL_GPL(s2mpb02_bulk_read
);
81 int s2mpb02_write_reg(struct i2c_client
*i2c
, u8 reg
, u8 value
)
83 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
86 mutex_lock(&s2mpb02
->i2c_lock
);
87 ret
= i2c_smbus_write_byte_data(i2c
, reg
, value
);
88 mutex_unlock(&s2mpb02
->i2c_lock
);
90 pr_info("%s:%s reg(0x%x), ret(%d)\n",
91 MFD_DEV_NAME
, __func__
, reg
, ret
);
95 EXPORT_SYMBOL_GPL(s2mpb02_write_reg
);
97 int s2mpb02_bulk_write(struct i2c_client
*i2c
, u8 reg
, int count
, u8
*buf
)
99 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
102 mutex_lock(&s2mpb02
->i2c_lock
);
103 ret
= i2c_smbus_write_i2c_block_data(i2c
, reg
, count
, buf
);
104 mutex_unlock(&s2mpb02
->i2c_lock
);
110 EXPORT_SYMBOL_GPL(s2mpb02_bulk_write
);
112 int s2mpb02_update_reg(struct i2c_client
*i2c
, u8 reg
, u8 val
, u8 mask
)
114 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
117 mutex_lock(&s2mpb02
->i2c_lock
);
118 ret
= i2c_smbus_read_byte_data(i2c
, reg
);
120 u8 old_val
= ret
& 0xff;
121 u8 new_val
= (val
& mask
) | (old_val
& (~mask
));
122 ret
= i2c_smbus_write_byte_data(i2c
, reg
, new_val
);
124 mutex_unlock(&s2mpb02
->i2c_lock
);
127 EXPORT_SYMBOL_GPL(s2mpb02_update_reg
);
130 static int of_s2mpb02_dt(struct device
*dev
,
131 struct s2mpb02_platform_data
*pdata
)
133 struct device_node
*np_s2mpb02
= dev
->of_node
;
138 pdata
->wakeup
= of_property_read_bool(np_s2mpb02
, "s2mpb02,wakeup");
143 static int of_s2mpb02_dt(struct device
*dev
,
144 struct s2mpb02_platform_data
*pdata
)
148 #endif /* CONFIG_OF */
150 static int s2mpb02_i2c_probe(struct i2c_client
*i2c
,
151 const struct i2c_device_id
*dev_id
)
153 struct s2mpb02_dev
*s2mpb02
;
154 struct s2mpb02_platform_data
*pdata
= i2c
->dev
.platform_data
;
159 pr_info("%s:%s\n", MFD_DEV_NAME
, __func__
);
161 s2mpb02
= kzalloc(sizeof(struct s2mpb02_dev
), GFP_KERNEL
);
163 dev_err(&i2c
->dev
, "%s: Failed to alloc mem for s2mpb02\n",
168 if (i2c
->dev
.of_node
) {
169 pdata
= devm_kzalloc(&i2c
->dev
,
170 sizeof(struct s2mpb02_platform_data
), GFP_KERNEL
);
172 dev_err(&i2c
->dev
, "Failed to allocate memory\n");
177 ret
= of_s2mpb02_dt(&i2c
->dev
, pdata
);
179 dev_err(&i2c
->dev
, "Failed to get device of_node\n");
183 i2c
->dev
.platform_data
= pdata
;
185 pdata
= i2c
->dev
.platform_data
;
187 s2mpb02
->dev
= &i2c
->dev
;
189 s2mpb02
->irq
= i2c
->irq
;
191 s2mpb02
->pdata
= pdata
;
193 pdata
->irq_base
= irq_alloc_descs(-1, 600, S2MPB02_IRQ_NR
, 0);
194 if (pdata
->irq_base
< 0) {
195 pr_err("%s:%s irq_alloc_descs Fail! ret(%d)\n",
196 MFD_DEV_NAME
, __func__
, pdata
->irq_base
);
200 s2mpb02
->irq_base
= pdata
->irq_base
;
203 s2mpb02
->wakeup
= pdata
->wakeup
;
208 mutex_init(&s2mpb02
->i2c_lock
);
210 i2c_set_clientdata(i2c
, s2mpb02
);
212 if (s2mpb02_read_reg(s2mpb02
->i2c
,
213 S2MPB02_REG_BST_CTRL2
, ®_data
) < 0) {
214 pr_err("device not found on this channel!!\n");
217 if (reg_data
== 0x90) {
218 S2MPB02_PMIC_REV(s2mpb02
) = 1;
220 S2MPB02_PMIC_REV(s2mpb02
) = 0;
221 pr_info("%s: device id 0x%x is found\n",
222 __func__
, s2mpb02
->rev_num
);
225 ret
= s2mpb02_irq_init(s2mpb02
);
229 ret
= mfd_add_devices(s2mpb02
->dev
, -1, s2mpb02_devs
,
230 ARRAY_SIZE(s2mpb02_devs
), NULL
, 0, NULL
);
234 device_init_wakeup(s2mpb02
->dev
, pdata
->wakeup
);
239 mutex_destroy(&s2mpb02
->i2c_lock
);
242 s2mpb02_irq_exit(s2mpb02
);
249 static int s2mpb02_i2c_remove(struct i2c_client
*i2c
)
251 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
253 mfd_remove_devices(s2mpb02
->dev
);
254 s2mpb02_irq_exit(s2mpb02
);
255 mutex_destroy(&s2mpb02
->i2c_lock
);
261 static const struct i2c_device_id s2mpb02_i2c_id
[] = {
262 { MFD_DEV_NAME
, TYPE_S2MPB02
},
265 MODULE_DEVICE_TABLE(i2c
, s2mpb02_i2c_id
);
267 #if defined(CONFIG_OF)
268 static struct of_device_id s2mpb02_i2c_dt_ids
[] = {
269 { .compatible
= "s2mpb02,s2mpb02mfd" },
272 MODULE_DEVICE_TABLE(of
, s2mpb02_i2c_dt_ids
);
273 #endif /* CONFIG_OF */
275 #if defined(CONFIG_PM)
276 static int s2mpb02_suspend(struct device
*dev
)
278 struct i2c_client
*i2c
= container_of(dev
, struct i2c_client
, dev
);
279 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
281 if (device_may_wakeup(dev
))
282 enable_irq_wake(s2mpb02
->irq
);
284 disable_irq(s2mpb02
->irq
);
289 static int s2mpb02_resume(struct device
*dev
)
291 struct i2c_client
*i2c
= container_of(dev
, struct i2c_client
, dev
);
292 struct s2mpb02_dev
*s2mpb02
= i2c_get_clientdata(i2c
);
294 if (device_may_wakeup(dev
))
295 disable_irq_wake(s2mpb02
->irq
);
297 enable_irq(s2mpb02
->irq
);
302 #define s2mpb02_suspend NULL
303 #define s2mpb02_resume NULL
304 #endif /* CONFIG_PM */
306 const struct dev_pm_ops s2mpb02_pm
= {
307 .suspend
= s2mpb02_suspend
,
308 .resume
= s2mpb02_resume
,
311 static struct i2c_driver s2mpb02_i2c_driver
= {
313 .name
= MFD_DEV_NAME
,
314 .owner
= THIS_MODULE
,
315 #if defined(CONFIG_PM)
317 #endif /* CONFIG_PM */
318 #if defined(CONFIG_OF)
319 .of_match_table
= s2mpb02_i2c_dt_ids
,
320 #endif /* CONFIG_OF */
321 .suppress_bind_attrs
= true,
323 .probe
= s2mpb02_i2c_probe
,
324 .remove
= s2mpb02_i2c_remove
,
325 .id_table
= s2mpb02_i2c_id
,
328 static int __init
s2mpb02_i2c_init(void)
330 pr_info("%s:%s\n", MFD_DEV_NAME
, __func__
);
331 return i2c_add_driver(&s2mpb02_i2c_driver
);
333 /* init early so consumer devices can complete system boot */
334 subsys_initcall(s2mpb02_i2c_init
);
336 static void __exit
s2mpb02_i2c_exit(void)
338 i2c_del_driver(&s2mpb02_i2c_driver
);
340 module_exit(s2mpb02_i2c_exit
);
342 MODULE_DESCRIPTION("SAMSUNG s2mpb02 multi-function core driver");
343 MODULE_LICENSE("GPL");