LP8758 - consolidated version
[mlp-open-source/kernel.git] / drivers / mfd / lm3631.c
1 /*
2  * TI LM3631 MFD Driver
3  *
4  * Copyright 2013 Texas Instruments
5  *
6  * Author: Milo Kim <milo.kim@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  */
14 #include <linux/delay.h>
15 #include <linux/err.h>
16 #include <linux/gpio.h>
17 #include <linux/i2c.h>
18 #include <linux/mfd/core.h>
19 #include <linux/mfd/lm3631.h>
20 #include <linux/module.h>
21 #include <linux/of.h>
22 #include <linux/of_gpio.h>
23 #include <linux/slab.h>
25 #define LM3631_DEV_LCD_BIAS(_id)                \
26 {                                               \
27         .name = "lm3631-regulator",             \
28         .id   = _id,                            \
29         .of_compatible = "ti,lm3631-regulator", \
30 }
32 #define LM3631_DEV_BL                           \
33 {                                               \
34         .name = "lm3631-backlight",             \
35         .of_compatible = "ti,lm3631-backlight", \
36 }
38 static struct mfd_cell lm3631_devs[] = {
39         /* 5 Regulators */
40         LM3631_DEV_LCD_BIAS(1),
41         LM3631_DEV_LCD_BIAS(2),
42         LM3631_DEV_LCD_BIAS(3),
43         LM3631_DEV_LCD_BIAS(4),
44         LM3631_DEV_LCD_BIAS(5),
46         /* Backlight */
47         LM3631_DEV_BL,
48 };
50 int lm3631_read_byte(struct lm3631 *lm3631, u8 reg, u8 *read)
51 {
52         int ret;
53         unsigned int val;
55         ret = regmap_read(lm3631->regmap, reg, &val);
56         if (ret < 0)
57                 return ret;
59         *read = (u8)val;
60         return 0;
61 }
62 EXPORT_SYMBOL_GPL(lm3631_read_byte);
64 int lm3631_write_byte(struct lm3631 *lm3631, u8 reg, u8 data)
65 {
66         return regmap_write(lm3631->regmap, reg, data);
67 }
68 EXPORT_SYMBOL_GPL(lm3631_write_byte);
70 int lm3631_update_bits(struct lm3631 *lm3631, u8 reg, u8 mask, u8 data)
71 {
72         return regmap_update_bits(lm3631->regmap, reg, mask, data);
73 }
74 EXPORT_SYMBOL_GPL(lm3631_update_bits);
76 static int lm3631_init_device(struct lm3631 *lm3631)
77 {
78         int ret;
80         /*
81          * Sequence
82          *
83          * 1) Enable nRST pin
84          * 2) Delay about 1ms (bias delay 200us + EPROM read time 700us)
85          * 3) Set LCD_EN bit to 1
86          */
88         ret = devm_gpio_request_one(lm3631->dev, lm3631->pdata->en_gpio,
89                                     GPIOF_OUT_INIT_HIGH, "lm3631_hwen");
90         if (ret)
91                 return ret;
93         usleep_range(1000, 1500);
95         return lm3631_update_bits(lm3631, LM3631_REG_DEVCTRL,
96                                   LM3631_LCD_EN_MASK,
97                                   1 << LM3631_LCD_EN_SHIFT);
98 }
100 static void lm3631_deinit_device(struct lm3631 *lm3631)
102         gpio_set_value(lm3631->pdata->en_gpio, 0);
105 static int lm3631_parse_dt(struct device *dev, struct lm3631 *lm3631)
107         struct device_node *node = dev->of_node;
108         struct lm3631_platform_data *pdata;
110         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
111         if (!pdata)
112                 return -ENOMEM;
114         pdata->en_gpio = of_get_named_gpio(node, "ti,en-gpio", 0);
115         if (pdata->en_gpio == -EPROBE_DEFER)
116                 return -EPROBE_DEFER;
118         lm3631->pdata = pdata;
120         return 0;
123 static struct regmap_config lm3631_regmap_config = {
124         .reg_bits = 8,
125         .val_bits = 8,
126         .max_register = LM3631_MAX_REGISTERS,
127 };
129 static int lm3631_probe(struct i2c_client *cl, const struct i2c_device_id *id)
131         struct lm3631 *lm3631;
132         struct device *dev = &cl->dev;
133         struct lm3631_platform_data *pdata = dev_get_platdata(dev);
134         int ret;
136         lm3631 = devm_kzalloc(dev, sizeof(*lm3631), GFP_KERNEL);
137         if (!lm3631)
138                 return -ENOMEM;
140         lm3631->pdata = pdata;
141         if (!pdata) {
142                 if (IS_ENABLED(CONFIG_OF))
143                         ret = lm3631_parse_dt(dev, lm3631);
144                 else
145                         ret = -ENODEV;
147                 if (ret)
148                         return ret;
149         }
151         lm3631->regmap = devm_regmap_init_i2c(cl, &lm3631_regmap_config);
152         if (IS_ERR(lm3631->regmap))
153                 return PTR_ERR(lm3631->regmap);
155         lm3631->dev = &cl->dev;
156         i2c_set_clientdata(cl, lm3631);
158         ret = lm3631_init_device(lm3631);
159         if (ret)
160                 return ret;
162         return mfd_add_devices(dev, -1, lm3631_devs, ARRAY_SIZE(lm3631_devs),
163                                NULL, 0, NULL);
166 static int lm3631_remove(struct i2c_client *cl)
168         struct lm3631 *lm3631 = i2c_get_clientdata(cl);
170         lm3631_deinit_device(lm3631);
171         mfd_remove_devices(lm3631->dev);
173         return 0;
176 static const struct i2c_device_id lm3631_ids[] = {
177         { "lm3631", 0 },
178         { }
179 };
180 MODULE_DEVICE_TABLE(i2c, lm3631_ids);
182 #ifdef CONFIG_OF
183 static const struct of_device_id lm3631_of_match[] = {
184         { .compatible = "ti,lm3631", },
185         { }
186 };
187 MODULE_DEVICE_TABLE(of, lm3631_of_match);
188 #endif
190 static struct i2c_driver lm3631_driver = {
191         .probe = lm3631_probe,
192         .remove = lm3631_remove,
193         .driver = {
194                 .name = "lm3631",
195                 .owner = THIS_MODULE,
196                 .of_match_table = of_match_ptr(lm3631_of_match),
197         },
198         .id_table = lm3631_ids,
199 };
200 module_i2c_driver(lm3631_driver);
202 MODULE_DESCRIPTION("TI LM3631 MFD Core");
203 MODULE_AUTHOR("Milo Kim");
204 MODULE_LICENSE("GPL");