diff options
author | Sebastian Reichel <sre@kernel.org> | 2016-06-17 07:54:32 -0400 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2016-08-10 19:11:03 -0400 |
commit | 8c0984e5a75337df513047ec92a6c09d78e3e5cd (patch) | |
tree | a2fc0a0dd7c7c40d9379bdd1c2b279c0959d0e1f /drivers/power/max8925_power.c | |
parent | 29b4817d4018df78086157ea3a55c1d9424a7cfc (diff) |
power: move power supply drivers to power/supply
This moves all power supply drivers from drivers/power/
to drivers/power/supply/. The intention is a cleaner
source tree, since drivers/power/ also contains frameworks
unrelated to power supply, like adaptive voltage scaling.
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Diffstat (limited to 'drivers/power/max8925_power.c')
-rw-r--r-- | drivers/power/max8925_power.c | 596 |
1 files changed, 0 insertions, 596 deletions
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c deleted file mode 100644 index 3b94620ce5c1..000000000000 --- a/drivers/power/max8925_power.c +++ /dev/null | |||
@@ -1,596 +0,0 @@ | |||
1 | /* | ||
2 | * Battery driver for Maxim MAX8925 | ||
3 | * | ||
4 | * Copyright (c) 2009-2010 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/power_supply.h> | ||
20 | #include <linux/mfd/max8925.h> | ||
21 | |||
22 | /* registers in GPM */ | ||
23 | #define MAX8925_OUT5VEN 0x54 | ||
24 | #define MAX8925_OUT3VEN 0x58 | ||
25 | #define MAX8925_CHG_CNTL1 0x7c | ||
26 | |||
27 | /* bits definition */ | ||
28 | #define MAX8925_CHG_STAT_VSYSLOW (1 << 0) | ||
29 | #define MAX8925_CHG_STAT_MODE_MASK (3 << 2) | ||
30 | #define MAX8925_CHG_STAT_EN_MASK (1 << 4) | ||
31 | #define MAX8925_CHG_MBDET (1 << 1) | ||
32 | #define MAX8925_CHG_AC_RANGE_MASK (3 << 6) | ||
33 | |||
34 | /* registers in ADC */ | ||
35 | #define MAX8925_ADC_RES_CNFG1 0x06 | ||
36 | #define MAX8925_ADC_AVG_CNFG1 0x07 | ||
37 | #define MAX8925_ADC_ACQ_CNFG1 0x08 | ||
38 | #define MAX8925_ADC_ACQ_CNFG2 0x09 | ||
39 | /* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */ | ||
40 | #define MAX8925_ADC_AUX2 0x62 | ||
41 | #define MAX8925_ADC_VCHG 0x64 | ||
42 | #define MAX8925_ADC_VBBATT 0x66 | ||
43 | #define MAX8925_ADC_VMBATT 0x68 | ||
44 | #define MAX8925_ADC_ISNS 0x6a | ||
45 | #define MAX8925_ADC_THM 0x6c | ||
46 | #define MAX8925_ADC_TDIE 0x6e | ||
47 | #define MAX8925_CMD_AUX2 0xc8 | ||
48 | #define MAX8925_CMD_VCHG 0xd0 | ||
49 | #define MAX8925_CMD_VBBATT 0xd8 | ||
50 | #define MAX8925_CMD_VMBATT 0xe0 | ||
51 | #define MAX8925_CMD_ISNS 0xe8 | ||
52 | #define MAX8925_CMD_THM 0xf0 | ||
53 | #define MAX8925_CMD_TDIE 0xf8 | ||
54 | |||
55 | enum { | ||
56 | MEASURE_AUX2, | ||
57 | MEASURE_VCHG, | ||
58 | MEASURE_VBBATT, | ||
59 | MEASURE_VMBATT, | ||
60 | MEASURE_ISNS, | ||
61 | MEASURE_THM, | ||
62 | MEASURE_TDIE, | ||
63 | MEASURE_MAX, | ||
64 | }; | ||
65 | |||
66 | struct max8925_power_info { | ||
67 | struct max8925_chip *chip; | ||
68 | struct i2c_client *gpm; | ||
69 | struct i2c_client *adc; | ||
70 | |||
71 | struct power_supply *ac; | ||
72 | struct power_supply *usb; | ||
73 | struct power_supply *battery; | ||
74 | int irq_base; | ||
75 | unsigned ac_online:1; | ||
76 | unsigned usb_online:1; | ||
77 | unsigned bat_online:1; | ||
78 | unsigned chg_mode:2; | ||
79 | unsigned batt_detect:1; /* detecing MB by ID pin */ | ||
80 | unsigned topoff_threshold:2; | ||
81 | unsigned fast_charge:3; | ||
82 | unsigned no_temp_support:1; | ||
83 | unsigned no_insert_detect:1; | ||
84 | |||
85 | int (*set_charger) (int); | ||
86 | }; | ||
87 | |||
88 | static int __set_charger(struct max8925_power_info *info, int enable) | ||
89 | { | ||
90 | struct max8925_chip *chip = info->chip; | ||
91 | if (enable) { | ||
92 | /* enable charger in platform */ | ||
93 | if (info->set_charger) | ||
94 | info->set_charger(1); | ||
95 | /* enable charger */ | ||
96 | max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0); | ||
97 | } else { | ||
98 | /* disable charge */ | ||
99 | max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7); | ||
100 | if (info->set_charger) | ||
101 | info->set_charger(0); | ||
102 | } | ||
103 | dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger" | ||
104 | : "Disable charger"); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static irqreturn_t max8925_charger_handler(int irq, void *data) | ||
109 | { | ||
110 | struct max8925_power_info *info = (struct max8925_power_info *)data; | ||
111 | struct max8925_chip *chip = info->chip; | ||
112 | |||
113 | switch (irq - chip->irq_base) { | ||
114 | case MAX8925_IRQ_VCHG_DC_R: | ||
115 | info->ac_online = 1; | ||
116 | __set_charger(info, 1); | ||
117 | dev_dbg(chip->dev, "Adapter inserted\n"); | ||
118 | break; | ||
119 | case MAX8925_IRQ_VCHG_DC_F: | ||
120 | info->ac_online = 0; | ||
121 | __set_charger(info, 0); | ||
122 | dev_dbg(chip->dev, "Adapter removed\n"); | ||
123 | break; | ||
124 | case MAX8925_IRQ_VCHG_THM_OK_F: | ||
125 | /* Battery is not ready yet */ | ||
126 | dev_dbg(chip->dev, "Battery temperature is out of range\n"); | ||
127 | case MAX8925_IRQ_VCHG_DC_OVP: | ||
128 | dev_dbg(chip->dev, "Error detection\n"); | ||
129 | __set_charger(info, 0); | ||
130 | break; | ||
131 | case MAX8925_IRQ_VCHG_THM_OK_R: | ||
132 | /* Battery is ready now */ | ||
133 | dev_dbg(chip->dev, "Battery temperature is in range\n"); | ||
134 | break; | ||
135 | case MAX8925_IRQ_VCHG_SYSLOW_R: | ||
136 | /* VSYS is low */ | ||
137 | dev_info(chip->dev, "Sys power is too low\n"); | ||
138 | break; | ||
139 | case MAX8925_IRQ_VCHG_SYSLOW_F: | ||
140 | dev_dbg(chip->dev, "Sys power is above low threshold\n"); | ||
141 | break; | ||
142 | case MAX8925_IRQ_VCHG_DONE: | ||
143 | __set_charger(info, 0); | ||
144 | dev_dbg(chip->dev, "Charging is done\n"); | ||
145 | break; | ||
146 | case MAX8925_IRQ_VCHG_TOPOFF: | ||
147 | dev_dbg(chip->dev, "Charging in top-off mode\n"); | ||
148 | break; | ||
149 | case MAX8925_IRQ_VCHG_TMR_FAULT: | ||
150 | __set_charger(info, 0); | ||
151 | dev_dbg(chip->dev, "Safe timer is expired\n"); | ||
152 | break; | ||
153 | case MAX8925_IRQ_VCHG_RST: | ||
154 | __set_charger(info, 0); | ||
155 | dev_dbg(chip->dev, "Charger is reset\n"); | ||
156 | break; | ||
157 | } | ||
158 | return IRQ_HANDLED; | ||
159 | } | ||
160 | |||
161 | static int start_measure(struct max8925_power_info *info, int type) | ||
162 | { | ||
163 | unsigned char buf[2] = {0, 0}; | ||
164 | int meas_cmd; | ||
165 | int meas_reg = 0, ret; | ||
166 | |||
167 | switch (type) { | ||
168 | case MEASURE_VCHG: | ||
169 | meas_cmd = MAX8925_CMD_VCHG; | ||
170 | meas_reg = MAX8925_ADC_VCHG; | ||
171 | break; | ||
172 | case MEASURE_VBBATT: | ||
173 | meas_cmd = MAX8925_CMD_VBBATT; | ||
174 | meas_reg = MAX8925_ADC_VBBATT; | ||
175 | break; | ||
176 | case MEASURE_VMBATT: | ||
177 | meas_cmd = MAX8925_CMD_VMBATT; | ||
178 | meas_reg = MAX8925_ADC_VMBATT; | ||
179 | break; | ||
180 | case MEASURE_ISNS: | ||
181 | meas_cmd = MAX8925_CMD_ISNS; | ||
182 | meas_reg = MAX8925_ADC_ISNS; | ||
183 | break; | ||
184 | default: | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | max8925_reg_write(info->adc, meas_cmd, 0); | ||
189 | max8925_bulk_read(info->adc, meas_reg, 2, buf); | ||
190 | ret = ((buf[0]<<8) | buf[1]) >> 4; | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static int max8925_ac_get_prop(struct power_supply *psy, | ||
196 | enum power_supply_property psp, | ||
197 | union power_supply_propval *val) | ||
198 | { | ||
199 | struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent); | ||
200 | int ret = 0; | ||
201 | |||
202 | switch (psp) { | ||
203 | case POWER_SUPPLY_PROP_ONLINE: | ||
204 | val->intval = info->ac_online; | ||
205 | break; | ||
206 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
207 | if (info->ac_online) { | ||
208 | ret = start_measure(info, MEASURE_VCHG); | ||
209 | if (ret >= 0) { | ||
210 | val->intval = ret * 2000; /* unit is uV */ | ||
211 | goto out; | ||
212 | } | ||
213 | } | ||
214 | ret = -ENODATA; | ||
215 | break; | ||
216 | default: | ||
217 | ret = -ENODEV; | ||
218 | break; | ||
219 | } | ||
220 | out: | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | static enum power_supply_property max8925_ac_props[] = { | ||
225 | POWER_SUPPLY_PROP_ONLINE, | ||
226 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
227 | }; | ||
228 | |||
229 | static int max8925_usb_get_prop(struct power_supply *psy, | ||
230 | enum power_supply_property psp, | ||
231 | union power_supply_propval *val) | ||
232 | { | ||
233 | struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent); | ||
234 | int ret = 0; | ||
235 | |||
236 | switch (psp) { | ||
237 | case POWER_SUPPLY_PROP_ONLINE: | ||
238 | val->intval = info->usb_online; | ||
239 | break; | ||
240 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
241 | if (info->usb_online) { | ||
242 | ret = start_measure(info, MEASURE_VCHG); | ||
243 | if (ret >= 0) { | ||
244 | val->intval = ret * 2000; /* unit is uV */ | ||
245 | goto out; | ||
246 | } | ||
247 | } | ||
248 | ret = -ENODATA; | ||
249 | break; | ||
250 | default: | ||
251 | ret = -ENODEV; | ||
252 | break; | ||
253 | } | ||
254 | out: | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | static enum power_supply_property max8925_usb_props[] = { | ||
259 | POWER_SUPPLY_PROP_ONLINE, | ||
260 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
261 | }; | ||
262 | |||
263 | static int max8925_bat_get_prop(struct power_supply *psy, | ||
264 | enum power_supply_property psp, | ||
265 | union power_supply_propval *val) | ||
266 | { | ||
267 | struct max8925_power_info *info = dev_get_drvdata(psy->dev.parent); | ||
268 | int ret = 0; | ||
269 | |||
270 | switch (psp) { | ||
271 | case POWER_SUPPLY_PROP_ONLINE: | ||
272 | val->intval = info->bat_online; | ||
273 | break; | ||
274 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
275 | if (info->bat_online) { | ||
276 | ret = start_measure(info, MEASURE_VMBATT); | ||
277 | if (ret >= 0) { | ||
278 | val->intval = ret * 2000; /* unit is uV */ | ||
279 | ret = 0; | ||
280 | break; | ||
281 | } | ||
282 | } | ||
283 | ret = -ENODATA; | ||
284 | break; | ||
285 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
286 | if (info->bat_online) { | ||
287 | ret = start_measure(info, MEASURE_ISNS); | ||
288 | if (ret >= 0) { | ||
289 | /* assume r_sns is 0.02 */ | ||
290 | ret = ((ret * 6250) - 3125) /* uA */; | ||
291 | val->intval = 0; | ||
292 | if (ret > 0) | ||
293 | val->intval = ret; /* unit is mA */ | ||
294 | ret = 0; | ||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | ret = -ENODATA; | ||
299 | break; | ||
300 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | ||
301 | if (!info->bat_online) { | ||
302 | ret = -ENODATA; | ||
303 | break; | ||
304 | } | ||
305 | ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); | ||
306 | ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2; | ||
307 | switch (ret) { | ||
308 | case 1: | ||
309 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; | ||
310 | break; | ||
311 | case 0: | ||
312 | case 2: | ||
313 | val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; | ||
314 | break; | ||
315 | case 3: | ||
316 | val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; | ||
317 | break; | ||
318 | } | ||
319 | ret = 0; | ||
320 | break; | ||
321 | case POWER_SUPPLY_PROP_STATUS: | ||
322 | if (!info->bat_online) { | ||
323 | ret = -ENODATA; | ||
324 | break; | ||
325 | } | ||
326 | ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); | ||
327 | if (info->usb_online || info->ac_online) { | ||
328 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
329 | if (ret & MAX8925_CHG_STAT_EN_MASK) | ||
330 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
331 | } else | ||
332 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
333 | ret = 0; | ||
334 | break; | ||
335 | default: | ||
336 | ret = -ENODEV; | ||
337 | break; | ||
338 | } | ||
339 | return ret; | ||
340 | } | ||
341 | |||
342 | static enum power_supply_property max8925_battery_props[] = { | ||
343 | POWER_SUPPLY_PROP_ONLINE, | ||
344 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
345 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
346 | POWER_SUPPLY_PROP_CHARGE_TYPE, | ||
347 | POWER_SUPPLY_PROP_STATUS, | ||
348 | }; | ||
349 | |||
350 | static const struct power_supply_desc ac_desc = { | ||
351 | .name = "max8925-ac", | ||
352 | .type = POWER_SUPPLY_TYPE_MAINS, | ||
353 | .properties = max8925_ac_props, | ||
354 | .num_properties = ARRAY_SIZE(max8925_ac_props), | ||
355 | .get_property = max8925_ac_get_prop, | ||
356 | }; | ||
357 | |||
358 | static const struct power_supply_desc usb_desc = { | ||
359 | .name = "max8925-usb", | ||
360 | .type = POWER_SUPPLY_TYPE_USB, | ||
361 | .properties = max8925_usb_props, | ||
362 | .num_properties = ARRAY_SIZE(max8925_usb_props), | ||
363 | .get_property = max8925_usb_get_prop, | ||
364 | }; | ||
365 | |||
366 | static const struct power_supply_desc battery_desc = { | ||
367 | .name = "max8925-battery", | ||
368 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
369 | .properties = max8925_battery_props, | ||
370 | .num_properties = ARRAY_SIZE(max8925_battery_props), | ||
371 | .get_property = max8925_bat_get_prop, | ||
372 | }; | ||
373 | |||
374 | #define REQUEST_IRQ(_irq, _name) \ | ||
375 | do { \ | ||
376 | ret = request_threaded_irq(chip->irq_base + _irq, NULL, \ | ||
377 | max8925_charger_handler, \ | ||
378 | IRQF_ONESHOT, _name, info); \ | ||
379 | if (ret) \ | ||
380 | dev_err(chip->dev, "Failed to request IRQ #%d: %d\n", \ | ||
381 | _irq, ret); \ | ||
382 | } while (0) | ||
383 | |||
384 | static int max8925_init_charger(struct max8925_chip *chip, | ||
385 | struct max8925_power_info *info) | ||
386 | { | ||
387 | int ret; | ||
388 | |||
389 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp"); | ||
390 | if (!info->no_insert_detect) { | ||
391 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove"); | ||
392 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert"); | ||
393 | } | ||
394 | if (!info->no_temp_support) { | ||
395 | REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range"); | ||
396 | REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range"); | ||
397 | } | ||
398 | REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high"); | ||
399 | REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low"); | ||
400 | REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset"); | ||
401 | REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done"); | ||
402 | REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff"); | ||
403 | REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire"); | ||
404 | |||
405 | info->usb_online = 0; | ||
406 | info->bat_online = 0; | ||
407 | |||
408 | /* check for power - can miss interrupt at boot time */ | ||
409 | if (start_measure(info, MEASURE_VCHG) * 2000 > 500000) | ||
410 | info->ac_online = 1; | ||
411 | else | ||
412 | info->ac_online = 0; | ||
413 | |||
414 | ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS); | ||
415 | if (ret >= 0) { | ||
416 | /* | ||
417 | * If battery detection is enabled, ID pin of battery is | ||
418 | * connected to MBDET pin of MAX8925. It could be used to | ||
419 | * detect battery presence. | ||
420 | * Otherwise, we have to assume that battery is always on. | ||
421 | */ | ||
422 | if (info->batt_detect) | ||
423 | info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1; | ||
424 | else | ||
425 | info->bat_online = 1; | ||
426 | if (ret & MAX8925_CHG_AC_RANGE_MASK) | ||
427 | info->ac_online = 1; | ||
428 | else | ||
429 | info->ac_online = 0; | ||
430 | } | ||
431 | /* disable charge */ | ||
432 | max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7); | ||
433 | /* set charging current in charge topoff mode */ | ||
434 | max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5, | ||
435 | info->topoff_threshold << 5); | ||
436 | /* set charing current in fast charge mode */ | ||
437 | max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge); | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int max8925_deinit_charger(struct max8925_power_info *info) | ||
443 | { | ||
444 | struct max8925_chip *chip = info->chip; | ||
445 | int irq; | ||
446 | |||
447 | irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP; | ||
448 | for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++) | ||
449 | free_irq(irq, info); | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | #ifdef CONFIG_OF | ||
455 | static struct max8925_power_pdata * | ||
456 | max8925_power_dt_init(struct platform_device *pdev) | ||
457 | { | ||
458 | struct device_node *nproot = pdev->dev.parent->of_node; | ||
459 | struct device_node *np; | ||
460 | int batt_detect; | ||
461 | int topoff_threshold; | ||
462 | int fast_charge; | ||
463 | int no_temp_support; | ||
464 | int no_insert_detect; | ||
465 | struct max8925_power_pdata *pdata; | ||
466 | |||
467 | if (!nproot) | ||
468 | return pdev->dev.platform_data; | ||
469 | |||
470 | np = of_get_child_by_name(nproot, "charger"); | ||
471 | if (!np) { | ||
472 | dev_err(&pdev->dev, "failed to find charger node\n"); | ||
473 | return NULL; | ||
474 | } | ||
475 | |||
476 | pdata = devm_kzalloc(&pdev->dev, | ||
477 | sizeof(struct max8925_power_pdata), | ||
478 | GFP_KERNEL); | ||
479 | if (!pdata) | ||
480 | goto ret; | ||
481 | |||
482 | of_property_read_u32(np, "topoff-threshold", &topoff_threshold); | ||
483 | of_property_read_u32(np, "batt-detect", &batt_detect); | ||
484 | of_property_read_u32(np, "fast-charge", &fast_charge); | ||
485 | of_property_read_u32(np, "no-insert-detect", &no_insert_detect); | ||
486 | of_property_read_u32(np, "no-temp-support", &no_temp_support); | ||
487 | |||
488 | pdata->batt_detect = batt_detect; | ||
489 | pdata->fast_charge = fast_charge; | ||
490 | pdata->topoff_threshold = topoff_threshold; | ||
491 | pdata->no_insert_detect = no_insert_detect; | ||
492 | pdata->no_temp_support = no_temp_support; | ||
493 | |||
494 | ret: | ||
495 | of_node_put(np); | ||
496 | return pdata; | ||
497 | } | ||
498 | #else | ||
499 | static struct max8925_power_pdata * | ||
500 | max8925_power_dt_init(struct platform_device *pdev) | ||
501 | { | ||
502 | return pdev->dev.platform_data; | ||
503 | } | ||
504 | #endif | ||
505 | |||
506 | static int max8925_power_probe(struct platform_device *pdev) | ||
507 | { | ||
508 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
509 | struct power_supply_config psy_cfg = {}; /* Only for ac and usb */ | ||
510 | struct max8925_power_pdata *pdata = NULL; | ||
511 | struct max8925_power_info *info; | ||
512 | int ret; | ||
513 | |||
514 | pdata = max8925_power_dt_init(pdev); | ||
515 | if (!pdata) { | ||
516 | dev_err(&pdev->dev, "platform data isn't assigned to " | ||
517 | "power supply\n"); | ||
518 | return -EINVAL; | ||
519 | } | ||
520 | |||
521 | info = devm_kzalloc(&pdev->dev, sizeof(struct max8925_power_info), | ||
522 | GFP_KERNEL); | ||
523 | if (!info) | ||
524 | return -ENOMEM; | ||
525 | info->chip = chip; | ||
526 | info->gpm = chip->i2c; | ||
527 | info->adc = chip->adc; | ||
528 | platform_set_drvdata(pdev, info); | ||
529 | |||
530 | psy_cfg.supplied_to = pdata->supplied_to; | ||
531 | psy_cfg.num_supplicants = pdata->num_supplicants; | ||
532 | |||
533 | info->ac = power_supply_register(&pdev->dev, &ac_desc, &psy_cfg); | ||
534 | if (IS_ERR(info->ac)) { | ||
535 | ret = PTR_ERR(info->ac); | ||
536 | goto out; | ||
537 | } | ||
538 | info->ac->dev.parent = &pdev->dev; | ||
539 | |||
540 | info->usb = power_supply_register(&pdev->dev, &usb_desc, &psy_cfg); | ||
541 | if (IS_ERR(info->usb)) { | ||
542 | ret = PTR_ERR(info->usb); | ||
543 | goto out_unregister_ac; | ||
544 | } | ||
545 | info->usb->dev.parent = &pdev->dev; | ||
546 | |||
547 | info->battery = power_supply_register(&pdev->dev, &battery_desc, NULL); | ||
548 | if (IS_ERR(info->battery)) { | ||
549 | ret = PTR_ERR(info->battery); | ||
550 | goto out_unregister_usb; | ||
551 | } | ||
552 | info->battery->dev.parent = &pdev->dev; | ||
553 | |||
554 | info->batt_detect = pdata->batt_detect; | ||
555 | info->topoff_threshold = pdata->topoff_threshold; | ||
556 | info->fast_charge = pdata->fast_charge; | ||
557 | info->set_charger = pdata->set_charger; | ||
558 | info->no_temp_support = pdata->no_temp_support; | ||
559 | info->no_insert_detect = pdata->no_insert_detect; | ||
560 | |||
561 | max8925_init_charger(chip, info); | ||
562 | return 0; | ||
563 | out_unregister_usb: | ||
564 | power_supply_unregister(info->usb); | ||
565 | out_unregister_ac: | ||
566 | power_supply_unregister(info->ac); | ||
567 | out: | ||
568 | return ret; | ||
569 | } | ||
570 | |||
571 | static int max8925_power_remove(struct platform_device *pdev) | ||
572 | { | ||
573 | struct max8925_power_info *info = platform_get_drvdata(pdev); | ||
574 | |||
575 | if (info) { | ||
576 | power_supply_unregister(info->ac); | ||
577 | power_supply_unregister(info->usb); | ||
578 | power_supply_unregister(info->battery); | ||
579 | max8925_deinit_charger(info); | ||
580 | } | ||
581 | return 0; | ||
582 | } | ||
583 | |||
584 | static struct platform_driver max8925_power_driver = { | ||
585 | .probe = max8925_power_probe, | ||
586 | .remove = max8925_power_remove, | ||
587 | .driver = { | ||
588 | .name = "max8925-power", | ||
589 | }, | ||
590 | }; | ||
591 | |||
592 | module_platform_driver(max8925_power_driver); | ||
593 | |||
594 | MODULE_LICENSE("GPL"); | ||
595 | MODULE_DESCRIPTION("Power supply driver for MAX8925"); | ||
596 | MODULE_ALIAS("platform:max8925-power"); | ||