diff options
-rw-r--r-- | drivers/regulator/Kconfig | 26 | ||||
-rw-r--r-- | drivers/regulator/Makefile | 3 | ||||
-rw-r--r-- | drivers/regulator/da903x.c | 2 | ||||
-rw-r--r-- | drivers/regulator/fixed.c | 18 | ||||
-rw-r--r-- | drivers/regulator/lp3971.c | 562 | ||||
-rw-r--r-- | drivers/regulator/max1586.c | 282 | ||||
-rw-r--r-- | drivers/regulator/pcf50633-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/userspace-consumer.c | 200 | ||||
-rw-r--r-- | drivers/regulator/virtual.c | 1 | ||||
-rw-r--r-- | drivers/regulator/wm8350-regulator.c | 1 | ||||
-rw-r--r-- | drivers/regulator/wm8400-regulator.c | 8 | ||||
-rw-r--r-- | include/linux/regulator/lp3971.h | 51 | ||||
-rw-r--r-- | include/linux/regulator/max1586.h | 63 | ||||
-rw-r--r-- | include/linux/regulator/userspace-consumer.h | 25 |
14 files changed, 1236 insertions, 8 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index e58c0ce65aa6..f4317798e47c 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -47,6 +47,16 @@ config REGULATOR_VIRTUAL_CONSUMER | |||
47 | 47 | ||
48 | If unsure, say no. | 48 | If unsure, say no. |
49 | 49 | ||
50 | config REGULATOR_USERSPACE_CONSUMER | ||
51 | tristate "Userspace regulator consumer support" | ||
52 | default n | ||
53 | help | ||
54 | There are some classes of devices that are controlled entirely | ||
55 | from user space. Usersapce consumer driver provides ability to | ||
56 | control power supplies for such devices. | ||
57 | |||
58 | If unsure, say no. | ||
59 | |||
50 | config REGULATOR_BQ24022 | 60 | config REGULATOR_BQ24022 |
51 | tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" | 61 | tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" |
52 | default n | 62 | default n |
@@ -56,6 +66,15 @@ config REGULATOR_BQ24022 | |||
56 | charging select between 100 mA and 500 mA charging current | 66 | charging select between 100 mA and 500 mA charging current |
57 | limit. | 67 | limit. |
58 | 68 | ||
69 | config REGULATOR_MAX1586 | ||
70 | tristate "Maxim 1586/1587 voltage regulator" | ||
71 | depends on I2C | ||
72 | default n | ||
73 | help | ||
74 | This driver controls a Maxim 1586 or 1587 voltage output | ||
75 | regulator via I2C bus. The provided regulator is suitable | ||
76 | for PXA27x chips to control VCC_CORE and VCC_USIM voltages. | ||
77 | |||
59 | config REGULATOR_TWL4030 | 78 | config REGULATOR_TWL4030 |
60 | bool "TI TWL4030/TWL5030/TPS695x0 PMIC" | 79 | bool "TI TWL4030/TWL5030/TPS695x0 PMIC" |
61 | depends on TWL4030_CORE | 80 | depends on TWL4030_CORE |
@@ -91,4 +110,11 @@ config REGULATOR_PCF50633 | |||
91 | Say Y here to support the voltage regulators and convertors | 110 | Say Y here to support the voltage regulators and convertors |
92 | on PCF50633 | 111 | on PCF50633 |
93 | 112 | ||
113 | config REGULATOR_LP3971 | ||
114 | tristate "National Semiconductors LP3971 PMIC regulator driver" | ||
115 | depends on I2C | ||
116 | help | ||
117 | Say Y here to support the voltage regulators and convertors | ||
118 | on National Semiconductors LP3971 PMIC | ||
119 | |||
94 | endif | 120 | endif |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index bac133afc061..4d762c4cccfd 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -6,8 +6,11 @@ | |||
6 | obj-$(CONFIG_REGULATOR) += core.o | 6 | obj-$(CONFIG_REGULATOR) += core.o |
7 | obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o | 7 | obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o |
8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o | 8 | obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o |
9 | obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o | ||
9 | 10 | ||
10 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o | 11 | obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o |
12 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | ||
13 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o | ||
11 | obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o | 14 | obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o |
12 | obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o | 15 | obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o |
13 | obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o | 16 | obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o |
diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index c6628f5a0af7..b8b89ef10a84 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c | |||
@@ -504,7 +504,7 @@ static int __init da903x_regulator_init(void) | |||
504 | { | 504 | { |
505 | return platform_driver_register(&da903x_regulator_driver); | 505 | return platform_driver_register(&da903x_regulator_driver); |
506 | } | 506 | } |
507 | module_init(da903x_regulator_init); | 507 | subsys_initcall(da903x_regulator_init); |
508 | 508 | ||
509 | static void __exit da903x_regulator_exit(void) | 509 | static void __exit da903x_regulator_exit(void) |
510 | { | 510 | { |
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 23d554628a76..cdc674fb46c3 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c | |||
@@ -44,10 +44,22 @@ static int fixed_voltage_get_voltage(struct regulator_dev *dev) | |||
44 | return data->microvolts; | 44 | return data->microvolts; |
45 | } | 45 | } |
46 | 46 | ||
47 | static int fixed_voltage_list_voltage(struct regulator_dev *dev, | ||
48 | unsigned selector) | ||
49 | { | ||
50 | struct fixed_voltage_data *data = rdev_get_drvdata(dev); | ||
51 | |||
52 | if (selector != 0) | ||
53 | return -EINVAL; | ||
54 | |||
55 | return data->microvolts; | ||
56 | } | ||
57 | |||
47 | static struct regulator_ops fixed_voltage_ops = { | 58 | static struct regulator_ops fixed_voltage_ops = { |
48 | .is_enabled = fixed_voltage_is_enabled, | 59 | .is_enabled = fixed_voltage_is_enabled, |
49 | .enable = fixed_voltage_enable, | 60 | .enable = fixed_voltage_enable, |
50 | .get_voltage = fixed_voltage_get_voltage, | 61 | .get_voltage = fixed_voltage_get_voltage, |
62 | .list_voltage = fixed_voltage_list_voltage, | ||
51 | }; | 63 | }; |
52 | 64 | ||
53 | static int regulator_fixed_voltage_probe(struct platform_device *pdev) | 65 | static int regulator_fixed_voltage_probe(struct platform_device *pdev) |
@@ -69,7 +81,8 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev) | |||
69 | } | 81 | } |
70 | drvdata->desc.type = REGULATOR_VOLTAGE; | 82 | drvdata->desc.type = REGULATOR_VOLTAGE; |
71 | drvdata->desc.owner = THIS_MODULE; | 83 | drvdata->desc.owner = THIS_MODULE; |
72 | drvdata->desc.ops = &fixed_voltage_ops, | 84 | drvdata->desc.ops = &fixed_voltage_ops; |
85 | drvdata->desc.n_voltages = 1; | ||
73 | 86 | ||
74 | drvdata->microvolts = config->microvolts; | 87 | drvdata->microvolts = config->microvolts; |
75 | 88 | ||
@@ -117,7 +130,7 @@ static int __init regulator_fixed_voltage_init(void) | |||
117 | { | 130 | { |
118 | return platform_driver_register(®ulator_fixed_voltage_driver); | 131 | return platform_driver_register(®ulator_fixed_voltage_driver); |
119 | } | 132 | } |
120 | module_init(regulator_fixed_voltage_init); | 133 | subsys_initcall(regulator_fixed_voltage_init); |
121 | 134 | ||
122 | static void __exit regulator_fixed_voltage_exit(void) | 135 | static void __exit regulator_fixed_voltage_exit(void) |
123 | { | 136 | { |
@@ -128,3 +141,4 @@ module_exit(regulator_fixed_voltage_exit); | |||
128 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 141 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
129 | MODULE_DESCRIPTION("Fixed voltage regulator"); | 142 | MODULE_DESCRIPTION("Fixed voltage regulator"); |
130 | MODULE_LICENSE("GPL"); | 143 | MODULE_LICENSE("GPL"); |
144 | MODULE_ALIAS("platform:reg-fixed-voltage"); | ||
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c new file mode 100644 index 000000000000..a61018a27698 --- /dev/null +++ b/drivers/regulator/lp3971.c | |||
@@ -0,0 +1,562 @@ | |||
1 | /* | ||
2 | * Regulator driver for National Semiconductors LP3971 PMIC chip | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics | ||
5 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | ||
6 | * | ||
7 | * Based on wm8350.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/bug.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/regulator/driver.h> | ||
20 | #include <linux/regulator/lp3971.h> | ||
21 | |||
22 | struct lp3971 { | ||
23 | struct device *dev; | ||
24 | struct mutex io_lock; | ||
25 | struct i2c_client *i2c; | ||
26 | int num_regulators; | ||
27 | struct regulator_dev **rdev; | ||
28 | }; | ||
29 | |||
30 | static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg); | ||
31 | static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val); | ||
32 | |||
33 | #define LP3971_SYS_CONTROL1_REG 0x07 | ||
34 | |||
35 | /* System control register 1 initial value, | ||
36 | bits 4 and 5 are EPROM programmable */ | ||
37 | #define SYS_CONTROL1_INIT_VAL 0x40 | ||
38 | #define SYS_CONTROL1_INIT_MASK 0xCF | ||
39 | |||
40 | #define LP3971_BUCK_VOL_ENABLE_REG 0x10 | ||
41 | #define LP3971_BUCK_VOL_CHANGE_REG 0x20 | ||
42 | |||
43 | /* Voltage control registers shift: | ||
44 | LP3971_BUCK1 -> 0 | ||
45 | LP3971_BUCK2 -> 4 | ||
46 | LP3971_BUCK3 -> 6 | ||
47 | */ | ||
48 | #define BUCK_VOL_CHANGE_SHIFT(x) (((1 << x) & ~0x01) << 1) | ||
49 | #define BUCK_VOL_CHANGE_FLAG_GO 0x01 | ||
50 | #define BUCK_VOL_CHANGE_FLAG_TARGET 0x02 | ||
51 | #define BUCK_VOL_CHANGE_FLAG_MASK 0x03 | ||
52 | |||
53 | #define LP3971_BUCK1_BASE 0x23 | ||
54 | #define LP3971_BUCK2_BASE 0x29 | ||
55 | #define LP3971_BUCK3_BASE 0x32 | ||
56 | |||
57 | const static int buck_base_addr[] = { | ||
58 | LP3971_BUCK1_BASE, | ||
59 | LP3971_BUCK2_BASE, | ||
60 | LP3971_BUCK3_BASE, | ||
61 | }; | ||
62 | |||
63 | #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x]) | ||
64 | #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1) | ||
65 | |||
66 | const static int buck_voltage_map[] = { | ||
67 | 0, 800, 850, 900, 950, 1000, 1050, 1100, | ||
68 | 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, | ||
69 | 1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800, | ||
70 | 3000, 3300, | ||
71 | }; | ||
72 | |||
73 | #define BUCK_TARGET_VOL_MASK 0x3f | ||
74 | #define BUCK_TARGET_VOL_MIN_IDX 0x01 | ||
75 | #define BUCK_TARGET_VOL_MAX_IDX 0x19 | ||
76 | |||
77 | #define LP3971_BUCK_RAMP_REG(x) (buck_base_addr[x]+2) | ||
78 | |||
79 | #define LP3971_LDO_ENABLE_REG 0x12 | ||
80 | #define LP3971_LDO_VOL_CONTR_BASE 0x39 | ||
81 | |||
82 | /* Voltage control registers: | ||
83 | LP3971_LDO1 -> LP3971_LDO_VOL_CONTR_BASE + 0 | ||
84 | LP3971_LDO2 -> LP3971_LDO_VOL_CONTR_BASE + 0 | ||
85 | LP3971_LDO3 -> LP3971_LDO_VOL_CONTR_BASE + 1 | ||
86 | LP3971_LDO4 -> LP3971_LDO_VOL_CONTR_BASE + 1 | ||
87 | LP3971_LDO5 -> LP3971_LDO_VOL_CONTR_BASE + 2 | ||
88 | */ | ||
89 | #define LP3971_LDO_VOL_CONTR_REG(x) (LP3971_LDO_VOL_CONTR_BASE + (x >> 1)) | ||
90 | |||
91 | /* Voltage control registers shift: | ||
92 | LP3971_LDO1 -> 0, LP3971_LDO2 -> 4 | ||
93 | LP3971_LDO3 -> 0, LP3971_LDO4 -> 4 | ||
94 | LP3971_LDO5 -> 0 | ||
95 | */ | ||
96 | #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2) | ||
97 | #define LDO_VOL_CONTR_MASK 0x0f | ||
98 | |||
99 | const static int ldo45_voltage_map[] = { | ||
100 | 1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, | ||
101 | 1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300, | ||
102 | }; | ||
103 | |||
104 | const static int ldo123_voltage_map[] = { | ||
105 | 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, | ||
106 | 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, | ||
107 | }; | ||
108 | |||
109 | const static int *ldo_voltage_map[] = { | ||
110 | ldo123_voltage_map, /* LDO1 */ | ||
111 | ldo123_voltage_map, /* LDO2 */ | ||
112 | ldo123_voltage_map, /* LDO3 */ | ||
113 | ldo45_voltage_map, /* LDO4 */ | ||
114 | ldo45_voltage_map, /* LDO5 */ | ||
115 | }; | ||
116 | |||
117 | #define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)]) | ||
118 | |||
119 | #define LDO_VOL_MIN_IDX 0x00 | ||
120 | #define LDO_VOL_MAX_IDX 0x0f | ||
121 | |||
122 | static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index) | ||
123 | { | ||
124 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | ||
125 | return 1000 * LDO_VOL_VALUE_MAP(ldo)[index]; | ||
126 | } | ||
127 | |||
128 | static int lp3971_ldo_is_enabled(struct regulator_dev *dev) | ||
129 | { | ||
130 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
131 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | ||
132 | u16 mask = 1 << (1 + ldo); | ||
133 | u16 val; | ||
134 | |||
135 | val = lp3971_reg_read(lp3971, LP3971_LDO_ENABLE_REG); | ||
136 | return (val & mask) != 0; | ||
137 | } | ||
138 | |||
139 | static int lp3971_ldo_enable(struct regulator_dev *dev) | ||
140 | { | ||
141 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
142 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | ||
143 | u16 mask = 1 << (1 + ldo); | ||
144 | |||
145 | return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, mask); | ||
146 | } | ||
147 | |||
148 | static int lp3971_ldo_disable(struct regulator_dev *dev) | ||
149 | { | ||
150 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
151 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | ||
152 | u16 mask = 1 << (1 + ldo); | ||
153 | |||
154 | return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0); | ||
155 | } | ||
156 | |||
157 | static int lp3971_ldo_get_voltage(struct regulator_dev *dev) | ||
158 | { | ||
159 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
160 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | ||
161 | u16 val, reg; | ||
162 | |||
163 | reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo)); | ||
164 | val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK; | ||
165 | |||
166 | return 1000 * LDO_VOL_VALUE_MAP(ldo)[val]; | ||
167 | } | ||
168 | |||
169 | static int lp3971_ldo_set_voltage(struct regulator_dev *dev, | ||
170 | int min_uV, int max_uV) | ||
171 | { | ||
172 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
173 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | ||
174 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
175 | const int *vol_map = LDO_VOL_VALUE_MAP(ldo); | ||
176 | u16 val; | ||
177 | |||
178 | if (min_vol < vol_map[LDO_VOL_MIN_IDX] || | ||
179 | min_vol > vol_map[LDO_VOL_MAX_IDX]) | ||
180 | return -EINVAL; | ||
181 | |||
182 | for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++) | ||
183 | if (vol_map[val] >= min_vol) | ||
184 | break; | ||
185 | |||
186 | if (vol_map[val] > max_vol) | ||
187 | return -EINVAL; | ||
188 | |||
189 | return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo), | ||
190 | LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), val); | ||
191 | } | ||
192 | |||
193 | static struct regulator_ops lp3971_ldo_ops = { | ||
194 | .list_voltage = lp3971_ldo_list_voltage, | ||
195 | .is_enabled = lp3971_ldo_is_enabled, | ||
196 | .enable = lp3971_ldo_enable, | ||
197 | .disable = lp3971_ldo_disable, | ||
198 | .get_voltage = lp3971_ldo_get_voltage, | ||
199 | .set_voltage = lp3971_ldo_set_voltage, | ||
200 | }; | ||
201 | |||
202 | static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) | ||
203 | { | ||
204 | return 1000 * buck_voltage_map[index]; | ||
205 | } | ||
206 | |||
207 | static int lp3971_dcdc_is_enabled(struct regulator_dev *dev) | ||
208 | { | ||
209 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
210 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | ||
211 | u16 mask = 1 << (buck * 2); | ||
212 | u16 val; | ||
213 | |||
214 | val = lp3971_reg_read(lp3971, LP3971_BUCK_VOL_ENABLE_REG); | ||
215 | return (val & mask) != 0; | ||
216 | } | ||
217 | |||
218 | static int lp3971_dcdc_enable(struct regulator_dev *dev) | ||
219 | { | ||
220 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
221 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | ||
222 | u16 mask = 1 << (buck * 2); | ||
223 | |||
224 | return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, mask); | ||
225 | } | ||
226 | |||
227 | static int lp3971_dcdc_disable(struct regulator_dev *dev) | ||
228 | { | ||
229 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
230 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | ||
231 | u16 mask = 1 << (buck * 2); | ||
232 | |||
233 | return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0); | ||
234 | } | ||
235 | |||
236 | static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) | ||
237 | { | ||
238 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
239 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | ||
240 | u16 reg; | ||
241 | int val; | ||
242 | |||
243 | reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck)); | ||
244 | reg &= BUCK_TARGET_VOL_MASK; | ||
245 | |||
246 | if (reg <= BUCK_TARGET_VOL_MAX_IDX) | ||
247 | val = 1000 * buck_voltage_map[reg]; | ||
248 | else { | ||
249 | val = 0; | ||
250 | dev_warn(&dev->dev, "chip reported incorrect voltage value.\n"); | ||
251 | } | ||
252 | |||
253 | return val; | ||
254 | } | ||
255 | |||
256 | static int lp3971_dcdc_set_voltage(struct regulator_dev *dev, | ||
257 | int min_uV, int max_uV) | ||
258 | { | ||
259 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | ||
260 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | ||
261 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
262 | const int *vol_map = buck_voltage_map; | ||
263 | u16 val; | ||
264 | int ret; | ||
265 | |||
266 | if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] || | ||
267 | min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX]) | ||
268 | return -EINVAL; | ||
269 | |||
270 | for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX; | ||
271 | val++) | ||
272 | if (vol_map[val] >= min_vol) | ||
273 | break; | ||
274 | |||
275 | if (vol_map[val] > max_vol) | ||
276 | return -EINVAL; | ||
277 | |||
278 | ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), | ||
279 | BUCK_TARGET_VOL_MASK, val); | ||
280 | if (ret) | ||
281 | return ret; | ||
282 | |||
283 | ret = lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG, | ||
284 | BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck), | ||
285 | BUCK_VOL_CHANGE_FLAG_GO << BUCK_VOL_CHANGE_SHIFT(buck)); | ||
286 | if (ret) | ||
287 | return ret; | ||
288 | |||
289 | return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG, | ||
290 | BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck), | ||
291 | 0 << BUCK_VOL_CHANGE_SHIFT(buck)); | ||
292 | } | ||
293 | |||
294 | static struct regulator_ops lp3971_dcdc_ops = { | ||
295 | .list_voltage = lp3971_dcdc_list_voltage, | ||
296 | .is_enabled = lp3971_dcdc_is_enabled, | ||
297 | .enable = lp3971_dcdc_enable, | ||
298 | .disable = lp3971_dcdc_disable, | ||
299 | .get_voltage = lp3971_dcdc_get_voltage, | ||
300 | .set_voltage = lp3971_dcdc_set_voltage, | ||
301 | }; | ||
302 | |||
303 | static struct regulator_desc regulators[] = { | ||
304 | { | ||
305 | .name = "LDO1", | ||
306 | .id = LP3971_LDO1, | ||
307 | .ops = &lp3971_ldo_ops, | ||
308 | .n_voltages = ARRAY_SIZE(ldo123_voltage_map), | ||
309 | .type = REGULATOR_VOLTAGE, | ||
310 | .owner = THIS_MODULE, | ||
311 | }, | ||
312 | { | ||
313 | .name = "LDO2", | ||
314 | .id = LP3971_LDO2, | ||
315 | .ops = &lp3971_ldo_ops, | ||
316 | .n_voltages = ARRAY_SIZE(ldo123_voltage_map), | ||
317 | .type = REGULATOR_VOLTAGE, | ||
318 | .owner = THIS_MODULE, | ||
319 | }, | ||
320 | { | ||
321 | .name = "LDO3", | ||
322 | .id = LP3971_LDO3, | ||
323 | .ops = &lp3971_ldo_ops, | ||
324 | .n_voltages = ARRAY_SIZE(ldo123_voltage_map), | ||
325 | .type = REGULATOR_VOLTAGE, | ||
326 | .owner = THIS_MODULE, | ||
327 | }, | ||
328 | { | ||
329 | .name = "LDO4", | ||
330 | .id = LP3971_LDO4, | ||
331 | .ops = &lp3971_ldo_ops, | ||
332 | .n_voltages = ARRAY_SIZE(ldo45_voltage_map), | ||
333 | .type = REGULATOR_VOLTAGE, | ||
334 | .owner = THIS_MODULE, | ||
335 | }, | ||
336 | { | ||
337 | .name = "LDO5", | ||
338 | .id = LP3971_LDO5, | ||
339 | .ops = &lp3971_ldo_ops, | ||
340 | .n_voltages = ARRAY_SIZE(ldo45_voltage_map), | ||
341 | .type = REGULATOR_VOLTAGE, | ||
342 | .owner = THIS_MODULE, | ||
343 | }, | ||
344 | { | ||
345 | .name = "DCDC1", | ||
346 | .id = LP3971_DCDC1, | ||
347 | .ops = &lp3971_dcdc_ops, | ||
348 | .n_voltages = ARRAY_SIZE(buck_voltage_map), | ||
349 | .type = REGULATOR_VOLTAGE, | ||
350 | .owner = THIS_MODULE, | ||
351 | }, | ||
352 | { | ||
353 | .name = "DCDC2", | ||
354 | .id = LP3971_DCDC2, | ||
355 | .ops = &lp3971_dcdc_ops, | ||
356 | .n_voltages = ARRAY_SIZE(buck_voltage_map), | ||
357 | .type = REGULATOR_VOLTAGE, | ||
358 | .owner = THIS_MODULE, | ||
359 | }, | ||
360 | { | ||
361 | .name = "DCDC3", | ||
362 | .id = LP3971_DCDC3, | ||
363 | .ops = &lp3971_dcdc_ops, | ||
364 | .n_voltages = ARRAY_SIZE(buck_voltage_map), | ||
365 | .type = REGULATOR_VOLTAGE, | ||
366 | .owner = THIS_MODULE, | ||
367 | }, | ||
368 | }; | ||
369 | |||
370 | static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, | ||
371 | u16 *dest) | ||
372 | { | ||
373 | int ret; | ||
374 | |||
375 | if (count != 1) | ||
376 | return -EIO; | ||
377 | ret = i2c_smbus_read_byte_data(i2c, reg); | ||
378 | if (ret < 0 || count != 1) | ||
379 | return -EIO; | ||
380 | |||
381 | *dest = ret; | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count, | ||
386 | const u16 *src) | ||
387 | { | ||
388 | int ret; | ||
389 | |||
390 | if (count != 1) | ||
391 | return -EIO; | ||
392 | ret = i2c_smbus_write_byte_data(i2c, reg, *src); | ||
393 | if (ret >= 0) | ||
394 | return 0; | ||
395 | |||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg) | ||
400 | { | ||
401 | u16 val = 0; | ||
402 | |||
403 | mutex_lock(&lp3971->io_lock); | ||
404 | |||
405 | lp3971_i2c_read(lp3971->i2c, reg, 1, &val); | ||
406 | |||
407 | dev_dbg(lp3971->dev, "reg read 0x%02x -> 0x%02x\n", (int)reg, | ||
408 | (unsigned)val&0xff); | ||
409 | |||
410 | mutex_unlock(&lp3971->io_lock); | ||
411 | |||
412 | return val & 0xff; | ||
413 | } | ||
414 | |||
415 | static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val) | ||
416 | { | ||
417 | u16 tmp; | ||
418 | int ret; | ||
419 | |||
420 | mutex_lock(&lp3971->io_lock); | ||
421 | |||
422 | ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp); | ||
423 | tmp = (tmp & ~mask) | val; | ||
424 | if (ret == 0) { | ||
425 | ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp); | ||
426 | dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg, | ||
427 | (unsigned)val&0xff); | ||
428 | } | ||
429 | mutex_unlock(&lp3971->io_lock); | ||
430 | |||
431 | return ret; | ||
432 | } | ||
433 | |||
434 | static int setup_regulators(struct lp3971 *lp3971, | ||
435 | struct lp3971_platform_data *pdata) | ||
436 | { | ||
437 | int i, err; | ||
438 | int num_regulators = pdata->num_regulators; | ||
439 | lp3971->num_regulators = num_regulators; | ||
440 | lp3971->rdev = kzalloc(sizeof(struct regulator_dev *) * num_regulators, | ||
441 | GFP_KERNEL); | ||
442 | |||
443 | /* Instantiate the regulators */ | ||
444 | for (i = 0; i < num_regulators; i++) { | ||
445 | int id = pdata->regulators[i].id; | ||
446 | lp3971->rdev[i] = regulator_register(®ulators[id], | ||
447 | lp3971->dev, pdata->regulators[i].initdata, lp3971); | ||
448 | |||
449 | err = IS_ERR(lp3971->rdev[i]); | ||
450 | if (err) { | ||
451 | dev_err(lp3971->dev, "regulator init failed: %d\n", | ||
452 | err); | ||
453 | goto error; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | return 0; | ||
458 | error: | ||
459 | for (i = 0; i < num_regulators; i++) | ||
460 | if (lp3971->rdev[i]) | ||
461 | regulator_unregister(lp3971->rdev[i]); | ||
462 | kfree(lp3971->rdev); | ||
463 | lp3971->rdev = NULL; | ||
464 | return err; | ||
465 | } | ||
466 | |||
467 | static int __devinit lp3971_i2c_probe(struct i2c_client *i2c, | ||
468 | const struct i2c_device_id *id) | ||
469 | { | ||
470 | struct lp3971 *lp3971; | ||
471 | struct lp3971_platform_data *pdata = i2c->dev.platform_data; | ||
472 | int ret; | ||
473 | u16 val; | ||
474 | |||
475 | lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL); | ||
476 | if (lp3971 == NULL) { | ||
477 | ret = -ENOMEM; | ||
478 | goto err; | ||
479 | } | ||
480 | |||
481 | lp3971->i2c = i2c; | ||
482 | lp3971->dev = &i2c->dev; | ||
483 | i2c_set_clientdata(i2c, lp3971); | ||
484 | |||
485 | mutex_init(&lp3971->io_lock); | ||
486 | |||
487 | /* Detect LP3971 */ | ||
488 | ret = lp3971_i2c_read(i2c, LP3971_SYS_CONTROL1_REG, 1, &val); | ||
489 | if (ret == 0 && (val & SYS_CONTROL1_INIT_MASK) != SYS_CONTROL1_INIT_VAL) | ||
490 | ret = -ENODEV; | ||
491 | if (ret < 0) { | ||
492 | dev_err(&i2c->dev, "failed to detect device\n"); | ||
493 | goto err_detect; | ||
494 | } | ||
495 | |||
496 | if (pdata) { | ||
497 | ret = setup_regulators(lp3971, pdata); | ||
498 | if (ret < 0) | ||
499 | goto err_detect; | ||
500 | } else | ||
501 | dev_warn(lp3971->dev, "No platform init data supplied\n"); | ||
502 | |||
503 | return 0; | ||
504 | |||
505 | err_detect: | ||
506 | i2c_set_clientdata(i2c, NULL); | ||
507 | kfree(lp3971); | ||
508 | err: | ||
509 | return ret; | ||
510 | } | ||
511 | |||
512 | static int __devexit lp3971_i2c_remove(struct i2c_client *i2c) | ||
513 | { | ||
514 | struct lp3971 *lp3971 = i2c_get_clientdata(i2c); | ||
515 | int i; | ||
516 | for (i = 0; i < lp3971->num_regulators; i++) | ||
517 | if (lp3971->rdev[i]) | ||
518 | regulator_unregister(lp3971->rdev[i]); | ||
519 | kfree(lp3971->rdev); | ||
520 | i2c_set_clientdata(i2c, NULL); | ||
521 | kfree(lp3971); | ||
522 | |||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | static const struct i2c_device_id lp3971_i2c_id[] = { | ||
527 | { "lp3971", 0 }, | ||
528 | { } | ||
529 | }; | ||
530 | MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id); | ||
531 | |||
532 | static struct i2c_driver lp3971_i2c_driver = { | ||
533 | .driver = { | ||
534 | .name = "LP3971", | ||
535 | .owner = THIS_MODULE, | ||
536 | }, | ||
537 | .probe = lp3971_i2c_probe, | ||
538 | .remove = __devexit_p(lp3971_i2c_remove), | ||
539 | .id_table = lp3971_i2c_id, | ||
540 | }; | ||
541 | |||
542 | static int __init lp3971_module_init(void) | ||
543 | { | ||
544 | int ret = -ENODEV; | ||
545 | |||
546 | ret = i2c_add_driver(&lp3971_i2c_driver); | ||
547 | if (ret != 0) | ||
548 | pr_err("Failed to register I2C driver: %d\n", ret); | ||
549 | |||
550 | return ret; | ||
551 | } | ||
552 | module_init(lp3971_module_init); | ||
553 | |||
554 | static void __exit lp3971_module_exit(void) | ||
555 | { | ||
556 | i2c_del_driver(&lp3971_i2c_driver); | ||
557 | } | ||
558 | module_exit(lp3971_module_exit); | ||
559 | |||
560 | MODULE_LICENSE("GPL"); | ||
561 | MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>"); | ||
562 | MODULE_DESCRIPTION("LP3971 PMIC driver"); | ||
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c new file mode 100644 index 000000000000..2c082d3ef484 --- /dev/null +++ b/drivers/regulator/max1586.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | * max1586.c -- Voltage and current regulation for the Maxim 1586 | ||
3 | * | ||
4 | * Copyright (C) 2008 Robert Jarzmik | ||
5 | * | ||
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. | ||
10 | * | ||
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. | ||
15 | * | ||
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 | ||
19 | */ | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/regulator/driver.h> | ||
25 | #include <linux/regulator/max1586.h> | ||
26 | |||
27 | #define MAX1586_V3_MAX_VSEL 31 | ||
28 | #define MAX1586_V6_MAX_VSEL 3 | ||
29 | |||
30 | #define MAX1586_V3_MIN_UV 700000 | ||
31 | #define MAX1586_V3_MAX_UV 1475000 | ||
32 | |||
33 | #define MAX1586_V6_MIN_UV 0 | ||
34 | #define MAX1586_V6_MAX_UV 3000000 | ||
35 | |||
36 | #define I2C_V3_SELECT (0 << 5) | ||
37 | #define I2C_V6_SELECT (1 << 5) | ||
38 | |||
39 | struct max1586_data { | ||
40 | struct i2c_client *client; | ||
41 | |||
42 | /* min/max V3 voltage */ | ||
43 | unsigned int min_uV; | ||
44 | unsigned int max_uV; | ||
45 | |||
46 | struct regulator_dev *rdev[0]; | ||
47 | }; | ||
48 | |||
49 | /* | ||
50 | * V3 voltage | ||
51 | * On I2C bus, sending a "x" byte to the max1586 means : | ||
52 | * set V3 to 0.700V + (x & 0x1f) * 0.025V | ||
53 | * This voltage can be increased by external resistors | ||
54 | * R24 and R25=100kOhm as described in the data sheet. | ||
55 | * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm | ||
56 | */ | ||
57 | static int max1586_v3_calc_voltage(struct max1586_data *max1586, | ||
58 | unsigned selector) | ||
59 | { | ||
60 | unsigned range_uV = max1586->max_uV - max1586->min_uV; | ||
61 | |||
62 | return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL); | ||
63 | } | ||
64 | |||
65 | static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV) | ||
66 | { | ||
67 | struct max1586_data *max1586 = rdev_get_drvdata(rdev); | ||
68 | struct i2c_client *client = max1586->client; | ||
69 | unsigned range_uV = max1586->max_uV - max1586->min_uV; | ||
70 | unsigned selector; | ||
71 | u8 v3_prog; | ||
72 | |||
73 | if (min_uV > max1586->max_uV || max_uV < max1586->min_uV) | ||
74 | return -EINVAL; | ||
75 | if (min_uV < max1586->min_uV) | ||
76 | min_uV = max1586->min_uV; | ||
77 | |||
78 | selector = ((min_uV - max1586->min_uV) * MAX1586_V3_MAX_VSEL + | ||
79 | range_uV - 1) / range_uV; | ||
80 | if (max1586_v3_calc_voltage(max1586, selector) > max_uV) | ||
81 | return -EINVAL; | ||
82 | |||
83 | dev_dbg(&client->dev, "changing voltage v3 to %dmv\n", | ||
84 | max1586_v3_calc_voltage(max1586, selector) / 1000); | ||
85 | |||
86 | v3_prog = I2C_V3_SELECT | (u8) selector; | ||
87 | return i2c_smbus_write_byte(client, v3_prog); | ||
88 | } | ||
89 | |||
90 | static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector) | ||
91 | { | ||
92 | struct max1586_data *max1586 = rdev_get_drvdata(rdev); | ||
93 | |||
94 | if (selector > MAX1586_V3_MAX_VSEL) | ||
95 | return -EINVAL; | ||
96 | return max1586_v3_calc_voltage(max1586, selector); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * V6 voltage | ||
101 | * On I2C bus, sending a "x" byte to the max1586 means : | ||
102 | * set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3) | ||
103 | * As regulator framework doesn't accept voltages to be 0V, we use 1uV. | ||
104 | */ | ||
105 | static int max1586_v6_calc_voltage(unsigned selector) | ||
106 | { | ||
107 | static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 }; | ||
108 | |||
109 | return voltages_uv[selector]; | ||
110 | } | ||
111 | |||
112 | static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV) | ||
113 | { | ||
114 | struct i2c_client *client = rdev_get_drvdata(rdev); | ||
115 | unsigned selector; | ||
116 | u8 v6_prog; | ||
117 | |||
118 | if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV) | ||
119 | return -EINVAL; | ||
120 | if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV) | ||
121 | return -EINVAL; | ||
122 | |||
123 | if (min_uV >= 3000000) | ||
124 | selector = 3; | ||
125 | if (min_uV < 3000000) | ||
126 | selector = 2; | ||
127 | if (min_uV < 2500000) | ||
128 | selector = 1; | ||
129 | if (min_uV < 1800000) | ||
130 | selector = 0; | ||
131 | |||
132 | if (max1586_v6_calc_voltage(selector) > max_uV) | ||
133 | return -EINVAL; | ||
134 | |||
135 | dev_dbg(&client->dev, "changing voltage v6 to %dmv\n", | ||
136 | max1586_v6_calc_voltage(selector) / 1000); | ||
137 | |||
138 | v6_prog = I2C_V6_SELECT | (u8) selector; | ||
139 | return i2c_smbus_write_byte(client, v6_prog); | ||
140 | } | ||
141 | |||
142 | static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector) | ||
143 | { | ||
144 | if (selector > MAX1586_V6_MAX_VSEL) | ||
145 | return -EINVAL; | ||
146 | return max1586_v6_calc_voltage(selector); | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * The Maxim 1586 controls V3 and V6 voltages, but offers no way of reading back | ||
151 | * the set up value. | ||
152 | */ | ||
153 | static struct regulator_ops max1586_v3_ops = { | ||
154 | .set_voltage = max1586_v3_set, | ||
155 | .list_voltage = max1586_v3_list, | ||
156 | }; | ||
157 | |||
158 | static struct regulator_ops max1586_v6_ops = { | ||
159 | .set_voltage = max1586_v6_set, | ||
160 | .list_voltage = max1586_v6_list, | ||
161 | }; | ||
162 | |||
163 | static struct regulator_desc max1586_reg[] = { | ||
164 | { | ||
165 | .name = "Output_V3", | ||
166 | .id = MAX1586_V3, | ||
167 | .ops = &max1586_v3_ops, | ||
168 | .type = REGULATOR_VOLTAGE, | ||
169 | .n_voltages = MAX1586_V3_MAX_VSEL + 1, | ||
170 | .owner = THIS_MODULE, | ||
171 | }, | ||
172 | { | ||
173 | .name = "Output_V6", | ||
174 | .id = MAX1586_V6, | ||
175 | .ops = &max1586_v6_ops, | ||
176 | .type = REGULATOR_VOLTAGE, | ||
177 | .n_voltages = MAX1586_V6_MAX_VSEL + 1, | ||
178 | .owner = THIS_MODULE, | ||
179 | }, | ||
180 | }; | ||
181 | |||
182 | static int max1586_pmic_probe(struct i2c_client *client, | ||
183 | const struct i2c_device_id *i2c_id) | ||
184 | { | ||
185 | struct regulator_dev **rdev; | ||
186 | struct max1586_platform_data *pdata = client->dev.platform_data; | ||
187 | struct max1586_data *max1586; | ||
188 | int i, id, ret = -ENOMEM; | ||
189 | |||
190 | max1586 = kzalloc(sizeof(struct max1586_data) + | ||
191 | sizeof(struct regulator_dev *) * (MAX1586_V6 + 1), | ||
192 | GFP_KERNEL); | ||
193 | if (!max1586) | ||
194 | goto out; | ||
195 | |||
196 | max1586->client = client; | ||
197 | |||
198 | if (!pdata->v3_gain) { | ||
199 | ret = -EINVAL; | ||
200 | goto out_unmap; | ||
201 | } | ||
202 | max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000; | ||
203 | max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000; | ||
204 | |||
205 | rdev = max1586->rdev; | ||
206 | for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) { | ||
207 | id = pdata->subdevs[i].id; | ||
208 | if (!pdata->subdevs[i].platform_data) | ||
209 | continue; | ||
210 | if (id < MAX1586_V3 || id > MAX1586_V6) { | ||
211 | dev_err(&client->dev, "invalid regulator id %d\n", id); | ||
212 | goto err; | ||
213 | } | ||
214 | rdev[i] = regulator_register(&max1586_reg[id], &client->dev, | ||
215 | pdata->subdevs[i].platform_data, | ||
216 | max1586); | ||
217 | if (IS_ERR(rdev[i])) { | ||
218 | ret = PTR_ERR(rdev[i]); | ||
219 | dev_err(&client->dev, "failed to register %s\n", | ||
220 | max1586_reg[id].name); | ||
221 | goto err; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | i2c_set_clientdata(client, rdev); | ||
226 | dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n"); | ||
227 | return 0; | ||
228 | |||
229 | err: | ||
230 | while (--i >= 0) | ||
231 | regulator_unregister(rdev[i]); | ||
232 | out_unmap: | ||
233 | kfree(max1586); | ||
234 | out: | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | static int max1586_pmic_remove(struct i2c_client *client) | ||
239 | { | ||
240 | struct regulator_dev **rdev = i2c_get_clientdata(client); | ||
241 | int i; | ||
242 | |||
243 | for (i = 0; i <= MAX1586_V6; i++) | ||
244 | if (rdev[i]) | ||
245 | regulator_unregister(rdev[i]); | ||
246 | kfree(rdev); | ||
247 | i2c_set_clientdata(client, NULL); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static const struct i2c_device_id max1586_id[] = { | ||
253 | { "max1586", 0 }, | ||
254 | { } | ||
255 | }; | ||
256 | MODULE_DEVICE_TABLE(i2c, max1586_id); | ||
257 | |||
258 | static struct i2c_driver max1586_pmic_driver = { | ||
259 | .probe = max1586_pmic_probe, | ||
260 | .remove = max1586_pmic_remove, | ||
261 | .driver = { | ||
262 | .name = "max1586", | ||
263 | }, | ||
264 | .id_table = max1586_id, | ||
265 | }; | ||
266 | |||
267 | static int __init max1586_pmic_init(void) | ||
268 | { | ||
269 | return i2c_add_driver(&max1586_pmic_driver); | ||
270 | } | ||
271 | subsys_initcall(max1586_pmic_init); | ||
272 | |||
273 | static void __exit max1586_pmic_exit(void) | ||
274 | { | ||
275 | i2c_del_driver(&max1586_pmic_driver); | ||
276 | } | ||
277 | module_exit(max1586_pmic_exit); | ||
278 | |||
279 | /* Module information */ | ||
280 | MODULE_DESCRIPTION("MAXIM 1586 voltage regulator driver"); | ||
281 | MODULE_AUTHOR("Robert Jarzmik"); | ||
282 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index cd761d85c8fd..8e14900eb686 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c | |||
@@ -316,7 +316,7 @@ static int __init pcf50633_regulator_init(void) | |||
316 | { | 316 | { |
317 | return platform_driver_register(&pcf50633_regulator_driver); | 317 | return platform_driver_register(&pcf50633_regulator_driver); |
318 | } | 318 | } |
319 | module_init(pcf50633_regulator_init); | 319 | subsys_initcall(pcf50633_regulator_init); |
320 | 320 | ||
321 | static void __exit pcf50633_regulator_exit(void) | 321 | static void __exit pcf50633_regulator_exit(void) |
322 | { | 322 | { |
diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c new file mode 100644 index 000000000000..06d2fa96a8b4 --- /dev/null +++ b/drivers/regulator/userspace-consumer.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* | ||
2 | * userspace-consumer.c | ||
3 | * | ||
4 | * Copyright 2009 CompuLab, Ltd. | ||
5 | * | ||
6 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
7 | * | ||
8 | * Based of virtual consumer driver: | ||
9 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
10 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License as | ||
14 | * published by the Free Software Foundation; either version 2 of the | ||
15 | * License, or (at your option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/err.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | #include <linux/regulator/userspace-consumer.h> | ||
24 | |||
25 | struct userspace_consumer_data { | ||
26 | const char *name; | ||
27 | |||
28 | struct mutex lock; | ||
29 | bool enabled; | ||
30 | |||
31 | int num_supplies; | ||
32 | struct regulator_bulk_data *supplies; | ||
33 | }; | ||
34 | |||
35 | static ssize_t reg_show_name(struct device *dev, | ||
36 | struct device_attribute *attr, char *buf) | ||
37 | { | ||
38 | struct userspace_consumer_data *data = dev_get_drvdata(dev); | ||
39 | |||
40 | return sprintf(buf, "%s\n", data->name); | ||
41 | } | ||
42 | |||
43 | static ssize_t reg_show_state(struct device *dev, | ||
44 | struct device_attribute *attr, char *buf) | ||
45 | { | ||
46 | struct userspace_consumer_data *data = dev_get_drvdata(dev); | ||
47 | |||
48 | if (data->enabled) | ||
49 | return sprintf(buf, "enabled\n"); | ||
50 | |||
51 | return sprintf(buf, "disabled\n"); | ||
52 | } | ||
53 | |||
54 | static ssize_t reg_set_state(struct device *dev, struct device_attribute *attr, | ||
55 | const char *buf, size_t count) | ||
56 | { | ||
57 | struct userspace_consumer_data *data = dev_get_drvdata(dev); | ||
58 | bool enabled; | ||
59 | int ret; | ||
60 | |||
61 | /* | ||
62 | * sysfs_streq() doesn't need the \n's, but we add them so the strings | ||
63 | * will be shared with show_state(), above. | ||
64 | */ | ||
65 | if (sysfs_streq(buf, "enabled\n") || sysfs_streq(buf, "1")) | ||
66 | enabled = true; | ||
67 | else if (sysfs_streq(buf, "disabled\n") || sysfs_streq(buf, "0")) | ||
68 | enabled = false; | ||
69 | else { | ||
70 | dev_err(dev, "Configuring invalid mode\n"); | ||
71 | return count; | ||
72 | } | ||
73 | |||
74 | mutex_lock(&data->lock); | ||
75 | if (enabled != data->enabled) { | ||
76 | if (enabled) | ||
77 | ret = regulator_bulk_enable(data->num_supplies, | ||
78 | data->supplies); | ||
79 | else | ||
80 | ret = regulator_bulk_disable(data->num_supplies, | ||
81 | data->supplies); | ||
82 | |||
83 | if (ret == 0) | ||
84 | data->enabled = enabled; | ||
85 | else | ||
86 | dev_err(dev, "Failed to configure state: %d\n", ret); | ||
87 | } | ||
88 | mutex_unlock(&data->lock); | ||
89 | |||
90 | return count; | ||
91 | } | ||
92 | |||
93 | static DEVICE_ATTR(name, 0444, reg_show_name, NULL); | ||
94 | static DEVICE_ATTR(state, 0644, reg_show_state, reg_set_state); | ||
95 | |||
96 | static struct device_attribute *attributes[] = { | ||
97 | &dev_attr_name, | ||
98 | &dev_attr_state, | ||
99 | }; | ||
100 | |||
101 | static int regulator_userspace_consumer_probe(struct platform_device *pdev) | ||
102 | { | ||
103 | struct regulator_userspace_consumer_data *pdata; | ||
104 | struct userspace_consumer_data *drvdata; | ||
105 | int ret, i; | ||
106 | |||
107 | pdata = pdev->dev.platform_data; | ||
108 | if (!pdata) | ||
109 | return -EINVAL; | ||
110 | |||
111 | drvdata = kzalloc(sizeof(struct userspace_consumer_data), GFP_KERNEL); | ||
112 | if (drvdata == NULL) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | drvdata->name = pdata->name; | ||
116 | drvdata->num_supplies = pdata->num_supplies; | ||
117 | drvdata->supplies = pdata->supplies; | ||
118 | |||
119 | mutex_init(&drvdata->lock); | ||
120 | |||
121 | ret = regulator_bulk_get(&pdev->dev, drvdata->num_supplies, | ||
122 | drvdata->supplies); | ||
123 | if (ret) { | ||
124 | dev_err(&pdev->dev, "Failed to get supplies: %d\n", ret); | ||
125 | goto err_alloc_supplies; | ||
126 | } | ||
127 | |||
128 | for (i = 0; i < ARRAY_SIZE(attributes); i++) { | ||
129 | ret = device_create_file(&pdev->dev, attributes[i]); | ||
130 | if (ret != 0) | ||
131 | goto err_create_attrs; | ||
132 | } | ||
133 | |||
134 | if (pdata->init_on) | ||
135 | ret = regulator_bulk_enable(drvdata->num_supplies, | ||
136 | drvdata->supplies); | ||
137 | |||
138 | drvdata->enabled = pdata->init_on; | ||
139 | |||
140 | if (ret) { | ||
141 | dev_err(&pdev->dev, "Failed to set initial state: %d\n", ret); | ||
142 | goto err_create_attrs; | ||
143 | } | ||
144 | |||
145 | platform_set_drvdata(pdev, drvdata); | ||
146 | |||
147 | return 0; | ||
148 | |||
149 | err_create_attrs: | ||
150 | for (i = 0; i < ARRAY_SIZE(attributes); i++) | ||
151 | device_remove_file(&pdev->dev, attributes[i]); | ||
152 | |||
153 | regulator_bulk_free(drvdata->num_supplies, drvdata->supplies); | ||
154 | |||
155 | err_alloc_supplies: | ||
156 | kfree(drvdata); | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int regulator_userspace_consumer_remove(struct platform_device *pdev) | ||
161 | { | ||
162 | struct userspace_consumer_data *data = platform_get_drvdata(pdev); | ||
163 | int i; | ||
164 | |||
165 | for (i = 0; i < ARRAY_SIZE(attributes); i++) | ||
166 | device_remove_file(&pdev->dev, attributes[i]); | ||
167 | |||
168 | if (data->enabled) | ||
169 | regulator_bulk_disable(data->num_supplies, data->supplies); | ||
170 | |||
171 | regulator_bulk_free(data->num_supplies, data->supplies); | ||
172 | kfree(data); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static struct platform_driver regulator_userspace_consumer_driver = { | ||
178 | .probe = regulator_userspace_consumer_probe, | ||
179 | .remove = regulator_userspace_consumer_remove, | ||
180 | .driver = { | ||
181 | .name = "reg-userspace-consumer", | ||
182 | }, | ||
183 | }; | ||
184 | |||
185 | |||
186 | static int __init regulator_userspace_consumer_init(void) | ||
187 | { | ||
188 | return platform_driver_register(®ulator_userspace_consumer_driver); | ||
189 | } | ||
190 | module_init(regulator_userspace_consumer_init); | ||
191 | |||
192 | static void __exit regulator_userspace_consumer_exit(void) | ||
193 | { | ||
194 | platform_driver_unregister(®ulator_userspace_consumer_driver); | ||
195 | } | ||
196 | module_exit(regulator_userspace_consumer_exit); | ||
197 | |||
198 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); | ||
199 | MODULE_DESCRIPTION("Userspace consumer for voltage and current regulators"); | ||
200 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c index 71403fa3ffa1..e7db5664722e 100644 --- a/drivers/regulator/virtual.c +++ b/drivers/regulator/virtual.c | |||
@@ -347,3 +347,4 @@ module_exit(regulator_virtual_consumer_exit); | |||
347 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 347 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
348 | MODULE_DESCRIPTION("Virtual regulator consumer"); | 348 | MODULE_DESCRIPTION("Virtual regulator consumer"); |
349 | MODULE_LICENSE("GPL"); | 349 | MODULE_LICENSE("GPL"); |
350 | MODULE_ALIAS("platform:reg-virt-consumer"); | ||
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 771eca1066b5..17a00b0fafd1 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c | |||
@@ -1570,3 +1570,4 @@ module_exit(wm8350_regulator_exit); | |||
1570 | MODULE_AUTHOR("Liam Girdwood"); | 1570 | MODULE_AUTHOR("Liam Girdwood"); |
1571 | MODULE_DESCRIPTION("WM8350 voltage and current regulator driver"); | 1571 | MODULE_DESCRIPTION("WM8350 voltage and current regulator driver"); |
1572 | MODULE_LICENSE("GPL"); | 1572 | MODULE_LICENSE("GPL"); |
1573 | MODULE_ALIAS("platform:wm8350-regulator"); | ||
diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 157426029071..d9a2c988c6e7 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c | |||
@@ -320,7 +320,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev) | |||
320 | struct regulator_dev *rdev; | 320 | struct regulator_dev *rdev; |
321 | 321 | ||
322 | rdev = regulator_register(®ulators[pdev->id], &pdev->dev, | 322 | rdev = regulator_register(®ulators[pdev->id], &pdev->dev, |
323 | pdev->dev.platform_data, pdev->dev.driver_data); | 323 | pdev->dev.platform_data, dev_get_drvdata(&pdev->dev)); |
324 | 324 | ||
325 | if (IS_ERR(rdev)) | 325 | if (IS_ERR(rdev)) |
326 | return PTR_ERR(rdev); | 326 | return PTR_ERR(rdev); |
@@ -359,7 +359,7 @@ static struct platform_driver wm8400_regulator_driver = { | |||
359 | int wm8400_register_regulator(struct device *dev, int reg, | 359 | int wm8400_register_regulator(struct device *dev, int reg, |
360 | struct regulator_init_data *initdata) | 360 | struct regulator_init_data *initdata) |
361 | { | 361 | { |
362 | struct wm8400 *wm8400 = dev->driver_data; | 362 | struct wm8400 *wm8400 = dev_get_drvdata(dev); |
363 | 363 | ||
364 | if (wm8400->regulators[reg].name) | 364 | if (wm8400->regulators[reg].name) |
365 | return -EBUSY; | 365 | return -EBUSY; |
@@ -369,8 +369,8 @@ int wm8400_register_regulator(struct device *dev, int reg, | |||
369 | wm8400->regulators[reg].name = "wm8400-regulator"; | 369 | wm8400->regulators[reg].name = "wm8400-regulator"; |
370 | wm8400->regulators[reg].id = reg; | 370 | wm8400->regulators[reg].id = reg; |
371 | wm8400->regulators[reg].dev.parent = dev; | 371 | wm8400->regulators[reg].dev.parent = dev; |
372 | wm8400->regulators[reg].dev.driver_data = wm8400; | ||
373 | wm8400->regulators[reg].dev.platform_data = initdata; | 372 | wm8400->regulators[reg].dev.platform_data = initdata; |
373 | dev_set_drvdata(&wm8400->regulators[reg].dev, wm8400); | ||
374 | 374 | ||
375 | return platform_device_register(&wm8400->regulators[reg]); | 375 | return platform_device_register(&wm8400->regulators[reg]); |
376 | } | 376 | } |
@@ -380,7 +380,7 @@ static int __init wm8400_regulator_init(void) | |||
380 | { | 380 | { |
381 | return platform_driver_register(&wm8400_regulator_driver); | 381 | return platform_driver_register(&wm8400_regulator_driver); |
382 | } | 382 | } |
383 | module_init(wm8400_regulator_init); | 383 | subsys_initcall(wm8400_regulator_init); |
384 | 384 | ||
385 | static void __exit wm8400_regulator_exit(void) | 385 | static void __exit wm8400_regulator_exit(void) |
386 | { | 386 | { |
diff --git a/include/linux/regulator/lp3971.h b/include/linux/regulator/lp3971.h new file mode 100644 index 000000000000..61401649fe7d --- /dev/null +++ b/include/linux/regulator/lp3971.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * National Semiconductors LP3971 PMIC chip client interface | ||
3 | * | ||
4 | * Copyright (C) 2009 Samsung Electronics | ||
5 | * Author: Marek Szyprowski <m.szyprowski@samsung.com> | ||
6 | * | ||
7 | * Based on wm8400.h | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #ifndef __LINUX_REGULATOR_LP3971_H | ||
25 | #define __LINUX_REGULATOR_LP3971_H | ||
26 | |||
27 | #include <linux/regulator/machine.h> | ||
28 | |||
29 | #define LP3971_LDO1 0 | ||
30 | #define LP3971_LDO2 1 | ||
31 | #define LP3971_LDO3 2 | ||
32 | #define LP3971_LDO4 3 | ||
33 | #define LP3971_LDO5 4 | ||
34 | |||
35 | #define LP3971_DCDC1 5 | ||
36 | #define LP3971_DCDC2 6 | ||
37 | #define LP3971_DCDC3 7 | ||
38 | |||
39 | #define LP3971_NUM_REGULATORS 8 | ||
40 | |||
41 | struct lp3971_regulator_subdev { | ||
42 | int id; | ||
43 | struct regulator_init_data *initdata; | ||
44 | }; | ||
45 | |||
46 | struct lp3971_platform_data { | ||
47 | int num_regulators; | ||
48 | struct lp3971_regulator_subdev *regulators; | ||
49 | }; | ||
50 | |||
51 | #endif | ||
diff --git a/include/linux/regulator/max1586.h b/include/linux/regulator/max1586.h new file mode 100644 index 000000000000..44563192bf16 --- /dev/null +++ b/include/linux/regulator/max1586.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * max1586.h -- Voltage regulation for the Maxim 1586 | ||
3 | * | ||
4 | * Copyright (C) 2008 Robert Jarzmik | ||
5 | * | ||
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. | ||
10 | * | ||
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. | ||
15 | * | ||
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 | ||
19 | */ | ||
20 | |||
21 | #ifndef REGULATOR_MAX1586 | ||
22 | #define REGULATOR_MAX1586 | ||
23 | |||
24 | #include <linux/regulator/machine.h> | ||
25 | |||
26 | #define MAX1586_V3 0 | ||
27 | #define MAX1586_V6 1 | ||
28 | |||
29 | /* precalculated values for v3_gain */ | ||
30 | #define MAX1586_GAIN_NO_R24 1000000 /* 700000 .. 1475000 mV */ | ||
31 | #define MAX1586_GAIN_R24_3k32 1051098 /* 735768 .. 1550369 mV */ | ||
32 | #define MAX1586_GAIN_R24_5k11 1078648 /* 755053 .. 1591005 mV */ | ||
33 | #define MAX1586_GAIN_R24_7k5 1115432 /* 780802 .. 1645262 mV */ | ||
34 | |||
35 | /** | ||
36 | * max1586_subdev_data - regulator data | ||
37 | * @id: regulator Id (either MAX1586_V3 or MAX1586_V6) | ||
38 | * @name: regulator cute name (example for V3: "vcc_core") | ||
39 | * @platform_data: regulator init data (contraints, supplies, ...) | ||
40 | */ | ||
41 | struct max1586_subdev_data { | ||
42 | int id; | ||
43 | char *name; | ||
44 | struct regulator_init_data *platform_data; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * max1586_platform_data - platform data for max1586 | ||
49 | * @num_subdevs: number of regultors used (may be 1 or 2) | ||
50 | * @subdevs: regulator used | ||
51 | * At most, there will be a regulator for V3 and one for V6 voltages. | ||
52 | * @v3_gain: gain on the V3 voltage output multiplied by 1e6. | ||
53 | * This can be calculated as ((1 + R24/R25 + R24/185.5kOhm) * 1e6) | ||
54 | * for an external resistor configuration as described in the | ||
55 | * data sheet (R25=100kOhm). | ||
56 | */ | ||
57 | struct max1586_platform_data { | ||
58 | int num_subdevs; | ||
59 | struct max1586_subdev_data *subdevs; | ||
60 | int v3_gain; | ||
61 | }; | ||
62 | |||
63 | #endif | ||
diff --git a/include/linux/regulator/userspace-consumer.h b/include/linux/regulator/userspace-consumer.h new file mode 100644 index 000000000000..b4554ce9d4bb --- /dev/null +++ b/include/linux/regulator/userspace-consumer.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef __REGULATOR_PLATFORM_CONSUMER_H_ | ||
2 | #define __REGULATOR_PLATFORM_CONSUMER_H_ | ||
3 | |||
4 | struct regulator_consumer_supply; | ||
5 | |||
6 | /** | ||
7 | * struct regulator_userspace_consumer_data - line consumer | ||
8 | * initialisation data. | ||
9 | * | ||
10 | * @name: Name for the consumer line | ||
11 | * @num_supplies: Number of supplies feeding the line | ||
12 | * @supplies: Supplies configuration. | ||
13 | * @init_on: Set if the regulators supplying the line should be | ||
14 | * enabled during initialisation | ||
15 | */ | ||
16 | struct regulator_userspace_consumer_data { | ||
17 | const char *name; | ||
18 | |||
19 | int num_supplies; | ||
20 | struct regulator_bulk_data *supplies; | ||
21 | |||
22 | bool init_on; | ||
23 | }; | ||
24 | |||
25 | #endif /* __REGULATOR_PLATFORM_CONSUMER_H_ */ | ||