Commit 4923b48b27fc89710ebc8b77fe0dd679724c0ffc
Committed by
Mark Brown
1 parent
372de4aa5e
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
regulator: da9052: Convert to set_voltage_sel and map_voltage
Signed-off-by: Axel Lin <axel.lin@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Showing 1 changed file with 24 additions and 13 deletions Inline Diff
drivers/regulator/da9052-regulator.c
1 | /* | 1 | /* |
2 | * da9052-regulator.c: Regulator driver for DA9052 | 2 | * da9052-regulator.c: Regulator driver for DA9052 |
3 | * | 3 | * |
4 | * Copyright(c) 2011 Dialog Semiconductor Ltd. | 4 | * Copyright(c) 2011 Dialog Semiconductor Ltd. |
5 | * | 5 | * |
6 | * Author: David Dajun Chen <dchen@diasemi.com> | 6 | * Author: David Dajun Chen <dchen@diasemi.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. | 11 | * (at your option) any later version. |
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
22 | #ifdef CONFIG_OF | 22 | #ifdef CONFIG_OF |
23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
24 | #include <linux/regulator/of_regulator.h> | 24 | #include <linux/regulator/of_regulator.h> |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #include <linux/mfd/da9052/da9052.h> | 27 | #include <linux/mfd/da9052/da9052.h> |
28 | #include <linux/mfd/da9052/reg.h> | 28 | #include <linux/mfd/da9052/reg.h> |
29 | #include <linux/mfd/da9052/pdata.h> | 29 | #include <linux/mfd/da9052/pdata.h> |
30 | 30 | ||
31 | /* Buck step size */ | 31 | /* Buck step size */ |
32 | #define DA9052_BUCK_PERI_3uV_STEP 100000 | 32 | #define DA9052_BUCK_PERI_3uV_STEP 100000 |
33 | #define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24 | 33 | #define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24 |
34 | #define DA9052_CONST_3uV 3000000 | 34 | #define DA9052_CONST_3uV 3000000 |
35 | 35 | ||
36 | #define DA9052_MIN_UA 0 | 36 | #define DA9052_MIN_UA 0 |
37 | #define DA9052_MAX_UA 3 | 37 | #define DA9052_MAX_UA 3 |
38 | #define DA9052_CURRENT_RANGE 4 | 38 | #define DA9052_CURRENT_RANGE 4 |
39 | 39 | ||
40 | /* Bit masks */ | 40 | /* Bit masks */ |
41 | #define DA9052_BUCK_ILIM_MASK_EVEN 0x0c | 41 | #define DA9052_BUCK_ILIM_MASK_EVEN 0x0c |
42 | #define DA9052_BUCK_ILIM_MASK_ODD 0xc0 | 42 | #define DA9052_BUCK_ILIM_MASK_ODD 0xc0 |
43 | 43 | ||
44 | /* DA9052 REGULATOR IDs */ | 44 | /* DA9052 REGULATOR IDs */ |
45 | #define DA9052_ID_BUCK1 0 | 45 | #define DA9052_ID_BUCK1 0 |
46 | #define DA9052_ID_BUCK2 1 | 46 | #define DA9052_ID_BUCK2 1 |
47 | #define DA9052_ID_BUCK3 2 | 47 | #define DA9052_ID_BUCK3 2 |
48 | #define DA9052_ID_BUCK4 3 | 48 | #define DA9052_ID_BUCK4 3 |
49 | #define DA9052_ID_LDO1 4 | 49 | #define DA9052_ID_LDO1 4 |
50 | #define DA9052_ID_LDO2 5 | 50 | #define DA9052_ID_LDO2 5 |
51 | #define DA9052_ID_LDO3 6 | 51 | #define DA9052_ID_LDO3 6 |
52 | #define DA9052_ID_LDO4 7 | 52 | #define DA9052_ID_LDO4 7 |
53 | #define DA9052_ID_LDO5 8 | 53 | #define DA9052_ID_LDO5 8 |
54 | #define DA9052_ID_LDO6 9 | 54 | #define DA9052_ID_LDO6 9 |
55 | #define DA9052_ID_LDO7 10 | 55 | #define DA9052_ID_LDO7 10 |
56 | #define DA9052_ID_LDO8 11 | 56 | #define DA9052_ID_LDO8 11 |
57 | #define DA9052_ID_LDO9 12 | 57 | #define DA9052_ID_LDO9 12 |
58 | #define DA9052_ID_LDO10 13 | 58 | #define DA9052_ID_LDO10 13 |
59 | 59 | ||
60 | static const u32 da9052_current_limits[3][4] = { | 60 | static const u32 da9052_current_limits[3][4] = { |
61 | {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */ | 61 | {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */ |
62 | {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */ | 62 | {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */ |
63 | {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO, | 63 | {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO, |
64 | * BUCK-MEM and BUCK-PERI | 64 | * BUCK-MEM and BUCK-PERI |
65 | */ | 65 | */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct da9052_regulator_info { | 68 | struct da9052_regulator_info { |
69 | struct regulator_desc reg_desc; | 69 | struct regulator_desc reg_desc; |
70 | int step_uV; | 70 | int step_uV; |
71 | int min_uV; | 71 | int min_uV; |
72 | int max_uV; | 72 | int max_uV; |
73 | unsigned char activate_bit; | 73 | unsigned char activate_bit; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | struct da9052_regulator { | 76 | struct da9052_regulator { |
77 | struct da9052 *da9052; | 77 | struct da9052 *da9052; |
78 | struct da9052_regulator_info *info; | 78 | struct da9052_regulator_info *info; |
79 | struct regulator_dev *rdev; | 79 | struct regulator_dev *rdev; |
80 | }; | 80 | }; |
81 | 81 | ||
82 | static int verify_range(struct da9052_regulator_info *info, | 82 | static int verify_range(struct da9052_regulator_info *info, |
83 | int min_uV, int max_uV) | 83 | int min_uV, int max_uV) |
84 | { | 84 | { |
85 | if (min_uV > info->max_uV || max_uV < info->min_uV) | 85 | if (min_uV > info->max_uV || max_uV < info->min_uV) |
86 | return -EINVAL; | 86 | return -EINVAL; |
87 | 87 | ||
88 | return 0; | 88 | return 0; |
89 | } | 89 | } |
90 | 90 | ||
91 | static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev) | 91 | static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev) |
92 | { | 92 | { |
93 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); | 93 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); |
94 | int offset = rdev_get_id(rdev); | 94 | int offset = rdev_get_id(rdev); |
95 | int ret, row = 2; | 95 | int ret, row = 2; |
96 | 96 | ||
97 | ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2); | 97 | ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2); |
98 | if (ret < 0) | 98 | if (ret < 0) |
99 | return ret; | 99 | return ret; |
100 | 100 | ||
101 | /* Determine the even or odd position of the buck current limit | 101 | /* Determine the even or odd position of the buck current limit |
102 | * register field | 102 | * register field |
103 | */ | 103 | */ |
104 | if (offset % 2 == 0) | 104 | if (offset % 2 == 0) |
105 | ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2; | 105 | ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2; |
106 | else | 106 | else |
107 | ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6; | 107 | ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6; |
108 | 108 | ||
109 | /* Select the appropriate current limit range */ | 109 | /* Select the appropriate current limit range */ |
110 | if (regulator->da9052->chip_id == DA9052) | 110 | if (regulator->da9052->chip_id == DA9052) |
111 | row = 0; | 111 | row = 0; |
112 | else if (offset == 0) | 112 | else if (offset == 0) |
113 | row = 1; | 113 | row = 1; |
114 | 114 | ||
115 | return da9052_current_limits[row][ret]; | 115 | return da9052_current_limits[row][ret]; |
116 | } | 116 | } |
117 | 117 | ||
118 | static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, | 118 | static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, |
119 | int max_uA) | 119 | int max_uA) |
120 | { | 120 | { |
121 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); | 121 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); |
122 | int offset = rdev_get_id(rdev); | 122 | int offset = rdev_get_id(rdev); |
123 | int reg_val = 0; | 123 | int reg_val = 0; |
124 | int i, row = 2; | 124 | int i, row = 2; |
125 | 125 | ||
126 | /* Select the appropriate current limit range */ | 126 | /* Select the appropriate current limit range */ |
127 | if (regulator->da9052->chip_id == DA9052) | 127 | if (regulator->da9052->chip_id == DA9052) |
128 | row = 0; | 128 | row = 0; |
129 | else if (offset == 0) | 129 | else if (offset == 0) |
130 | row = 1; | 130 | row = 1; |
131 | 131 | ||
132 | if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] || | 132 | if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] || |
133 | max_uA < da9052_current_limits[row][DA9052_MIN_UA]) | 133 | max_uA < da9052_current_limits[row][DA9052_MIN_UA]) |
134 | return -EINVAL; | 134 | return -EINVAL; |
135 | 135 | ||
136 | for (i = 0; i < DA9052_CURRENT_RANGE; i++) { | 136 | for (i = 0; i < DA9052_CURRENT_RANGE; i++) { |
137 | if (min_uA <= da9052_current_limits[row][i]) { | 137 | if (min_uA <= da9052_current_limits[row][i]) { |
138 | reg_val = i; | 138 | reg_val = i; |
139 | break; | 139 | break; |
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | /* Determine the even or odd position of the buck current limit | 143 | /* Determine the even or odd position of the buck current limit |
144 | * register field | 144 | * register field |
145 | */ | 145 | */ |
146 | if (offset % 2 == 0) | 146 | if (offset % 2 == 0) |
147 | return da9052_reg_update(regulator->da9052, | 147 | return da9052_reg_update(regulator->da9052, |
148 | DA9052_BUCKA_REG + offset/2, | 148 | DA9052_BUCKA_REG + offset/2, |
149 | DA9052_BUCK_ILIM_MASK_EVEN, | 149 | DA9052_BUCK_ILIM_MASK_EVEN, |
150 | reg_val << 2); | 150 | reg_val << 2); |
151 | else | 151 | else |
152 | return da9052_reg_update(regulator->da9052, | 152 | return da9052_reg_update(regulator->da9052, |
153 | DA9052_BUCKA_REG + offset/2, | 153 | DA9052_BUCKA_REG + offset/2, |
154 | DA9052_BUCK_ILIM_MASK_ODD, | 154 | DA9052_BUCK_ILIM_MASK_ODD, |
155 | reg_val << 6); | 155 | reg_val << 6); |
156 | } | 156 | } |
157 | 157 | ||
158 | static int da9052_list_voltage(struct regulator_dev *rdev, | 158 | static int da9052_list_voltage(struct regulator_dev *rdev, |
159 | unsigned int selector) | 159 | unsigned int selector) |
160 | { | 160 | { |
161 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); | 161 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); |
162 | struct da9052_regulator_info *info = regulator->info; | 162 | struct da9052_regulator_info *info = regulator->info; |
163 | int id = rdev_get_id(rdev); | 163 | int id = rdev_get_id(rdev); |
164 | int volt_uV; | 164 | int volt_uV; |
165 | 165 | ||
166 | if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) | 166 | if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) |
167 | && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) { | 167 | && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) { |
168 | volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV) | 168 | volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV) |
169 | + info->min_uV); | 169 | + info->min_uV); |
170 | volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV) | 170 | volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV) |
171 | * (DA9052_BUCK_PERI_3uV_STEP); | 171 | * (DA9052_BUCK_PERI_3uV_STEP); |
172 | } else { | 172 | } else { |
173 | volt_uV = (selector * info->step_uV) + info->min_uV; | 173 | volt_uV = (selector * info->step_uV) + info->min_uV; |
174 | } | 174 | } |
175 | 175 | ||
176 | if (volt_uV > info->max_uV) | 176 | if (volt_uV > info->max_uV) |
177 | return -EINVAL; | 177 | return -EINVAL; |
178 | 178 | ||
179 | return volt_uV; | 179 | return volt_uV; |
180 | } | 180 | } |
181 | 181 | ||
182 | static int da9052_regulator_set_voltage(struct regulator_dev *rdev, | 182 | static int da9052_map_voltage(struct regulator_dev *rdev, |
183 | int min_uV, int max_uV, | 183 | int min_uV, int max_uV) |
184 | unsigned int *selector) | ||
185 | { | 184 | { |
186 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); | 185 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); |
187 | struct da9052_regulator_info *info = regulator->info; | 186 | struct da9052_regulator_info *info = regulator->info; |
188 | int id = rdev_get_id(rdev); | 187 | int id = rdev_get_id(rdev); |
189 | int ret; | 188 | int ret, sel; |
190 | 189 | ||
191 | ret = verify_range(info, min_uV, max_uV); | 190 | ret = verify_range(info, min_uV, max_uV); |
192 | if (ret < 0) | 191 | if (ret < 0) |
193 | return ret; | 192 | return ret; |
194 | 193 | ||
195 | if (min_uV < info->min_uV) | 194 | if (min_uV < info->min_uV) |
196 | min_uV = info->min_uV; | 195 | min_uV = info->min_uV; |
197 | 196 | ||
198 | if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) | 197 | if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052) |
199 | && (min_uV >= DA9052_CONST_3uV)) { | 198 | && (min_uV >= DA9052_CONST_3uV)) { |
200 | *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + | 199 | sel = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + |
201 | DIV_ROUND_UP(min_uV - DA9052_CONST_3uV, | 200 | DIV_ROUND_UP(min_uV - DA9052_CONST_3uV, |
202 | DA9052_BUCK_PERI_3uV_STEP); | 201 | DA9052_BUCK_PERI_3uV_STEP); |
203 | } else { | 202 | } else { |
204 | *selector = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); | 203 | sel = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV); |
205 | } | 204 | } |
206 | 205 | ||
207 | ret = da9052_list_voltage(rdev, *selector); | 206 | ret = da9052_list_voltage(rdev, sel); |
208 | if (ret < 0) | 207 | if (ret < 0) |
209 | return ret; | 208 | return ret; |
210 | 209 | ||
210 | return sel; | ||
211 | } | ||
212 | |||
213 | static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev, | ||
214 | unsigned int selector) | ||
215 | { | ||
216 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); | ||
217 | struct da9052_regulator_info *info = regulator->info; | ||
218 | int id = rdev_get_id(rdev); | ||
219 | int ret; | ||
220 | |||
211 | ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg, | 221 | ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg, |
212 | rdev->desc->vsel_mask, *selector); | 222 | rdev->desc->vsel_mask, selector); |
213 | if (ret < 0) | 223 | if (ret < 0) |
214 | return ret; | 224 | return ret; |
215 | 225 | ||
216 | /* Some LDOs and DCDCs are DVC controlled which requires enabling of | 226 | /* Some LDOs and DCDCs are DVC controlled which requires enabling of |
217 | * the activate bit to implment the changes on the output. | 227 | * the activate bit to implment the changes on the output. |
218 | */ | 228 | */ |
219 | switch (id) { | 229 | switch (id) { |
220 | case DA9052_ID_BUCK1: | 230 | case DA9052_ID_BUCK1: |
221 | case DA9052_ID_BUCK2: | 231 | case DA9052_ID_BUCK2: |
222 | case DA9052_ID_BUCK3: | 232 | case DA9052_ID_BUCK3: |
223 | case DA9052_ID_LDO2: | 233 | case DA9052_ID_LDO2: |
224 | case DA9052_ID_LDO3: | 234 | case DA9052_ID_LDO3: |
225 | ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, | 235 | ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, |
226 | info->activate_bit, info->activate_bit); | 236 | info->activate_bit, info->activate_bit); |
227 | break; | 237 | break; |
228 | } | 238 | } |
229 | 239 | ||
230 | return ret; | 240 | return ret; |
231 | } | 241 | } |
232 | 242 | ||
233 | static struct regulator_ops da9052_dcdc_ops = { | 243 | static struct regulator_ops da9052_dcdc_ops = { |
234 | .set_voltage = da9052_regulator_set_voltage, | ||
235 | .get_current_limit = da9052_dcdc_get_current_limit, | 244 | .get_current_limit = da9052_dcdc_get_current_limit, |
236 | .set_current_limit = da9052_dcdc_set_current_limit, | 245 | .set_current_limit = da9052_dcdc_set_current_limit, |
237 | 246 | ||
238 | .list_voltage = da9052_list_voltage, | 247 | .list_voltage = da9052_list_voltage, |
248 | .map_voltage = da9052_map_voltage, | ||
239 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 249 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
250 | .set_voltage_sel = da9052_regulator_set_voltage_sel, | ||
240 | .is_enabled = regulator_is_enabled_regmap, | 251 | .is_enabled = regulator_is_enabled_regmap, |
241 | .enable = regulator_enable_regmap, | 252 | .enable = regulator_enable_regmap, |
242 | .disable = regulator_disable_regmap, | 253 | .disable = regulator_disable_regmap, |
243 | }; | 254 | }; |
244 | 255 | ||
245 | static struct regulator_ops da9052_ldo_ops = { | 256 | static struct regulator_ops da9052_ldo_ops = { |
246 | .set_voltage = da9052_regulator_set_voltage, | ||
247 | |||
248 | .list_voltage = da9052_list_voltage, | 257 | .list_voltage = da9052_list_voltage, |
258 | .map_voltage = da9052_map_voltage, | ||
249 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 259 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
260 | .set_voltage_sel = da9052_regulator_set_voltage_sel, | ||
250 | .is_enabled = regulator_is_enabled_regmap, | 261 | .is_enabled = regulator_is_enabled_regmap, |
251 | .enable = regulator_enable_regmap, | 262 | .enable = regulator_enable_regmap, |
252 | .disable = regulator_disable_regmap, | 263 | .disable = regulator_disable_regmap, |
253 | }; | 264 | }; |
254 | 265 | ||
255 | #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ | 266 | #define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ |
256 | {\ | 267 | {\ |
257 | .reg_desc = {\ | 268 | .reg_desc = {\ |
258 | .name = #_id,\ | 269 | .name = #_id,\ |
259 | .ops = &da9052_ldo_ops,\ | 270 | .ops = &da9052_ldo_ops,\ |
260 | .type = REGULATOR_VOLTAGE,\ | 271 | .type = REGULATOR_VOLTAGE,\ |
261 | .id = DA9052_ID_##_id,\ | 272 | .id = DA9052_ID_##_id,\ |
262 | .n_voltages = (max - min) / step + 1, \ | 273 | .n_voltages = (max - min) / step + 1, \ |
263 | .owner = THIS_MODULE,\ | 274 | .owner = THIS_MODULE,\ |
264 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 275 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
265 | .vsel_mask = (1 << (sbits)) - 1,\ | 276 | .vsel_mask = (1 << (sbits)) - 1,\ |
266 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 277 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
267 | .enable_mask = 1 << (ebits),\ | 278 | .enable_mask = 1 << (ebits),\ |
268 | },\ | 279 | },\ |
269 | .min_uV = (min) * 1000,\ | 280 | .min_uV = (min) * 1000,\ |
270 | .max_uV = (max) * 1000,\ | 281 | .max_uV = (max) * 1000,\ |
271 | .step_uV = (step) * 1000,\ | 282 | .step_uV = (step) * 1000,\ |
272 | .activate_bit = (abits),\ | 283 | .activate_bit = (abits),\ |
273 | } | 284 | } |
274 | 285 | ||
275 | #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ | 286 | #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ |
276 | {\ | 287 | {\ |
277 | .reg_desc = {\ | 288 | .reg_desc = {\ |
278 | .name = #_id,\ | 289 | .name = #_id,\ |
279 | .ops = &da9052_dcdc_ops,\ | 290 | .ops = &da9052_dcdc_ops,\ |
280 | .type = REGULATOR_VOLTAGE,\ | 291 | .type = REGULATOR_VOLTAGE,\ |
281 | .id = DA9052_ID_##_id,\ | 292 | .id = DA9052_ID_##_id,\ |
282 | .n_voltages = (max - min) / step + 1, \ | 293 | .n_voltages = (max - min) / step + 1, \ |
283 | .owner = THIS_MODULE,\ | 294 | .owner = THIS_MODULE,\ |
284 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 295 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
285 | .vsel_mask = (1 << (sbits)) - 1,\ | 296 | .vsel_mask = (1 << (sbits)) - 1,\ |
286 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 297 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
287 | .enable_mask = 1 << (ebits),\ | 298 | .enable_mask = 1 << (ebits),\ |
288 | },\ | 299 | },\ |
289 | .min_uV = (min) * 1000,\ | 300 | .min_uV = (min) * 1000,\ |
290 | .max_uV = (max) * 1000,\ | 301 | .max_uV = (max) * 1000,\ |
291 | .step_uV = (step) * 1000,\ | 302 | .step_uV = (step) * 1000,\ |
292 | .activate_bit = (abits),\ | 303 | .activate_bit = (abits),\ |
293 | } | 304 | } |
294 | 305 | ||
295 | static struct da9052_regulator_info da9052_regulator_info[] = { | 306 | static struct da9052_regulator_info da9052_regulator_info[] = { |
296 | DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), | 307 | DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), |
297 | DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), | 308 | DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), |
298 | DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), | 309 | DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), |
299 | DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0), | 310 | DA9052_DCDC(BUCK4, 50, 1800, 3600, 5, 6, 0), |
300 | DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), | 311 | DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), |
301 | DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), | 312 | DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), |
302 | DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), | 313 | DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), |
303 | DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), | 314 | DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), |
304 | DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), | 315 | DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), |
305 | DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), | 316 | DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), |
306 | DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), | 317 | DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), |
307 | DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), | 318 | DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), |
308 | DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), | 319 | DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), |
309 | DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), | 320 | DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), |
310 | }; | 321 | }; |
311 | 322 | ||
312 | static struct da9052_regulator_info da9053_regulator_info[] = { | 323 | static struct da9052_regulator_info da9053_regulator_info[] = { |
313 | DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), | 324 | DA9052_DCDC(BUCK1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), |
314 | DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), | 325 | DA9052_DCDC(BUCK2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), |
315 | DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), | 326 | DA9052_DCDC(BUCK3, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), |
316 | DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0), | 327 | DA9052_DCDC(BUCK4, 25, 925, 2500, 6, 6, 0), |
317 | DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), | 328 | DA9052_LDO(LDO1, 50, 600, 1800, 5, 6, 0), |
318 | DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), | 329 | DA9052_LDO(LDO2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), |
319 | DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), | 330 | DA9052_LDO(LDO3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), |
320 | DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), | 331 | DA9052_LDO(LDO4, 25, 1725, 3300, 6, 6, 0), |
321 | DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), | 332 | DA9052_LDO(LDO5, 50, 1200, 3600, 6, 6, 0), |
322 | DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), | 333 | DA9052_LDO(LDO6, 50, 1200, 3600, 6, 6, 0), |
323 | DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), | 334 | DA9052_LDO(LDO7, 50, 1200, 3600, 6, 6, 0), |
324 | DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), | 335 | DA9052_LDO(LDO8, 50, 1200, 3600, 6, 6, 0), |
325 | DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), | 336 | DA9052_LDO(LDO9, 50, 1250, 3650, 6, 6, 0), |
326 | DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), | 337 | DA9052_LDO(LDO10, 50, 1200, 3600, 6, 6, 0), |
327 | }; | 338 | }; |
328 | 339 | ||
329 | static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, | 340 | static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, |
330 | int id) | 341 | int id) |
331 | { | 342 | { |
332 | struct da9052_regulator_info *info; | 343 | struct da9052_regulator_info *info; |
333 | int i; | 344 | int i; |
334 | 345 | ||
335 | switch (chip_id) { | 346 | switch (chip_id) { |
336 | case DA9052: | 347 | case DA9052: |
337 | for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) { | 348 | for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) { |
338 | info = &da9052_regulator_info[i]; | 349 | info = &da9052_regulator_info[i]; |
339 | if (info->reg_desc.id == id) | 350 | if (info->reg_desc.id == id) |
340 | return info; | 351 | return info; |
341 | } | 352 | } |
342 | break; | 353 | break; |
343 | case DA9053_AA: | 354 | case DA9053_AA: |
344 | case DA9053_BA: | 355 | case DA9053_BA: |
345 | case DA9053_BB: | 356 | case DA9053_BB: |
346 | for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) { | 357 | for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) { |
347 | info = &da9053_regulator_info[i]; | 358 | info = &da9053_regulator_info[i]; |
348 | if (info->reg_desc.id == id) | 359 | if (info->reg_desc.id == id) |
349 | return info; | 360 | return info; |
350 | } | 361 | } |
351 | break; | 362 | break; |
352 | } | 363 | } |
353 | 364 | ||
354 | return NULL; | 365 | return NULL; |
355 | } | 366 | } |
356 | 367 | ||
357 | static int __devinit da9052_regulator_probe(struct platform_device *pdev) | 368 | static int __devinit da9052_regulator_probe(struct platform_device *pdev) |
358 | { | 369 | { |
359 | struct regulator_config config = { }; | 370 | struct regulator_config config = { }; |
360 | struct da9052_regulator *regulator; | 371 | struct da9052_regulator *regulator; |
361 | struct da9052 *da9052; | 372 | struct da9052 *da9052; |
362 | struct da9052_pdata *pdata; | 373 | struct da9052_pdata *pdata; |
363 | 374 | ||
364 | regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator), | 375 | regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator), |
365 | GFP_KERNEL); | 376 | GFP_KERNEL); |
366 | if (!regulator) | 377 | if (!regulator) |
367 | return -ENOMEM; | 378 | return -ENOMEM; |
368 | 379 | ||
369 | da9052 = dev_get_drvdata(pdev->dev.parent); | 380 | da9052 = dev_get_drvdata(pdev->dev.parent); |
370 | pdata = da9052->dev->platform_data; | 381 | pdata = da9052->dev->platform_data; |
371 | regulator->da9052 = da9052; | 382 | regulator->da9052 = da9052; |
372 | 383 | ||
373 | regulator->info = find_regulator_info(regulator->da9052->chip_id, | 384 | regulator->info = find_regulator_info(regulator->da9052->chip_id, |
374 | pdev->id); | 385 | pdev->id); |
375 | if (regulator->info == NULL) { | 386 | if (regulator->info == NULL) { |
376 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); | 387 | dev_err(&pdev->dev, "invalid regulator ID specified\n"); |
377 | return -EINVAL; | 388 | return -EINVAL; |
378 | } | 389 | } |
379 | 390 | ||
380 | config.dev = &pdev->dev; | 391 | config.dev = &pdev->dev; |
381 | config.driver_data = regulator; | 392 | config.driver_data = regulator; |
382 | config.regmap = da9052->regmap; | 393 | config.regmap = da9052->regmap; |
383 | if (pdata && pdata->regulators) { | 394 | if (pdata && pdata->regulators) { |
384 | config.init_data = pdata->regulators[pdev->id]; | 395 | config.init_data = pdata->regulators[pdev->id]; |
385 | } else { | 396 | } else { |
386 | #ifdef CONFIG_OF | 397 | #ifdef CONFIG_OF |
387 | struct device_node *nproot = da9052->dev->of_node; | 398 | struct device_node *nproot = da9052->dev->of_node; |
388 | struct device_node *np; | 399 | struct device_node *np; |
389 | 400 | ||
390 | if (!nproot) | 401 | if (!nproot) |
391 | return -ENODEV; | 402 | return -ENODEV; |
392 | 403 | ||
393 | nproot = of_find_node_by_name(nproot, "regulators"); | 404 | nproot = of_find_node_by_name(nproot, "regulators"); |
394 | if (!nproot) | 405 | if (!nproot) |
395 | return -ENODEV; | 406 | return -ENODEV; |
396 | 407 | ||
397 | for (np = of_get_next_child(nproot, NULL); np; | 408 | for (np = of_get_next_child(nproot, NULL); np; |
398 | np = of_get_next_child(nproot, np)) { | 409 | np = of_get_next_child(nproot, np)) { |
399 | if (!of_node_cmp(np->name, | 410 | if (!of_node_cmp(np->name, |
400 | regulator->info->reg_desc.name)) { | 411 | regulator->info->reg_desc.name)) { |
401 | config.init_data = of_get_regulator_init_data( | 412 | config.init_data = of_get_regulator_init_data( |
402 | &pdev->dev, np); | 413 | &pdev->dev, np); |
403 | break; | 414 | break; |
404 | } | 415 | } |
405 | } | 416 | } |
406 | #endif | 417 | #endif |
407 | } | 418 | } |
408 | 419 | ||
409 | regulator->rdev = regulator_register(®ulator->info->reg_desc, | 420 | regulator->rdev = regulator_register(®ulator->info->reg_desc, |
410 | &config); | 421 | &config); |
411 | if (IS_ERR(regulator->rdev)) { | 422 | if (IS_ERR(regulator->rdev)) { |
412 | dev_err(&pdev->dev, "failed to register regulator %s\n", | 423 | dev_err(&pdev->dev, "failed to register regulator %s\n", |
413 | regulator->info->reg_desc.name); | 424 | regulator->info->reg_desc.name); |
414 | return PTR_ERR(regulator->rdev); | 425 | return PTR_ERR(regulator->rdev); |
415 | } | 426 | } |
416 | 427 | ||
417 | platform_set_drvdata(pdev, regulator); | 428 | platform_set_drvdata(pdev, regulator); |
418 | 429 | ||
419 | return 0; | 430 | return 0; |
420 | } | 431 | } |
421 | 432 | ||
422 | static int __devexit da9052_regulator_remove(struct platform_device *pdev) | 433 | static int __devexit da9052_regulator_remove(struct platform_device *pdev) |
423 | { | 434 | { |
424 | struct da9052_regulator *regulator = platform_get_drvdata(pdev); | 435 | struct da9052_regulator *regulator = platform_get_drvdata(pdev); |
425 | 436 | ||
426 | regulator_unregister(regulator->rdev); | 437 | regulator_unregister(regulator->rdev); |
427 | return 0; | 438 | return 0; |
428 | } | 439 | } |
429 | 440 | ||
430 | static struct platform_driver da9052_regulator_driver = { | 441 | static struct platform_driver da9052_regulator_driver = { |
431 | .probe = da9052_regulator_probe, | 442 | .probe = da9052_regulator_probe, |
432 | .remove = __devexit_p(da9052_regulator_remove), | 443 | .remove = __devexit_p(da9052_regulator_remove), |
433 | .driver = { | 444 | .driver = { |
434 | .name = "da9052-regulator", | 445 | .name = "da9052-regulator", |
435 | .owner = THIS_MODULE, | 446 | .owner = THIS_MODULE, |
436 | }, | 447 | }, |
437 | }; | 448 | }; |
438 | 449 | ||
439 | static int __init da9052_regulator_init(void) | 450 | static int __init da9052_regulator_init(void) |
440 | { | 451 | { |
441 | return platform_driver_register(&da9052_regulator_driver); | 452 | return platform_driver_register(&da9052_regulator_driver); |
442 | } | 453 | } |
443 | subsys_initcall(da9052_regulator_init); | 454 | subsys_initcall(da9052_regulator_init); |
444 | 455 | ||
445 | static void __exit da9052_regulator_exit(void) | 456 | static void __exit da9052_regulator_exit(void) |
446 | { | 457 | { |
447 | platform_driver_unregister(&da9052_regulator_driver); | 458 | platform_driver_unregister(&da9052_regulator_driver); |
448 | } | 459 | } |
449 | module_exit(da9052_regulator_exit); | 460 | module_exit(da9052_regulator_exit); |
450 | 461 | ||
451 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | 462 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); |