diff options
author | Daniel Jeong | 2015-10-15 01:26:58 -0500 |
---|---|---|
committer | Daniel Jeong | 2015-10-15 01:26:58 -0500 |
commit | cbdb8f5916cf6512917a7fe2386b8701bbf7b728 (patch) | |
tree | 461262ad274971a1d2f2fc9f8893cc6fe6cec9b5 /drivers | |
parent | e32a1e65d0df3645ba18099c1b157506f6636de6 (diff) | |
download | kernel-master.tar.gz kernel-master.tar.xz kernel-master.zip |
Signed-off-by: Daniel Jeong <gshark.jeong@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/regulator/lp8758.c | 440 |
1 files changed, 312 insertions, 128 deletions
diff --git a/drivers/regulator/lp8758.c b/drivers/regulator/lp8758.c index 523162c..dbe9e59 100644 --- a/drivers/regulator/lp8758.c +++ b/drivers/regulator/lp8758.c | |||
@@ -11,36 +11,28 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /******************************************************************** | ||
15 | Notice : | ||
16 | It is a preliminary version based on f0 for reference. | ||
17 | A consolidated verson will be released soon. | ||
18 | ********************************************************************/ | ||
19 | |||
20 | |||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/gpio.h> | ||
25 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
26 | #include <linux/regmap.h> | ||
27 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
28 | #include <linux/gpio.h> | 18 | #include <linux/module.h> |
29 | #include <linux/of.h> | 19 | #include <linux/of.h> |
30 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
31 | #include <linux/uaccess.h> | 21 | #include <linux/regmap.h> |
32 | #include <linux/regulator/driver.h> | 22 | #include <linux/regulator/driver.h> |
23 | #include <linux/regulator/lp8758.h> | ||
33 | #include <linux/regulator/machine.h> | 24 | #include <linux/regulator/machine.h> |
34 | #include <linux/regulator/of_regulator.h> | 25 | #include <linux/regulator/of_regulator.h> |
35 | #include <linux/platform_data/lp8758.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/uaccess.h> | ||
36 | 28 | ||
37 | struct lp8758_chip { | 29 | struct lp8758_chip { |
38 | struct device *dev; | 30 | struct device *dev; |
39 | struct regmap *regmap; | 31 | struct regmap *regmap; |
40 | struct lp8758_platform_data *pdata; | 32 | struct lp8758_platform_data *pdata; |
41 | 33 | ||
42 | int irq; | ||
43 | struct regulator_dev *rdev[LP8758_BUCK_MAX]; | 34 | struct regulator_dev *rdev[LP8758_BUCK_MAX]; |
35 | struct regulator_desc regulators[LP8758_BUCK_MAX]; | ||
44 | }; | 36 | }; |
45 | 37 | ||
46 | /* voltage map */ | 38 | /* voltage map */ |
@@ -88,22 +80,42 @@ static const unsigned int lp8758_current_limit_uA[] = { | |||
88 | 1500000, 2000000, 2500000, 3000000, 3500000, 4000000, 4500000, 5000000 | 80 | 1500000, 2000000, 2500000, 3000000, 3500000, 4000000, 4500000, 5000000 |
89 | }; | 81 | }; |
90 | 82 | ||
91 | static int lp8758_read(struct lp8758_chip *pchip, unsigned int reg, | 83 | const static int sub_version_config[LP8758_SUB_VER_MAX][LP8758_BUCK_MAX] ={ |
92 | unsigned int *val) | 84 | [LP8758_SUB_VER_B0] = { LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE, |
93 | { | 85 | LP8758_BUCK_SLAVE, LP8758_BUCK_SLAVE }, |
94 | return regmap_read(pchip->regmap, reg, val); | 86 | [LP8758_SUB_VER_D0] = { LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE, |
87 | LP8758_BUCK_MASTER, LP8758_BUCK_MASTER }, | ||
88 | [LP8758_SUB_VER_E0] = { LP8758_BUCK_MASTER, LP8758_BUCK_MASTER, | ||
89 | LP8758_BUCK_MASTER, LP8758_BUCK_MASTER }, | ||
90 | [LP8758_SUB_VER_F0] = { LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE, | ||
91 | LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE } | ||
92 | }; | ||
93 | |||
94 | static bool lp8758_is_master(struct lp8758_chip *pchip, enum lp8758_bucks buck) { | ||
95 | int ver = pchip->pdata->sub_version; | ||
96 | if(sub_version_config[ver][buck] == LP8758_BUCK_MASTER) | ||
97 | return true; | ||
98 | return false; | ||
95 | } | 99 | } |
96 | 100 | ||
97 | static int lp8758_write(struct lp8758_chip *pchip, unsigned int reg, | 101 | static unsigned int lp8758_get_ctrl1_address(enum lp8758_bucks buck){ |
98 | unsigned int val) | 102 | unsigned int ctrl_register[LP8758_BUCK_MAX] = { |
99 | { | 103 | [LP8758_BUCK0] = LP8758_REG_BUCK0_CTRL1, |
100 | return regmap_write(pchip->regmap, reg, val); | 104 | [LP8758_BUCK1] = LP8758_REG_BUCK1_CTRL1, |
105 | [LP8758_BUCK2] = LP8758_REG_BUCK2_CTRL1, | ||
106 | [LP8758_BUCK3] = LP8758_REG_BUCK3_CTRL1 | ||
107 | }; | ||
108 | return ctrl_register[buck]; | ||
101 | } | 109 | } |
102 | 110 | ||
103 | static int lp8758_update_bits(struct lp8758_chip *pchip, unsigned int reg, | 111 | static unsigned int lp8758_get_ctrl2_address(enum lp8758_bucks buck){ |
104 | unsigned int mask, unsigned int val) | 112 | unsigned int ctrl_register[LP8758_BUCK_MAX] = { |
105 | { | 113 | [LP8758_BUCK0] = LP8758_REG_BUCK0_CTRL2, |
106 | return regmap_update_bits(pchip->regmap, reg, mask, val); | 114 | [LP8758_BUCK1] = LP8758_REG_BUCK1_CTRL2, |
115 | [LP8758_BUCK2] = LP8758_REG_BUCK2_CTRL2, | ||
116 | [LP8758_BUCK3] = LP8758_REG_BUCK3_CTRL2 | ||
117 | }; | ||
118 | return ctrl_register[buck]; | ||
107 | } | 119 | } |
108 | 120 | ||
109 | static int lp8758_buck_set_current_limit(struct regulator_dev *rdev, | 121 | static int lp8758_buck_set_current_limit(struct regulator_dev *rdev, |
@@ -112,24 +124,17 @@ static int lp8758_buck_set_current_limit(struct regulator_dev *rdev, | |||
112 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); | 124 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); |
113 | enum lp8758_bucks buck = rdev_get_id(rdev); | 125 | enum lp8758_bucks buck = rdev_get_id(rdev); |
114 | int icnt; | 126 | int icnt; |
115 | u8 addr; | 127 | |
116 | 128 | if(buck > LP8758_BUCK_MAX-1) | |
117 | switch (buck) { | ||
118 | case LP8758_BUCK0: | ||
119 | addr = LP8758_REG_BUCK0_CTRL2; | ||
120 | break; | ||
121 | case LP8758_BUCK2: | ||
122 | addr = LP8758_REG_BUCK2_CTRL2; | ||
123 | break; | ||
124 | default: | ||
125 | return -EINVAL; | 129 | return -EINVAL; |
126 | } | ||
127 | 130 | ||
128 | for (icnt = ARRAY_SIZE(lp8758_current_limit_uA) - 1; icnt >= 0; icnt--) { | 131 | for (icnt = ARRAY_SIZE(lp8758_current_limit_uA) - 1; icnt >= 0; icnt--) { |
129 | if (lp8758_current_limit_uA[icnt] >= min_uA && | 132 | if (lp8758_current_limit_uA[icnt] >= min_uA && |
130 | lp8758_current_limit_uA[icnt] <= max_uA) | 133 | lp8758_current_limit_uA[icnt] <= max_uA){ |
131 | return lp8758_update_bits(pchip, addr, | 134 | return regmap_update_bits(pchip->regmap, |
132 | LP8758_ILIM_MASK, icnt << LP8758_ILIM_SHIFT); | 135 | lp8758_get_ctrl2_address(buck), |
136 | LP8758_ILIM_MASK, icnt << LP8758_ILIM_SHIFT); | ||
137 | } | ||
133 | } | 138 | } |
134 | 139 | ||
135 | return -EINVAL; | 140 | return -EINVAL; |
@@ -139,22 +144,13 @@ static int lp8758_buck_get_current_limit(struct regulator_dev *rdev) | |||
139 | { | 144 | { |
140 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); | 145 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); |
141 | enum lp8758_bucks buck = rdev_get_id(rdev); | 146 | enum lp8758_bucks buck = rdev_get_id(rdev); |
142 | u8 addr; | ||
143 | unsigned int val; | 147 | unsigned int val; |
144 | int ret; | 148 | int ret; |
145 | 149 | ||
146 | switch (buck) { | 150 | if(buck > LP8758_BUCK_MAX-1) |
147 | case LP8758_BUCK0: | ||
148 | addr = LP8758_REG_BUCK0_CTRL2; | ||
149 | break; | ||
150 | case LP8758_BUCK2: | ||
151 | addr = LP8758_REG_BUCK2_CTRL2; | ||
152 | break; | ||
153 | default: | ||
154 | return -EINVAL; | 151 | return -EINVAL; |
155 | } | ||
156 | 152 | ||
157 | ret = lp8758_read(pchip, addr, &val); | 153 | ret = regmap_read(pchip->regmap, lp8758_get_ctrl2_address(buck), &val); |
158 | if (ret) | 154 | if (ret) |
159 | return ret; | 155 | return ret; |
160 | 156 | ||
@@ -168,23 +164,20 @@ static int lp8758_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) | |||
168 | { | 164 | { |
169 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); | 165 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); |
170 | enum lp8758_bucks buck = rdev_get_id(rdev); | 166 | enum lp8758_bucks buck = rdev_get_id(rdev); |
171 | u8 addr; | 167 | unsigned int addr; |
172 | 168 | ||
173 | switch (buck) { | 169 | if(buck > LP8758_BUCK_MAX-1) |
174 | case LP8758_BUCK0: | ||
175 | addr = LP8758_REG_BUCK0_CTRL1; | ||
176 | break; | ||
177 | case LP8758_BUCK2: | ||
178 | addr = LP8758_REG_BUCK2_CTRL1; | ||
179 | break; | ||
180 | default: | ||
181 | return -EINVAL; | 170 | return -EINVAL; |
182 | } | ||
183 | 171 | ||
172 | addr = lp8758_get_ctrl1_address(buck); | ||
184 | if (mode == REGULATOR_MODE_FAST) | 173 | if (mode == REGULATOR_MODE_FAST) |
185 | return lp8758_update_bits(pchip, addr, 0x02, 0x02); | 174 | return regmap_update_bits(pchip->regmap, addr, |
175 | LP8758_BUCK_OP_MODE_MASK, | ||
176 | LP8758_BUCK_OP_FPWM); | ||
186 | else if (mode == REGULATOR_MODE_NORMAL) | 177 | else if (mode == REGULATOR_MODE_NORMAL) |
187 | return lp8758_update_bits(pchip, addr, 0x02, 0x00); | 178 | return regmap_update_bits(pchip->regmap, addr, |
179 | LP8758_BUCK_OP_MODE_MASK, | ||
180 | LP8758_BUCK_OP_AUTO); | ||
188 | else | 181 | else |
189 | return -EINVAL; | 182 | return -EINVAL; |
190 | } | 183 | } |
@@ -194,28 +187,69 @@ static unsigned int lp8758_buck_get_mode(struct regulator_dev *rdev) | |||
194 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); | 187 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); |
195 | enum lp8758_bucks buck = rdev_get_id(rdev); | 188 | enum lp8758_bucks buck = rdev_get_id(rdev); |
196 | unsigned int val; | 189 | unsigned int val; |
197 | u8 addr; | ||
198 | int ret; | 190 | int ret; |
199 | 191 | ||
200 | switch (buck) { | 192 | if(buck > LP8758_BUCK_MAX-1) |
201 | case LP8758_BUCK0: | ||
202 | addr = LP8758_REG_BUCK0_CTRL1; | ||
203 | break; | ||
204 | case LP8758_BUCK2: | ||
205 | addr = LP8758_REG_BUCK2_CTRL1; | ||
206 | break; | ||
207 | default: | ||
208 | return -EINVAL; | 193 | return -EINVAL; |
209 | } | ||
210 | 194 | ||
211 | ret = lp8758_read(pchip, addr, &val); | 195 | ret = regmap_read(pchip->regmap, lp8758_get_ctrl1_address(buck), &val); |
212 | if (ret) | 196 | if (ret) |
213 | return ret; | 197 | return ret; |
214 | 198 | ||
215 | return val & 0x02 ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; | 199 | return (val & LP8758_BUCK_OP_MODE_MASK) |
200 | ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; | ||
201 | } | ||
202 | |||
203 | static int lp8758_buck_set_ramp(struct regulator_dev *rdev, int ramp) | ||
204 | { | ||
205 | int ret = -EINVAL; | ||
206 | unsigned int regval = 0x00; | ||
207 | enum lp8758_bucks buck = rdev_get_id(rdev); | ||
208 | struct lp8758_chip *pchip = rdev_get_drvdata(rdev); | ||
209 | |||
210 | if(buck > LP8758_BUCK_MAX-1) | ||
211 | return -EINVAL; | ||
212 | |||
213 | if(lp8758_is_master(pchip,buck)) { | ||
214 | /* uV/us */ | ||
215 | switch (ramp) { | ||
216 | case 0 ... 470: | ||
217 | regval = 0x07; | ||
218 | break; | ||
219 | case 471 ... 940: | ||
220 | regval = 0x06; | ||
221 | break; | ||
222 | case 941 ... 1900: | ||
223 | regval = 0x05; | ||
224 | break; | ||
225 | case 1901 ... 3800: | ||
226 | regval = 0x04; | ||
227 | break; | ||
228 | case 3801 ... 7500: | ||
229 | regval = 0x03; | ||
230 | break; | ||
231 | case 7501 ... 10000: | ||
232 | regval = 0x02; | ||
233 | break; | ||
234 | case 10001 ... 15000: | ||
235 | regval = 0x01; | ||
236 | break; | ||
237 | case 15001 ... 30000: | ||
238 | regval = 0x00; | ||
239 | break; | ||
240 | default: | ||
241 | dev_err(pchip->dev, | ||
242 | "Not supported ramp value %d %s\n", ramp, __func__); | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | ret = regmap_update_bits(pchip->regmap, lp8758_get_ctrl2_address(buck), | ||
246 | LP8758_BUCK_RAMP_MASK, regval); | ||
247 | } | ||
248 | return ret; | ||
216 | } | 249 | } |
217 | 250 | ||
218 | static struct regulator_ops lp8758_buck_ops = { | 251 | /* regulator operation when it is set to master */ |
252 | static struct regulator_ops lp8758_buck_master_ops = { | ||
219 | .map_voltage = regulator_map_voltage_ascend, | 253 | .map_voltage = regulator_map_voltage_ascend, |
220 | .list_voltage = regulator_list_voltage_table, | 254 | .list_voltage = regulator_list_voltage_table, |
221 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 255 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
@@ -227,38 +261,138 @@ static struct regulator_ops lp8758_buck_ops = { | |||
227 | .get_mode = lp8758_buck_get_mode, | 261 | .get_mode = lp8758_buck_get_mode, |
228 | .set_current_limit = lp8758_buck_set_current_limit, | 262 | .set_current_limit = lp8758_buck_set_current_limit, |
229 | .get_current_limit = lp8758_buck_get_current_limit, | 263 | .get_current_limit = lp8758_buck_get_current_limit, |
264 | .set_ramp_delay = lp8758_buck_set_ramp, | ||
265 | }; | ||
266 | |||
267 | /* regulator operation when it is tied to another as slave */ | ||
268 | static struct regulator_ops lp8758_buck_slave_ops = { | ||
269 | .set_current_limit = lp8758_buck_set_current_limit, | ||
270 | .get_current_limit = lp8758_buck_get_current_limit, | ||
230 | }; | 271 | }; |
231 | 272 | ||
232 | static struct regulator_desc lp8758_regulators[LP8758_BUCK_MAX] = { | 273 | #define lp8758_rail(_id) "lp8755-buck"#_id |
274 | /* regulator description when it is set to master */ | ||
275 | #define lp8758_buck_master_desc(_id)\ | ||
276 | {\ | ||
277 | .name = lp8758_rail(_id),\ | ||
278 | .id = LP8758_BUCK##_id,\ | ||
279 | .ops = &lp8758_buck_master_ops,\ | ||
280 | .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map),\ | ||
281 | .volt_table = lp8758_buck_voltage_map,\ | ||
282 | .type = REGULATOR_VOLTAGE,\ | ||
283 | .owner = THIS_MODULE,\ | ||
284 | .enable_reg = LP8758_REG_BUCK##_id##_CTRL1,\ | ||
285 | .enable_mask = LP8758_BUCK_EN_MASK,\ | ||
286 | .vsel_reg = LP8758_REG_BUCK##_id##_VOUT,\ | ||
287 | .vsel_mask = LP8758_BUCK_VOUT_MASK,\ | ||
288 | } | ||
289 | |||
290 | /* regulator description when it is set to master and roof/floor control */ | ||
291 | #define lp8758_buck_master_roof_floor_desc(_id)\ | ||
292 | {\ | ||
293 | .name = lp8758_rail(_id),\ | ||
294 | .id = LP8758_BUCK##_id,\ | ||
295 | .ops = &lp8758_buck_master_ops,\ | ||
296 | .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map),\ | ||
297 | .volt_table = lp8758_buck_voltage_map,\ | ||
298 | .type = REGULATOR_VOLTAGE,\ | ||
299 | .owner = THIS_MODULE,\ | ||
300 | .enable_reg = LP8758_REG_BUCK##_id##_CTRL1,\ | ||
301 | .enable_mask = LP8758_BUCK_EN_MASK,\ | ||
302 | .vsel_reg = LP8758_REG_BUCK##_id##_FLOORVOUT,\ | ||
303 | .vsel_mask = LP8758_BUCK_VOUT_MASK,\ | ||
304 | } | ||
305 | |||
306 | /* regulator description when it is tied to another as slave */ | ||
307 | #define lp8758_buck_slave_desc(_id)\ | ||
308 | {\ | ||
309 | .name = lp8758_rail(_id),\ | ||
310 | .id = LP8758_BUCK##_id,\ | ||
311 | .ops = &lp8758_buck_slave_ops,\ | ||
312 | .type = REGULATOR_CURRENT,\ | ||
313 | .owner = THIS_MODULE,\ | ||
314 | } | ||
315 | |||
316 | /* regulators description for all configuration */ | ||
317 | static struct regulator_desc lp8758_buck_master_config[LP8758_BUCK_MAX][LP8758_CTRL_MAX] = { | ||
318 | { | ||
319 | [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(0), | ||
320 | [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(0), | ||
321 | [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(0), | ||
322 | [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(0), | ||
323 | [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(0) | ||
324 | }, | ||
233 | { | 325 | { |
234 | .name = "lp8758-buck0", | 326 | [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(1), |
235 | .id = LP8758_BUCK0, | 327 | [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(1), |
236 | .ops = &lp8758_buck_ops, | 328 | [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(1), |
237 | .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map), | 329 | [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(1), |
238 | .volt_table = lp8758_buck_voltage_map, | 330 | [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(1) |
239 | .type = REGULATOR_VOLTAGE, | ||
240 | .owner = THIS_MODULE, | ||
241 | .enable_reg = LP8758_REG_BUCK0_CTRL1, | ||
242 | .enable_mask = LP8758_BUCK_EN_MASK, | ||
243 | .vsel_reg = LP8758_REG_BUCK0_VOUT, | ||
244 | .vsel_mask = LP8758_BUCK_VOUT_MASK, | ||
245 | }, | 331 | }, |
246 | { | 332 | { |
247 | .name = "lp8758-buck2", | 333 | [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(2), |
248 | .id = LP8758_BUCK2, | 334 | [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(2), |
249 | .ops = &lp8758_buck_ops, | 335 | [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(2), |
250 | .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map), | 336 | [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(2), |
251 | .volt_table = lp8758_buck_voltage_map, | 337 | [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(2) |
252 | .type = REGULATOR_VOLTAGE, | 338 | }, |
253 | .owner = THIS_MODULE, | 339 | { |
254 | .enable_reg = LP8758_REG_BUCK2_CTRL1, | 340 | [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(3), |
255 | .enable_mask = LP8758_BUCK_EN_MASK, | 341 | [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(3), |
256 | .vsel_reg = LP8758_REG_BUCK2_VOUT, | 342 | [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(3), |
257 | .vsel_mask = LP8758_BUCK_VOUT_MASK, | 343 | [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(3), |
344 | [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(3) | ||
258 | } | 345 | } |
259 | }; | 346 | }; |
260 | 347 | ||
261 | static int lp8758_regulator_init(struct lp8758_chip *pchip) | 348 | static struct regulator_desc lp8758_buck_slave_config[LP8758_BUCK_MAX] = { |
349 | lp8758_buck_slave_desc(0), | ||
350 | lp8758_buck_slave_desc(1), | ||
351 | lp8758_buck_slave_desc(2), | ||
352 | lp8758_buck_slave_desc(3) | ||
353 | }; | ||
354 | |||
355 | /* | ||
356 | * select regulator description for each buck | ||
357 | * and write configuration value into control register | ||
358 | */ | ||
359 | static int lp8758_regulator_init(struct lp8758_chip *pchip){ | ||
360 | int icnt, ret, bctrl_mode; | ||
361 | struct regulator_desc *reg; | ||
362 | |||
363 | if(pchip->pdata->sub_version > LP8758_SUB_VER_MAX-1) | ||
364 | return -EINVAL; | ||
365 | |||
366 | /* select regulator description based on sub version*/ | ||
367 | for(icnt = LP8758_BUCK0 ; icnt < LP8758_BUCK_MAX; icnt++){ | ||
368 | /* select regulator description based on sub version & control mode */ | ||
369 | if(lp8758_is_master(pchip,icnt)) { | ||
370 | bctrl_mode = pchip->pdata->buck_ctrl[icnt]; | ||
371 | if(bctrl_mode > LP8758_CTRL_MAX-1) | ||
372 | return -EINVAL; | ||
373 | reg = &lp8758_buck_master_config[icnt][bctrl_mode]; | ||
374 | |||
375 | /* control registser set */ | ||
376 | if(bctrl_mode != LP8758_CTRL_MODE0) | ||
377 | bctrl_mode = (bctrl_mode - 1) | LP8758_CTRL_PIN_EN_MASK; | ||
378 | |||
379 | ret = regmap_update_bits(pchip->regmap, lp8758_get_ctrl1_address(icnt), | ||
380 | LP8758_CTRL_BUCK_MASK, | ||
381 | bctrl_mode << LP8758_CTRL_BUCK_SHIFT); | ||
382 | if(ret < 0){ | ||
383 | dev_err(pchip->dev, "lp8758 %s i2c error \n",__func__); | ||
384 | return ret; | ||
385 | } | ||
386 | } else { | ||
387 | reg = &lp8758_buck_slave_config[icnt], | ||
388 | dev_err(pchip->dev, "lp8758 %d regulator is SLAVE\n",icnt); | ||
389 | } | ||
390 | memcpy(&pchip->regulators[icnt], reg, sizeof(struct regulator_desc)); | ||
391 | } | ||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int lp8758_regulator_register(struct lp8758_chip *pchip) | ||
262 | { | 396 | { |
263 | int ret, icnt; | 397 | int ret, icnt; |
264 | struct lp8758_platform_data *pdata = pchip->pdata; | 398 | struct lp8758_platform_data *pdata = pchip->pdata; |
@@ -273,7 +407,7 @@ static int lp8758_regulator_init(struct lp8758_chip *pchip) | |||
273 | rconfig.of_node = pchip->dev->of_node; | 407 | rconfig.of_node = pchip->dev->of_node; |
274 | pchip->rdev[icnt] = | 408 | pchip->rdev[icnt] = |
275 | devm_regulator_register(pchip->dev, | 409 | devm_regulator_register(pchip->dev, |
276 | &lp8758_regulators[icnt], &rconfig); | 410 | &pchip->regulators[icnt], &rconfig); |
277 | if (IS_ERR(pchip->rdev[icnt])) { | 411 | if (IS_ERR(pchip->rdev[icnt])) { |
278 | ret = PTR_ERR(pchip->rdev[icnt]); | 412 | ret = PTR_ERR(pchip->rdev[icnt]); |
279 | pchip->rdev[icnt] = NULL; | 413 | pchip->rdev[icnt] = NULL; |
@@ -281,7 +415,6 @@ static int lp8758_regulator_init(struct lp8758_chip *pchip) | |||
281 | "regulator init failed: buck %d\n", icnt); | 415 | "regulator init failed: buck %d\n", icnt); |
282 | return ret; | 416 | return ret; |
283 | } | 417 | } |
284 | dev_info(pchip->dev, "lp8758 regulator %d\n is registered",icnt); | ||
285 | } | 418 | } |
286 | return 0; | 419 | return 0; |
287 | } | 420 | } |
@@ -289,20 +422,53 @@ static int lp8758_regulator_init(struct lp8758_chip *pchip) | |||
289 | static irqreturn_t lp8758_irq_handler(int irq, void *data) | 422 | static irqreturn_t lp8758_irq_handler(int irq, void *data) |
290 | { | 423 | { |
291 | int ret, icnt; | 424 | int ret, icnt; |
292 | unsigned int int_top; | 425 | unsigned int int_top, rdata; |
293 | struct lp8758_chip *pchip = data; | 426 | struct lp8758_chip *pchip = data; |
294 | 427 | ||
295 | ret = lp8758_read(pchip, LP8758_REG_INT_TOP, &int_top); | 428 | ret = regmap_read(pchip->regmap, LP8758_REG_INT_TOP, &int_top); |
296 | if(int_top & LP8758_OVERTEMP_MASK) | 429 | if(int_top & LP8758_INT_TMEP_MASK) |
297 | for(icnt = LP8758_BUCK0; icnt < LP8758_BUCK_MAX; icnt++) | 430 | for(icnt = LP8758_BUCK0; icnt < LP8758_BUCK_MAX; icnt++) |
298 | regulator_notifier_call_chain(pchip->rdev[icnt], | 431 | regulator_notifier_call_chain(pchip->rdev[icnt], |
299 | REGULATOR_EVENT_OVER_TEMP, NULL); | 432 | REGULATOR_EVENT_OVER_TEMP, NULL); |
300 | 433 | ||
301 | lp8758_write(pchip, LP8758_REG_INT_BUCK_0_1, 0x77); | 434 | if(int_top & LP8758_INT_BUCK01_MASK) { |
302 | lp8758_write(pchip, LP8758_REG_INT_BUCK_2_3, 0x77); | 435 | ret = regmap_read(pchip->regmap, LP8758_REG_INT_BUCK_01, &rdata); |
303 | lp8758_write(pchip, LP8758_REG_INT_TOP, 0x0f); | 436 | if(rdata & LP8758_INT_OVC_BUCK0_MASK) |
437 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK0], | ||
438 | LP8758_EVENT_OCP, NULL); | ||
439 | if(rdata & LP8758_INT_OVC_BUCK1_MASK) | ||
440 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK1], | ||
441 | LP8758_EVENT_OCP, NULL); | ||
442 | if(rdata & LP8758_INT_PWR_FAULT_BUCK0_MASK) | ||
443 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK0], | ||
444 | LP8758_EVENT_PWR_FAULT, NULL); | ||
445 | if(rdata & LP8758_INT_PWR_FAULT_BUCK1_MASK) | ||
446 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK1], | ||
447 | LP8758_EVENT_PWR_FAULT, NULL); | ||
448 | } | ||
449 | |||
450 | if(int_top & LP8758_INT_BUCK23_MASK) { | ||
451 | ret = regmap_read(pchip->regmap, LP8758_REG_INT_BUCK_23, &rdata); | ||
452 | if(rdata & LP8758_INT_OVC_BUCK2_MASK) | ||
453 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK2], | ||
454 | LP8758_EVENT_OCP, NULL); | ||
455 | if(rdata & LP8758_INT_OVC_BUCK3_MASK) | ||
456 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK3], | ||
457 | LP8758_EVENT_OCP, NULL); | ||
458 | if(rdata & LP8758_INT_PWR_FAULT_BUCK2_MASK) | ||
459 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK2], | ||
460 | LP8758_EVENT_PWR_FAULT, NULL); | ||
461 | if(rdata & LP8758_INT_PWR_FAULT_BUCK3_MASK) | ||
462 | regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK3], | ||
463 | LP8758_EVENT_PWR_FAULT, NULL); | ||
464 | } | ||
465 | |||
466 | /* clear interrupt */ | ||
467 | regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_01, LP8758_INT_CLEAR_BUCK); | ||
468 | regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_23, LP8758_INT_CLEAR_BUCK); | ||
469 | regmap_write(pchip->regmap, LP8758_REG_INT_TOP, LP8758_INT_CLEAR_TOP); | ||
304 | 470 | ||
305 | dev_info(pchip->dev, "lp8758 IRQ Handeled"); | 471 | dev_err(pchip->dev, "lp8758 IRQ Handeled"); |
306 | return IRQ_HANDLED; | 472 | return IRQ_HANDLED; |
307 | } | 473 | } |
308 | 474 | ||
@@ -310,17 +476,18 @@ static int lp8758_intr_config(struct lp8758_chip *pchip) | |||
310 | { | 476 | { |
311 | int ret, irq; | 477 | int ret, irq; |
312 | 478 | ||
313 | if (pchip->irq == 0) { | 479 | if (pchip->pdata->irq == 0) { |
314 | dev_warn(pchip->dev, "not use interrupt : %s\n", __func__); | 480 | dev_warn(pchip->dev, "not use interrupt : %s\n", __func__); |
315 | return 0; | 481 | return 0; |
316 | } | 482 | } |
317 | 483 | ||
318 | lp8758_write(pchip, LP8758_REG_INT_BUCK_0_1, 0x77); | 484 | /* initially clear interrupt */ |
319 | lp8758_write(pchip, LP8758_REG_INT_BUCK_2_3, 0x77); | 485 | regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_01, LP8758_INT_CLEAR_BUCK); |
320 | lp8758_write(pchip, LP8758_REG_INT_TOP, 0x0f); | 486 | regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_23, LP8758_INT_CLEAR_BUCK); |
487 | regmap_write(pchip->regmap, LP8758_REG_INT_TOP, LP8758_INT_CLEAR_TOP); | ||
321 | 488 | ||
322 | gpio_request_one(pchip->irq, GPIOF_DIR_IN,"lp8758-irq"); | 489 | gpio_request_one(pchip->pdata->irq, GPIOF_DIR_IN,"lp8758-irq"); |
323 | irq = gpio_to_irq(pchip->irq); | 490 | irq = gpio_to_irq(pchip->pdata->irq); |
324 | if(irq < 0){ | 491 | if(irq < 0){ |
325 | dev_warn(pchip->dev, "irq can't be configurated\n"); | 492 | dev_warn(pchip->dev, "irq can't be configurated\n"); |
326 | return -EINVAL; | 493 | return -EINVAL; |
@@ -329,22 +496,21 @@ static int lp8758_intr_config(struct lp8758_chip *pchip) | |||
329 | ret = request_threaded_irq(irq, NULL, lp8758_irq_handler, | 496 | ret = request_threaded_irq(irq, NULL, lp8758_irq_handler, |
330 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 497 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
331 | "lp8758-irq", pchip); | 498 | "lp8758-irq", pchip); |
332 | dev_info(pchip->dev, "irq config is configured gpio %d irq %d\n", | ||
333 | pchip->irq, irq); | ||
334 | |||
335 | return ret; | 499 | return ret; |
336 | } | 500 | } |
337 | 501 | ||
338 | static struct of_regulator_match lp8758_matches[LP8758_BUCK_MAX] = { | 502 | static struct of_regulator_match lp8758_matches[LP8758_BUCK_MAX] = { |
339 | { .name = "buck0", .driver_data = (void *)LP8758_BUCK0, }, | 503 | { .name = "buck0", .driver_data = (void *)LP8758_BUCK0, }, |
504 | { .name = "buck1", .driver_data = (void *)LP8758_BUCK1, }, | ||
340 | { .name = "buck2", .driver_data = (void *)LP8758_BUCK2, }, | 505 | { .name = "buck2", .driver_data = (void *)LP8758_BUCK2, }, |
506 | { .name = "buck3", .driver_data = (void *)LP8758_BUCK3, }, | ||
341 | }; | 507 | }; |
342 | 508 | ||
343 | static int lp8758_parse_dt(struct i2c_client *client, | 509 | static int lp8758_parse_dt(struct i2c_client *client, |
344 | struct lp8758_chip *pchip) | 510 | struct lp8758_chip *pchip) |
345 | { | 511 | { |
346 | struct device_node *node = client->dev.of_node; | 512 | struct device_node *node = client->dev.of_node; |
347 | int count, icnt; | 513 | int err, icnt; |
348 | 514 | ||
349 | pchip->pdata = devm_kzalloc(&client->dev, | 515 | pchip->pdata = devm_kzalloc(&client->dev, |
350 | sizeof(struct lp8758_platform_data), GFP_KERNEL); | 516 | sizeof(struct lp8758_platform_data), GFP_KERNEL); |
@@ -353,17 +519,31 @@ static int lp8758_parse_dt(struct i2c_client *client, | |||
353 | return -ENOMEM; | 519 | return -ENOMEM; |
354 | } | 520 | } |
355 | 521 | ||
356 | count = of_regulator_match(&client->dev, node, | 522 | err = of_regulator_match(&client->dev, node, |
357 | lp8758_matches, LP8758_BUCK_MAX); | 523 | lp8758_matches, LP8758_BUCK_MAX); |
358 | if (count <= 0) | 524 | if (err <= 0){ |
359 | dev_err(&client->dev, "lp8758 --ERR - of regulator match\n"); | 525 | dev_err(&client->dev, "lp8758 --ERR - of regulator match\n"); |
526 | return -EINVAL; | ||
527 | } | ||
360 | 528 | ||
361 | for(icnt = 0; icnt < LP8758_BUCK_MAX; icnt++){ | 529 | for(icnt = 0; icnt < LP8758_BUCK_MAX; icnt++){ |
362 | pchip->pdata->buck_data[icnt] = lp8758_matches[icnt].init_data; | 530 | pchip->pdata->buck_data[icnt] = lp8758_matches[icnt].init_data; |
363 | } | 531 | } |
364 | 532 | ||
365 | pchip->irq = of_get_named_gpio(node,"irq-gpio", 0); | 533 | pchip->pdata->irq = of_get_named_gpio(node,"irq-gpio", 0); |
366 | 534 | err = of_property_read_u32(node, "sub_version", | |
535 | &pchip->pdata->sub_version); | ||
536 | if(err < 0){ | ||
537 | dev_err(&client->dev, "lp8758 --ERR - of chip version read\n"); | ||
538 | return -EINVAL; | ||
539 | } | ||
540 | |||
541 | err = of_property_read_u32_array(node, "buck_ctrl", | ||
542 | pchip->pdata->buck_ctrl, LP8758_BUCK_MAX); | ||
543 | if(err < 0){ | ||
544 | dev_err(&client->dev, "lp8758 --ERR - pin ctrl data\n"); | ||
545 | return -EINVAL; | ||
546 | } | ||
367 | return 0; | 547 | return 0; |
368 | } | 548 | } |
369 | 549 | ||
@@ -384,7 +564,6 @@ static int lp8758_probe(struct i2c_client *client, | |||
384 | struct lp8758_chip *pchip; | 564 | struct lp8758_chip *pchip; |
385 | int ret = 0; | 565 | int ret = 0; |
386 | 566 | ||
387 | dev_info(&client->dev, "lp8758 module probe\n"); | ||
388 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 567 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
389 | dev_err(&client->dev, "i2c functionality check fail.\n"); | 568 | dev_err(&client->dev, "i2c functionality check fail.\n"); |
390 | return -EOPNOTSUPP; | 569 | return -EOPNOTSUPP; |
@@ -405,7 +584,6 @@ static int lp8758_probe(struct i2c_client *client, | |||
405 | ret = lp8758_parse_dt(client, pchip); | 584 | ret = lp8758_parse_dt(client, pchip); |
406 | if(ret < 0) | 585 | if(ret < 0) |
407 | return ret; | 586 | return ret; |
408 | |||
409 | pchip->dev = &client->dev; | 587 | pchip->dev = &client->dev; |
410 | i2c_set_clientdata(client, pchip); | 588 | i2c_set_clientdata(client, pchip); |
411 | 589 | ||
@@ -415,6 +593,12 @@ static int lp8758_probe(struct i2c_client *client, | |||
415 | return ret; | 593 | return ret; |
416 | } | 594 | } |
417 | 595 | ||
596 | ret = lp8758_regulator_register(pchip); | ||
597 | if (ret < 0) { | ||
598 | dev_err(&client->dev, "fail to register regulators\n"); | ||
599 | return ret; | ||
600 | } | ||
601 | |||
418 | ret = lp8758_intr_config(pchip); | 602 | ret = lp8758_intr_config(pchip); |
419 | if (ret < 0) { | 603 | if (ret < 0) { |
420 | dev_err(&client->dev, "fail to irq config\n"); | 604 | dev_err(&client->dev, "fail to irq config\n"); |