Commit 4b24ff71108164e047cf2c95990b77651163e315
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge tag 'for-v3.6' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov: "The tag contains just a few battery-related changes for v3.6. It's is all pretty straightforward, except one thing. One of our patches added thermal support for power supply class, but thermal/ subsystem changed under our feet. We (well, Stephen, that is) caught the issue and it was decided[1] that I'd just delay the battery pull request, and then will fix it up by merging upstream back into battery tree at the specific commit. That's not all though: another[2] small fixup for thermal subsystem was needed to get rid of a warning in power supply subsystem (the warning was not drivers/power's "fault", the thermal registration function just needed a proper const annotation, which is also done by a small commit on top of the merge. So, to sum this up: - The 'master' branch of the battery tree was in the -next tree for weeks, was never rebased, altered etc. It should be all OK; - Although, for-v3.6 tag contains the 'master' branch + merge + the warning fix. [1] http://lkml.org/lkml/2012/6/19/23 [2] http://lkml.org/lkml/2012/6/18/28" * tag 'for-v3.6' of git://git.infradead.org/battery-2.6: (23 commits) thermal: Constify 'type' argument for the registration routine olpc-battery: update CHARGE_FULL_DESIGN property for BYD LiFe batteries olpc-battery: Add VOLTAGE_MAX_DESIGN property charger-manager: Fix build break related to EXTCON lp8727_charger: Move header file into platform_data directory power_supply: Add min/max alert properties for CAPACITY, TEMP, TEMP_AMBIENT bq27x00_battery: Add support for BQ27425 chip charger-manager: Set current limit of regulator for over current protection charger-manager: Use EXTCON Subsystem to detect charger cables for charging test_power: Add VOLTAGE_NOW and BATTERY_TEMP properties test_power: Add support for USB AC source gpio-charger: Use cansleep version of gpio_set_value bq27x00_battery: Add support for power average and health properties sbs-battery: Don't trigger false supply_changed event twl4030_charger: Allow charger to control the regulator that feeds it twl4030_charger: Add backup-battery charging twl4030_charger: Fix some typos max17042_battery: Support CHARGE_COUNTER power supply attribute smb347-charger: Add constant charge and current properties power_supply: Add constant charge_current and charge_voltage properties ...
Showing 24 changed files Side-by-side Diff
- Documentation/power/power_supply_class.txt
- drivers/mfd/twl-core.c
- drivers/power/Kconfig
- drivers/power/bq27x00_battery.c
- drivers/power/charger-manager.c
- drivers/power/ds2781_battery.c
- drivers/power/gpio-charger.c
- drivers/power/lp8727_charger.c
- drivers/power/max17042_battery.c
- drivers/power/olpc_battery.c
- drivers/power/pda_power.c
- drivers/power/power_supply_core.c
- drivers/power/power_supply_sysfs.c
- drivers/power/sbs-battery.c
- drivers/power/smb347-charger.c
- drivers/power/test_power.c
- drivers/power/twl4030_charger.c
- drivers/thermal/thermal_sys.c
- include/linux/i2c/twl.h
- include/linux/lp8727.h
- include/linux/platform_data/lp8727.h
- include/linux/power/charger-manager.h
- include/linux/power_supply.h
- include/linux/thermal.h
Documentation/power/power_supply_class.txt
... | ... | @@ -112,14 +112,24 @@ |
112 | 112 | be negative; there is no empty or full value. It is only useful for |
113 | 113 | relative, time-based measurements. |
114 | 114 | |
115 | +CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger. | |
116 | + | |
117 | +CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. | |
118 | + | |
115 | 119 | ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. |
116 | 120 | |
117 | 121 | CAPACITY - capacity in percents. |
122 | +CAPACITY_ALERT_MIN - minimum capacity alert value in percents. | |
123 | +CAPACITY_ALERT_MAX - maximum capacity alert value in percents. | |
118 | 124 | CAPACITY_LEVEL - capacity level. This corresponds to |
119 | 125 | POWER_SUPPLY_CAPACITY_LEVEL_*. |
120 | 126 | |
121 | 127 | TEMP - temperature of the power supply. |
128 | +TEMP_ALERT_MIN - minimum battery temperature alert value in milli centigrade. | |
129 | +TEMP_ALERT_MAX - maximum battery temperature alert value in milli centigrade. | |
122 | 130 | TEMP_AMBIENT - ambient temperature. |
131 | +TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert value in milli centigrade. | |
132 | +TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert value in milli centigrade. | |
123 | 133 | |
124 | 134 | TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e. |
125 | 135 | while battery powers a load) |
drivers/mfd/twl-core.c
... | ... | @@ -717,8 +717,9 @@ |
717 | 717 | static struct regulator_consumer_supply usb1v8 = { |
718 | 718 | .supply = "usb1v8", |
719 | 719 | }; |
720 | - static struct regulator_consumer_supply usb3v1 = { | |
721 | - .supply = "usb3v1", | |
720 | + static struct regulator_consumer_supply usb3v1[] = { | |
721 | + { .supply = "usb3v1" }, | |
722 | + { .supply = "bci3v1" }, | |
722 | 723 | }; |
723 | 724 | |
724 | 725 | /* First add the regulators so that they can be used by transceiver */ |
... | ... | @@ -746,7 +747,7 @@ |
746 | 747 | return PTR_ERR(child); |
747 | 748 | |
748 | 749 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, |
749 | - &usb_fixed, &usb3v1, 1, | |
750 | + &usb_fixed, usb3v1, 2, | |
750 | 751 | features); |
751 | 752 | if (IS_ERR(child)) |
752 | 753 | return PTR_ERR(child); |
... | ... | @@ -767,7 +768,7 @@ |
767 | 768 | if (twl_has_regulator() && child) { |
768 | 769 | usb1v5.dev_name = dev_name(child); |
769 | 770 | usb1v8.dev_name = dev_name(child); |
770 | - usb3v1.dev_name = dev_name(child); | |
771 | + usb3v1[0].dev_name = dev_name(child); | |
771 | 772 | } |
772 | 773 | } |
773 | 774 | if (twl_has_usb() && pdata->usb && twl_class_is_6030()) { |
drivers/power/Kconfig
... | ... | @@ -268,6 +268,7 @@ |
268 | 268 | config CHARGER_MANAGER |
269 | 269 | bool "Battery charger manager for multiple chargers" |
270 | 270 | depends on REGULATOR && RTC_CLASS |
271 | + select EXTCON | |
271 | 272 | help |
272 | 273 | Say Y to enable charger-manager support, which allows multiple |
273 | 274 | chargers attached to a battery and multiple batteries attached to a |
drivers/power/bq27x00_battery.c
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | * Datasheets: |
23 | 23 | * http://focus.ti.com/docs/prod/folders/print/bq27000.html |
24 | 24 | * http://focus.ti.com/docs/prod/folders/print/bq27500.html |
25 | + * http://www.ti.com/product/bq27425-g1 | |
25 | 26 | */ |
26 | 27 | |
27 | 28 | #include <linux/module.h> |
... | ... | @@ -51,6 +52,7 @@ |
51 | 52 | #define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ |
52 | 53 | #define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ |
53 | 54 | #define BQ27x00_REG_AE 0x22 /* Available energy */ |
55 | +#define BQ27x00_POWER_AVG 0x24 | |
54 | 56 | |
55 | 57 | #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ |
56 | 58 | #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ |
57 | 59 | |
58 | 60 | |
59 | 61 | |
... | ... | @@ -66,15 +68,21 @@ |
66 | 68 | #define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ |
67 | 69 | #define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ |
68 | 70 | #define BQ27500_FLAG_FC BIT(9) |
71 | +#define BQ27500_FLAG_OTC BIT(15) | |
69 | 72 | |
73 | +/* bq27425 register addresses are same as bq27x00 addresses minus 4 */ | |
74 | +#define BQ27425_REG_OFFSET 0x04 | |
75 | +#define BQ27425_REG_SOC 0x18 /* Register address plus offset */ | |
76 | + | |
70 | 77 | #define BQ27000_RS 20 /* Resistor sense */ |
78 | +#define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000) | |
71 | 79 | |
72 | 80 | struct bq27x00_device_info; |
73 | 81 | struct bq27x00_access_methods { |
74 | 82 | int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); |
75 | 83 | }; |
76 | 84 | |
77 | -enum bq27x00_chip { BQ27000, BQ27500 }; | |
85 | +enum bq27x00_chip { BQ27000, BQ27500, BQ27425}; | |
78 | 86 | |
79 | 87 | struct bq27x00_reg_cache { |
80 | 88 | int temperature; |
... | ... | @@ -86,6 +94,8 @@ |
86 | 94 | int capacity; |
87 | 95 | int energy; |
88 | 96 | int flags; |
97 | + int power_avg; | |
98 | + int health; | |
89 | 99 | }; |
90 | 100 | |
91 | 101 | struct bq27x00_device_info { |
92 | 102 | |
... | ... | @@ -123,8 +133,24 @@ |
123 | 133 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, |
124 | 134 | POWER_SUPPLY_PROP_CYCLE_COUNT, |
125 | 135 | POWER_SUPPLY_PROP_ENERGY_NOW, |
136 | + POWER_SUPPLY_PROP_POWER_AVG, | |
137 | + POWER_SUPPLY_PROP_HEALTH, | |
126 | 138 | }; |
127 | 139 | |
140 | +static enum power_supply_property bq27425_battery_props[] = { | |
141 | + POWER_SUPPLY_PROP_STATUS, | |
142 | + POWER_SUPPLY_PROP_PRESENT, | |
143 | + POWER_SUPPLY_PROP_VOLTAGE_NOW, | |
144 | + POWER_SUPPLY_PROP_CURRENT_NOW, | |
145 | + POWER_SUPPLY_PROP_CAPACITY, | |
146 | + POWER_SUPPLY_PROP_CAPACITY_LEVEL, | |
147 | + POWER_SUPPLY_PROP_TEMP, | |
148 | + POWER_SUPPLY_PROP_TECHNOLOGY, | |
149 | + POWER_SUPPLY_PROP_CHARGE_FULL, | |
150 | + POWER_SUPPLY_PROP_CHARGE_NOW, | |
151 | + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | |
152 | +}; | |
153 | + | |
128 | 154 | static unsigned int poll_interval = 360; |
129 | 155 | module_param(poll_interval, uint, 0644); |
130 | 156 | MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ |
131 | 157 | |
... | ... | @@ -137,10 +163,24 @@ |
137 | 163 | static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, |
138 | 164 | bool single) |
139 | 165 | { |
166 | + if (di->chip == BQ27425) | |
167 | + return di->bus.read(di, reg - BQ27425_REG_OFFSET, single); | |
140 | 168 | return di->bus.read(di, reg, single); |
141 | 169 | } |
142 | 170 | |
143 | 171 | /* |
172 | + * Higher versions of the chip like BQ27425 and BQ27500 | |
173 | + * differ from BQ27000 and BQ27200 in calculation of certain | |
174 | + * parameters. Hence we need to check for the chip type. | |
175 | + */ | |
176 | +static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) | |
177 | +{ | |
178 | + if (di->chip == BQ27425 || di->chip == BQ27500) | |
179 | + return true; | |
180 | + return false; | |
181 | +} | |
182 | + | |
183 | +/* | |
144 | 184 | * Return the battery Relative State-of-Charge |
145 | 185 | * Or < 0 if something fails. |
146 | 186 | */ |
... | ... | @@ -150,6 +190,8 @@ |
150 | 190 | |
151 | 191 | if (di->chip == BQ27500) |
152 | 192 | rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); |
193 | + else if (di->chip == BQ27425) | |
194 | + rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); | |
153 | 195 | else |
154 | 196 | rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); |
155 | 197 | |
... | ... | @@ -174,7 +216,7 @@ |
174 | 216 | return charge; |
175 | 217 | } |
176 | 218 | |
177 | - if (di->chip == BQ27500) | |
219 | + if (bq27xxx_is_chip_version_higher(di)) | |
178 | 220 | charge *= 1000; |
179 | 221 | else |
180 | 222 | charge = charge * 3570 / BQ27000_RS; |
... | ... | @@ -208,7 +250,7 @@ |
208 | 250 | { |
209 | 251 | int ilmd; |
210 | 252 | |
211 | - if (di->chip == BQ27500) | |
253 | + if (bq27xxx_is_chip_version_higher(di)) | |
212 | 254 | ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); |
213 | 255 | else |
214 | 256 | ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); |
... | ... | @@ -218,7 +260,7 @@ |
218 | 260 | return ilmd; |
219 | 261 | } |
220 | 262 | |
221 | - if (di->chip == BQ27500) | |
263 | + if (bq27xxx_is_chip_version_higher(di)) | |
222 | 264 | ilmd *= 1000; |
223 | 265 | else |
224 | 266 | ilmd = ilmd * 256 * 3570 / BQ27000_RS; |
... | ... | @@ -262,7 +304,7 @@ |
262 | 304 | return temp; |
263 | 305 | } |
264 | 306 | |
265 | - if (di->chip == BQ27500) | |
307 | + if (bq27xxx_is_chip_version_higher(di)) | |
266 | 308 | temp -= 2731; |
267 | 309 | else |
268 | 310 | temp = ((temp * 5) - 5463) / 2; |
269 | 311 | |
270 | 312 | |
... | ... | @@ -306,14 +348,70 @@ |
306 | 348 | return tval * 60; |
307 | 349 | } |
308 | 350 | |
351 | +/* | |
352 | + * Read a power avg register. | |
353 | + * Return < 0 if something fails. | |
354 | + */ | |
355 | +static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg) | |
356 | +{ | |
357 | + int tval; | |
358 | + | |
359 | + tval = bq27x00_read(di, reg, false); | |
360 | + if (tval < 0) { | |
361 | + dev_err(di->dev, "error reading power avg rgister %02x: %d\n", | |
362 | + reg, tval); | |
363 | + return tval; | |
364 | + } | |
365 | + | |
366 | + if (di->chip == BQ27500) | |
367 | + return tval; | |
368 | + else | |
369 | + return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS; | |
370 | +} | |
371 | + | |
372 | +/* | |
373 | + * Read flag register. | |
374 | + * Return < 0 if something fails. | |
375 | + */ | |
376 | +static int bq27x00_battery_read_health(struct bq27x00_device_info *di) | |
377 | +{ | |
378 | + int tval; | |
379 | + | |
380 | + tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | |
381 | + if (tval < 0) { | |
382 | + dev_err(di->dev, "error reading flag register:%d\n", tval); | |
383 | + return tval; | |
384 | + } | |
385 | + | |
386 | + if ((di->chip == BQ27500)) { | |
387 | + if (tval & BQ27500_FLAG_SOCF) | |
388 | + tval = POWER_SUPPLY_HEALTH_DEAD; | |
389 | + else if (tval & BQ27500_FLAG_OTC) | |
390 | + tval = POWER_SUPPLY_HEALTH_OVERHEAT; | |
391 | + else | |
392 | + tval = POWER_SUPPLY_HEALTH_GOOD; | |
393 | + return tval; | |
394 | + } else { | |
395 | + if (tval & BQ27000_FLAG_EDV1) | |
396 | + tval = POWER_SUPPLY_HEALTH_DEAD; | |
397 | + else | |
398 | + tval = POWER_SUPPLY_HEALTH_GOOD; | |
399 | + return tval; | |
400 | + } | |
401 | + | |
402 | + return -1; | |
403 | +} | |
404 | + | |
309 | 405 | static void bq27x00_update(struct bq27x00_device_info *di) |
310 | 406 | { |
311 | 407 | struct bq27x00_reg_cache cache = {0, }; |
312 | 408 | bool is_bq27500 = di->chip == BQ27500; |
409 | + bool is_bq27425 = di->chip == BQ27425; | |
313 | 410 | |
314 | 411 | cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); |
315 | 412 | if (cache.flags >= 0) { |
316 | - if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) { | |
413 | + if (!is_bq27500 && !is_bq27425 | |
414 | + && (cache.flags & BQ27000_FLAG_CI)) { | |
317 | 415 | dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); |
318 | 416 | cache.capacity = -ENODATA; |
319 | 417 | cache.energy = -ENODATA; |
320 | 418 | |
321 | 419 | |
322 | 420 | |
323 | 421 | |
... | ... | @@ -321,16 +419,30 @@ |
321 | 419 | cache.time_to_empty_avg = -ENODATA; |
322 | 420 | cache.time_to_full = -ENODATA; |
323 | 421 | cache.charge_full = -ENODATA; |
422 | + cache.health = -ENODATA; | |
324 | 423 | } else { |
325 | 424 | cache.capacity = bq27x00_battery_read_rsoc(di); |
326 | - cache.energy = bq27x00_battery_read_energy(di); | |
327 | - cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE); | |
328 | - cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP); | |
329 | - cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF); | |
425 | + if (!is_bq27425) { | |
426 | + cache.energy = bq27x00_battery_read_energy(di); | |
427 | + cache.time_to_empty = | |
428 | + bq27x00_battery_read_time(di, | |
429 | + BQ27x00_REG_TTE); | |
430 | + cache.time_to_empty_avg = | |
431 | + bq27x00_battery_read_time(di, | |
432 | + BQ27x00_REG_TTECP); | |
433 | + cache.time_to_full = | |
434 | + bq27x00_battery_read_time(di, | |
435 | + BQ27x00_REG_TTF); | |
436 | + } | |
330 | 437 | cache.charge_full = bq27x00_battery_read_lmd(di); |
438 | + cache.health = bq27x00_battery_read_health(di); | |
331 | 439 | } |
332 | 440 | cache.temperature = bq27x00_battery_read_temperature(di); |
441 | + if (!is_bq27425) | |
442 | + cache.cycle_count = bq27x00_battery_read_cyct(di); | |
333 | 443 | cache.cycle_count = bq27x00_battery_read_cyct(di); |
444 | + cache.power_avg = | |
445 | + bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); | |
334 | 446 | |
335 | 447 | /* We only have to read charge design full once */ |
336 | 448 | if (di->charge_design_full <= 0) |
... | ... | @@ -376,7 +488,7 @@ |
376 | 488 | return curr; |
377 | 489 | } |
378 | 490 | |
379 | - if (di->chip == BQ27500) { | |
491 | + if (bq27xxx_is_chip_version_higher(di)) { | |
380 | 492 | /* bq27500 returns signed value */ |
381 | 493 | val->intval = (int)((s16)curr) * 1000; |
382 | 494 | } else { |
... | ... | @@ -397,7 +509,7 @@ |
397 | 509 | { |
398 | 510 | int status; |
399 | 511 | |
400 | - if (di->chip == BQ27500) { | |
512 | + if (bq27xxx_is_chip_version_higher(di)) { | |
401 | 513 | if (di->cache.flags & BQ27500_FLAG_FC) |
402 | 514 | status = POWER_SUPPLY_STATUS_FULL; |
403 | 515 | else if (di->cache.flags & BQ27500_FLAG_DSC) |
... | ... | @@ -425,7 +537,7 @@ |
425 | 537 | { |
426 | 538 | int level; |
427 | 539 | |
428 | - if (di->chip == BQ27500) { | |
540 | + if (bq27xxx_is_chip_version_higher(di)) { | |
429 | 541 | if (di->cache.flags & BQ27500_FLAG_FC) |
430 | 542 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; |
431 | 543 | else if (di->cache.flags & BQ27500_FLAG_SOC1) |
... | ... | @@ -550,6 +662,12 @@ |
550 | 662 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
551 | 663 | ret = bq27x00_simple_value(di->cache.energy, val); |
552 | 664 | break; |
665 | + case POWER_SUPPLY_PROP_POWER_AVG: | |
666 | + ret = bq27x00_simple_value(di->cache.power_avg, val); | |
667 | + break; | |
668 | + case POWER_SUPPLY_PROP_HEALTH: | |
669 | + ret = bq27x00_simple_value(di->cache.health, val); | |
670 | + break; | |
553 | 671 | default: |
554 | 672 | return -EINVAL; |
555 | 673 | } |
... | ... | @@ -570,8 +688,14 @@ |
570 | 688 | int ret; |
571 | 689 | |
572 | 690 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
573 | - di->bat.properties = bq27x00_battery_props; | |
574 | - di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); | |
691 | + di->chip = BQ27425; | |
692 | + if (di->chip == BQ27425) { | |
693 | + di->bat.properties = bq27425_battery_props; | |
694 | + di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props); | |
695 | + } else { | |
696 | + di->bat.properties = bq27x00_battery_props; | |
697 | + di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); | |
698 | + } | |
575 | 699 | di->bat.get_property = bq27x00_battery_get_property; |
576 | 700 | di->bat.external_power_changed = bq27x00_external_power_changed; |
577 | 701 | |
... | ... | @@ -729,6 +853,7 @@ |
729 | 853 | static const struct i2c_device_id bq27x00_id[] = { |
730 | 854 | { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ |
731 | 855 | { "bq27500", BQ27500 }, |
856 | + { "bq27425", BQ27425 }, | |
732 | 857 | {}, |
733 | 858 | }; |
734 | 859 | MODULE_DEVICE_TABLE(i2c, bq27x00_id); |
drivers/power/charger-manager.c
... | ... | @@ -271,16 +271,13 @@ |
271 | 271 | if (enable) { |
272 | 272 | if (cm->emergency_stop) |
273 | 273 | return -EAGAIN; |
274 | - err = regulator_bulk_enable(desc->num_charger_regulators, | |
275 | - desc->charger_regulators); | |
274 | + for (i = 0 ; i < desc->num_charger_regulators ; i++) | |
275 | + regulator_enable(desc->charger_regulators[i].consumer); | |
276 | 276 | } else { |
277 | 277 | /* |
278 | 278 | * Abnormal battery state - Stop charging forcibly, |
279 | 279 | * even if charger was enabled at the other places |
280 | 280 | */ |
281 | - err = regulator_bulk_disable(desc->num_charger_regulators, | |
282 | - desc->charger_regulators); | |
283 | - | |
284 | 281 | for (i = 0; i < desc->num_charger_regulators; i++) { |
285 | 282 | if (regulator_is_enabled( |
286 | 283 | desc->charger_regulators[i].consumer)) { |
... | ... | @@ -288,7 +285,7 @@ |
288 | 285 | desc->charger_regulators[i].consumer); |
289 | 286 | dev_warn(cm->dev, |
290 | 287 | "Disable regulator(%s) forcibly.\n", |
291 | - desc->charger_regulators[i].supply); | |
288 | + desc->charger_regulators[i].regulator_name); | |
292 | 289 | } |
293 | 290 | } |
294 | 291 | } |
295 | 292 | |
... | ... | @@ -994,11 +991,92 @@ |
994 | 991 | } |
995 | 992 | EXPORT_SYMBOL_GPL(setup_charger_manager); |
996 | 993 | |
994 | +/** | |
995 | + * charger_extcon_work - enable/diable charger according to the state | |
996 | + * of charger cable | |
997 | + * | |
998 | + * @work: work_struct of the function charger_extcon_work. | |
999 | + */ | |
1000 | +static void charger_extcon_work(struct work_struct *work) | |
1001 | +{ | |
1002 | + struct charger_cable *cable = | |
1003 | + container_of(work, struct charger_cable, wq); | |
1004 | + int ret; | |
1005 | + | |
1006 | + if (cable->attached && cable->min_uA != 0 && cable->max_uA != 0) { | |
1007 | + ret = regulator_set_current_limit(cable->charger->consumer, | |
1008 | + cable->min_uA, cable->max_uA); | |
1009 | + if (ret < 0) { | |
1010 | + pr_err("Cannot set current limit of %s (%s)\n", | |
1011 | + cable->charger->regulator_name, cable->name); | |
1012 | + return; | |
1013 | + } | |
1014 | + | |
1015 | + pr_info("Set current limit of %s : %duA ~ %duA\n", | |
1016 | + cable->charger->regulator_name, | |
1017 | + cable->min_uA, cable->max_uA); | |
1018 | + } | |
1019 | + | |
1020 | + try_charger_enable(cable->cm, cable->attached); | |
1021 | +} | |
1022 | + | |
1023 | +/** | |
1024 | + * charger_extcon_notifier - receive the state of charger cable | |
1025 | + * when registered cable is attached or detached. | |
1026 | + * | |
1027 | + * @self: the notifier block of the charger_extcon_notifier. | |
1028 | + * @event: the cable state. | |
1029 | + * @ptr: the data pointer of notifier block. | |
1030 | + */ | |
1031 | +static int charger_extcon_notifier(struct notifier_block *self, | |
1032 | + unsigned long event, void *ptr) | |
1033 | +{ | |
1034 | + struct charger_cable *cable = | |
1035 | + container_of(self, struct charger_cable, nb); | |
1036 | + | |
1037 | + cable->attached = event; | |
1038 | + schedule_work(&cable->wq); | |
1039 | + | |
1040 | + return NOTIFY_DONE; | |
1041 | +} | |
1042 | + | |
1043 | +/** | |
1044 | + * charger_extcon_init - register external connector to use it | |
1045 | + * as the charger cable | |
1046 | + * | |
1047 | + * @cm: the Charger Manager representing the battery. | |
1048 | + * @cable: the Charger cable representing the external connector. | |
1049 | + */ | |
1050 | +static int charger_extcon_init(struct charger_manager *cm, | |
1051 | + struct charger_cable *cable) | |
1052 | +{ | |
1053 | + int ret = 0; | |
1054 | + | |
1055 | + /* | |
1056 | + * Charger manager use Extcon framework to identify | |
1057 | + * the charger cable among various external connector | |
1058 | + * cable (e.g., TA, USB, MHL, Dock). | |
1059 | + */ | |
1060 | + INIT_WORK(&cable->wq, charger_extcon_work); | |
1061 | + cable->nb.notifier_call = charger_extcon_notifier; | |
1062 | + ret = extcon_register_interest(&cable->extcon_dev, | |
1063 | + cable->extcon_name, cable->name, &cable->nb); | |
1064 | + if (ret < 0) { | |
1065 | + pr_info("Cannot register extcon_dev for %s(cable: %s).\n", | |
1066 | + cable->extcon_name, | |
1067 | + cable->name); | |
1068 | + ret = -EINVAL; | |
1069 | + } | |
1070 | + | |
1071 | + return ret; | |
1072 | +} | |
1073 | + | |
997 | 1074 | static int charger_manager_probe(struct platform_device *pdev) |
998 | 1075 | { |
999 | 1076 | struct charger_desc *desc = dev_get_platdata(&pdev->dev); |
1000 | 1077 | struct charger_manager *cm; |
1001 | 1078 | int ret = 0, i = 0; |
1079 | + int j = 0; | |
1002 | 1080 | union power_supply_propval val; |
1003 | 1081 | |
1004 | 1082 | if (g_desc && !rtc_dev && g_desc->rtc_name) { |
... | ... | @@ -1167,11 +1245,31 @@ |
1167 | 1245 | goto err_register; |
1168 | 1246 | } |
1169 | 1247 | |
1170 | - ret = regulator_bulk_get(&pdev->dev, desc->num_charger_regulators, | |
1171 | - desc->charger_regulators); | |
1172 | - if (ret) { | |
1173 | - dev_err(&pdev->dev, "Cannot get charger regulators.\n"); | |
1174 | - goto err_bulk_get; | |
1248 | + for (i = 0 ; i < desc->num_charger_regulators ; i++) { | |
1249 | + struct charger_regulator *charger | |
1250 | + = &desc->charger_regulators[i]; | |
1251 | + | |
1252 | + charger->consumer = regulator_get(&pdev->dev, | |
1253 | + charger->regulator_name); | |
1254 | + if (charger->consumer == NULL) { | |
1255 | + dev_err(&pdev->dev, "Cannot find charger(%s)n", | |
1256 | + charger->regulator_name); | |
1257 | + ret = -EINVAL; | |
1258 | + goto err_chg_get; | |
1259 | + } | |
1260 | + | |
1261 | + for (j = 0 ; j < charger->num_cables ; j++) { | |
1262 | + struct charger_cable *cable = &charger->cables[j]; | |
1263 | + | |
1264 | + ret = charger_extcon_init(cm, cable); | |
1265 | + if (ret < 0) { | |
1266 | + dev_err(&pdev->dev, "Cannot find charger(%s)n", | |
1267 | + charger->regulator_name); | |
1268 | + goto err_extcon; | |
1269 | + } | |
1270 | + cable->charger = charger; | |
1271 | + cable->cm = cm; | |
1272 | + } | |
1175 | 1273 | } |
1176 | 1274 | |
1177 | 1275 | ret = try_charger_enable(cm, true); |
... | ... | @@ -1197,9 +1295,19 @@ |
1197 | 1295 | return 0; |
1198 | 1296 | |
1199 | 1297 | err_chg_enable: |
1200 | - regulator_bulk_free(desc->num_charger_regulators, | |
1201 | - desc->charger_regulators); | |
1202 | -err_bulk_get: | |
1298 | +err_extcon: | |
1299 | + for (i = 0 ; i < desc->num_charger_regulators ; i++) { | |
1300 | + struct charger_regulator *charger | |
1301 | + = &desc->charger_regulators[i]; | |
1302 | + for (j = 0 ; j < charger->num_cables ; j++) { | |
1303 | + struct charger_cable *cable = &charger->cables[j]; | |
1304 | + extcon_unregister_interest(&cable->extcon_dev); | |
1305 | + } | |
1306 | + } | |
1307 | +err_chg_get: | |
1308 | + for (i = 0 ; i < desc->num_charger_regulators ; i++) | |
1309 | + regulator_put(desc->charger_regulators[i].consumer); | |
1310 | + | |
1203 | 1311 | power_supply_unregister(&cm->charger_psy); |
1204 | 1312 | err_register: |
1205 | 1313 | kfree(cm->charger_psy.properties); |
... | ... | @@ -1218,6 +1326,8 @@ |
1218 | 1326 | { |
1219 | 1327 | struct charger_manager *cm = platform_get_drvdata(pdev); |
1220 | 1328 | struct charger_desc *desc = cm->desc; |
1329 | + int i = 0; | |
1330 | + int j = 0; | |
1221 | 1331 | |
1222 | 1332 | /* Remove from the list */ |
1223 | 1333 | mutex_lock(&cm_list_mtx); |
... | ... | @@ -1229,8 +1339,18 @@ |
1229 | 1339 | if (delayed_work_pending(&cm_monitor_work)) |
1230 | 1340 | cancel_delayed_work_sync(&cm_monitor_work); |
1231 | 1341 | |
1232 | - regulator_bulk_free(desc->num_charger_regulators, | |
1233 | - desc->charger_regulators); | |
1342 | + for (i = 0 ; i < desc->num_charger_regulators ; i++) { | |
1343 | + struct charger_regulator *charger | |
1344 | + = &desc->charger_regulators[i]; | |
1345 | + for (j = 0 ; j < charger->num_cables ; j++) { | |
1346 | + struct charger_cable *cable = &charger->cables[j]; | |
1347 | + extcon_unregister_interest(&cable->extcon_dev); | |
1348 | + } | |
1349 | + } | |
1350 | + | |
1351 | + for (i = 0 ; i < desc->num_charger_regulators ; i++) | |
1352 | + regulator_put(desc->charger_regulators[i].consumer); | |
1353 | + | |
1234 | 1354 | power_supply_unregister(&cm->charger_psy); |
1235 | 1355 | |
1236 | 1356 | try_charger_enable(cm, false); |
drivers/power/ds2781_battery.c
... | ... | @@ -64,7 +64,7 @@ |
64 | 64 | return w1_ds2781_io(dev_info->w1_dev, buf, addr, count, io); |
65 | 65 | } |
66 | 66 | |
67 | -int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, | |
67 | +static int w1_ds2781_read(struct ds2781_device_info *dev_info, char *buf, | |
68 | 68 | int addr, size_t count) |
69 | 69 | { |
70 | 70 | return ds2781_battery_io(dev_info, buf, addr, count, 0); |
drivers/power/gpio-charger.c
drivers/power/lp8727_charger.c
drivers/power/max17042_battery.c
... | ... | @@ -113,6 +113,7 @@ |
113 | 113 | POWER_SUPPLY_PROP_VOLTAGE_OCV, |
114 | 114 | POWER_SUPPLY_PROP_CAPACITY, |
115 | 115 | POWER_SUPPLY_PROP_CHARGE_FULL, |
116 | + POWER_SUPPLY_PROP_CHARGE_COUNTER, | |
116 | 117 | POWER_SUPPLY_PROP_TEMP, |
117 | 118 | POWER_SUPPLY_PROP_CURRENT_NOW, |
118 | 119 | POWER_SUPPLY_PROP_CURRENT_AVG, |
... | ... | @@ -196,6 +197,13 @@ |
196 | 197 | break; |
197 | 198 | case POWER_SUPPLY_PROP_CHARGE_FULL: |
198 | 199 | ret = max17042_read_reg(chip->client, MAX17042_FullCAP); |
200 | + if (ret < 0) | |
201 | + return ret; | |
202 | + | |
203 | + val->intval = ret * 1000 / 2; | |
204 | + break; | |
205 | + case POWER_SUPPLY_PROP_CHARGE_COUNTER: | |
206 | + ret = max17042_read_reg(chip->client, MAX17042_QH); | |
199 | 207 | if (ret < 0) |
200 | 208 | return ret; |
201 | 209 |
drivers/power/olpc_battery.c
... | ... | @@ -231,12 +231,10 @@ |
231 | 231 | |
232 | 232 | case POWER_SUPPLY_TECHNOLOGY_LiFe: |
233 | 233 | switch (mfr) { |
234 | - case 1: /* Gold Peak */ | |
234 | + case 1: /* Gold Peak, fall through */ | |
235 | + case 2: /* BYD */ | |
235 | 236 | val->intval = 2800000; |
236 | 237 | break; |
237 | - case 2: /* BYD */ | |
238 | - val->intval = 3100000; | |
239 | - break; | |
240 | 238 | default: |
241 | 239 | return -EIO; |
242 | 240 | } |
... | ... | @@ -267,6 +265,55 @@ |
267 | 265 | return 0; |
268 | 266 | } |
269 | 267 | |
268 | +static int olpc_bat_get_voltage_max_design(union power_supply_propval *val) | |
269 | +{ | |
270 | + uint8_t ec_byte; | |
271 | + union power_supply_propval tech; | |
272 | + int mfr; | |
273 | + int ret; | |
274 | + | |
275 | + ret = olpc_bat_get_tech(&tech); | |
276 | + if (ret) | |
277 | + return ret; | |
278 | + | |
279 | + ec_byte = BAT_ADDR_MFR_TYPE; | |
280 | + ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &ec_byte, 1); | |
281 | + if (ret) | |
282 | + return ret; | |
283 | + | |
284 | + mfr = ec_byte >> 4; | |
285 | + | |
286 | + switch (tech.intval) { | |
287 | + case POWER_SUPPLY_TECHNOLOGY_NiMH: | |
288 | + switch (mfr) { | |
289 | + case 1: /* Gold Peak */ | |
290 | + val->intval = 6000000; | |
291 | + break; | |
292 | + default: | |
293 | + return -EIO; | |
294 | + } | |
295 | + break; | |
296 | + | |
297 | + case POWER_SUPPLY_TECHNOLOGY_LiFe: | |
298 | + switch (mfr) { | |
299 | + case 1: /* Gold Peak */ | |
300 | + val->intval = 6400000; | |
301 | + break; | |
302 | + case 2: /* BYD */ | |
303 | + val->intval = 6500000; | |
304 | + break; | |
305 | + default: | |
306 | + return -EIO; | |
307 | + } | |
308 | + break; | |
309 | + | |
310 | + default: | |
311 | + return -EIO; | |
312 | + } | |
313 | + | |
314 | + return ret; | |
315 | +} | |
316 | + | |
270 | 317 | /********************************************************************* |
271 | 318 | * Battery properties |
272 | 319 | *********************************************************************/ |
... | ... | @@ -401,6 +448,11 @@ |
401 | 448 | sprintf(bat_serial, "%016llx", (long long)be64_to_cpu(ser_buf)); |
402 | 449 | val->strval = bat_serial; |
403 | 450 | break; |
451 | + case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | |
452 | + ret = olpc_bat_get_voltage_max_design(val); | |
453 | + if (ret) | |
454 | + return ret; | |
455 | + break; | |
404 | 456 | default: |
405 | 457 | ret = -EINVAL; |
406 | 458 | break; |
... | ... | @@ -428,6 +480,7 @@ |
428 | 480 | POWER_SUPPLY_PROP_MANUFACTURER, |
429 | 481 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
430 | 482 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
483 | + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | |
431 | 484 | }; |
432 | 485 | |
433 | 486 | /* XO-1.5 does not have ambient temperature property */ |
... | ... | @@ -449,6 +502,7 @@ |
449 | 502 | POWER_SUPPLY_PROP_MANUFACTURER, |
450 | 503 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
451 | 504 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
505 | + POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | |
452 | 506 | }; |
453 | 507 | |
454 | 508 | /* EEPROM reading goes completely around the power_supply API, sadly */ |
drivers/power/pda_power.c
... | ... | @@ -134,13 +134,13 @@ |
134 | 134 | regulator_set_current_limit(ac_draw, max_uA, max_uA); |
135 | 135 | if (!regulator_enabled) { |
136 | 136 | dev_dbg(dev, "charger on (AC)\n"); |
137 | - regulator_enable(ac_draw); | |
137 | + WARN_ON(regulator_enable(ac_draw)); | |
138 | 138 | regulator_enabled = 1; |
139 | 139 | } |
140 | 140 | } else { |
141 | 141 | if (regulator_enabled) { |
142 | 142 | dev_dbg(dev, "charger off\n"); |
143 | - regulator_disable(ac_draw); | |
143 | + WARN_ON(regulator_disable(ac_draw)); | |
144 | 144 | regulator_enabled = 0; |
145 | 145 | } |
146 | 146 | } |
drivers/power/power_supply_core.c
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | #include <linux/device.h> |
18 | 18 | #include <linux/err.h> |
19 | 19 | #include <linux/power_supply.h> |
20 | +#include <linux/thermal.h> | |
20 | 21 | #include "power_supply.h" |
21 | 22 | |
22 | 23 | /* exported for the APM Power driver, APM emulation */ |
... | ... | @@ -169,6 +170,63 @@ |
169 | 170 | kfree(dev); |
170 | 171 | } |
171 | 172 | |
173 | +#ifdef CONFIG_THERMAL | |
174 | +static int power_supply_read_temp(struct thermal_zone_device *tzd, | |
175 | + unsigned long *temp) | |
176 | +{ | |
177 | + struct power_supply *psy; | |
178 | + union power_supply_propval val; | |
179 | + int ret; | |
180 | + | |
181 | + WARN_ON(tzd == NULL); | |
182 | + psy = tzd->devdata; | |
183 | + ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val); | |
184 | + | |
185 | + /* Convert tenths of degree Celsius to milli degree Celsius. */ | |
186 | + if (!ret) | |
187 | + *temp = val.intval * 100; | |
188 | + | |
189 | + return ret; | |
190 | +} | |
191 | + | |
192 | +static struct thermal_zone_device_ops psy_tzd_ops = { | |
193 | + .get_temp = power_supply_read_temp, | |
194 | +}; | |
195 | + | |
196 | +static int psy_register_thermal(struct power_supply *psy) | |
197 | +{ | |
198 | + int i; | |
199 | + | |
200 | + /* Register battery zone device psy reports temperature */ | |
201 | + for (i = 0; i < psy->num_properties; i++) { | |
202 | + if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { | |
203 | + psy->tzd = thermal_zone_device_register(psy->name, 0, 0, | |
204 | + psy, &psy_tzd_ops, 0, 0, 0, 0); | |
205 | + if (IS_ERR(psy->tzd)) | |
206 | + return PTR_ERR(psy->tzd); | |
207 | + break; | |
208 | + } | |
209 | + } | |
210 | + return 0; | |
211 | +} | |
212 | + | |
213 | +static void psy_unregister_thermal(struct power_supply *psy) | |
214 | +{ | |
215 | + if (IS_ERR_OR_NULL(psy->tzd)) | |
216 | + return; | |
217 | + thermal_zone_device_unregister(psy->tzd); | |
218 | +} | |
219 | +#else | |
220 | +static int psy_register_thermal(struct power_supply *psy) | |
221 | +{ | |
222 | + return 0; | |
223 | +} | |
224 | + | |
225 | +static void psy_unregister_thermal(struct power_supply *psy) | |
226 | +{ | |
227 | +} | |
228 | +#endif | |
229 | + | |
172 | 230 | int power_supply_register(struct device *parent, struct power_supply *psy) |
173 | 231 | { |
174 | 232 | struct device *dev; |
... | ... | @@ -197,6 +255,10 @@ |
197 | 255 | if (rc) |
198 | 256 | goto device_add_failed; |
199 | 257 | |
258 | + rc = psy_register_thermal(psy); | |
259 | + if (rc) | |
260 | + goto register_thermal_failed; | |
261 | + | |
200 | 262 | rc = power_supply_create_triggers(psy); |
201 | 263 | if (rc) |
202 | 264 | goto create_triggers_failed; |
... | ... | @@ -206,6 +268,8 @@ |
206 | 268 | goto success; |
207 | 269 | |
208 | 270 | create_triggers_failed: |
271 | + psy_unregister_thermal(psy); | |
272 | +register_thermal_failed: | |
209 | 273 | device_del(dev); |
210 | 274 | kobject_set_name_failed: |
211 | 275 | device_add_failed: |
... | ... | @@ -220,6 +284,7 @@ |
220 | 284 | cancel_work_sync(&psy->changed_work); |
221 | 285 | sysfs_remove_link(&psy->dev->kobj, "powers"); |
222 | 286 | power_supply_remove_triggers(psy); |
287 | + psy_unregister_thermal(psy); | |
223 | 288 | device_unregister(psy->dev); |
224 | 289 | } |
225 | 290 | EXPORT_SYMBOL_GPL(power_supply_unregister); |
drivers/power/power_supply_sysfs.c
... | ... | @@ -159,6 +159,8 @@ |
159 | 159 | POWER_SUPPLY_ATTR(charge_now), |
160 | 160 | POWER_SUPPLY_ATTR(charge_avg), |
161 | 161 | POWER_SUPPLY_ATTR(charge_counter), |
162 | + POWER_SUPPLY_ATTR(constant_charge_current), | |
163 | + POWER_SUPPLY_ATTR(constant_charge_voltage), | |
162 | 164 | POWER_SUPPLY_ATTR(energy_full_design), |
163 | 165 | POWER_SUPPLY_ATTR(energy_empty_design), |
164 | 166 | POWER_SUPPLY_ATTR(energy_full), |
165 | 167 | |
166 | 168 | |
... | ... | @@ -166,9 +168,15 @@ |
166 | 168 | POWER_SUPPLY_ATTR(energy_now), |
167 | 169 | POWER_SUPPLY_ATTR(energy_avg), |
168 | 170 | POWER_SUPPLY_ATTR(capacity), |
171 | + POWER_SUPPLY_ATTR(capacity_alert_min), | |
172 | + POWER_SUPPLY_ATTR(capacity_alert_max), | |
169 | 173 | POWER_SUPPLY_ATTR(capacity_level), |
170 | 174 | POWER_SUPPLY_ATTR(temp), |
175 | + POWER_SUPPLY_ATTR(temp_alert_min), | |
176 | + POWER_SUPPLY_ATTR(temp_alert_max), | |
171 | 177 | POWER_SUPPLY_ATTR(temp_ambient), |
178 | + POWER_SUPPLY_ATTR(temp_ambient_alert_min), | |
179 | + POWER_SUPPLY_ATTR(temp_ambient_alert_max), | |
172 | 180 | POWER_SUPPLY_ATTR(time_to_empty_now), |
173 | 181 | POWER_SUPPLY_ATTR(time_to_empty_avg), |
174 | 182 | POWER_SUPPLY_ATTR(time_to_full_now), |
drivers/power/sbs-battery.c
drivers/power/smb347-charger.c
... | ... | @@ -196,6 +196,14 @@ |
196 | 196 | 1200000, |
197 | 197 | }; |
198 | 198 | |
199 | +/* Convert register value to current using lookup table */ | |
200 | +static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val) | |
201 | +{ | |
202 | + if (val >= size) | |
203 | + return -EINVAL; | |
204 | + return tbl[val]; | |
205 | +} | |
206 | + | |
199 | 207 | /* Convert current to register value using lookup table */ |
200 | 208 | static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) |
201 | 209 | { |
202 | 210 | |
203 | 211 | |
204 | 212 | |
205 | 213 | |
206 | 214 | |
... | ... | @@ -841,22 +849,101 @@ |
841 | 849 | return ret; |
842 | 850 | } |
843 | 851 | |
852 | +/* | |
853 | + * Returns the constant charge current programmed | |
854 | + * into the charger in uA. | |
855 | + */ | |
856 | +static int get_const_charge_current(struct smb347_charger *smb) | |
857 | +{ | |
858 | + int ret, intval; | |
859 | + unsigned int v; | |
860 | + | |
861 | + if (!smb347_is_ps_online(smb)) | |
862 | + return -ENODATA; | |
863 | + | |
864 | + ret = regmap_read(smb->regmap, STAT_B, &v); | |
865 | + if (ret < 0) | |
866 | + return ret; | |
867 | + | |
868 | + /* | |
869 | + * The current value is composition of FCC and PCC values | |
870 | + * and we can detect which table to use from bit 5. | |
871 | + */ | |
872 | + if (v & 0x20) { | |
873 | + intval = hw_to_current(fcc_tbl, ARRAY_SIZE(fcc_tbl), v & 7); | |
874 | + } else { | |
875 | + v >>= 3; | |
876 | + intval = hw_to_current(pcc_tbl, ARRAY_SIZE(pcc_tbl), v & 7); | |
877 | + } | |
878 | + | |
879 | + return intval; | |
880 | +} | |
881 | + | |
882 | +/* | |
883 | + * Returns the constant charge voltage programmed | |
884 | + * into the charger in uV. | |
885 | + */ | |
886 | +static int get_const_charge_voltage(struct smb347_charger *smb) | |
887 | +{ | |
888 | + int ret, intval; | |
889 | + unsigned int v; | |
890 | + | |
891 | + if (!smb347_is_ps_online(smb)) | |
892 | + return -ENODATA; | |
893 | + | |
894 | + ret = regmap_read(smb->regmap, STAT_A, &v); | |
895 | + if (ret < 0) | |
896 | + return ret; | |
897 | + | |
898 | + v &= STAT_A_FLOAT_VOLTAGE_MASK; | |
899 | + if (v > 0x3d) | |
900 | + v = 0x3d; | |
901 | + | |
902 | + intval = 3500000 + v * 20000; | |
903 | + | |
904 | + return intval; | |
905 | +} | |
906 | + | |
844 | 907 | static int smb347_mains_get_property(struct power_supply *psy, |
845 | 908 | enum power_supply_property prop, |
846 | 909 | union power_supply_propval *val) |
847 | 910 | { |
848 | 911 | struct smb347_charger *smb = |
849 | 912 | container_of(psy, struct smb347_charger, mains); |
913 | + int ret; | |
850 | 914 | |
851 | - if (prop == POWER_SUPPLY_PROP_ONLINE) { | |
915 | + switch (prop) { | |
916 | + case POWER_SUPPLY_PROP_ONLINE: | |
852 | 917 | val->intval = smb->mains_online; |
853 | - return 0; | |
918 | + break; | |
919 | + | |
920 | + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | |
921 | + ret = get_const_charge_voltage(smb); | |
922 | + if (ret < 0) | |
923 | + return ret; | |
924 | + else | |
925 | + val->intval = ret; | |
926 | + break; | |
927 | + | |
928 | + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | |
929 | + ret = get_const_charge_current(smb); | |
930 | + if (ret < 0) | |
931 | + return ret; | |
932 | + else | |
933 | + val->intval = ret; | |
934 | + break; | |
935 | + | |
936 | + default: | |
937 | + return -EINVAL; | |
854 | 938 | } |
855 | - return -EINVAL; | |
939 | + | |
940 | + return 0; | |
856 | 941 | } |
857 | 942 | |
858 | 943 | static enum power_supply_property smb347_mains_properties[] = { |
859 | 944 | POWER_SUPPLY_PROP_ONLINE, |
945 | + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | |
946 | + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | |
860 | 947 | }; |
861 | 948 | |
862 | 949 | static int smb347_usb_get_property(struct power_supply *psy, |
863 | 950 | |
864 | 951 | |
865 | 952 | |
866 | 953 | |
... | ... | @@ -865,16 +952,40 @@ |
865 | 952 | { |
866 | 953 | struct smb347_charger *smb = |
867 | 954 | container_of(psy, struct smb347_charger, usb); |
955 | + int ret; | |
868 | 956 | |
869 | - if (prop == POWER_SUPPLY_PROP_ONLINE) { | |
957 | + switch (prop) { | |
958 | + case POWER_SUPPLY_PROP_ONLINE: | |
870 | 959 | val->intval = smb->usb_online; |
871 | - return 0; | |
960 | + break; | |
961 | + | |
962 | + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | |
963 | + ret = get_const_charge_voltage(smb); | |
964 | + if (ret < 0) | |
965 | + return ret; | |
966 | + else | |
967 | + val->intval = ret; | |
968 | + break; | |
969 | + | |
970 | + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | |
971 | + ret = get_const_charge_current(smb); | |
972 | + if (ret < 0) | |
973 | + return ret; | |
974 | + else | |
975 | + val->intval = ret; | |
976 | + break; | |
977 | + | |
978 | + default: | |
979 | + return -EINVAL; | |
872 | 980 | } |
873 | - return -EINVAL; | |
981 | + | |
982 | + return 0; | |
874 | 983 | } |
875 | 984 | |
876 | 985 | static enum power_supply_property smb347_usb_properties[] = { |
877 | 986 | POWER_SUPPLY_PROP_ONLINE, |
987 | + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | |
988 | + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | |
878 | 989 | }; |
879 | 990 | |
880 | 991 | static int smb347_battery_get_property(struct power_supply *psy, |
drivers/power/test_power.c
... | ... | @@ -22,11 +22,13 @@ |
22 | 22 | #include <linux/vermagic.h> |
23 | 23 | |
24 | 24 | static int ac_online = 1; |
25 | +static int usb_online = 1; | |
25 | 26 | static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
26 | 27 | static int battery_health = POWER_SUPPLY_HEALTH_GOOD; |
27 | 28 | static int battery_present = 1; /* true */ |
28 | 29 | static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION; |
29 | 30 | static int battery_capacity = 50; |
31 | +static int battery_voltage = 3300; | |
30 | 32 | |
31 | 33 | static int test_power_get_ac_property(struct power_supply *psy, |
32 | 34 | enum power_supply_property psp, |
... | ... | @@ -42,6 +44,20 @@ |
42 | 44 | return 0; |
43 | 45 | } |
44 | 46 | |
47 | +static int test_power_get_usb_property(struct power_supply *psy, | |
48 | + enum power_supply_property psp, | |
49 | + union power_supply_propval *val) | |
50 | +{ | |
51 | + switch (psp) { | |
52 | + case POWER_SUPPLY_PROP_ONLINE: | |
53 | + val->intval = usb_online; | |
54 | + break; | |
55 | + default: | |
56 | + return -EINVAL; | |
57 | + } | |
58 | + return 0; | |
59 | +} | |
60 | + | |
45 | 61 | static int test_power_get_battery_property(struct power_supply *psy, |
46 | 62 | enum power_supply_property psp, |
47 | 63 | union power_supply_propval *val) |
... | ... | @@ -86,6 +102,12 @@ |
86 | 102 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: |
87 | 103 | val->intval = 3600; |
88 | 104 | break; |
105 | + case POWER_SUPPLY_PROP_TEMP: | |
106 | + val->intval = 26; | |
107 | + break; | |
108 | + case POWER_SUPPLY_PROP_VOLTAGE_NOW: | |
109 | + val->intval = battery_voltage; | |
110 | + break; | |
89 | 111 | default: |
90 | 112 | pr_info("%s: some properties deliberately report errors.\n", |
91 | 113 | __func__); |
... | ... | @@ -114,6 +136,8 @@ |
114 | 136 | POWER_SUPPLY_PROP_MODEL_NAME, |
115 | 137 | POWER_SUPPLY_PROP_MANUFACTURER, |
116 | 138 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
139 | + POWER_SUPPLY_PROP_TEMP, | |
140 | + POWER_SUPPLY_PROP_VOLTAGE_NOW, | |
117 | 141 | }; |
118 | 142 | |
119 | 143 | static char *test_power_ac_supplied_to[] = { |
... | ... | @@ -135,6 +159,14 @@ |
135 | 159 | .properties = test_power_battery_props, |
136 | 160 | .num_properties = ARRAY_SIZE(test_power_battery_props), |
137 | 161 | .get_property = test_power_get_battery_property, |
162 | + }, { | |
163 | + .name = "test_usb", | |
164 | + .type = POWER_SUPPLY_TYPE_USB, | |
165 | + .supplied_to = test_power_ac_supplied_to, | |
166 | + .num_supplicants = ARRAY_SIZE(test_power_ac_supplied_to), | |
167 | + .properties = test_power_ac_props, | |
168 | + .num_properties = ARRAY_SIZE(test_power_ac_props), | |
169 | + .get_property = test_power_get_usb_property, | |
138 | 170 | }, |
139 | 171 | }; |
140 | 172 | |
... | ... | @@ -167,6 +199,7 @@ |
167 | 199 | |
168 | 200 | /* Let's see how we handle changes... */ |
169 | 201 | ac_online = 0; |
202 | + usb_online = 0; | |
170 | 203 | battery_status = POWER_SUPPLY_STATUS_DISCHARGING; |
171 | 204 | for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) |
172 | 205 | power_supply_changed(&test_power_supplies[i]); |
... | ... | @@ -275,6 +308,19 @@ |
275 | 308 | return strlen(buffer); |
276 | 309 | } |
277 | 310 | |
311 | +static int param_set_usb_online(const char *key, const struct kernel_param *kp) | |
312 | +{ | |
313 | + usb_online = map_get_value(map_ac_online, key, usb_online); | |
314 | + power_supply_changed(&test_power_supplies[2]); | |
315 | + return 0; | |
316 | +} | |
317 | + | |
318 | +static int param_get_usb_online(char *buffer, const struct kernel_param *kp) | |
319 | +{ | |
320 | + strcpy(buffer, map_get_key(map_ac_online, usb_online, "unknown")); | |
321 | + return strlen(buffer); | |
322 | +} | |
323 | + | |
278 | 324 | static int param_set_battery_status(const char *key, |
279 | 325 | const struct kernel_param *kp) |
280 | 326 | { |
281 | 327 | |
282 | 328 | |
283 | 329 | |
... | ... | @@ -350,13 +396,31 @@ |
350 | 396 | |
351 | 397 | #define param_get_battery_capacity param_get_int |
352 | 398 | |
399 | +static int param_set_battery_voltage(const char *key, | |
400 | + const struct kernel_param *kp) | |
401 | +{ | |
402 | + int tmp; | |
353 | 403 | |
404 | + if (1 != sscanf(key, "%d", &tmp)) | |
405 | + return -EINVAL; | |
354 | 406 | |
407 | + battery_voltage = tmp; | |
408 | + power_supply_changed(&test_power_supplies[1]); | |
409 | + return 0; | |
410 | +} | |
411 | + | |
412 | +#define param_get_battery_voltage param_get_int | |
413 | + | |
355 | 414 | static struct kernel_param_ops param_ops_ac_online = { |
356 | 415 | .set = param_set_ac_online, |
357 | 416 | .get = param_get_ac_online, |
358 | 417 | }; |
359 | 418 | |
419 | +static struct kernel_param_ops param_ops_usb_online = { | |
420 | + .set = param_set_usb_online, | |
421 | + .get = param_get_usb_online, | |
422 | +}; | |
423 | + | |
360 | 424 | static struct kernel_param_ops param_ops_battery_status = { |
361 | 425 | .set = param_set_battery_status, |
362 | 426 | .get = param_get_battery_status, |
363 | 427 | |
364 | 428 | |
365 | 429 | |
... | ... | @@ -382,18 +446,27 @@ |
382 | 446 | .get = param_get_battery_capacity, |
383 | 447 | }; |
384 | 448 | |
449 | +static struct kernel_param_ops param_ops_battery_voltage = { | |
450 | + .set = param_set_battery_voltage, | |
451 | + .get = param_get_battery_voltage, | |
452 | +}; | |
385 | 453 | |
386 | 454 | #define param_check_ac_online(name, p) __param_check(name, p, void); |
455 | +#define param_check_usb_online(name, p) __param_check(name, p, void); | |
387 | 456 | #define param_check_battery_status(name, p) __param_check(name, p, void); |
388 | 457 | #define param_check_battery_present(name, p) __param_check(name, p, void); |
389 | 458 | #define param_check_battery_technology(name, p) __param_check(name, p, void); |
390 | 459 | #define param_check_battery_health(name, p) __param_check(name, p, void); |
391 | 460 | #define param_check_battery_capacity(name, p) __param_check(name, p, void); |
461 | +#define param_check_battery_voltage(name, p) __param_check(name, p, void); | |
392 | 462 | |
393 | 463 | |
394 | 464 | module_param(ac_online, ac_online, 0644); |
395 | 465 | MODULE_PARM_DESC(ac_online, "AC charging state <on|off>"); |
396 | 466 | |
467 | +module_param(usb_online, usb_online, 0644); | |
468 | +MODULE_PARM_DESC(usb_online, "USB charging state <on|off>"); | |
469 | + | |
397 | 470 | module_param(battery_status, battery_status, 0644); |
398 | 471 | MODULE_PARM_DESC(battery_status, |
399 | 472 | "battery status <charging|discharging|not-charging|full>"); |
... | ... | @@ -413,6 +486,8 @@ |
413 | 486 | module_param(battery_capacity, battery_capacity, 0644); |
414 | 487 | MODULE_PARM_DESC(battery_capacity, "battery capacity (percentage)"); |
415 | 488 | |
489 | +module_param(battery_voltage, battery_voltage, 0644); | |
490 | +MODULE_PARM_DESC(battery_voltage, "battery voltage (millivolts)"); | |
416 | 491 | |
417 | 492 | MODULE_DESCRIPTION("Power supply driver for testing"); |
418 | 493 | MODULE_AUTHOR("Anton Vorontsov <cbouatmailru@gmail.com>"); |
drivers/power/twl4030_charger.c
... | ... | @@ -22,6 +22,7 @@ |
22 | 22 | #include <linux/power_supply.h> |
23 | 23 | #include <linux/notifier.h> |
24 | 24 | #include <linux/usb/otg.h> |
25 | +#include <linux/regulator/machine.h> | |
25 | 26 | |
26 | 27 | #define TWL4030_BCIMSTATEC 0x02 |
27 | 28 | #define TWL4030_BCIICHG 0x08 |
... | ... | @@ -29,6 +30,7 @@ |
29 | 30 | #define TWL4030_BCIVBUS 0x0c |
30 | 31 | #define TWL4030_BCIMFSTS4 0x10 |
31 | 32 | #define TWL4030_BCICTL1 0x23 |
33 | +#define TWL4030_BB_CFG 0x12 | |
32 | 34 | |
33 | 35 | #define TWL4030_BCIAUTOWEN BIT(5) |
34 | 36 | #define TWL4030_CONFIG_DONE BIT(4) |
... | ... | @@ -38,6 +40,17 @@ |
38 | 40 | #define TWL4030_USBFASTMCHG BIT(2) |
39 | 41 | #define TWL4030_STS_VBUS BIT(7) |
40 | 42 | #define TWL4030_STS_USB_ID BIT(2) |
43 | +#define TWL4030_BBCHEN BIT(4) | |
44 | +#define TWL4030_BBSEL_MASK 0b1100 | |
45 | +#define TWL4030_BBSEL_2V5 0b0000 | |
46 | +#define TWL4030_BBSEL_3V0 0b0100 | |
47 | +#define TWL4030_BBSEL_3V1 0b1000 | |
48 | +#define TWL4030_BBSEL_3V2 0b1100 | |
49 | +#define TWL4030_BBISEL_MASK 0b11 | |
50 | +#define TWL4030_BBISEL_25uA 0b00 | |
51 | +#define TWL4030_BBISEL_150uA 0b01 | |
52 | +#define TWL4030_BBISEL_500uA 0b10 | |
53 | +#define TWL4030_BBISEL_1000uA 0b11 | |
41 | 54 | |
42 | 55 | /* BCI interrupts */ |
43 | 56 | #define TWL4030_WOVF BIT(0) /* Watchdog overflow */ |
... | ... | @@ -75,6 +88,8 @@ |
75 | 88 | struct work_struct work; |
76 | 89 | int irq_chg; |
77 | 90 | int irq_bci; |
91 | + struct regulator *usb_reg; | |
92 | + int usb_enabled; | |
78 | 93 | |
79 | 94 | unsigned long event; |
80 | 95 | }; |
... | ... | @@ -104,7 +119,7 @@ |
104 | 119 | |
105 | 120 | static int twl4030_clear_set_boot_bci(u8 clear, u8 set) |
106 | 121 | { |
107 | - return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0, | |
122 | + return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear, | |
108 | 123 | TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, |
109 | 124 | TWL4030_PM_MASTER_BOOT_BCI); |
110 | 125 | } |
111 | 126 | |
... | ... | @@ -152,14 +167,14 @@ |
152 | 167 | } |
153 | 168 | |
154 | 169 | /* |
155 | - * Enable/Disable USB Charge funtionality. | |
170 | + * Enable/Disable USB Charge functionality. | |
156 | 171 | */ |
157 | 172 | static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) |
158 | 173 | { |
159 | 174 | int ret; |
160 | 175 | |
161 | 176 | if (enable) { |
162 | - /* Check for USB charger conneted */ | |
177 | + /* Check for USB charger connected */ | |
163 | 178 | if (!twl4030_bci_have_vbus(bci)) |
164 | 179 | return -ENODEV; |
165 | 180 | |
... | ... | @@ -172,6 +187,12 @@ |
172 | 187 | return -EACCES; |
173 | 188 | } |
174 | 189 | |
190 | + /* Need to keep regulator on */ | |
191 | + if (!bci->usb_enabled) { | |
192 | + regulator_enable(bci->usb_reg); | |
193 | + bci->usb_enabled = 1; | |
194 | + } | |
195 | + | |
175 | 196 | /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */ |
176 | 197 | ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB); |
177 | 198 | if (ret < 0) |
... | ... | @@ -182,6 +203,10 @@ |
182 | 203 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); |
183 | 204 | } else { |
184 | 205 | ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); |
206 | + if (bci->usb_enabled) { | |
207 | + regulator_disable(bci->usb_reg); | |
208 | + bci->usb_enabled = 0; | |
209 | + } | |
185 | 210 | } |
186 | 211 | |
187 | 212 | return ret; |
... | ... | @@ -203,6 +228,49 @@ |
203 | 228 | } |
204 | 229 | |
205 | 230 | /* |
231 | + * Enable/Disable charging of Backup Battery. | |
232 | + */ | |
233 | +static int twl4030_charger_enable_backup(int uvolt, int uamp) | |
234 | +{ | |
235 | + int ret; | |
236 | + u8 flags; | |
237 | + | |
238 | + if (uvolt < 2500000 || | |
239 | + uamp < 25) { | |
240 | + /* disable charging of backup battery */ | |
241 | + ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, | |
242 | + TWL4030_BBCHEN, 0, TWL4030_BB_CFG); | |
243 | + return ret; | |
244 | + } | |
245 | + | |
246 | + flags = TWL4030_BBCHEN; | |
247 | + if (uvolt >= 3200000) | |
248 | + flags |= TWL4030_BBSEL_3V2; | |
249 | + else if (uvolt >= 3100000) | |
250 | + flags |= TWL4030_BBSEL_3V1; | |
251 | + else if (uvolt >= 3000000) | |
252 | + flags |= TWL4030_BBSEL_3V0; | |
253 | + else | |
254 | + flags |= TWL4030_BBSEL_2V5; | |
255 | + | |
256 | + if (uamp >= 1000) | |
257 | + flags |= TWL4030_BBISEL_1000uA; | |
258 | + else if (uamp >= 500) | |
259 | + flags |= TWL4030_BBISEL_500uA; | |
260 | + else if (uamp >= 150) | |
261 | + flags |= TWL4030_BBISEL_150uA; | |
262 | + else | |
263 | + flags |= TWL4030_BBISEL_25uA; | |
264 | + | |
265 | + ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, | |
266 | + TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK, | |
267 | + flags, | |
268 | + TWL4030_BB_CFG); | |
269 | + | |
270 | + return ret; | |
271 | +} | |
272 | + | |
273 | +/* | |
206 | 274 | * TWL4030 CHG_PRES (AC charger presence) events |
207 | 275 | */ |
208 | 276 | static irqreturn_t twl4030_charger_interrupt(int irq, void *arg) |
... | ... | @@ -425,6 +493,7 @@ |
425 | 493 | static int __init twl4030_bci_probe(struct platform_device *pdev) |
426 | 494 | { |
427 | 495 | struct twl4030_bci *bci; |
496 | + struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; | |
428 | 497 | int ret; |
429 | 498 | u32 reg; |
430 | 499 | |
... | ... | @@ -456,6 +525,8 @@ |
456 | 525 | bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props); |
457 | 526 | bci->usb.get_property = twl4030_bci_get_property; |
458 | 527 | |
528 | + bci->usb_reg = regulator_get(bci->dev, "bci3v1"); | |
529 | + | |
459 | 530 | ret = power_supply_register(&pdev->dev, &bci->usb); |
460 | 531 | if (ret) { |
461 | 532 | dev_err(&pdev->dev, "failed to register usb: %d\n", ret); |
... | ... | @@ -504,6 +575,8 @@ |
504 | 575 | |
505 | 576 | twl4030_charger_enable_ac(true); |
506 | 577 | twl4030_charger_enable_usb(bci, true); |
578 | + twl4030_charger_enable_backup(pdata->bb_uvolt, | |
579 | + pdata->bb_uamp); | |
507 | 580 | |
508 | 581 | return 0; |
509 | 582 | |
... | ... | @@ -532,6 +605,7 @@ |
532 | 605 | |
533 | 606 | twl4030_charger_enable_ac(false); |
534 | 607 | twl4030_charger_enable_usb(bci, false); |
608 | + twl4030_charger_enable_backup(0, 0); | |
535 | 609 | |
536 | 610 | /* mask interrupts */ |
537 | 611 | twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, |
drivers/thermal/thermal_sys.c
... | ... | @@ -1251,7 +1251,7 @@ |
1251 | 1251 | * longer needed. The passive cooling formula uses tc1 and tc2 as described in |
1252 | 1252 | * section 11.1.5.1 of the ACPI specification 3.0. |
1253 | 1253 | */ |
1254 | -struct thermal_zone_device *thermal_zone_device_register(char *type, | |
1254 | +struct thermal_zone_device *thermal_zone_device_register(const char *type, | |
1255 | 1255 | int trips, int mask, void *devdata, |
1256 | 1256 | const struct thermal_zone_device_ops *ops, |
1257 | 1257 | int tc1, int tc2, int passive_delay, int polling_delay) |
include/linux/i2c/twl.h
... | ... | @@ -555,6 +555,8 @@ |
555 | 555 | struct twl4030_bci_platform_data { |
556 | 556 | int *battery_tmp_tbl; |
557 | 557 | unsigned int tblsize; |
558 | + int bb_uvolt; /* voltage to charge backup battery */ | |
559 | + int bb_uamp; /* current for backup battery charging */ | |
558 | 560 | }; |
559 | 561 | |
560 | 562 | /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */ |
include/linux/lp8727.h
1 | -/* | |
2 | - * LP8727 Micro/Mini USB IC with integrated charger | |
3 | - * | |
4 | - * Copyright (C) 2011 Texas Instruments | |
5 | - * Copyright (C) 2011 National Semiconductor | |
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 | -#ifndef _LP8727_H | |
13 | -#define _LP8727_H | |
14 | - | |
15 | -enum lp8727_eoc_level { | |
16 | - EOC_5P, | |
17 | - EOC_10P, | |
18 | - EOC_16P, | |
19 | - EOC_20P, | |
20 | - EOC_25P, | |
21 | - EOC_33P, | |
22 | - EOC_50P, | |
23 | -}; | |
24 | - | |
25 | -enum lp8727_ichg { | |
26 | - ICHG_90mA, | |
27 | - ICHG_100mA, | |
28 | - ICHG_400mA, | |
29 | - ICHG_450mA, | |
30 | - ICHG_500mA, | |
31 | - ICHG_600mA, | |
32 | - ICHG_700mA, | |
33 | - ICHG_800mA, | |
34 | - ICHG_900mA, | |
35 | - ICHG_1000mA, | |
36 | -}; | |
37 | - | |
38 | -/** | |
39 | - * struct lp8727_chg_param | |
40 | - * @eoc_level : end of charge level setting | |
41 | - * @ichg : charging current | |
42 | - */ | |
43 | -struct lp8727_chg_param { | |
44 | - enum lp8727_eoc_level eoc_level; | |
45 | - enum lp8727_ichg ichg; | |
46 | -}; | |
47 | - | |
48 | -/** | |
49 | - * struct lp8727_platform_data | |
50 | - * @get_batt_present : check battery status - exists or not | |
51 | - * @get_batt_level : get battery voltage (mV) | |
52 | - * @get_batt_capacity : get battery capacity (%) | |
53 | - * @get_batt_temp : get battery temperature | |
54 | - * @ac, @usb : charging parameters each charger type | |
55 | - */ | |
56 | -struct lp8727_platform_data { | |
57 | - u8 (*get_batt_present)(void); | |
58 | - u16 (*get_batt_level)(void); | |
59 | - u8 (*get_batt_capacity)(void); | |
60 | - u8 (*get_batt_temp)(void); | |
61 | - struct lp8727_chg_param ac; | |
62 | - struct lp8727_chg_param usb; | |
63 | -}; | |
64 | - | |
65 | -#endif |
include/linux/platform_data/lp8727.h
1 | +/* | |
2 | + * LP8727 Micro/Mini USB IC with integrated charger | |
3 | + * | |
4 | + * Copyright (C) 2011 Texas Instruments | |
5 | + * Copyright (C) 2011 National Semiconductor | |
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 | +#ifndef _LP8727_H | |
13 | +#define _LP8727_H | |
14 | + | |
15 | +enum lp8727_eoc_level { | |
16 | + EOC_5P, | |
17 | + EOC_10P, | |
18 | + EOC_16P, | |
19 | + EOC_20P, | |
20 | + EOC_25P, | |
21 | + EOC_33P, | |
22 | + EOC_50P, | |
23 | +}; | |
24 | + | |
25 | +enum lp8727_ichg { | |
26 | + ICHG_90mA, | |
27 | + ICHG_100mA, | |
28 | + ICHG_400mA, | |
29 | + ICHG_450mA, | |
30 | + ICHG_500mA, | |
31 | + ICHG_600mA, | |
32 | + ICHG_700mA, | |
33 | + ICHG_800mA, | |
34 | + ICHG_900mA, | |
35 | + ICHG_1000mA, | |
36 | +}; | |
37 | + | |
38 | +/** | |
39 | + * struct lp8727_chg_param | |
40 | + * @eoc_level : end of charge level setting | |
41 | + * @ichg : charging current | |
42 | + */ | |
43 | +struct lp8727_chg_param { | |
44 | + enum lp8727_eoc_level eoc_level; | |
45 | + enum lp8727_ichg ichg; | |
46 | +}; | |
47 | + | |
48 | +/** | |
49 | + * struct lp8727_platform_data | |
50 | + * @get_batt_present : check battery status - exists or not | |
51 | + * @get_batt_level : get battery voltage (mV) | |
52 | + * @get_batt_capacity : get battery capacity (%) | |
53 | + * @get_batt_temp : get battery temperature | |
54 | + * @ac, @usb : charging parameters each charger type | |
55 | + */ | |
56 | +struct lp8727_platform_data { | |
57 | + u8 (*get_batt_present)(void); | |
58 | + u16 (*get_batt_level)(void); | |
59 | + u8 (*get_batt_capacity)(void); | |
60 | + u8 (*get_batt_temp)(void); | |
61 | + struct lp8727_chg_param ac; | |
62 | + struct lp8727_chg_param usb; | |
63 | +}; | |
64 | + | |
65 | +#endif |
include/linux/power/charger-manager.h
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | #define _CHARGER_MANAGER_H |
17 | 17 | |
18 | 18 | #include <linux/power_supply.h> |
19 | +#include <linux/extcon.h> | |
19 | 20 | |
20 | 21 | enum data_source { |
21 | 22 | CM_BATTERY_PRESENT, |
... | ... | @@ -65,6 +66,70 @@ |
65 | 66 | }; |
66 | 67 | |
67 | 68 | /** |
69 | + * struct charger_cable | |
70 | + * @extcon_name: the name of extcon device. | |
71 | + * @name: the name of charger cable(external connector). | |
72 | + * @extcon_dev: the extcon device. | |
73 | + * @wq: the workqueue to control charger according to the state of | |
74 | + * charger cable. If charger cable is attached, enable charger. | |
75 | + * But if charger cable is detached, disable charger. | |
76 | + * @nb: the notifier block to receive changed state from EXTCON | |
77 | + * (External Connector) when charger cable is attached/detached. | |
78 | + * @attached: the state of charger cable. | |
79 | + * true: the charger cable is attached | |
80 | + * false: the charger cable is detached | |
81 | + * @charger: the instance of struct charger_regulator. | |
82 | + * @cm: the Charger Manager representing the battery. | |
83 | + */ | |
84 | +struct charger_cable { | |
85 | + const char *extcon_name; | |
86 | + const char *name; | |
87 | + | |
88 | + /* The charger-manager use Exton framework*/ | |
89 | + struct extcon_specific_cable_nb extcon_dev; | |
90 | + struct work_struct wq; | |
91 | + struct notifier_block nb; | |
92 | + | |
93 | + /* The state of charger cable */ | |
94 | + bool attached; | |
95 | + | |
96 | + struct charger_regulator *charger; | |
97 | + | |
98 | + /* | |
99 | + * Set min/max current of regulator to protect over-current issue | |
100 | + * according to a kind of charger cable when cable is attached. | |
101 | + */ | |
102 | + int min_uA; | |
103 | + int max_uA; | |
104 | + | |
105 | + struct charger_manager *cm; | |
106 | +}; | |
107 | + | |
108 | +/** | |
109 | + * struct charger_regulator | |
110 | + * @regulator_name: the name of regulator for using charger. | |
111 | + * @consumer: the regulator consumer for the charger. | |
112 | + * @cables: | |
113 | + * the array of charger cables to enable/disable charger | |
114 | + * and set current limit according to constratint data of | |
115 | + * struct charger_cable if only charger cable included | |
116 | + * in the array of charger cables is attached/detached. | |
117 | + * @num_cables: the number of charger cables. | |
118 | + */ | |
119 | +struct charger_regulator { | |
120 | + /* The name of regulator for charging */ | |
121 | + const char *regulator_name; | |
122 | + struct regulator *consumer; | |
123 | + | |
124 | + /* | |
125 | + * Store constraint information related to current limit, | |
126 | + * each cable have different condition for charging. | |
127 | + */ | |
128 | + struct charger_cable *cables; | |
129 | + int num_cables; | |
130 | +}; | |
131 | + | |
132 | +/** | |
68 | 133 | * struct charger_desc |
69 | 134 | * @psy_name: the name of power-supply-class for charger manager |
70 | 135 | * @polling_mode: |
... | ... | @@ -109,7 +174,7 @@ |
109 | 174 | char **psy_charger_stat; |
110 | 175 | |
111 | 176 | int num_charger_regulators; |
112 | - struct regulator_bulk_data *charger_regulators; | |
177 | + struct charger_regulator *charger_regulators; | |
113 | 178 | |
114 | 179 | char *psy_fuel_gauge; |
115 | 180 |
include/linux/power_supply.h
... | ... | @@ -109,6 +109,8 @@ |
109 | 109 | POWER_SUPPLY_PROP_CHARGE_NOW, |
110 | 110 | POWER_SUPPLY_PROP_CHARGE_AVG, |
111 | 111 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
112 | + POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | |
113 | + POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | |
112 | 114 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, |
113 | 115 | POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, |
114 | 116 | POWER_SUPPLY_PROP_ENERGY_FULL, |
115 | 117 | |
116 | 118 | |
... | ... | @@ -116,9 +118,15 @@ |
116 | 118 | POWER_SUPPLY_PROP_ENERGY_NOW, |
117 | 119 | POWER_SUPPLY_PROP_ENERGY_AVG, |
118 | 120 | POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ |
121 | + POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN, /* in percents! */ | |
122 | + POWER_SUPPLY_PROP_CAPACITY_ALERT_MAX, /* in percents! */ | |
119 | 123 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, |
120 | 124 | POWER_SUPPLY_PROP_TEMP, |
125 | + POWER_SUPPLY_PROP_TEMP_ALERT_MIN, | |
126 | + POWER_SUPPLY_PROP_TEMP_ALERT_MAX, | |
121 | 127 | POWER_SUPPLY_PROP_TEMP_AMBIENT, |
128 | + POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MIN, | |
129 | + POWER_SUPPLY_PROP_TEMP_AMBIENT_ALERT_MAX, | |
122 | 130 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, |
123 | 131 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, |
124 | 132 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, |
... | ... | @@ -173,6 +181,9 @@ |
173 | 181 | /* private */ |
174 | 182 | struct device *dev; |
175 | 183 | struct work_struct changed_work; |
184 | +#ifdef CONFIG_THERMAL | |
185 | + struct thermal_zone_device *tzd; | |
186 | +#endif | |
176 | 187 | |
177 | 188 | #ifdef CONFIG_LEDS_TRIGGERS |
178 | 189 | struct led_trigger *charging_full_trig; |
... | ... | @@ -236,6 +247,7 @@ |
236 | 247 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
237 | 248 | case POWER_SUPPLY_PROP_CHARGE_AVG: |
238 | 249 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: |
250 | + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | |
239 | 251 | case POWER_SUPPLY_PROP_CURRENT_MAX: |
240 | 252 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
241 | 253 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
... | ... | @@ -263,6 +275,7 @@ |
263 | 275 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
264 | 276 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
265 | 277 | case POWER_SUPPLY_PROP_VOLTAGE_OCV: |
278 | + case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | |
266 | 279 | case POWER_SUPPLY_PROP_POWER_NOW: |
267 | 280 | return 1; |
268 | 281 | default: |
include/linux/thermal.h
... | ... | @@ -151,7 +151,7 @@ |
151 | 151 | }; |
152 | 152 | #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) |
153 | 153 | |
154 | -struct thermal_zone_device *thermal_zone_device_register(char *, int, int, | |
154 | +struct thermal_zone_device *thermal_zone_device_register(const char *, int, int, | |
155 | 155 | void *, const struct thermal_zone_device_ops *, int tc1, |
156 | 156 | int tc2, int passive_freq, int polling_freq); |
157 | 157 | void thermal_zone_device_unregister(struct thermal_zone_device *); |