aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2013-12-06 06:32:13 -0500
committerMark Brown <broonie@linaro.org>2013-12-18 14:23:28 -0500
commitb0902bbeb7684f2cf8dd1c54fe2616cc2ab1b91d (patch)
treef50dc5b506986b589639237e7e717df1dc975e18
parent6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae (diff)
regulator: max14577: Add regulator driver for Maxim 14577
MAX14577 chip is a multi-function device which includes MUIC, charger and voltage regulator. The driver is located in drivers/mfd. This patch adds regulator driver for MAX14577 chip. There are two regulators in this chip: 1. Safeout LDO with constant voltage output of 4.9V. It can be only enabled or disabled. 2. Current regulator for the charger. It provides current from 90mA up to 950mA. Driver supports Device Tree. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--drivers/regulator/Kconfig7
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/max14577.c272
3 files changed, 280 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index ce785f481281..11ee05341926 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -249,6 +249,13 @@ config REGULATOR_LP8788
249 help 249 help
250 This driver supports LP8788 voltage regulator chip. 250 This driver supports LP8788 voltage regulator chip.
251 251
252config REGULATOR_MAX14577
253 tristate "Maxim 14577 regulator"
254 depends on MFD_MAX14577
255 help
256 This driver controls a Maxim 14577 regulator via I2C bus.
257 The regulators include safeout LDO and current regulator 'CHARGER'.
258
252config REGULATOR_MAX1586 259config REGULATOR_MAX1586
253 tristate "Maxim 1586/1587 voltage regulator" 260 tristate "Maxim 1586/1587 voltage regulator"
254 depends on I2C 261 depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 01c597ea1744..654bd43a7426 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
35obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o 35obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o
36obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o 36obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
37obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o 37obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o
38obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o
38obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o 39obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
39obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o 40obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
40obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o 41obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
diff --git a/drivers/regulator/max14577.c b/drivers/regulator/max14577.c
new file mode 100644
index 000000000000..516e8af05641
--- /dev/null
+++ b/drivers/regulator/max14577.c
@@ -0,0 +1,272 @@
1/*
2 * max14577.c - Regulator driver for the Maxim 14577
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Krzysztof Kozlowski <k.kozlowski@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/module.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/driver.h>
21#include <linux/mfd/max14577.h>
22#include <linux/mfd/max14577-private.h>
23#include <linux/regulator/of_regulator.h>
24
25struct max14577_regulator {
26 struct device *dev;
27 struct max14577 *max14577;
28 struct regulator_dev **regulators;
29};
30
31static int max14577_reg_is_enabled(struct regulator_dev *rdev)
32{
33 int rid = rdev_get_id(rdev);
34 struct regmap *rmap = rdev->regmap;
35 u8 reg_data;
36
37 switch (rid) {
38 case MAX14577_CHARGER:
39 max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL2, &reg_data);
40 if ((reg_data & CHGCTRL2_MBCHOSTEN_MASK) == 0)
41 return 0;
42 max14577_read_reg(rmap, MAX14577_CHG_REG_STATUS3, &reg_data);
43 if ((reg_data & STATUS3_CGMBC_MASK) == 0)
44 return 0;
45 /* MBCHOSTEN and CGMBC are on */
46 return 1;
47 default:
48 return -EINVAL;
49 }
50}
51
52static int max14577_reg_get_current_limit(struct regulator_dev *rdev)
53{
54 u8 reg_data;
55 struct regmap *rmap = rdev->regmap;
56
57 if (rdev_get_id(rdev) != MAX14577_CHARGER)
58 return -EINVAL;
59
60 max14577_read_reg(rmap, MAX14577_CHG_REG_CHG_CTRL4, &reg_data);
61
62 if ((reg_data & CHGCTRL4_MBCICHWRCL_MASK) == 0)
63 return MAX14577_REGULATOR_CURRENT_LIMIT_MIN;
64
65 reg_data = ((reg_data & CHGCTRL4_MBCICHWRCH_MASK) >>
66 CHGCTRL4_MBCICHWRCH_SHIFT);
67 return MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START +
68 reg_data * MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP;
69}
70
71static int max14577_reg_set_current_limit(struct regulator_dev *rdev,
72 int min_uA, int max_uA)
73{
74 int i, current_bits = 0xf;
75 u8 reg_data;
76
77 if (rdev_get_id(rdev) != MAX14577_CHARGER)
78 return -EINVAL;
79
80 if (min_uA > MAX14577_REGULATOR_CURRENT_LIMIT_MAX ||
81 max_uA < MAX14577_REGULATOR_CURRENT_LIMIT_MIN)
82 return -EINVAL;
83
84 if (max_uA < MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START) {
85 /* Less than 200 mA, so set 90mA (turn only Low Bit off) */
86 u8 reg_data = 0x0 << CHGCTRL4_MBCICHWRCL_SHIFT;
87 return max14577_update_reg(rdev->regmap,
88 MAX14577_CHG_REG_CHG_CTRL4,
89 CHGCTRL4_MBCICHWRCL_MASK, reg_data);
90 }
91
92 /* max_uA is in range: <LIMIT_HIGH_START, inifinite>, so search for
93 * valid current starting from LIMIT_MAX. */
94 for (i = MAX14577_REGULATOR_CURRENT_LIMIT_MAX;
95 i >= MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START;
96 i -= MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP) {
97 if (i <= max_uA)
98 break;
99 current_bits--;
100 }
101 BUG_ON(current_bits < 0); /* Cannot happen */
102 /* Turn Low Bit on (use range 200mA-950 mA) */
103 reg_data = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT;
104 /* and set proper High Bits */
105 reg_data |= current_bits << CHGCTRL4_MBCICHWRCH_SHIFT;
106
107 return max14577_update_reg(rdev->regmap, MAX14577_CHG_REG_CHG_CTRL4,
108 CHGCTRL4_MBCICHWRCL_MASK | CHGCTRL4_MBCICHWRCH_MASK,
109 reg_data);
110}
111
112static struct regulator_ops max14577_safeout_ops = {
113 .is_enabled = regulator_is_enabled_regmap,
114 .enable = regulator_enable_regmap,
115 .disable = regulator_disable_regmap,
116 .list_voltage = regulator_list_voltage_linear,
117};
118
119static struct regulator_ops max14577_charger_ops = {
120 .is_enabled = max14577_reg_is_enabled,
121 .enable = regulator_enable_regmap,
122 .disable = regulator_disable_regmap,
123 .get_current_limit = max14577_reg_get_current_limit,
124 .set_current_limit = max14577_reg_set_current_limit,
125};
126
127static const struct regulator_desc supported_regulators[] = {
128 [MAX14577_SAFEOUT] = {
129 .name = "SAFEOUT",
130 .id = MAX14577_SAFEOUT,
131 .ops = &max14577_safeout_ops,
132 .type = REGULATOR_VOLTAGE,
133 .owner = THIS_MODULE,
134 .n_voltages = 1,
135 .min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE,
136 .enable_reg = MAX14577_REG_CONTROL2,
137 .enable_mask = CTRL2_SFOUTORD_MASK,
138 },
139 [MAX14577_CHARGER] = {
140 .name = "CHARGER",
141 .id = MAX14577_CHARGER,
142 .ops = &max14577_charger_ops,
143 .type = REGULATOR_CURRENT,
144 .owner = THIS_MODULE,
145 .enable_reg = MAX14577_CHG_REG_CHG_CTRL2,
146 .enable_mask = CHGCTRL2_MBCHOSTEN_MASK,
147 },
148};
149
150#ifdef CONFIG_OF
151static struct of_regulator_match max14577_regulator_matches[] = {
152 { .name = "SAFEOUT", },
153 { .name = "CHARGER", },
154};
155
156static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev)
157{
158 int ret;
159 struct device_node *np;
160
161 np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
162 if (!np) {
163 dev_err(&pdev->dev, "Failed to get child OF node for regulators\n");
164 return -EINVAL;
165 }
166
167 ret = of_regulator_match(&pdev->dev, np, max14577_regulator_matches,
168 MAX14577_REG_MAX);
169 if (ret < 0) {
170 dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
171 return ret;
172 }
173
174 return 0;
175}
176
177static inline struct regulator_init_data *match_init_data(int index)
178{
179 return max14577_regulator_matches[index].init_data;
180}
181
182static inline struct device_node *match_of_node(int index)
183{
184 return max14577_regulator_matches[index].of_node;
185}
186#else /* CONFIG_OF */
187static int max14577_regulator_dt_parse_pdata(struct platform_device *pdev)
188{
189 return 0;
190}
191static inline struct regulator_init_data *match_init_data(int index)
192{
193 return NULL;
194}
195
196static inline struct device_node *match_of_node(int index)
197{
198 return NULL;
199}
200#endif /* CONFIG_OF */
201
202
203static int max14577_regulator_probe(struct platform_device *pdev)
204{
205 struct max14577 *max14577 = dev_get_drvdata(pdev->dev.parent);
206 struct max14577_platform_data *pdata = dev_get_platdata(max14577->dev);
207 int i, ret;
208 struct regulator_config config = {};
209
210 ret = max14577_regulator_dt_parse_pdata(pdev);
211 if (ret)
212 return ret;
213
214 config.dev = &pdev->dev;
215 config.regmap = max14577->regmap;
216
217 for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) {
218 struct regulator_dev *regulator;
219 /*
220 * Index of supported_regulators[] is also the id and must
221 * match index of pdata->regulators[].
222 */
223 if (pdata && pdata->regulators) {
224 config.init_data = pdata->regulators[i].initdata;
225 config.of_node = pdata->regulators[i].of_node;
226 } else {
227 config.init_data = match_init_data(i);
228 config.of_node = match_of_node(i);
229 }
230
231 regulator = devm_regulator_register(&pdev->dev,
232 &supported_regulators[i], &config);
233 if (IS_ERR(regulator)) {
234 ret = PTR_ERR(regulator);
235 dev_err(&pdev->dev,
236 "Regulator init failed for ID %d with error: %d\n",
237 i, ret);
238 return ret;
239 }
240 }
241
242 return ret;
243}
244
245static struct platform_driver max14577_regulator_driver = {
246 .driver = {
247 .owner = THIS_MODULE,
248 .name = "max14577-regulator",
249 },
250 .probe = max14577_regulator_probe,
251};
252
253static int __init max14577_regulator_init(void)
254{
255 BUILD_BUG_ON(MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_START +
256 MAX14577_REGULATOR_CURRENT_LIMIT_HIGH_STEP * 0xf !=
257 MAX14577_REGULATOR_CURRENT_LIMIT_MAX);
258 BUILD_BUG_ON(ARRAY_SIZE(supported_regulators) != MAX14577_REG_MAX);
259
260 return platform_driver_register(&max14577_regulator_driver);
261}
262subsys_initcall(max14577_regulator_init);
263
264static void __exit max14577_regulator_exit(void)
265{
266 platform_driver_unregister(&max14577_regulator_driver);
267}
268module_exit(max14577_regulator_exit);
269
270MODULE_AUTHOR("Krzysztof Kozlowski <k.kozlowski@samsung.com>");
271MODULE_DESCRIPTION("MAXIM 14577 regulator driver");
272MODULE_LICENSE("GPL");