aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaewon Kim <jaewon02.kim@samsung.com>2015-02-05 01:35:58 -0500
committerMark Brown <broonie@kernel.org>2015-02-05 12:33:39 -0500
commit9dfffb7a3d190797b88e419c3456af1855aff81e (patch)
tree17f325aab4944c1320573b9afe60cc83202328db
parent97bf6af1f928216fd6c5a66e8a57bfa95a659672 (diff)
regulator: max77843: Add max77843 regulator driver
This patch adds new regulator driver to support max77843 MFD(Multi Function Device) chip`s regulators. The Max77843 has two voltage regulators for USB safeout. Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com> Signed-off-by: Beomho Seo <beomho.seo@samsung.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/regulator/Kconfig8
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/max77843.c227
3 files changed, 236 insertions, 0 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c3a60b57a865..c1f9c339da7c 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -414,6 +414,14 @@ config REGULATOR_MAX77802
414 Exynos5420/Exynos5800 SoCs to control various voltages. 414 Exynos5420/Exynos5800 SoCs to control various voltages.
415 It includes support for control of voltage and ramp speed. 415 It includes support for control of voltage and ramp speed.
416 416
417config REGULATOR_MAX77843
418 tristate "Maxim 77843 regulator"
419 depends on MFD_MAX77843
420 help
421 This driver controls a Maxim 77843 regulator.
422 The regulator include two 'SAFEOUT' for USB(Universal Serial Bus)
423 This is suitable for Exynos5433 SoC chips.
424
417config REGULATOR_MC13XXX_CORE 425config REGULATOR_MC13XXX_CORE
418 tristate 426 tristate
419 427
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 1f28ebfc6f3a..12408d66ba20 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
55obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o 55obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
56obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o 56obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o
57obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o 57obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o
58obj-$(CONFIG_REGULATOR_MAX77843) += max77843.o
58obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o 59obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
59obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o 60obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
60obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o 61obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
diff --git a/drivers/regulator/max77843.c b/drivers/regulator/max77843.c
new file mode 100644
index 000000000000..c132ef527cdd
--- /dev/null
+++ b/drivers/regulator/max77843.c
@@ -0,0 +1,227 @@
1/*
2 * max77843.c - Regulator driver for the Maxim MAX77843
3 *
4 * Copyright (C) 2015 Samsung Electronics
5 * Author: Jaewon Kim <jaewon02.kim@samsung.com>
6 * Author: Beomho Seo <beomho.seo@samsung.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 as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
18#include <linux/mfd/max77843-private.h>
19#include <linux/regulator/of_regulator.h>
20
21enum max77843_regulator_type {
22 MAX77843_SAFEOUT1 = 0,
23 MAX77843_SAFEOUT2,
24 MAX77843_CHARGER,
25
26 MAX77843_NUM,
27};
28
29static const unsigned int max77843_safeout_voltage_table[] = {
30 4850000,
31 4900000,
32 4950000,
33 3300000,
34};
35
36static int max77843_reg_is_enabled(struct regulator_dev *rdev)
37{
38 struct regmap *regmap = rdev->regmap;
39 int ret;
40 unsigned int reg;
41
42 ret = regmap_read(regmap, rdev->desc->enable_reg, &reg);
43 if (ret) {
44 dev_err(&rdev->dev, "Fialed to read charger register\n");
45 return ret;
46 }
47
48 return (reg & rdev->desc->enable_mask) == rdev->desc->enable_mask;
49}
50
51static int max77843_reg_get_current_limit(struct regulator_dev *rdev)
52{
53 struct regmap *regmap = rdev->regmap;
54 unsigned int chg_min_uA = rdev->constraints->min_uA;
55 unsigned int chg_max_uA = rdev->constraints->max_uA;
56 unsigned int val;
57 int ret;
58 unsigned int reg, sel;
59
60 ret = regmap_read(regmap, MAX77843_CHG_REG_CHG_CNFG_02, &reg);
61 if (ret) {
62 dev_err(&rdev->dev, "Failed to read charger register\n");
63 return ret;
64 }
65
66 sel = reg & MAX77843_CHG_FAST_CHG_CURRENT_MASK;
67
68 if (sel < 0x03)
69 sel = 0;
70 else
71 sel -= 2;
72
73 val = chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel;
74 if (val > chg_max_uA)
75 return -EINVAL;
76
77 return val;
78}
79
80static int max77843_reg_set_current_limit(struct regulator_dev *rdev,
81 int min_uA, int max_uA)
82{
83 struct regmap *regmap = rdev->regmap;
84 unsigned int chg_min_uA = rdev->constraints->min_uA;
85 int sel = 0;
86
87 while (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel < min_uA)
88 sel++;
89
90 if (chg_min_uA + MAX77843_CHG_FAST_CHG_CURRENT_STEP * sel > max_uA)
91 return -EINVAL;
92
93 sel += 2;
94
95 return regmap_write(regmap, MAX77843_CHG_REG_CHG_CNFG_02, sel);
96}
97
98static struct regulator_ops max77843_charger_ops = {
99 .is_enabled = max77843_reg_is_enabled,
100 .enable = regulator_enable_regmap,
101 .disable = regulator_disable_regmap,
102 .get_current_limit = max77843_reg_get_current_limit,
103 .set_current_limit = max77843_reg_set_current_limit,
104};
105
106static struct regulator_ops max77843_regulator_ops = {
107 .is_enabled = regulator_is_enabled_regmap,
108 .enable = regulator_enable_regmap,
109 .disable = regulator_disable_regmap,
110 .list_voltage = regulator_list_voltage_table,
111 .get_voltage_sel = regulator_get_voltage_sel_regmap,
112 .set_voltage_sel = regulator_set_voltage_sel_regmap,
113};
114
115static const struct regulator_desc max77843_supported_regulators[] = {
116 [MAX77843_SAFEOUT1] = {
117 .name = "SAFEOUT1",
118 .id = MAX77843_SAFEOUT1,
119 .ops = &max77843_regulator_ops,
120 .of_match = of_match_ptr("SAFEOUT1"),
121 .regulators_node = of_match_ptr("regulators"),
122 .type = REGULATOR_VOLTAGE,
123 .owner = THIS_MODULE,
124 .n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table),
125 .volt_table = max77843_safeout_voltage_table,
126 .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
127 .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT1,
128 .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
129 .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT1_MASK,
130 },
131 [MAX77843_SAFEOUT2] = {
132 .name = "SAFEOUT2",
133 .id = MAX77843_SAFEOUT2,
134 .ops = &max77843_regulator_ops,
135 .of_match = of_match_ptr("SAFEOUT2"),
136 .regulators_node = of_match_ptr("regulators"),
137 .type = REGULATOR_VOLTAGE,
138 .owner = THIS_MODULE,
139 .n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table),
140 .volt_table = max77843_safeout_voltage_table,
141 .enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
142 .enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT2,
143 .vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
144 .vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT2_MASK,
145 },
146 [MAX77843_CHARGER] = {
147 .name = "CHARGER",
148 .id = MAX77843_CHARGER,
149 .ops = &max77843_charger_ops,
150 .of_match = of_match_ptr("CHARGER"),
151 .regulators_node = of_match_ptr("regulators"),
152 .type = REGULATOR_CURRENT,
153 .owner = THIS_MODULE,
154 .enable_reg = MAX77843_CHG_REG_CHG_CNFG_00,
155 .enable_mask = MAX77843_CHG_MASK,
156 },
157};
158
159static struct regmap *max77843_get_regmap(struct max77843 *max77843, int reg_id)
160{
161 switch (reg_id) {
162 case MAX77843_SAFEOUT1:
163 case MAX77843_SAFEOUT2:
164 return max77843->regmap;
165 case MAX77843_CHARGER:
166 return max77843->regmap_chg;
167 default:
168 return max77843->regmap;
169 }
170}
171
172static int max77843_regulator_probe(struct platform_device *pdev)
173{
174 struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent);
175 struct regulator_config config = {};
176 int i;
177
178 config.dev = max77843->dev;
179 config.driver_data = max77843;
180
181 for (i = 0; i < ARRAY_SIZE(max77843_supported_regulators); i++) {
182 struct regulator_dev *regulator;
183
184 config.regmap = max77843_get_regmap(max77843,
185 max77843_supported_regulators[i].id);
186
187 regulator = devm_regulator_register(&pdev->dev,
188 &max77843_supported_regulators[i], &config);
189 if (IS_ERR(regulator)) {
190 dev_err(&pdev->dev,
191 "Failed to regiser regulator-%d\n", i);
192 return PTR_ERR(regulator);
193 }
194 }
195
196 return 0;
197}
198
199static const struct platform_device_id max77843_regulator_id[] = {
200 { "max77843-regulator", },
201 { /* sentinel */ },
202};
203
204static struct platform_driver max77843_regulator_driver = {
205 .driver = {
206 .name = "max77843-regulator",
207 },
208 .probe = max77843_regulator_probe,
209 .id_table = max77843_regulator_id,
210};
211
212static int __init max77843_regulator_init(void)
213{
214 return platform_driver_register(&max77843_regulator_driver);
215}
216subsys_initcall(max77843_regulator_init);
217
218static void __exit max77843_regulator_exit(void)
219{
220 platform_driver_unregister(&max77843_regulator_driver);
221}
222module_exit(max77843_regulator_exit);
223
224MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>");
225MODULE_AUTHOR("Beomho Seo <beomho.seo@samsung.com>");
226MODULE_DESCRIPTION("Maxim MAX77843 regulator driver");
227MODULE_LICENSE("GPL");