LP8758 - consolidated version
[mlp-open-source/kernel.git] / drivers / mfd / lm3632.c
1 /*
2  * TI LM3632 MFD Driver
3  *
4  * Copyright 2015 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/lm3632.h>
20 #include <linux/module.h>
21 #include <linux/of.h>
22 #include <linux/of_gpio.h>
23 #include <linux/slab.h>
25 #define LM3632_DEV_LCD_BIAS(_id)                \
26 {                                               \
27         .name = "lm3632-regulator",             \
28         .id   = _id,                            \
29         .of_compatible = "ti,lm3632-regulator", \
30 }
32 #define LM3632_DEV_BL                           \
33 {                                               \
34         .name = "lm3632-backlight",             \
35         .of_compatible = "ti,lm3632-backlight", \
36 }
38 #define LM3632_DEV_FLASH                                \
39 {                                               \
40         .name = "lm3632-flash",         \
41         .of_compatible = "ti,lm3632-flash",     \
42 }
44 static struct mfd_cell lm3632_devs[] = {
45         /* 3 Regulators */
46         LM3632_DEV_LCD_BIAS(1),
47         LM3632_DEV_LCD_BIAS(2),
48         LM3632_DEV_LCD_BIAS(3),
50         /* Backlight */
51         LM3632_DEV_BL,
52         /* Torch Flash */
53         LM3632_DEV_FLASH,
54 };
56 int lm3632_read_byte(struct lm3632 *lm3632, u8 reg, u8 *read)
57 {
58         int ret;
59         unsigned int val;
61         ret = regmap_read(lm3632->regmap, reg, &val);
62         if (ret < 0)
63                 return ret;
65         *read = (u8)val;
66         return 0;
67 }
68 EXPORT_SYMBOL_GPL(lm3632_read_byte);
70 int lm3632_write_byte(struct lm3632 *lm3632, u8 reg, u8 data)
71 {
72         return regmap_write(lm3632->regmap, reg, data);
73 }
74 EXPORT_SYMBOL_GPL(lm3632_write_byte);
76 int lm3632_update_bits(struct lm3632 *lm3632, u8 reg, u8 mask, u8 data)
77 {
78         return regmap_update_bits(lm3632->regmap, reg, mask, data);
79 }
80 EXPORT_SYMBOL_GPL(lm3632_update_bits);
82 static int lm3632_init_device(struct lm3632 *lm3632)
83 {
84         return devm_gpio_request_one(lm3632->dev, lm3632->pdata->en_gpio,
85                                      GPIOF_OUT_INIT_HIGH, "lm3632_hwen");
86 }
88 static void lm3632_deinit_device(struct lm3632 *lm3632)
89 {
90         gpio_set_value(lm3632->pdata->en_gpio, 0);
91 }
93 static int lm3632_parse_dt(struct device *dev, struct lm3632 *lm3632)
94 {
95         struct device_node *node = dev->of_node;
96         struct lm3632_platform_data *pdata;
98         pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
99         if (!pdata)
100                 return -ENOMEM;
102         pdata->en_gpio = of_get_named_gpio(node, "ti,en-gpio", 0);
103         if (pdata->en_gpio == -EPROBE_DEFER)
104                 return -EPROBE_DEFER;
106         lm3632->pdata = pdata;
108         return 0;
111 static struct regmap_config lm3632_regmap_config = {
112         .reg_bits = 8,
113         .val_bits = 8,
114         .max_register = LM3632_MAX_REGISTERS,
115 };
117 static int lm3632_probe(struct i2c_client *cl, const struct i2c_device_id *id)
119         struct lm3632 *lm3632;
120         struct device *dev = &cl->dev;
121         struct lm3632_platform_data *pdata = dev_get_platdata(dev);
122         int ret;
124         lm3632 = devm_kzalloc(dev, sizeof(*lm3632), GFP_KERNEL);
125         if (!lm3632)
126                 return -ENOMEM;
128         lm3632->pdata = pdata;
129         if (!pdata) {
130                 if (IS_ENABLED(CONFIG_OF))
131                         ret = lm3632_parse_dt(dev, lm3632);
132                 else
133                         ret = -ENODEV;
135                 if (ret)
136                         return ret;
137         }
139         lm3632->regmap = devm_regmap_init_i2c(cl, &lm3632_regmap_config);
140         if (IS_ERR(lm3632->regmap))
141                 return PTR_ERR(lm3632->regmap);
143         lm3632->dev = &cl->dev;
144         i2c_set_clientdata(cl, lm3632);
146         ret = lm3632_init_device(lm3632);
147         if (ret)
148                 return ret;
150         return mfd_add_devices(dev, -1, lm3632_devs, ARRAY_SIZE(lm3632_devs),
151                                NULL, 0, NULL);
154 static int lm3632_remove(struct i2c_client *cl)
156         struct lm3632 *lm3632 = i2c_get_clientdata(cl);
158         lm3632_deinit_device(lm3632);
159         mfd_remove_devices(lm3632->dev);
161         return 0;
164 static const struct i2c_device_id lm3632_ids[] = {
165         { "lm3632", 0 },
166         { }
167 };
168 MODULE_DEVICE_TABLE(i2c, lm3632_ids);
170 #ifdef CONFIG_OF
171 static const struct of_device_id lm3632_of_match[] = {
172         { .compatible = "ti,lm3632", },
173         { }
174 };
175 MODULE_DEVICE_TABLE(of, lm3632_of_match);
176 #endif
178 static struct i2c_driver lm3632_driver = {
179         .probe = lm3632_probe,
180         .remove = lm3632_remove,
181         .driver = {
182                 .name = "lm3632",
183                 .owner = THIS_MODULE,
184                 .of_match_table = of_match_ptr(lm3632_of_match),
185         },
186         .id_table = lm3632_ids,
187 };
188 module_i2c_driver(lm3632_driver);
190 MODULE_DESCRIPTION("TI LM3632 MFD Core");
191 MODULE_AUTHOR("Milo Kim");
192 MODULE_LICENSE("GPL");