diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 13:19:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-20 13:19:07 -0500 |
commit | 5a1203914a637b642442a861cf462d16401548e1 (patch) | |
tree | 894ea523ad45686b9103410f7daeb3a8e670553a | |
parent | c560dc8793ecf4c3bb4ba6e7b8cae8a64486d96b (diff) | |
parent | ac6324e7021dfa917ce4f9a836318c3e46fbb84e (diff) |
Merge tag 'for-v3.9' of git://git.infradead.org/battery-2.6
Pull battery updates from Anton Vorontsov:
"Four new drivers:
- goldfish_battery:
This is Android Emulator battery driver. Originally from Google,
but Intel folks reshaped it for mainline
- pm2301_charger:
A new driver for ST-Ericsson 2301 Power Management chip, uses
AB8500 battery management core
- qnap-poweroff:
The driver adds poweroff functionality for QNAP NAS boxes
- restart-poweroff:
A generic driver that implements 'power off by restarting'. The
actual poweroff functionality is implemented through a bootloader,
so Linux' task is just to restart the box. The driver is useful on
Buffalo Linkstation LS-XHL and LS-CHLv2 boards. Andrew Lunn worked
on submitting the driver (as well as qnap-poweroff above).
Additionally:
- A lot of fixes for ab8500 drivers. This is a part of efforts of
syncing internal ST-Ericsson development tree with the mainline.
Lee Jones @ Linaro worked on compilation and reshaping these
series.
- New health properties for the power supplies: "Watchdog timer
expire" and "Safety timer expire"
- As usual, a bunch of fixes/cleanups here and there"
* tag 'for-v3.9' of git://git.infradead.org/battery-2.6: (81 commits)
bq2415x_charger: Add support for offline and 100mA mode
generic-adc-battery: Fix forever loop in gab_remove()
goldfish_battery: Add missing GENERIC_HARDIRQS dependency
da9030_battery: Include notifier.h
bq27x00_battery: Fix reporting battery temperature
power/reset: Remove newly introduced __dev* annotations
lp8727_charger: Small cleanup in naming
ab8500_btemp: Demote initcall sequence
ds2782_battery: Add power_supply_changed() calls for proper uevent support
power: Add battery driver for goldfish emulator
u8500-charger: Delay for USB enumeration
ab8500-bm: Remove individual [charger|btemp|fg|chargalg] pdata structures
ab8500-charger: Do not touch VBUSOVV bits
ab8500-fg: Use correct battery charge full design
pm2301: LPN mode control support
pm2301: Enable vbat low monitoring
ab8500-bm: Flush all work queues before suspending
ab8500-fg: Go to INIT_RECOVERY when charger removed
ab8500-charger: Add support for autopower on AB8505 and AB9540
abx500-chargalg: Add new sysfs interface to get current charge status
...
Fix up fairly straightforward conflicts in the ab8500 driver. But since
it seems to be ARM-specific, I can't even compile-test the result..
36 files changed, 4173 insertions, 999 deletions
diff --git a/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt new file mode 100644 index 000000000000..9a599d27bd75 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/qnap-poweroff.txt | |||
@@ -0,0 +1,13 @@ | |||
1 | * QNAP Power Off | ||
2 | |||
3 | QNAP NAS devices have a microcontroller controlling the main power | ||
4 | supply. This microcontroller is connected to UART1 of the Kirkwood and | ||
5 | Orion5x SoCs. Sending the charactor 'A', at 19200 baud, tells the | ||
6 | microcontroller to turn the power off. This driver adds a handler to | ||
7 | pm_power_off which is called to turn the power off. | ||
8 | |||
9 | Required Properties: | ||
10 | - compatible: Should be "qnap,power-off" | ||
11 | |||
12 | - reg: Address and length of the register set for UART1 | ||
13 | - clocks: tclk clock | ||
diff --git a/Documentation/devicetree/bindings/power_supply/restart-poweroff.txt b/Documentation/devicetree/bindings/power_supply/restart-poweroff.txt new file mode 100644 index 000000000000..5776e684afda --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/restart-poweroff.txt | |||
@@ -0,0 +1,8 @@ | |||
1 | * Restart Power Off | ||
2 | |||
3 | Buffalo Linkstation LS-XHL and LS-CHLv2, and other devices power off | ||
4 | by restarting and letting u-boot keep hold of the machine until the | ||
5 | user presses a button. | ||
6 | |||
7 | Required Properties: | ||
8 | - compatible: Should be "restart-poweroff" | ||
diff --git a/MAINTAINERS b/MAINTAINERS index b7013e41b623..b1f98503ebda 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7612,6 +7612,22 @@ F: Documentation/backlight/lp855x-driver.txt | |||
7612 | F: drivers/video/backlight/lp855x_bl.c | 7612 | F: drivers/video/backlight/lp855x_bl.c |
7613 | F: include/linux/platform_data/lp855x.h | 7613 | F: include/linux/platform_data/lp855x.h |
7614 | 7614 | ||
7615 | TI LP8727 CHARGER DRIVER | ||
7616 | M: Milo Kim <milo.kim@ti.com> | ||
7617 | S: Maintained | ||
7618 | F: drivers/power/lp8727_charger.c | ||
7619 | F: include/linux/platform_data/lp8727.h | ||
7620 | |||
7621 | TI LP8788 MFD DRIVER | ||
7622 | M: Milo Kim <milo.kim@ti.com> | ||
7623 | S: Maintained | ||
7624 | F: drivers/iio/adc/lp8788_adc.c | ||
7625 | F: drivers/leds/leds-lp8788.c | ||
7626 | F: drivers/mfd/lp8788*.c | ||
7627 | F: drivers/power/lp8788-charger.c | ||
7628 | F: drivers/regulator/lp8788-*.c | ||
7629 | F: include/linux/mfd/lp8788*.h | ||
7630 | |||
7615 | TI TWL4030 SERIES SOC CODEC DRIVER | 7631 | TI TWL4030 SERIES SOC CODEC DRIVER |
7616 | M: Peter Ujfalusi <peter.ujfalusi@ti.com> | 7632 | M: Peter Ujfalusi <peter.ujfalusi@ti.com> |
7617 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 7633 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 4778bb124efe..8b5d685ab980 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -750,6 +750,12 @@ static struct resource ab8500_charger_resources[] = { | |||
750 | .end = AB8500_INT_CH_WD_EXP, | 750 | .end = AB8500_INT_CH_WD_EXP, |
751 | .flags = IORESOURCE_IRQ, | 751 | .flags = IORESOURCE_IRQ, |
752 | }, | 752 | }, |
753 | { | ||
754 | .name = "VBUS_CH_DROP_END", | ||
755 | .start = AB8500_INT_VBUS_CH_DROP_END, | ||
756 | .end = AB8500_INT_VBUS_CH_DROP_END, | ||
757 | .flags = IORESOURCE_IRQ, | ||
758 | }, | ||
753 | }; | 759 | }; |
754 | 760 | ||
755 | static struct resource ab8500_btemp_resources[] = { | 761 | static struct resource ab8500_btemp_resources[] = { |
@@ -1012,40 +1018,32 @@ static struct mfd_cell ab8500_bm_devs[] = { | |||
1012 | .of_compatible = "stericsson,ab8500-charger", | 1018 | .of_compatible = "stericsson,ab8500-charger", |
1013 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), | 1019 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), |
1014 | .resources = ab8500_charger_resources, | 1020 | .resources = ab8500_charger_resources, |
1015 | #ifndef CONFIG_OF | ||
1016 | .platform_data = &ab8500_bm_data, | 1021 | .platform_data = &ab8500_bm_data, |
1017 | .pdata_size = sizeof(ab8500_bm_data), | 1022 | .pdata_size = sizeof(ab8500_bm_data), |
1018 | #endif | ||
1019 | }, | 1023 | }, |
1020 | { | 1024 | { |
1021 | .name = "ab8500-btemp", | 1025 | .name = "ab8500-btemp", |
1022 | .of_compatible = "stericsson,ab8500-btemp", | 1026 | .of_compatible = "stericsson,ab8500-btemp", |
1023 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), | 1027 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), |
1024 | .resources = ab8500_btemp_resources, | 1028 | .resources = ab8500_btemp_resources, |
1025 | #ifndef CONFIG_OF | ||
1026 | .platform_data = &ab8500_bm_data, | 1029 | .platform_data = &ab8500_bm_data, |
1027 | .pdata_size = sizeof(ab8500_bm_data), | 1030 | .pdata_size = sizeof(ab8500_bm_data), |
1028 | #endif | ||
1029 | }, | 1031 | }, |
1030 | { | 1032 | { |
1031 | .name = "ab8500-fg", | 1033 | .name = "ab8500-fg", |
1032 | .of_compatible = "stericsson,ab8500-fg", | 1034 | .of_compatible = "stericsson,ab8500-fg", |
1033 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), | 1035 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), |
1034 | .resources = ab8500_fg_resources, | 1036 | .resources = ab8500_fg_resources, |
1035 | #ifndef CONFIG_OF | ||
1036 | .platform_data = &ab8500_bm_data, | 1037 | .platform_data = &ab8500_bm_data, |
1037 | .pdata_size = sizeof(ab8500_bm_data), | 1038 | .pdata_size = sizeof(ab8500_bm_data), |
1038 | #endif | ||
1039 | }, | 1039 | }, |
1040 | { | 1040 | { |
1041 | .name = "ab8500-chargalg", | 1041 | .name = "ab8500-chargalg", |
1042 | .of_compatible = "stericsson,ab8500-chargalg", | 1042 | .of_compatible = "stericsson,ab8500-chargalg", |
1043 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), | 1043 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), |
1044 | .resources = ab8500_chargalg_resources, | 1044 | .resources = ab8500_chargalg_resources, |
1045 | #ifndef CONFIG_OF | ||
1046 | .platform_data = &ab8500_bm_data, | 1045 | .platform_data = &ab8500_bm_data, |
1047 | .pdata_size = sizeof(ab8500_bm_data), | 1046 | .pdata_size = sizeof(ab8500_bm_data), |
1048 | #endif | ||
1049 | }, | 1047 | }, |
1050 | }; | 1048 | }; |
1051 | 1049 | ||
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c index 8bc80b05c63c..d338c1c4e8c8 100644 --- a/drivers/power/88pm860x_battery.c +++ b/drivers/power/88pm860x_battery.c | |||
@@ -915,15 +915,13 @@ static int pm860x_battery_probe(struct platform_device *pdev) | |||
915 | info->irq_cc = platform_get_irq(pdev, 0); | 915 | info->irq_cc = platform_get_irq(pdev, 0); |
916 | if (info->irq_cc <= 0) { | 916 | if (info->irq_cc <= 0) { |
917 | dev_err(&pdev->dev, "No IRQ resource!\n"); | 917 | dev_err(&pdev->dev, "No IRQ resource!\n"); |
918 | ret = -EINVAL; | 918 | return -EINVAL; |
919 | goto out; | ||
920 | } | 919 | } |
921 | 920 | ||
922 | info->irq_batt = platform_get_irq(pdev, 1); | 921 | info->irq_batt = platform_get_irq(pdev, 1); |
923 | if (info->irq_batt <= 0) { | 922 | if (info->irq_batt <= 0) { |
924 | dev_err(&pdev->dev, "No IRQ resource!\n"); | 923 | dev_err(&pdev->dev, "No IRQ resource!\n"); |
925 | ret = -EINVAL; | 924 | return -EINVAL; |
926 | goto out; | ||
927 | } | 925 | } |
928 | 926 | ||
929 | info->chip = chip; | 927 | info->chip = chip; |
@@ -957,7 +955,7 @@ static int pm860x_battery_probe(struct platform_device *pdev) | |||
957 | 955 | ||
958 | ret = power_supply_register(&pdev->dev, &info->battery); | 956 | ret = power_supply_register(&pdev->dev, &info->battery); |
959 | if (ret) | 957 | if (ret) |
960 | goto out; | 958 | return ret; |
961 | info->battery.dev->parent = &pdev->dev; | 959 | info->battery.dev->parent = &pdev->dev; |
962 | 960 | ||
963 | ret = request_threaded_irq(info->irq_cc, NULL, | 961 | ret = request_threaded_irq(info->irq_cc, NULL, |
@@ -984,8 +982,6 @@ out_coulomb: | |||
984 | free_irq(info->irq_cc, info); | 982 | free_irq(info->irq_cc, info); |
985 | out_reg: | 983 | out_reg: |
986 | power_supply_unregister(&info->battery); | 984 | power_supply_unregister(&info->battery); |
987 | out: | ||
988 | kfree(info); | ||
989 | return ret; | 985 | return ret; |
990 | } | 986 | } |
991 | 987 | ||
@@ -993,10 +989,9 @@ static int pm860x_battery_remove(struct platform_device *pdev) | |||
993 | { | 989 | { |
994 | struct pm860x_battery_info *info = platform_get_drvdata(pdev); | 990 | struct pm860x_battery_info *info = platform_get_drvdata(pdev); |
995 | 991 | ||
996 | power_supply_unregister(&info->battery); | ||
997 | free_irq(info->irq_batt, info); | 992 | free_irq(info->irq_batt, info); |
998 | free_irq(info->irq_cc, info); | 993 | free_irq(info->irq_cc, info); |
999 | kfree(info); | 994 | power_supply_unregister(&info->battery); |
1000 | platform_set_drvdata(pdev, NULL); | 995 | platform_set_drvdata(pdev, NULL); |
1001 | return 0; | 996 | return 0; |
1002 | } | 997 | } |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 9f45e2f77d53..9e00c389e777 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -346,6 +346,20 @@ config AB8500_BM | |||
346 | help | 346 | help |
347 | Say Y to include support for AB8500 battery management. | 347 | Say Y to include support for AB8500 battery management. |
348 | 348 | ||
349 | config BATTERY_GOLDFISH | ||
350 | tristate "Goldfish battery driver" | ||
351 | depends on GENERIC_HARDIRQS | ||
352 | help | ||
353 | Say Y to enable support for the battery and AC power in the | ||
354 | Goldfish emulator. | ||
355 | |||
356 | config CHARGER_PM2301 | ||
357 | bool "PM2301 Battery Charger Driver" | ||
358 | depends on AB8500_BM | ||
359 | help | ||
360 | Say Y to include support for PM2301 charger driver. | ||
361 | Depends on AB8500 battery management core. | ||
362 | |||
349 | source "drivers/power/reset/Kconfig" | 363 | source "drivers/power/reset/Kconfig" |
350 | 364 | ||
351 | endif # POWER_SUPPLY | 365 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 22c8913382c0..3f66436af45c 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_BATTERY_DS2760) += ds2760_battery.o | |||
20 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o | 20 | obj-$(CONFIG_BATTERY_DS2780) += ds2780_battery.o |
21 | obj-$(CONFIG_BATTERY_DS2781) += ds2781_battery.o | 21 | obj-$(CONFIG_BATTERY_DS2781) += ds2781_battery.o |
22 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o | 22 | obj-$(CONFIG_BATTERY_DS2782) += ds2782_battery.o |
23 | obj-$(CONFIG_BATTERY_GOLDFISH) += goldfish_battery.o | ||
23 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o | 24 | obj-$(CONFIG_BATTERY_PMU) += pmu_battery.o |
24 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o | 25 | obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o |
25 | obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o | 26 | obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o |
@@ -38,7 +39,7 @@ obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | |||
38 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 39 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
39 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | 40 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o |
40 | obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o | 41 | obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o |
41 | obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o | 42 | obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o abx500_chargalg.o |
42 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o | 43 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o |
43 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o | 44 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o |
44 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o | 45 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o |
@@ -46,6 +47,7 @@ obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o | |||
46 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o | 47 | obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o |
47 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | 48 | obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o |
48 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o | 49 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o |
50 | obj-$(CONFIG_CHARGER_PM2301) += pm2301_charger.o | ||
49 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 51 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
50 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 52 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
51 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 53 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o |
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c index f034ae43e045..7a96c0650fbb 100644 --- a/drivers/power/ab8500_bmdata.c +++ b/drivers/power/ab8500_bmdata.c | |||
@@ -182,206 +182,206 @@ static struct batres_vs_temp temp_to_batres_tbl_9100[] = { | |||
182 | }; | 182 | }; |
183 | 183 | ||
184 | static struct abx500_battery_type bat_type_thermistor[] = { | 184 | static struct abx500_battery_type bat_type_thermistor[] = { |
185 | [BATTERY_UNKNOWN] = { | 185 | [BATTERY_UNKNOWN] = { |
186 | /* First element always represent the UNKNOWN battery */ | 186 | /* First element always represent the UNKNOWN battery */ |
187 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, | 187 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, |
188 | .resis_high = 0, | 188 | .resis_high = 0, |
189 | .resis_low = 0, | 189 | .resis_low = 0, |
190 | .battery_resistance = 300, | 190 | .battery_resistance = 300, |
191 | .charge_full_design = 612, | 191 | .charge_full_design = 612, |
192 | .nominal_voltage = 3700, | 192 | .nominal_voltage = 3700, |
193 | .termination_vol = 4050, | 193 | .termination_vol = 4050, |
194 | .termination_curr = 200, | 194 | .termination_curr = 200, |
195 | .recharge_vol = 3990, | 195 | .recharge_cap = 95, |
196 | .normal_cur_lvl = 400, | 196 | .normal_cur_lvl = 400, |
197 | .normal_vol_lvl = 4100, | 197 | .normal_vol_lvl = 4100, |
198 | .maint_a_cur_lvl = 400, | 198 | .maint_a_cur_lvl = 400, |
199 | .maint_a_vol_lvl = 4050, | 199 | .maint_a_vol_lvl = 4050, |
200 | .maint_a_chg_timer_h = 60, | 200 | .maint_a_chg_timer_h = 60, |
201 | .maint_b_cur_lvl = 400, | 201 | .maint_b_cur_lvl = 400, |
202 | .maint_b_vol_lvl = 4000, | 202 | .maint_b_vol_lvl = 4000, |
203 | .maint_b_chg_timer_h = 200, | 203 | .maint_b_chg_timer_h = 200, |
204 | .low_high_cur_lvl = 300, | 204 | .low_high_cur_lvl = 300, |
205 | .low_high_vol_lvl = 4000, | 205 | .low_high_vol_lvl = 4000, |
206 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | 206 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
207 | .r_to_t_tbl = temp_tbl, | 207 | .r_to_t_tbl = temp_tbl, |
208 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | 208 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
209 | .v_to_cap_tbl = cap_tbl, | 209 | .v_to_cap_tbl = cap_tbl, |
210 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 210 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
211 | .batres_tbl = temp_to_batres_tbl_thermistor, | 211 | .batres_tbl = temp_to_batres_tbl_thermistor, |
212 | }, | 212 | }, |
213 | { | 213 | { |
214 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | 214 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, |
215 | .resis_high = 53407, | 215 | .resis_high = 53407, |
216 | .resis_low = 12500, | 216 | .resis_low = 12500, |
217 | .battery_resistance = 300, | 217 | .battery_resistance = 300, |
218 | .charge_full_design = 900, | 218 | .charge_full_design = 900, |
219 | .nominal_voltage = 3600, | 219 | .nominal_voltage = 3600, |
220 | .termination_vol = 4150, | 220 | .termination_vol = 4150, |
221 | .termination_curr = 80, | 221 | .termination_curr = 80, |
222 | .recharge_vol = 4130, | 222 | .recharge_cap = 95, |
223 | .normal_cur_lvl = 700, | 223 | .normal_cur_lvl = 700, |
224 | .normal_vol_lvl = 4200, | 224 | .normal_vol_lvl = 4200, |
225 | .maint_a_cur_lvl = 600, | 225 | .maint_a_cur_lvl = 600, |
226 | .maint_a_vol_lvl = 4150, | 226 | .maint_a_vol_lvl = 4150, |
227 | .maint_a_chg_timer_h = 60, | 227 | .maint_a_chg_timer_h = 60, |
228 | .maint_b_cur_lvl = 600, | 228 | .maint_b_cur_lvl = 600, |
229 | .maint_b_vol_lvl = 4100, | 229 | .maint_b_vol_lvl = 4100, |
230 | .maint_b_chg_timer_h = 200, | 230 | .maint_b_chg_timer_h = 200, |
231 | .low_high_cur_lvl = 300, | 231 | .low_high_cur_lvl = 300, |
232 | .low_high_vol_lvl = 4000, | 232 | .low_high_vol_lvl = 4000, |
233 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor), | 233 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor), |
234 | .r_to_t_tbl = temp_tbl_A_thermistor, | 234 | .r_to_t_tbl = temp_tbl_A_thermistor, |
235 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor), | 235 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor), |
236 | .v_to_cap_tbl = cap_tbl_A_thermistor, | 236 | .v_to_cap_tbl = cap_tbl_A_thermistor, |
237 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 237 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
238 | .batres_tbl = temp_to_batres_tbl_thermistor, | 238 | .batres_tbl = temp_to_batres_tbl_thermistor, |
239 | 239 | ||
240 | }, | 240 | }, |
241 | { | 241 | { |
242 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | 242 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, |
243 | .resis_high = 200000, | 243 | .resis_high = 200000, |
244 | .resis_low = 82869, | 244 | .resis_low = 82869, |
245 | .battery_resistance = 300, | 245 | .battery_resistance = 300, |
246 | .charge_full_design = 900, | 246 | .charge_full_design = 900, |
247 | .nominal_voltage = 3600, | 247 | .nominal_voltage = 3600, |
248 | .termination_vol = 4150, | 248 | .termination_vol = 4150, |
249 | .termination_curr = 80, | 249 | .termination_curr = 80, |
250 | .recharge_vol = 4130, | 250 | .recharge_cap = 95, |
251 | .normal_cur_lvl = 700, | 251 | .normal_cur_lvl = 700, |
252 | .normal_vol_lvl = 4200, | 252 | .normal_vol_lvl = 4200, |
253 | .maint_a_cur_lvl = 600, | 253 | .maint_a_cur_lvl = 600, |
254 | .maint_a_vol_lvl = 4150, | 254 | .maint_a_vol_lvl = 4150, |
255 | .maint_a_chg_timer_h = 60, | 255 | .maint_a_chg_timer_h = 60, |
256 | .maint_b_cur_lvl = 600, | 256 | .maint_b_cur_lvl = 600, |
257 | .maint_b_vol_lvl = 4100, | 257 | .maint_b_vol_lvl = 4100, |
258 | .maint_b_chg_timer_h = 200, | 258 | .maint_b_chg_timer_h = 200, |
259 | .low_high_cur_lvl = 300, | 259 | .low_high_cur_lvl = 300, |
260 | .low_high_vol_lvl = 4000, | 260 | .low_high_vol_lvl = 4000, |
261 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor), | 261 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor), |
262 | .r_to_t_tbl = temp_tbl_B_thermistor, | 262 | .r_to_t_tbl = temp_tbl_B_thermistor, |
263 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor), | 263 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor), |
264 | .v_to_cap_tbl = cap_tbl_B_thermistor, | 264 | .v_to_cap_tbl = cap_tbl_B_thermistor, |
265 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 265 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
266 | .batres_tbl = temp_to_batres_tbl_thermistor, | 266 | .batres_tbl = temp_to_batres_tbl_thermistor, |
267 | }, | 267 | }, |
268 | }; | 268 | }; |
269 | 269 | ||
270 | static struct abx500_battery_type bat_type_ext_thermistor[] = { | 270 | static struct abx500_battery_type bat_type_ext_thermistor[] = { |
271 | [BATTERY_UNKNOWN] = { | 271 | [BATTERY_UNKNOWN] = { |
272 | /* First element always represent the UNKNOWN battery */ | 272 | /* First element always represent the UNKNOWN battery */ |
273 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, | 273 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, |
274 | .resis_high = 0, | 274 | .resis_high = 0, |
275 | .resis_low = 0, | 275 | .resis_low = 0, |
276 | .battery_resistance = 300, | 276 | .battery_resistance = 300, |
277 | .charge_full_design = 612, | 277 | .charge_full_design = 612, |
278 | .nominal_voltage = 3700, | 278 | .nominal_voltage = 3700, |
279 | .termination_vol = 4050, | 279 | .termination_vol = 4050, |
280 | .termination_curr = 200, | 280 | .termination_curr = 200, |
281 | .recharge_vol = 3990, | 281 | .recharge_cap = 95, |
282 | .normal_cur_lvl = 400, | 282 | .normal_cur_lvl = 400, |
283 | .normal_vol_lvl = 4100, | 283 | .normal_vol_lvl = 4100, |
284 | .maint_a_cur_lvl = 400, | 284 | .maint_a_cur_lvl = 400, |
285 | .maint_a_vol_lvl = 4050, | 285 | .maint_a_vol_lvl = 4050, |
286 | .maint_a_chg_timer_h = 60, | 286 | .maint_a_chg_timer_h = 60, |
287 | .maint_b_cur_lvl = 400, | 287 | .maint_b_cur_lvl = 400, |
288 | .maint_b_vol_lvl = 4000, | 288 | .maint_b_vol_lvl = 4000, |
289 | .maint_b_chg_timer_h = 200, | 289 | .maint_b_chg_timer_h = 200, |
290 | .low_high_cur_lvl = 300, | 290 | .low_high_cur_lvl = 300, |
291 | .low_high_vol_lvl = 4000, | 291 | .low_high_vol_lvl = 4000, |
292 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | 292 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
293 | .r_to_t_tbl = temp_tbl, | 293 | .r_to_t_tbl = temp_tbl, |
294 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | 294 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
295 | .v_to_cap_tbl = cap_tbl, | 295 | .v_to_cap_tbl = cap_tbl, |
296 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 296 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
297 | .batres_tbl = temp_to_batres_tbl_thermistor, | 297 | .batres_tbl = temp_to_batres_tbl_thermistor, |
298 | }, | 298 | }, |
299 | /* | 299 | /* |
300 | * These are the batteries that doesn't have an internal NTC resistor to measure | 300 | * These are the batteries that doesn't have an internal NTC resistor to measure |
301 | * its temperature. The temperature in this case is measure with a NTC placed | 301 | * its temperature. The temperature in this case is measure with a NTC placed |
302 | * near the battery but on the PCB. | 302 | * near the battery but on the PCB. |
303 | */ | 303 | */ |
304 | { | 304 | { |
305 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | 305 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, |
306 | .resis_high = 76000, | 306 | .resis_high = 76000, |
307 | .resis_low = 53000, | 307 | .resis_low = 53000, |
308 | .battery_resistance = 300, | 308 | .battery_resistance = 300, |
309 | .charge_full_design = 900, | 309 | .charge_full_design = 900, |
310 | .nominal_voltage = 3700, | 310 | .nominal_voltage = 3700, |
311 | .termination_vol = 4150, | 311 | .termination_vol = 4150, |
312 | .termination_curr = 100, | 312 | .termination_curr = 100, |
313 | .recharge_vol = 4130, | 313 | .recharge_cap = 95, |
314 | .normal_cur_lvl = 700, | 314 | .normal_cur_lvl = 700, |
315 | .normal_vol_lvl = 4200, | 315 | .normal_vol_lvl = 4200, |
316 | .maint_a_cur_lvl = 600, | 316 | .maint_a_cur_lvl = 600, |
317 | .maint_a_vol_lvl = 4150, | 317 | .maint_a_vol_lvl = 4150, |
318 | .maint_a_chg_timer_h = 60, | 318 | .maint_a_chg_timer_h = 60, |
319 | .maint_b_cur_lvl = 600, | 319 | .maint_b_cur_lvl = 600, |
320 | .maint_b_vol_lvl = 4100, | 320 | .maint_b_vol_lvl = 4100, |
321 | .maint_b_chg_timer_h = 200, | 321 | .maint_b_chg_timer_h = 200, |
322 | .low_high_cur_lvl = 300, | 322 | .low_high_cur_lvl = 300, |
323 | .low_high_vol_lvl = 4000, | 323 | .low_high_vol_lvl = 4000, |
324 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | 324 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
325 | .r_to_t_tbl = temp_tbl, | 325 | .r_to_t_tbl = temp_tbl, |
326 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | 326 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
327 | .v_to_cap_tbl = cap_tbl, | 327 | .v_to_cap_tbl = cap_tbl, |
328 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 328 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
329 | .batres_tbl = temp_to_batres_tbl_thermistor, | 329 | .batres_tbl = temp_to_batres_tbl_thermistor, |
330 | }, | 330 | }, |
331 | { | 331 | { |
332 | .name = POWER_SUPPLY_TECHNOLOGY_LION, | 332 | .name = POWER_SUPPLY_TECHNOLOGY_LION, |
333 | .resis_high = 30000, | 333 | .resis_high = 30000, |
334 | .resis_low = 10000, | 334 | .resis_low = 10000, |
335 | .battery_resistance = 300, | 335 | .battery_resistance = 300, |
336 | .charge_full_design = 950, | 336 | .charge_full_design = 950, |
337 | .nominal_voltage = 3700, | 337 | .nominal_voltage = 3700, |
338 | .termination_vol = 4150, | 338 | .termination_vol = 4150, |
339 | .termination_curr = 100, | 339 | .termination_curr = 100, |
340 | .recharge_vol = 4130, | 340 | .recharge_cap = 95, |
341 | .normal_cur_lvl = 700, | 341 | .normal_cur_lvl = 700, |
342 | .normal_vol_lvl = 4200, | 342 | .normal_vol_lvl = 4200, |
343 | .maint_a_cur_lvl = 600, | 343 | .maint_a_cur_lvl = 600, |
344 | .maint_a_vol_lvl = 4150, | 344 | .maint_a_vol_lvl = 4150, |
345 | .maint_a_chg_timer_h = 60, | 345 | .maint_a_chg_timer_h = 60, |
346 | .maint_b_cur_lvl = 600, | 346 | .maint_b_cur_lvl = 600, |
347 | .maint_b_vol_lvl = 4100, | 347 | .maint_b_vol_lvl = 4100, |
348 | .maint_b_chg_timer_h = 200, | 348 | .maint_b_chg_timer_h = 200, |
349 | .low_high_cur_lvl = 300, | 349 | .low_high_cur_lvl = 300, |
350 | .low_high_vol_lvl = 4000, | 350 | .low_high_vol_lvl = 4000, |
351 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | 351 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
352 | .r_to_t_tbl = temp_tbl, | 352 | .r_to_t_tbl = temp_tbl, |
353 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | 353 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
354 | .v_to_cap_tbl = cap_tbl, | 354 | .v_to_cap_tbl = cap_tbl, |
355 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 355 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
356 | .batres_tbl = temp_to_batres_tbl_thermistor, | 356 | .batres_tbl = temp_to_batres_tbl_thermistor, |
357 | }, | 357 | }, |
358 | { | 358 | { |
359 | .name = POWER_SUPPLY_TECHNOLOGY_LION, | 359 | .name = POWER_SUPPLY_TECHNOLOGY_LION, |
360 | .resis_high = 95000, | 360 | .resis_high = 95000, |
361 | .resis_low = 76001, | 361 | .resis_low = 76001, |
362 | .battery_resistance = 300, | 362 | .battery_resistance = 300, |
363 | .charge_full_design = 950, | 363 | .charge_full_design = 950, |
364 | .nominal_voltage = 3700, | 364 | .nominal_voltage = 3700, |
365 | .termination_vol = 4150, | 365 | .termination_vol = 4150, |
366 | .termination_curr = 100, | 366 | .termination_curr = 100, |
367 | .recharge_vol = 4130, | 367 | .recharge_cap = 95, |
368 | .normal_cur_lvl = 700, | 368 | .normal_cur_lvl = 700, |
369 | .normal_vol_lvl = 4200, | 369 | .normal_vol_lvl = 4200, |
370 | .maint_a_cur_lvl = 600, | 370 | .maint_a_cur_lvl = 600, |
371 | .maint_a_vol_lvl = 4150, | 371 | .maint_a_vol_lvl = 4150, |
372 | .maint_a_chg_timer_h = 60, | 372 | .maint_a_chg_timer_h = 60, |
373 | .maint_b_cur_lvl = 600, | 373 | .maint_b_cur_lvl = 600, |
374 | .maint_b_vol_lvl = 4100, | 374 | .maint_b_vol_lvl = 4100, |
375 | .maint_b_chg_timer_h = 200, | 375 | .maint_b_chg_timer_h = 200, |
376 | .low_high_cur_lvl = 300, | 376 | .low_high_cur_lvl = 300, |
377 | .low_high_vol_lvl = 4000, | 377 | .low_high_vol_lvl = 4000, |
378 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | 378 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), |
379 | .r_to_t_tbl = temp_tbl, | 379 | .r_to_t_tbl = temp_tbl, |
380 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | 380 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), |
381 | .v_to_cap_tbl = cap_tbl, | 381 | .v_to_cap_tbl = cap_tbl, |
382 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | 382 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), |
383 | .batres_tbl = temp_to_batres_tbl_thermistor, | 383 | .batres_tbl = temp_to_batres_tbl_thermistor, |
384 | }, | 384 | }, |
385 | }; | 385 | }; |
386 | 386 | ||
387 | static const struct abx500_bm_capacity_levels cap_levels = { | 387 | static const struct abx500_bm_capacity_levels cap_levels = { |
@@ -405,8 +405,8 @@ static const struct abx500_fg_parameters fg = { | |||
405 | .lowbat_threshold = 3100, | 405 | .lowbat_threshold = 3100, |
406 | .battok_falling_th_sel0 = 2860, | 406 | .battok_falling_th_sel0 = 2860, |
407 | .battok_raising_th_sel1 = 2860, | 407 | .battok_raising_th_sel1 = 2860, |
408 | .maint_thres = 95, | ||
408 | .user_cap_limit = 15, | 409 | .user_cap_limit = 15, |
409 | .maint_thres = 97, | ||
410 | }; | 410 | }; |
411 | 411 | ||
412 | static const struct abx500_maxim_parameters maxi_params = { | 412 | static const struct abx500_maxim_parameters maxi_params = { |
@@ -424,96 +424,84 @@ static const struct abx500_bm_charger_parameters chg = { | |||
424 | }; | 424 | }; |
425 | 425 | ||
426 | struct abx500_bm_data ab8500_bm_data = { | 426 | struct abx500_bm_data ab8500_bm_data = { |
427 | .temp_under = 3, | 427 | .temp_under = 3, |
428 | .temp_low = 8, | 428 | .temp_low = 8, |
429 | .temp_high = 43, | 429 | .temp_high = 43, |
430 | .temp_over = 48, | 430 | .temp_over = 48, |
431 | .main_safety_tmr_h = 4, | 431 | .main_safety_tmr_h = 4, |
432 | .temp_interval_chg = 20, | 432 | .temp_interval_chg = 20, |
433 | .temp_interval_nochg = 120, | 433 | .temp_interval_nochg = 120, |
434 | .usb_safety_tmr_h = 4, | 434 | .usb_safety_tmr_h = 4, |
435 | .bkup_bat_v = BUP_VCH_SEL_2P6V, | 435 | .bkup_bat_v = BUP_VCH_SEL_2P6V, |
436 | .bkup_bat_i = BUP_ICH_SEL_150UA, | 436 | .bkup_bat_i = BUP_ICH_SEL_150UA, |
437 | .no_maintenance = false, | 437 | .no_maintenance = false, |
438 | .adc_therm = ABx500_ADC_THERM_BATCTRL, | 438 | .capacity_scaling = false, |
439 | .chg_unknown_bat = false, | 439 | .adc_therm = ABx500_ADC_THERM_BATCTRL, |
440 | .enable_overshoot = false, | 440 | .chg_unknown_bat = false, |
441 | .fg_res = 100, | 441 | .enable_overshoot = false, |
442 | .cap_levels = &cap_levels, | 442 | .fg_res = 100, |
443 | .bat_type = bat_type_thermistor, | 443 | .cap_levels = &cap_levels, |
444 | .n_btypes = 3, | 444 | .bat_type = bat_type_thermistor, |
445 | .batt_id = 0, | 445 | .n_btypes = 3, |
446 | .interval_charging = 5, | 446 | .batt_id = 0, |
447 | .interval_not_charging = 120, | 447 | .interval_charging = 5, |
448 | .temp_hysteresis = 3, | 448 | .interval_not_charging = 120, |
449 | .gnd_lift_resistance = 34, | 449 | .temp_hysteresis = 3, |
450 | .maxi = &maxi_params, | 450 | .gnd_lift_resistance = 34, |
451 | .chg_params = &chg, | 451 | .maxi = &maxi_params, |
452 | .fg_params = &fg, | 452 | .chg_params = &chg, |
453 | .fg_params = &fg, | ||
453 | }; | 454 | }; |
454 | 455 | ||
455 | int bmdevs_of_probe(struct device *dev, struct device_node *np, | 456 | int ab8500_bm_of_probe(struct device *dev, |
456 | struct abx500_bm_data **battery) | 457 | struct device_node *np, |
458 | struct abx500_bm_data *bm) | ||
457 | { | 459 | { |
458 | struct abx500_battery_type *btype; | 460 | struct batres_vs_temp *tmp_batres_tbl; |
459 | struct device_node *np_bat_supply; | 461 | struct device_node *battery_node; |
460 | struct abx500_bm_data *bat; | ||
461 | const char *btech; | 462 | const char *btech; |
462 | char bat_tech[8]; | 463 | int i; |
463 | int i, thermistor; | ||
464 | |||
465 | *battery = &ab8500_bm_data; | ||
466 | 464 | ||
467 | /* get phandle to 'battery-info' node */ | 465 | /* get phandle to 'battery-info' node */ |
468 | np_bat_supply = of_parse_phandle(np, "battery", 0); | 466 | battery_node = of_parse_phandle(np, "battery", 0); |
469 | if (!np_bat_supply) { | 467 | if (!battery_node) { |
470 | dev_err(dev, "missing property battery\n"); | 468 | dev_err(dev, "battery node or reference missing\n"); |
471 | return -EINVAL; | 469 | return -EINVAL; |
472 | } | 470 | } |
473 | if (of_property_read_bool(np_bat_supply, | ||
474 | "thermistor-on-batctrl")) | ||
475 | thermistor = NTC_INTERNAL; | ||
476 | else | ||
477 | thermistor = NTC_EXTERNAL; | ||
478 | 471 | ||
479 | bat = *battery; | 472 | btech = of_get_property(battery_node, "stericsson,battery-type", NULL); |
480 | if (thermistor == NTC_EXTERNAL) { | ||
481 | bat->n_btypes = 4; | ||
482 | bat->bat_type = bat_type_ext_thermistor; | ||
483 | bat->adc_therm = ABx500_ADC_THERM_BATTEMP; | ||
484 | } | ||
485 | btech = of_get_property(np_bat_supply, | ||
486 | "stericsson,battery-type", NULL); | ||
487 | if (!btech) { | 473 | if (!btech) { |
488 | dev_warn(dev, "missing property battery-name/type\n"); | 474 | dev_warn(dev, "missing property battery-name/type\n"); |
489 | strcpy(bat_tech, "UNKNOWN"); | 475 | return -EINVAL; |
490 | } else { | ||
491 | strcpy(bat_tech, btech); | ||
492 | } | 476 | } |
493 | 477 | ||
494 | if (strncmp(bat_tech, "LION", 4) == 0) { | 478 | if (strncmp(btech, "LION", 4) == 0) { |
495 | bat->no_maintenance = true; | 479 | bm->no_maintenance = true; |
496 | bat->chg_unknown_bat = true; | 480 | bm->chg_unknown_bat = true; |
497 | bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; | 481 | bm->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; |
498 | bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; | 482 | bm->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; |
499 | bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130; | 483 | bm->bat_type[BATTERY_UNKNOWN].recharge_cap = 95; |
500 | bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; | 484 | bm->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; |
501 | bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; | 485 | bm->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; |
502 | } | 486 | } |
503 | /* select the battery resolution table */ | 487 | |
504 | for (i = 0; i < bat->n_btypes; ++i) { | 488 | if (of_property_read_bool(battery_node, "thermistor-on-batctrl")) { |
505 | btype = (bat->bat_type + i); | 489 | if (strncmp(btech, "LION", 4) == 0) |
506 | if (thermistor == NTC_EXTERNAL) { | 490 | tmp_batres_tbl = temp_to_batres_tbl_9100; |
507 | btype->batres_tbl = | 491 | else |
508 | temp_to_batres_tbl_ext_thermistor; | 492 | tmp_batres_tbl = temp_to_batres_tbl_thermistor; |
509 | } else if (strncmp(bat_tech, "LION", 4) == 0) { | 493 | } else { |
510 | btype->batres_tbl = | 494 | bm->n_btypes = 4; |
511 | temp_to_batres_tbl_9100; | 495 | bm->bat_type = bat_type_ext_thermistor; |
512 | } else { | 496 | bm->adc_therm = ABx500_ADC_THERM_BATTEMP; |
513 | btype->batres_tbl = | 497 | tmp_batres_tbl = temp_to_batres_tbl_ext_thermistor; |
514 | temp_to_batres_tbl_thermistor; | ||
515 | } | ||
516 | } | 498 | } |
517 | of_node_put(np_bat_supply); | 499 | |
500 | /* select the battery resolution table */ | ||
501 | for (i = 0; i < bm->n_btypes; ++i) | ||
502 | bm->bat_type[i].batres_tbl = tmp_batres_tbl; | ||
503 | |||
504 | of_node_put(battery_node); | ||
505 | |||
518 | return 0; | 506 | return 0; |
519 | } | 507 | } |
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index 20e2a7d3ef43..07689064996e 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c | |||
@@ -39,6 +39,9 @@ | |||
39 | #define BTEMP_BATCTRL_CURR_SRC_7UA 7 | 39 | #define BTEMP_BATCTRL_CURR_SRC_7UA 7 |
40 | #define BTEMP_BATCTRL_CURR_SRC_20UA 20 | 40 | #define BTEMP_BATCTRL_CURR_SRC_20UA 20 |
41 | 41 | ||
42 | #define BTEMP_BATCTRL_CURR_SRC_16UA 16 | ||
43 | #define BTEMP_BATCTRL_CURR_SRC_18UA 18 | ||
44 | |||
42 | #define to_ab8500_btemp_device_info(x) container_of((x), \ | 45 | #define to_ab8500_btemp_device_info(x) container_of((x), \ |
43 | struct ab8500_btemp, btemp_psy); | 46 | struct ab8500_btemp, btemp_psy); |
44 | 47 | ||
@@ -78,12 +81,13 @@ struct ab8500_btemp_ranges { | |||
78 | * @parent: Pointer to the struct ab8500 | 81 | * @parent: Pointer to the struct ab8500 |
79 | * @gpadc: Pointer to the struct gpadc | 82 | * @gpadc: Pointer to the struct gpadc |
80 | * @fg: Pointer to the struct fg | 83 | * @fg: Pointer to the struct fg |
81 | * @bat: Pointer to the abx500_bm platform data | 84 | * @bm: Platform specific battery management information |
82 | * @btemp_psy: Structure for BTEMP specific battery properties | 85 | * @btemp_psy: Structure for BTEMP specific battery properties |
83 | * @events: Structure for information about events triggered | 86 | * @events: Structure for information about events triggered |
84 | * @btemp_ranges: Battery temperature range structure | 87 | * @btemp_ranges: Battery temperature range structure |
85 | * @btemp_wq: Work queue for measuring the temperature periodically | 88 | * @btemp_wq: Work queue for measuring the temperature periodically |
86 | * @btemp_periodic_work: Work for measuring the temperature periodically | 89 | * @btemp_periodic_work: Work for measuring the temperature periodically |
90 | * @initialized: True if battery id read. | ||
87 | */ | 91 | */ |
88 | struct ab8500_btemp { | 92 | struct ab8500_btemp { |
89 | struct device *dev; | 93 | struct device *dev; |
@@ -94,12 +98,13 @@ struct ab8500_btemp { | |||
94 | struct ab8500 *parent; | 98 | struct ab8500 *parent; |
95 | struct ab8500_gpadc *gpadc; | 99 | struct ab8500_gpadc *gpadc; |
96 | struct ab8500_fg *fg; | 100 | struct ab8500_fg *fg; |
97 | struct abx500_bm_data *bat; | 101 | struct abx500_bm_data *bm; |
98 | struct power_supply btemp_psy; | 102 | struct power_supply btemp_psy; |
99 | struct ab8500_btemp_events events; | 103 | struct ab8500_btemp_events events; |
100 | struct ab8500_btemp_ranges btemp_ranges; | 104 | struct ab8500_btemp_ranges btemp_ranges; |
101 | struct workqueue_struct *btemp_wq; | 105 | struct workqueue_struct *btemp_wq; |
102 | struct delayed_work btemp_periodic_work; | 106 | struct delayed_work btemp_periodic_work; |
107 | bool initialized; | ||
103 | }; | 108 | }; |
104 | 109 | ||
105 | /* BTEMP power supply properties */ | 110 | /* BTEMP power supply properties */ |
@@ -147,13 +152,13 @@ static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, | |||
147 | return (450000 * (v_batctrl)) / (1800 - v_batctrl); | 152 | return (450000 * (v_batctrl)) / (1800 - v_batctrl); |
148 | } | 153 | } |
149 | 154 | ||
150 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL) { | 155 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) { |
151 | /* | 156 | /* |
152 | * If the battery has internal NTC, we use the current | 157 | * If the battery has internal NTC, we use the current |
153 | * source to calculate the resistance, 7uA or 20uA | 158 | * source to calculate the resistance, 7uA or 20uA |
154 | */ | 159 | */ |
155 | rbs = (v_batctrl * 1000 | 160 | rbs = (v_batctrl * 1000 |
156 | - di->bat->gnd_lift_resistance * inst_curr) | 161 | - di->bm->gnd_lift_resistance * inst_curr) |
157 | / di->curr_source; | 162 | / di->curr_source; |
158 | } else { | 163 | } else { |
159 | /* | 164 | /* |
@@ -209,11 +214,19 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
209 | return 0; | 214 | return 0; |
210 | 215 | ||
211 | /* Only do this for batteries with internal NTC */ | 216 | /* Only do this for batteries with internal NTC */ |
212 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { | 217 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) { |
213 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA) | 218 | |
214 | curr = BAT_CTRL_7U_ENA; | 219 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { |
215 | else | 220 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA) |
216 | curr = BAT_CTRL_20U_ENA; | 221 | curr = BAT_CTRL_16U_ENA; |
222 | else | ||
223 | curr = BAT_CTRL_18U_ENA; | ||
224 | } else { | ||
225 | if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA) | ||
226 | curr = BAT_CTRL_7U_ENA; | ||
227 | else | ||
228 | curr = BAT_CTRL_20U_ENA; | ||
229 | } | ||
217 | 230 | ||
218 | dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source); | 231 | dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source); |
219 | 232 | ||
@@ -241,14 +254,25 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
241 | __func__); | 254 | __func__); |
242 | goto disable_curr_source; | 255 | goto disable_curr_source; |
243 | } | 256 | } |
244 | } else if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { | 257 | } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) { |
245 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); | 258 | dev_dbg(di->dev, "Disable BATCTRL curr source\n"); |
246 | 259 | ||
247 | /* Write 0 to the curr bits */ | 260 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { |
248 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 261 | /* Write 0 to the curr bits */ |
249 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | 262 | ret = abx500_mask_and_set_register_interruptible( |
250 | BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, | 263 | di->dev, |
251 | ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); | 264 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, |
265 | BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA, | ||
266 | ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA)); | ||
267 | } else { | ||
268 | /* Write 0 to the curr bits */ | ||
269 | ret = abx500_mask_and_set_register_interruptible( | ||
270 | di->dev, | ||
271 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
272 | BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, | ||
273 | ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); | ||
274 | } | ||
275 | |||
252 | if (ret) { | 276 | if (ret) { |
253 | dev_err(di->dev, "%s failed disabling current source\n", | 277 | dev_err(di->dev, "%s failed disabling current source\n", |
254 | __func__); | 278 | __func__); |
@@ -290,11 +314,20 @@ static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di, | |||
290 | * if we got an error above | 314 | * if we got an error above |
291 | */ | 315 | */ |
292 | disable_curr_source: | 316 | disable_curr_source: |
293 | /* Write 0 to the curr bits */ | 317 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { |
294 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 318 | /* Write 0 to the curr bits */ |
319 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
320 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | ||
321 | BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA, | ||
322 | ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA)); | ||
323 | } else { | ||
324 | /* Write 0 to the curr bits */ | ||
325 | ret = abx500_mask_and_set_register_interruptible(di->dev, | ||
295 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, | 326 | AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE, |
296 | BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, | 327 | BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA, |
297 | ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); | 328 | ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA)); |
329 | } | ||
330 | |||
298 | if (ret) { | 331 | if (ret) { |
299 | dev_err(di->dev, "%s failed disabling current source\n", | 332 | dev_err(di->dev, "%s failed disabling current source\n", |
300 | __func__); | 333 | __func__); |
@@ -372,13 +405,10 @@ static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di) | |||
372 | return ret; | 405 | return ret; |
373 | } | 406 | } |
374 | 407 | ||
375 | /* | 408 | do { |
376 | * Since there is no interrupt when current measurement is done, | 409 | msleep(20); |
377 | * loop for over 250ms (250ms is one sample conversion time | 410 | } while (!ab8500_fg_inst_curr_started(di->fg)); |
378 | * with 32.768 Khz RTC clock). Note that a stop time must be set | 411 | |
379 | * since the ab8500_btemp_read_batctrl_voltage call can block and | ||
380 | * take an unknown amount of time to complete. | ||
381 | */ | ||
382 | i = 0; | 412 | i = 0; |
383 | 413 | ||
384 | do { | 414 | do { |
@@ -457,9 +487,9 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) | |||
457 | int rbat, rntc, vntc; | 487 | int rbat, rntc, vntc; |
458 | u8 id; | 488 | u8 id; |
459 | 489 | ||
460 | id = di->bat->batt_id; | 490 | id = di->bm->batt_id; |
461 | 491 | ||
462 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && | 492 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && |
463 | id != BATTERY_UNKNOWN) { | 493 | id != BATTERY_UNKNOWN) { |
464 | 494 | ||
465 | rbat = ab8500_btemp_get_batctrl_res(di); | 495 | rbat = ab8500_btemp_get_batctrl_res(di); |
@@ -474,8 +504,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) | |||
474 | } | 504 | } |
475 | 505 | ||
476 | temp = ab8500_btemp_res_to_temp(di, | 506 | temp = ab8500_btemp_res_to_temp(di, |
477 | di->bat->bat_type[id].r_to_t_tbl, | 507 | di->bm->bat_type[id].r_to_t_tbl, |
478 | di->bat->bat_type[id].n_temp_tbl_elements, rbat); | 508 | di->bm->bat_type[id].n_temp_tbl_elements, rbat); |
479 | } else { | 509 | } else { |
480 | vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL); | 510 | vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL); |
481 | if (vntc < 0) { | 511 | if (vntc < 0) { |
@@ -491,8 +521,8 @@ static int ab8500_btemp_measure_temp(struct ab8500_btemp *di) | |||
491 | rntc = 230000 * vntc / (VTVOUT_V - vntc); | 521 | rntc = 230000 * vntc / (VTVOUT_V - vntc); |
492 | 522 | ||
493 | temp = ab8500_btemp_res_to_temp(di, | 523 | temp = ab8500_btemp_res_to_temp(di, |
494 | di->bat->bat_type[id].r_to_t_tbl, | 524 | di->bm->bat_type[id].r_to_t_tbl, |
495 | di->bat->bat_type[id].n_temp_tbl_elements, rntc); | 525 | di->bm->bat_type[id].n_temp_tbl_elements, rntc); |
496 | prev = temp; | 526 | prev = temp; |
497 | } | 527 | } |
498 | dev_dbg(di->dev, "Battery temperature is %d\n", temp); | 528 | dev_dbg(di->dev, "Battery temperature is %d\n", temp); |
@@ -511,9 +541,12 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
511 | { | 541 | { |
512 | int res; | 542 | int res; |
513 | u8 i; | 543 | u8 i; |
544 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) | ||
545 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; | ||
546 | else | ||
547 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; | ||
514 | 548 | ||
515 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; | 549 | di->bm->batt_id = BATTERY_UNKNOWN; |
516 | di->bat->batt_id = BATTERY_UNKNOWN; | ||
517 | 550 | ||
518 | res = ab8500_btemp_get_batctrl_res(di); | 551 | res = ab8500_btemp_get_batctrl_res(di); |
519 | if (res < 0) { | 552 | if (res < 0) { |
@@ -522,23 +555,23 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
522 | } | 555 | } |
523 | 556 | ||
524 | /* BATTERY_UNKNOWN is defined on position 0, skip it! */ | 557 | /* BATTERY_UNKNOWN is defined on position 0, skip it! */ |
525 | for (i = BATTERY_UNKNOWN + 1; i < di->bat->n_btypes; i++) { | 558 | for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) { |
526 | if ((res <= di->bat->bat_type[i].resis_high) && | 559 | if ((res <= di->bm->bat_type[i].resis_high) && |
527 | (res >= di->bat->bat_type[i].resis_low)) { | 560 | (res >= di->bm->bat_type[i].resis_low)) { |
528 | dev_dbg(di->dev, "Battery detected on %s" | 561 | dev_dbg(di->dev, "Battery detected on %s" |
529 | " low %d < res %d < high: %d" | 562 | " low %d < res %d < high: %d" |
530 | " index: %d\n", | 563 | " index: %d\n", |
531 | di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL ? | 564 | di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ? |
532 | "BATCTRL" : "BATTEMP", | 565 | "BATCTRL" : "BATTEMP", |
533 | di->bat->bat_type[i].resis_low, res, | 566 | di->bm->bat_type[i].resis_low, res, |
534 | di->bat->bat_type[i].resis_high, i); | 567 | di->bm->bat_type[i].resis_high, i); |
535 | 568 | ||
536 | di->bat->batt_id = i; | 569 | di->bm->batt_id = i; |
537 | break; | 570 | break; |
538 | } | 571 | } |
539 | } | 572 | } |
540 | 573 | ||
541 | if (di->bat->batt_id == BATTERY_UNKNOWN) { | 574 | if (di->bm->batt_id == BATTERY_UNKNOWN) { |
542 | dev_warn(di->dev, "Battery identified as unknown" | 575 | dev_warn(di->dev, "Battery identified as unknown" |
543 | ", resistance %d Ohm\n", res); | 576 | ", resistance %d Ohm\n", res); |
544 | return -ENXIO; | 577 | return -ENXIO; |
@@ -548,13 +581,18 @@ static int ab8500_btemp_id(struct ab8500_btemp *di) | |||
548 | * We only have to change current source if the | 581 | * We only have to change current source if the |
549 | * detected type is Type 1, else we use the 7uA source | 582 | * detected type is Type 1, else we use the 7uA source |
550 | */ | 583 | */ |
551 | if (di->bat->adc_therm == ABx500_ADC_THERM_BATCTRL && | 584 | if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && |
552 | di->bat->batt_id == 1) { | 585 | di->bm->batt_id == 1) { |
553 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); | 586 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { |
554 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA; | 587 | dev_dbg(di->dev, "Set BATCTRL current source to 16uA\n"); |
588 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA; | ||
589 | } else { | ||
590 | dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n"); | ||
591 | di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA; | ||
592 | } | ||
555 | } | 593 | } |
556 | 594 | ||
557 | return di->bat->batt_id; | 595 | return di->bm->batt_id; |
558 | } | 596 | } |
559 | 597 | ||
560 | /** | 598 | /** |
@@ -569,6 +607,13 @@ static void ab8500_btemp_periodic_work(struct work_struct *work) | |||
569 | struct ab8500_btemp *di = container_of(work, | 607 | struct ab8500_btemp *di = container_of(work, |
570 | struct ab8500_btemp, btemp_periodic_work.work); | 608 | struct ab8500_btemp, btemp_periodic_work.work); |
571 | 609 | ||
610 | if (!di->initialized) { | ||
611 | di->initialized = true; | ||
612 | /* Identify the battery */ | ||
613 | if (ab8500_btemp_id(di) < 0) | ||
614 | dev_warn(di->dev, "failed to identify the battery\n"); | ||
615 | } | ||
616 | |||
572 | di->bat_temp = ab8500_btemp_measure_temp(di); | 617 | di->bat_temp = ab8500_btemp_measure_temp(di); |
573 | 618 | ||
574 | if (di->bat_temp != di->prev_bat_temp) { | 619 | if (di->bat_temp != di->prev_bat_temp) { |
@@ -577,9 +622,9 @@ static void ab8500_btemp_periodic_work(struct work_struct *work) | |||
577 | } | 622 | } |
578 | 623 | ||
579 | if (di->events.ac_conn || di->events.usb_conn) | 624 | if (di->events.ac_conn || di->events.usb_conn) |
580 | interval = di->bat->temp_interval_chg; | 625 | interval = di->bm->temp_interval_chg; |
581 | else | 626 | else |
582 | interval = di->bat->temp_interval_nochg; | 627 | interval = di->bm->temp_interval_nochg; |
583 | 628 | ||
584 | /* Schedule a new measurement */ | 629 | /* Schedule a new measurement */ |
585 | queue_delayed_work(di->btemp_wq, | 630 | queue_delayed_work(di->btemp_wq, |
@@ -616,9 +661,9 @@ static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di) | |||
616 | { | 661 | { |
617 | struct ab8500_btemp *di = _di; | 662 | struct ab8500_btemp *di = _di; |
618 | 663 | ||
619 | if (is_ab8500_2p0_or_earlier(di->parent)) { | 664 | if (is_ab8500_3p3_or_earlier(di->parent)) { |
620 | dev_dbg(di->dev, "Ignore false btemp low irq" | 665 | dev_dbg(di->dev, "Ignore false btemp low irq" |
621 | " for ABB cut 1.0, 1.1 and 2.0\n"); | 666 | " for ABB cut 1.0, 1.1, 2.0 and 3.3\n"); |
622 | } else { | 667 | } else { |
623 | dev_crit(di->dev, "Battery temperature lower than -10deg c\n"); | 668 | dev_crit(di->dev, "Battery temperature lower than -10deg c\n"); |
624 | 669 | ||
@@ -732,30 +777,30 @@ static int ab8500_btemp_get_temp(struct ab8500_btemp *di) | |||
732 | int temp = 0; | 777 | int temp = 0; |
733 | 778 | ||
734 | /* | 779 | /* |
735 | * The BTEMP events are not reliabe on AB8500 cut2.0 | 780 | * The BTEMP events are not reliabe on AB8500 cut3.3 |
736 | * and prior versions | 781 | * and prior versions |
737 | */ | 782 | */ |
738 | if (is_ab8500_2p0_or_earlier(di->parent)) { | 783 | if (is_ab8500_3p3_or_earlier(di->parent)) { |
739 | temp = di->bat_temp * 10; | 784 | temp = di->bat_temp * 10; |
740 | } else { | 785 | } else { |
741 | if (di->events.btemp_low) { | 786 | if (di->events.btemp_low) { |
742 | if (temp > di->btemp_ranges.btemp_low_limit) | 787 | if (temp > di->btemp_ranges.btemp_low_limit) |
743 | temp = di->btemp_ranges.btemp_low_limit; | 788 | temp = di->btemp_ranges.btemp_low_limit * 10; |
744 | else | 789 | else |
745 | temp = di->bat_temp * 10; | 790 | temp = di->bat_temp * 10; |
746 | } else if (di->events.btemp_high) { | 791 | } else if (di->events.btemp_high) { |
747 | if (temp < di->btemp_ranges.btemp_high_limit) | 792 | if (temp < di->btemp_ranges.btemp_high_limit) |
748 | temp = di->btemp_ranges.btemp_high_limit; | 793 | temp = di->btemp_ranges.btemp_high_limit * 10; |
749 | else | 794 | else |
750 | temp = di->bat_temp * 10; | 795 | temp = di->bat_temp * 10; |
751 | } else if (di->events.btemp_lowmed) { | 796 | } else if (di->events.btemp_lowmed) { |
752 | if (temp > di->btemp_ranges.btemp_med_limit) | 797 | if (temp > di->btemp_ranges.btemp_med_limit) |
753 | temp = di->btemp_ranges.btemp_med_limit; | 798 | temp = di->btemp_ranges.btemp_med_limit * 10; |
754 | else | 799 | else |
755 | temp = di->bat_temp * 10; | 800 | temp = di->bat_temp * 10; |
756 | } else if (di->events.btemp_medhigh) { | 801 | } else if (di->events.btemp_medhigh) { |
757 | if (temp < di->btemp_ranges.btemp_med_limit) | 802 | if (temp < di->btemp_ranges.btemp_med_limit) |
758 | temp = di->btemp_ranges.btemp_med_limit; | 803 | temp = di->btemp_ranges.btemp_med_limit * 10; |
759 | else | 804 | else |
760 | temp = di->bat_temp * 10; | 805 | temp = di->bat_temp * 10; |
761 | } else | 806 | } else |
@@ -806,7 +851,7 @@ static int ab8500_btemp_get_property(struct power_supply *psy, | |||
806 | val->intval = 1; | 851 | val->intval = 1; |
807 | break; | 852 | break; |
808 | case POWER_SUPPLY_PROP_TECHNOLOGY: | 853 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
809 | val->intval = di->bat->bat_type[di->bat->batt_id].name; | 854 | val->intval = di->bm->bat_type[di->bm->batt_id].name; |
810 | break; | 855 | break; |
811 | case POWER_SUPPLY_PROP_TEMP: | 856 | case POWER_SUPPLY_PROP_TEMP: |
812 | val->intval = ab8500_btemp_get_temp(di); | 857 | val->intval = ab8500_btemp_get_temp(di); |
@@ -967,6 +1012,7 @@ static char *supply_interface[] = { | |||
967 | static int ab8500_btemp_probe(struct platform_device *pdev) | 1012 | static int ab8500_btemp_probe(struct platform_device *pdev) |
968 | { | 1013 | { |
969 | struct device_node *np = pdev->dev.of_node; | 1014 | struct device_node *np = pdev->dev.of_node; |
1015 | struct abx500_bm_data *plat = pdev->dev.platform_data; | ||
970 | struct ab8500_btemp *di; | 1016 | struct ab8500_btemp *di; |
971 | int irq, i, ret = 0; | 1017 | int irq, i, ret = 0; |
972 | u8 val; | 1018 | u8 val; |
@@ -976,21 +1022,19 @@ static int ab8500_btemp_probe(struct platform_device *pdev) | |||
976 | dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); | 1022 | dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); |
977 | return -ENOMEM; | 1023 | return -ENOMEM; |
978 | } | 1024 | } |
979 | di->bat = pdev->mfd_cell->platform_data; | 1025 | |
980 | if (!di->bat) { | 1026 | if (!plat) { |
981 | if (np) { | 1027 | dev_err(&pdev->dev, "no battery management data supplied\n"); |
982 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | 1028 | return -EINVAL; |
983 | if (ret) { | 1029 | } |
984 | dev_err(&pdev->dev, | 1030 | di->bm = plat; |
985 | "failed to get battery information\n"); | 1031 | |
986 | return ret; | 1032 | if (np) { |
987 | } | 1033 | ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); |
988 | } else { | 1034 | if (ret) { |
989 | dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n"); | 1035 | dev_err(&pdev->dev, "failed to get battery information\n"); |
990 | return -EINVAL; | 1036 | return ret; |
991 | } | 1037 | } |
992 | } else { | ||
993 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
994 | } | 1038 | } |
995 | 1039 | ||
996 | /* get parent data */ | 1040 | /* get parent data */ |
@@ -998,6 +1042,8 @@ static int ab8500_btemp_probe(struct platform_device *pdev) | |||
998 | di->parent = dev_get_drvdata(pdev->dev.parent); | 1042 | di->parent = dev_get_drvdata(pdev->dev.parent); |
999 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 1043 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
1000 | 1044 | ||
1045 | di->initialized = false; | ||
1046 | |||
1001 | /* BTEMP supply */ | 1047 | /* BTEMP supply */ |
1002 | di->btemp_psy.name = "ab8500_btemp"; | 1048 | di->btemp_psy.name = "ab8500_btemp"; |
1003 | di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; | 1049 | di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; |
@@ -1022,10 +1068,6 @@ static int ab8500_btemp_probe(struct platform_device *pdev) | |||
1022 | INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, | 1068 | INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, |
1023 | ab8500_btemp_periodic_work); | 1069 | ab8500_btemp_periodic_work); |
1024 | 1070 | ||
1025 | /* Identify the battery */ | ||
1026 | if (ab8500_btemp_id(di) < 0) | ||
1027 | dev_warn(di->dev, "failed to identify the battery\n"); | ||
1028 | |||
1029 | /* Set BTEMP thermal limits. Low and Med are fixed */ | 1071 | /* Set BTEMP thermal limits. Low and Med are fixed */ |
1030 | di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; | 1072 | di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; |
1031 | di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; | 1073 | di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; |
@@ -1123,7 +1165,7 @@ static void __exit ab8500_btemp_exit(void) | |||
1123 | platform_driver_unregister(&ab8500_btemp_driver); | 1165 | platform_driver_unregister(&ab8500_btemp_driver); |
1124 | } | 1166 | } |
1125 | 1167 | ||
1126 | subsys_initcall_sync(ab8500_btemp_init); | 1168 | device_initcall(ab8500_btemp_init); |
1127 | module_exit(ab8500_btemp_exit); | 1169 | module_exit(ab8500_btemp_exit); |
1128 | 1170 | ||
1129 | MODULE_LICENSE("GPL v2"); | 1171 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 3be9c0ee3fc5..24b30b7ea5ca 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/mfd/abx500/ab8500-gpadc.h> | 31 | #include <linux/mfd/abx500/ab8500-gpadc.h> |
32 | #include <linux/mfd/abx500/ux500_chargalg.h> | 32 | #include <linux/mfd/abx500/ux500_chargalg.h> |
33 | #include <linux/usb/otg.h> | 33 | #include <linux/usb/otg.h> |
34 | #include <linux/mutex.h> | ||
34 | 35 | ||
35 | /* Charger constants */ | 36 | /* Charger constants */ |
36 | #define NO_PW_CONN 0 | 37 | #define NO_PW_CONN 0 |
@@ -54,6 +55,7 @@ | |||
54 | 55 | ||
55 | #define MAIN_CH_INPUT_CURR_SHIFT 4 | 56 | #define MAIN_CH_INPUT_CURR_SHIFT 4 |
56 | #define VBUS_IN_CURR_LIM_SHIFT 4 | 57 | #define VBUS_IN_CURR_LIM_SHIFT 4 |
58 | #define AUTO_VBUS_IN_CURR_LIM_SHIFT 4 | ||
57 | 59 | ||
58 | #define LED_INDICATOR_PWM_ENA 0x01 | 60 | #define LED_INDICATOR_PWM_ENA 0x01 |
59 | #define LED_INDICATOR_PWM_DIS 0x00 | 61 | #define LED_INDICATOR_PWM_DIS 0x00 |
@@ -68,6 +70,11 @@ | |||
68 | #define MAIN_CH_NOK 0x01 | 70 | #define MAIN_CH_NOK 0x01 |
69 | #define VBUS_DET 0x80 | 71 | #define VBUS_DET 0x80 |
70 | 72 | ||
73 | #define MAIN_CH_STATUS2_MAINCHGDROP 0x80 | ||
74 | #define MAIN_CH_STATUS2_MAINCHARGERDETDBNC 0x40 | ||
75 | #define USB_CH_VBUSDROP 0x40 | ||
76 | #define USB_CH_VBUSDETDBNC 0x01 | ||
77 | |||
71 | /* UsbLineStatus register bit masks */ | 78 | /* UsbLineStatus register bit masks */ |
72 | #define AB8500_USB_LINK_STATUS 0x78 | 79 | #define AB8500_USB_LINK_STATUS 0x78 |
73 | #define AB8500_STD_HOST_SUSP 0x18 | 80 | #define AB8500_STD_HOST_SUSP 0x18 |
@@ -79,6 +86,17 @@ | |||
79 | /* Lowest charger voltage is 3.39V -> 0x4E */ | 86 | /* Lowest charger voltage is 3.39V -> 0x4E */ |
80 | #define LOW_VOLT_REG 0x4E | 87 | #define LOW_VOLT_REG 0x4E |
81 | 88 | ||
89 | /* Step up/down delay in us */ | ||
90 | #define STEP_UDELAY 1000 | ||
91 | |||
92 | #define CHARGER_STATUS_POLL 10 /* in ms */ | ||
93 | |||
94 | #define CHG_WD_INTERVAL (60 * HZ) | ||
95 | |||
96 | #define AB8500_SW_CONTROL_FALLBACK 0x03 | ||
97 | /* Wait for enumeration before charing in us */ | ||
98 | #define WAIT_ACA_RID_ENUMERATION (5 * 1000) | ||
99 | |||
82 | /* UsbLineStatus register - usb types */ | 100 | /* UsbLineStatus register - usb types */ |
83 | enum ab8500_charger_link_status { | 101 | enum ab8500_charger_link_status { |
84 | USB_STAT_NOT_CONFIGURED, | 102 | USB_STAT_NOT_CONFIGURED, |
@@ -97,6 +115,13 @@ enum ab8500_charger_link_status { | |||
97 | USB_STAT_HM_IDGND, | 115 | USB_STAT_HM_IDGND, |
98 | USB_STAT_RESERVED, | 116 | USB_STAT_RESERVED, |
99 | USB_STAT_NOT_VALID_LINK, | 117 | USB_STAT_NOT_VALID_LINK, |
118 | USB_STAT_PHY_EN, | ||
119 | USB_STAT_SUP_NO_IDGND_VBUS, | ||
120 | USB_STAT_SUP_IDGND_VBUS, | ||
121 | USB_STAT_CHARGER_LINE_1, | ||
122 | USB_STAT_CARKIT_1, | ||
123 | USB_STAT_CARKIT_2, | ||
124 | USB_STAT_ACA_DOCK_CHARGER, | ||
100 | }; | 125 | }; |
101 | 126 | ||
102 | enum ab8500_usb_state { | 127 | enum ab8500_usb_state { |
@@ -149,6 +174,7 @@ struct ab8500_charger_info { | |||
149 | int charger_voltage; | 174 | int charger_voltage; |
150 | int cv_active; | 175 | int cv_active; |
151 | bool wd_expired; | 176 | bool wd_expired; |
177 | int charger_current; | ||
152 | }; | 178 | }; |
153 | 179 | ||
154 | struct ab8500_charger_event_flags { | 180 | struct ab8500_charger_event_flags { |
@@ -159,12 +185,14 @@ struct ab8500_charger_event_flags { | |||
159 | bool usbchargernotok; | 185 | bool usbchargernotok; |
160 | bool chgwdexp; | 186 | bool chgwdexp; |
161 | bool vbus_collapse; | 187 | bool vbus_collapse; |
188 | bool vbus_drop_end; | ||
162 | }; | 189 | }; |
163 | 190 | ||
164 | struct ab8500_charger_usb_state { | 191 | struct ab8500_charger_usb_state { |
165 | bool usb_changed; | ||
166 | int usb_current; | 192 | int usb_current; |
193 | int usb_current_tmp; | ||
167 | enum ab8500_usb_state state; | 194 | enum ab8500_usb_state state; |
195 | enum ab8500_usb_state state_tmp; | ||
168 | spinlock_t usb_lock; | 196 | spinlock_t usb_lock; |
169 | }; | 197 | }; |
170 | 198 | ||
@@ -182,11 +210,17 @@ struct ab8500_charger_usb_state { | |||
182 | * charger is enabled | 210 | * charger is enabled |
183 | * @vbat Battery voltage | 211 | * @vbat Battery voltage |
184 | * @old_vbat Previously measured battery voltage | 212 | * @old_vbat Previously measured battery voltage |
213 | * @usb_device_is_unrecognised USB device is unrecognised by the hardware | ||
185 | * @autopower Indicate if we should have automatic pwron after pwrloss | 214 | * @autopower Indicate if we should have automatic pwron after pwrloss |
186 | * @autopower_cfg platform specific power config support for "pwron after pwrloss" | 215 | * @autopower_cfg platform specific power config support for "pwron after pwrloss" |
216 | * @invalid_charger_detect_state State when forcing AB to use invalid charger | ||
217 | * @is_usb_host: Indicate if last detected USB type is host | ||
218 | * @is_aca_rid: Incicate if accessory is ACA type | ||
219 | * @current_stepping_sessions: | ||
220 | * Counter for current stepping sessions | ||
187 | * @parent: Pointer to the struct ab8500 | 221 | * @parent: Pointer to the struct ab8500 |
188 | * @gpadc: Pointer to the struct gpadc | 222 | * @gpadc: Pointer to the struct gpadc |
189 | * @bat: Pointer to the abx500_bm platform data | 223 | * @bm: Platform specific battery management information |
190 | * @flags: Structure for information about events triggered | 224 | * @flags: Structure for information about events triggered |
191 | * @usb_state: Structure for usb stack information | 225 | * @usb_state: Structure for usb stack information |
192 | * @ac_chg: AC charger power supply | 226 | * @ac_chg: AC charger power supply |
@@ -195,19 +229,28 @@ struct ab8500_charger_usb_state { | |||
195 | * @usb: Structure that holds the USB charger properties | 229 | * @usb: Structure that holds the USB charger properties |
196 | * @regu: Pointer to the struct regulator | 230 | * @regu: Pointer to the struct regulator |
197 | * @charger_wq: Work queue for the IRQs and checking HW state | 231 | * @charger_wq: Work queue for the IRQs and checking HW state |
232 | * @usb_ipt_crnt_lock: Lock to protect VBUS input current setting from mutuals | ||
233 | * @pm_lock: Lock to prevent system to suspend | ||
198 | * @check_vbat_work Work for checking vbat threshold to adjust vbus current | 234 | * @check_vbat_work Work for checking vbat threshold to adjust vbus current |
199 | * @check_hw_failure_work: Work for checking HW state | 235 | * @check_hw_failure_work: Work for checking HW state |
200 | * @check_usbchgnotok_work: Work for checking USB charger not ok status | 236 | * @check_usbchgnotok_work: Work for checking USB charger not ok status |
201 | * @kick_wd_work: Work for kicking the charger watchdog in case | 237 | * @kick_wd_work: Work for kicking the charger watchdog in case |
202 | * of ABB rev 1.* due to the watchog logic bug | 238 | * of ABB rev 1.* due to the watchog logic bug |
239 | * @ac_charger_attached_work: Work for checking if AC charger is still | ||
240 | * connected | ||
241 | * @usb_charger_attached_work: Work for checking if USB charger is still | ||
242 | * connected | ||
203 | * @ac_work: Work for checking AC charger connection | 243 | * @ac_work: Work for checking AC charger connection |
204 | * @detect_usb_type_work: Work for detecting the USB type connected | 244 | * @detect_usb_type_work: Work for detecting the USB type connected |
205 | * @usb_link_status_work: Work for checking the new USB link status | 245 | * @usb_link_status_work: Work for checking the new USB link status |
206 | * @usb_state_changed_work: Work for checking USB state | 246 | * @usb_state_changed_work: Work for checking USB state |
247 | * @attach_work: Work for detecting USB type | ||
248 | * @vbus_drop_end_work: Work for detecting VBUS drop end | ||
207 | * @check_main_thermal_prot_work: | 249 | * @check_main_thermal_prot_work: |
208 | * Work for checking Main thermal status | 250 | * Work for checking Main thermal status |
209 | * @check_usb_thermal_prot_work: | 251 | * @check_usb_thermal_prot_work: |
210 | * Work for checking USB thermal status | 252 | * Work for checking USB thermal status |
253 | * @charger_attached_mutex: For controlling the wakelock | ||
211 | */ | 254 | */ |
212 | struct ab8500_charger { | 255 | struct ab8500_charger { |
213 | struct device *dev; | 256 | struct device *dev; |
@@ -219,11 +262,16 @@ struct ab8500_charger { | |||
219 | bool vddadc_en_usb; | 262 | bool vddadc_en_usb; |
220 | int vbat; | 263 | int vbat; |
221 | int old_vbat; | 264 | int old_vbat; |
265 | bool usb_device_is_unrecognised; | ||
222 | bool autopower; | 266 | bool autopower; |
223 | bool autopower_cfg; | 267 | bool autopower_cfg; |
268 | int invalid_charger_detect_state; | ||
269 | bool is_usb_host; | ||
270 | int is_aca_rid; | ||
271 | atomic_t current_stepping_sessions; | ||
224 | struct ab8500 *parent; | 272 | struct ab8500 *parent; |
225 | struct ab8500_gpadc *gpadc; | 273 | struct ab8500_gpadc *gpadc; |
226 | struct abx500_bm_data *bat; | 274 | struct abx500_bm_data *bm; |
227 | struct ab8500_charger_event_flags flags; | 275 | struct ab8500_charger_event_flags flags; |
228 | struct ab8500_charger_usb_state usb_state; | 276 | struct ab8500_charger_usb_state usb_state; |
229 | struct ux500_charger ac_chg; | 277 | struct ux500_charger ac_chg; |
@@ -232,18 +280,24 @@ struct ab8500_charger { | |||
232 | struct ab8500_charger_info usb; | 280 | struct ab8500_charger_info usb; |
233 | struct regulator *regu; | 281 | struct regulator *regu; |
234 | struct workqueue_struct *charger_wq; | 282 | struct workqueue_struct *charger_wq; |
283 | struct mutex usb_ipt_crnt_lock; | ||
235 | struct delayed_work check_vbat_work; | 284 | struct delayed_work check_vbat_work; |
236 | struct delayed_work check_hw_failure_work; | 285 | struct delayed_work check_hw_failure_work; |
237 | struct delayed_work check_usbchgnotok_work; | 286 | struct delayed_work check_usbchgnotok_work; |
238 | struct delayed_work kick_wd_work; | 287 | struct delayed_work kick_wd_work; |
288 | struct delayed_work usb_state_changed_work; | ||
289 | struct delayed_work attach_work; | ||
290 | struct delayed_work ac_charger_attached_work; | ||
291 | struct delayed_work usb_charger_attached_work; | ||
292 | struct delayed_work vbus_drop_end_work; | ||
239 | struct work_struct ac_work; | 293 | struct work_struct ac_work; |
240 | struct work_struct detect_usb_type_work; | 294 | struct work_struct detect_usb_type_work; |
241 | struct work_struct usb_link_status_work; | 295 | struct work_struct usb_link_status_work; |
242 | struct work_struct usb_state_changed_work; | ||
243 | struct work_struct check_main_thermal_prot_work; | 296 | struct work_struct check_main_thermal_prot_work; |
244 | struct work_struct check_usb_thermal_prot_work; | 297 | struct work_struct check_usb_thermal_prot_work; |
245 | struct usb_phy *usb_phy; | 298 | struct usb_phy *usb_phy; |
246 | struct notifier_block nb; | 299 | struct notifier_block nb; |
300 | struct mutex charger_attached_mutex; | ||
247 | }; | 301 | }; |
248 | 302 | ||
249 | /* AC properties */ | 303 | /* AC properties */ |
@@ -267,50 +321,65 @@ static enum power_supply_property ab8500_charger_usb_props[] = { | |||
267 | POWER_SUPPLY_PROP_CURRENT_NOW, | 321 | POWER_SUPPLY_PROP_CURRENT_NOW, |
268 | }; | 322 | }; |
269 | 323 | ||
270 | /** | 324 | /* |
271 | * ab8500_power_loss_handling - set how we handle powerloss. | 325 | * Function for enabling and disabling sw fallback mode |
272 | * @di: pointer to the ab8500_charger structure | 326 | * should always be disabled when no charger is connected. |
273 | * | ||
274 | * Magic nummbers are from STE HW department. | ||
275 | */ | 327 | */ |
276 | static void ab8500_power_loss_handling(struct ab8500_charger *di) | 328 | static void ab8500_enable_disable_sw_fallback(struct ab8500_charger *di, |
329 | bool fallback) | ||
277 | { | 330 | { |
331 | u8 val; | ||
278 | u8 reg; | 332 | u8 reg; |
333 | u8 bank; | ||
334 | u8 bit; | ||
279 | int ret; | 335 | int ret; |
280 | 336 | ||
281 | dev_dbg(di->dev, "Autopower : %d\n", di->autopower); | 337 | dev_dbg(di->dev, "SW Fallback: %d\n", fallback); |
282 | 338 | ||
283 | /* read the autopower register */ | 339 | if (is_ab8500(di->parent)) { |
284 | ret = abx500_get_register_interruptible(di->dev, 0x15, 0x00, ®); | 340 | bank = 0x15; |
285 | if (ret) { | 341 | reg = 0x0; |
286 | dev_err(di->dev, "%d write failed\n", __LINE__); | 342 | bit = 3; |
287 | return; | 343 | } else { |
344 | bank = AB8500_SYS_CTRL1_BLOCK; | ||
345 | reg = AB8500_SW_CONTROL_FALLBACK; | ||
346 | bit = 0; | ||
288 | } | 347 | } |
289 | 348 | ||
290 | /* enable the OPT emulation registers */ | 349 | /* read the register containing fallback bit */ |
291 | ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2); | 350 | ret = abx500_get_register_interruptible(di->dev, bank, reg, &val); |
292 | if (ret) { | 351 | if (ret < 0) { |
293 | dev_err(di->dev, "%d write failed\n", __LINE__); | 352 | dev_err(di->dev, "%d read failed\n", __LINE__); |
294 | return; | 353 | return; |
295 | } | 354 | } |
296 | 355 | ||
297 | if (di->autopower) | 356 | if (is_ab8500(di->parent)) { |
298 | reg |= 0x8; | 357 | /* enable the OPT emulation registers */ |
358 | ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x2); | ||
359 | if (ret) { | ||
360 | dev_err(di->dev, "%d write failed\n", __LINE__); | ||
361 | goto disable_otp; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | if (fallback) | ||
366 | val |= (1 << bit); | ||
299 | else | 367 | else |
300 | reg &= ~0x8; | 368 | val &= ~(1 << bit); |
301 | 369 | ||
302 | /* write back the changed value to autopower reg */ | 370 | /* write back the changed fallback bit value to register */ |
303 | ret = abx500_set_register_interruptible(di->dev, 0x15, 0x00, reg); | 371 | ret = abx500_set_register_interruptible(di->dev, bank, reg, val); |
304 | if (ret) { | 372 | if (ret) { |
305 | dev_err(di->dev, "%d write failed\n", __LINE__); | 373 | dev_err(di->dev, "%d write failed\n", __LINE__); |
306 | return; | ||
307 | } | 374 | } |
308 | 375 | ||
309 | /* disable the set OTP registers again */ | 376 | disable_otp: |
310 | ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0); | 377 | if (is_ab8500(di->parent)) { |
311 | if (ret) { | 378 | /* disable the set OTP registers again */ |
312 | dev_err(di->dev, "%d write failed\n", __LINE__); | 379 | ret = abx500_set_register_interruptible(di->dev, 0x11, 0x00, 0x0); |
313 | return; | 380 | if (ret) { |
381 | dev_err(di->dev, "%d write failed\n", __LINE__); | ||
382 | } | ||
314 | } | 383 | } |
315 | } | 384 | } |
316 | 385 | ||
@@ -329,12 +398,12 @@ static void ab8500_power_supply_changed(struct ab8500_charger *di, | |||
329 | !di->ac.charger_connected && | 398 | !di->ac.charger_connected && |
330 | di->autopower) { | 399 | di->autopower) { |
331 | di->autopower = false; | 400 | di->autopower = false; |
332 | ab8500_power_loss_handling(di); | 401 | ab8500_enable_disable_sw_fallback(di, false); |
333 | } else if (!di->autopower && | 402 | } else if (!di->autopower && |
334 | (di->ac.charger_connected || | 403 | (di->ac.charger_connected || |
335 | di->usb.charger_connected)) { | 404 | di->usb.charger_connected)) { |
336 | di->autopower = true; | 405 | di->autopower = true; |
337 | ab8500_power_loss_handling(di); | 406 | ab8500_enable_disable_sw_fallback(di, true); |
338 | } | 407 | } |
339 | } | 408 | } |
340 | power_supply_changed(psy); | 409 | power_supply_changed(psy); |
@@ -347,6 +416,19 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di, | |||
347 | dev_dbg(di->dev, "USB connected:%i\n", connected); | 416 | dev_dbg(di->dev, "USB connected:%i\n", connected); |
348 | di->usb.charger_connected = connected; | 417 | di->usb.charger_connected = connected; |
349 | sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); | 418 | sysfs_notify(&di->usb_chg.psy.dev->kobj, NULL, "present"); |
419 | |||
420 | if (connected) { | ||
421 | mutex_lock(&di->charger_attached_mutex); | ||
422 | mutex_unlock(&di->charger_attached_mutex); | ||
423 | |||
424 | queue_delayed_work(di->charger_wq, | ||
425 | &di->usb_charger_attached_work, | ||
426 | HZ); | ||
427 | } else { | ||
428 | cancel_delayed_work_sync(&di->usb_charger_attached_work); | ||
429 | mutex_lock(&di->charger_attached_mutex); | ||
430 | mutex_unlock(&di->charger_attached_mutex); | ||
431 | } | ||
350 | } | 432 | } |
351 | } | 433 | } |
352 | 434 | ||
@@ -500,6 +582,7 @@ static int ab8500_charger_usb_cv(struct ab8500_charger *di) | |||
500 | /** | 582 | /** |
501 | * ab8500_charger_detect_chargers() - Detect the connected chargers | 583 | * ab8500_charger_detect_chargers() - Detect the connected chargers |
502 | * @di: pointer to the ab8500_charger structure | 584 | * @di: pointer to the ab8500_charger structure |
585 | * @probe: if probe, don't delay and wait for HW | ||
503 | * | 586 | * |
504 | * Returns the type of charger connected. | 587 | * Returns the type of charger connected. |
505 | * For USB it will not mean we can actually charge from it | 588 | * For USB it will not mean we can actually charge from it |
@@ -513,7 +596,7 @@ static int ab8500_charger_usb_cv(struct ab8500_charger *di) | |||
513 | * USB_PW_CONN if the USB power supply is connected | 596 | * USB_PW_CONN if the USB power supply is connected |
514 | * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected | 597 | * AC_PW_CONN + USB_PW_CONN if USB and AC power supplies are both connected |
515 | */ | 598 | */ |
516 | static int ab8500_charger_detect_chargers(struct ab8500_charger *di) | 599 | static int ab8500_charger_detect_chargers(struct ab8500_charger *di, bool probe) |
517 | { | 600 | { |
518 | int result = NO_PW_CONN; | 601 | int result = NO_PW_CONN; |
519 | int ret; | 602 | int ret; |
@@ -531,13 +614,25 @@ static int ab8500_charger_detect_chargers(struct ab8500_charger *di) | |||
531 | result = AC_PW_CONN; | 614 | result = AC_PW_CONN; |
532 | 615 | ||
533 | /* Check for USB charger */ | 616 | /* Check for USB charger */ |
617 | |||
618 | if (!probe) { | ||
619 | /* | ||
620 | * AB8500 says VBUS_DET_DBNC1 & VBUS_DET_DBNC100 | ||
621 | * when disconnecting ACA even though no | ||
622 | * charger was connected. Try waiting a little | ||
623 | * longer than the 100 ms of VBUS_DET_DBNC100... | ||
624 | */ | ||
625 | msleep(110); | ||
626 | } | ||
534 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | 627 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, |
535 | AB8500_CH_USBCH_STAT1_REG, &val); | 628 | AB8500_CH_USBCH_STAT1_REG, &val); |
536 | if (ret < 0) { | 629 | if (ret < 0) { |
537 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 630 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
538 | return ret; | 631 | return ret; |
539 | } | 632 | } |
540 | 633 | dev_dbg(di->dev, | |
634 | "%s AB8500_CH_USBCH_STAT1_REG %x\n", __func__, | ||
635 | val); | ||
541 | if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100)) | 636 | if ((val & VBUS_DET_DBNC1) && (val & VBUS_DET_DBNC100)) |
542 | result |= USB_PW_CONN; | 637 | result |= USB_PW_CONN; |
543 | 638 | ||
@@ -554,31 +649,53 @@ static int ab8500_charger_detect_chargers(struct ab8500_charger *di) | |||
554 | * Returns error code in case of failure else 0 on success | 649 | * Returns error code in case of failure else 0 on success |
555 | */ | 650 | */ |
556 | static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | 651 | static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, |
557 | enum ab8500_charger_link_status link_status) | 652 | enum ab8500_charger_link_status link_status) |
558 | { | 653 | { |
559 | int ret = 0; | 654 | int ret = 0; |
560 | 655 | ||
656 | di->usb_device_is_unrecognised = false; | ||
657 | |||
658 | /* | ||
659 | * Platform only supports USB 2.0. | ||
660 | * This means that charging current from USB source | ||
661 | * is maximum 500 mA. Every occurence of USB_STAT_*_HOST_* | ||
662 | * should set USB_CH_IP_CUR_LVL_0P5. | ||
663 | */ | ||
664 | |||
561 | switch (link_status) { | 665 | switch (link_status) { |
562 | case USB_STAT_STD_HOST_NC: | 666 | case USB_STAT_STD_HOST_NC: |
563 | case USB_STAT_STD_HOST_C_NS: | 667 | case USB_STAT_STD_HOST_C_NS: |
564 | case USB_STAT_STD_HOST_C_S: | 668 | case USB_STAT_STD_HOST_C_S: |
565 | dev_dbg(di->dev, "USB Type - Standard host is " | 669 | dev_dbg(di->dev, "USB Type - Standard host is " |
566 | "detected through USB driver\n"); | 670 | "detected through USB driver\n"); |
567 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P09; | 671 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; |
672 | di->is_usb_host = true; | ||
673 | di->is_aca_rid = 0; | ||
568 | break; | 674 | break; |
569 | case USB_STAT_HOST_CHG_HS_CHIRP: | 675 | case USB_STAT_HOST_CHG_HS_CHIRP: |
570 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | 676 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; |
677 | di->is_usb_host = true; | ||
678 | di->is_aca_rid = 0; | ||
571 | break; | 679 | break; |
572 | case USB_STAT_HOST_CHG_HS: | 680 | case USB_STAT_HOST_CHG_HS: |
681 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
682 | di->is_usb_host = true; | ||
683 | di->is_aca_rid = 0; | ||
684 | break; | ||
573 | case USB_STAT_ACA_RID_C_HS: | 685 | case USB_STAT_ACA_RID_C_HS: |
574 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; | 686 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P9; |
687 | di->is_usb_host = false; | ||
688 | di->is_aca_rid = 0; | ||
575 | break; | 689 | break; |
576 | case USB_STAT_ACA_RID_A: | 690 | case USB_STAT_ACA_RID_A: |
577 | /* | 691 | /* |
578 | * Dedicated charger level minus maximum current accessory | 692 | * Dedicated charger level minus maximum current accessory |
579 | * can consume (300mA). Closest level is 1100mA | 693 | * can consume (900mA). Closest level is 500mA |
580 | */ | 694 | */ |
581 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P1; | 695 | dev_dbg(di->dev, "USB_STAT_ACA_RID_A detected\n"); |
696 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
697 | di->is_usb_host = false; | ||
698 | di->is_aca_rid = 1; | ||
582 | break; | 699 | break; |
583 | case USB_STAT_ACA_RID_B: | 700 | case USB_STAT_ACA_RID_B: |
584 | /* | 701 | /* |
@@ -586,34 +703,68 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
586 | * 100mA for potential accessory). Closest level is 1300mA | 703 | * 100mA for potential accessory). Closest level is 1300mA |
587 | */ | 704 | */ |
588 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; | 705 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P3; |
706 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
707 | di->max_usb_in_curr); | ||
708 | di->is_usb_host = false; | ||
709 | di->is_aca_rid = 1; | ||
589 | break; | 710 | break; |
590 | case USB_STAT_DEDICATED_CHG: | ||
591 | case USB_STAT_HOST_CHG_NM: | 711 | case USB_STAT_HOST_CHG_NM: |
712 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
713 | di->is_usb_host = true; | ||
714 | di->is_aca_rid = 0; | ||
715 | break; | ||
716 | case USB_STAT_DEDICATED_CHG: | ||
717 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | ||
718 | di->is_usb_host = false; | ||
719 | di->is_aca_rid = 0; | ||
720 | break; | ||
592 | case USB_STAT_ACA_RID_C_HS_CHIRP: | 721 | case USB_STAT_ACA_RID_C_HS_CHIRP: |
593 | case USB_STAT_ACA_RID_C_NM: | 722 | case USB_STAT_ACA_RID_C_NM: |
594 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | 723 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; |
724 | di->is_usb_host = false; | ||
725 | di->is_aca_rid = 1; | ||
595 | break; | 726 | break; |
596 | case USB_STAT_RESERVED: | ||
597 | /* | ||
598 | * This state is used to indicate that VBUS has dropped below | ||
599 | * the detection level 4 times in a row. This is due to the | ||
600 | * charger output current is set to high making the charger | ||
601 | * voltage collapse. This have to be propagated through to | ||
602 | * chargalg. This is done using the property | ||
603 | * POWER_SUPPLY_PROP_CURRENT_AVG = 1 | ||
604 | */ | ||
605 | di->flags.vbus_collapse = true; | ||
606 | dev_dbg(di->dev, "USB Type - USB_STAT_RESERVED " | ||
607 | "VBUS has collapsed\n"); | ||
608 | ret = -1; | ||
609 | break; | ||
610 | case USB_STAT_HM_IDGND: | ||
611 | case USB_STAT_NOT_CONFIGURED: | 727 | case USB_STAT_NOT_CONFIGURED: |
612 | case USB_STAT_NOT_VALID_LINK: | 728 | if (di->vbus_detected) { |
729 | di->usb_device_is_unrecognised = true; | ||
730 | dev_dbg(di->dev, "USB Type - Legacy charger.\n"); | ||
731 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_1P5; | ||
732 | break; | ||
733 | } | ||
734 | case USB_STAT_HM_IDGND: | ||
613 | dev_err(di->dev, "USB Type - Charging not allowed\n"); | 735 | dev_err(di->dev, "USB Type - Charging not allowed\n"); |
614 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 736 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; |
615 | ret = -ENXIO; | 737 | ret = -ENXIO; |
616 | break; | 738 | break; |
739 | case USB_STAT_RESERVED: | ||
740 | if (is_ab8500(di->parent)) { | ||
741 | di->flags.vbus_collapse = true; | ||
742 | dev_err(di->dev, "USB Type - USB_STAT_RESERVED " | ||
743 | "VBUS has collapsed\n"); | ||
744 | ret = -ENXIO; | ||
745 | break; | ||
746 | } | ||
747 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) { | ||
748 | dev_dbg(di->dev, "USB Type - Charging not allowed\n"); | ||
749 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | ||
750 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", | ||
751 | link_status, di->max_usb_in_curr); | ||
752 | ret = -ENXIO; | ||
753 | break; | ||
754 | } | ||
755 | break; | ||
756 | case USB_STAT_CARKIT_1: | ||
757 | case USB_STAT_CARKIT_2: | ||
758 | case USB_STAT_ACA_DOCK_CHARGER: | ||
759 | case USB_STAT_CHARGER_LINE_1: | ||
760 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
761 | dev_dbg(di->dev, "USB Type - 0x%02x MaxCurr: %d", link_status, | ||
762 | di->max_usb_in_curr); | ||
763 | case USB_STAT_NOT_VALID_LINK: | ||
764 | dev_err(di->dev, "USB Type invalid - try charging anyway\n"); | ||
765 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P5; | ||
766 | break; | ||
767 | |||
617 | default: | 768 | default: |
618 | dev_err(di->dev, "USB Type - Unknown\n"); | 769 | dev_err(di->dev, "USB Type - Unknown\n"); |
619 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; | 770 | di->max_usb_in_curr = USB_CH_IP_CUR_LVL_0P05; |
@@ -645,8 +796,14 @@ static int ab8500_charger_read_usb_type(struct ab8500_charger *di) | |||
645 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 796 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
646 | return ret; | 797 | return ret; |
647 | } | 798 | } |
648 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 799 | if (is_ab8500(di->parent)) { |
649 | AB8500_USB_LINE_STAT_REG, &val); | 800 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, |
801 | AB8500_USB_LINE_STAT_REG, &val); | ||
802 | } else { | ||
803 | if (is_ab9540(di->parent) || is_ab8505(di->parent)) | ||
804 | ret = abx500_get_register_interruptible(di->dev, | ||
805 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); | ||
806 | } | ||
650 | if (ret < 0) { | 807 | if (ret < 0) { |
651 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 808 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
652 | return ret; | 809 | return ret; |
@@ -682,16 +839,25 @@ static int ab8500_charger_detect_usb_type(struct ab8500_charger *di) | |||
682 | ret = abx500_get_register_interruptible(di->dev, | 839 | ret = abx500_get_register_interruptible(di->dev, |
683 | AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, | 840 | AB8500_INTERRUPT, AB8500_IT_SOURCE21_REG, |
684 | &val); | 841 | &val); |
842 | dev_dbg(di->dev, "%s AB8500_IT_SOURCE21_REG %x\n", | ||
843 | __func__, val); | ||
685 | if (ret < 0) { | 844 | if (ret < 0) { |
686 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 845 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
687 | return ret; | 846 | return ret; |
688 | } | 847 | } |
689 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | 848 | |
690 | AB8500_USB_LINE_STAT_REG, &val); | 849 | if (is_ab8500(di->parent)) |
850 | ret = abx500_get_register_interruptible(di->dev, | ||
851 | AB8500_USB, AB8500_USB_LINE_STAT_REG, &val); | ||
852 | else | ||
853 | ret = abx500_get_register_interruptible(di->dev, | ||
854 | AB8500_USB, AB8500_USB_LINK1_STAT_REG, &val); | ||
691 | if (ret < 0) { | 855 | if (ret < 0) { |
692 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 856 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
693 | return ret; | 857 | return ret; |
694 | } | 858 | } |
859 | dev_dbg(di->dev, "%s AB8500_USB_LINE_STAT_REG %x\n", __func__, | ||
860 | val); | ||
695 | /* | 861 | /* |
696 | * Until the IT source register is read the UsbLineStatus | 862 | * Until the IT source register is read the UsbLineStatus |
697 | * register is not updated, hence doing the same | 863 | * register is not updated, hence doing the same |
@@ -936,6 +1102,144 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) | |||
936 | } | 1102 | } |
937 | 1103 | ||
938 | /** | 1104 | /** |
1105 | * ab8500_charger_set_current() - set charger current | ||
1106 | * @di: pointer to the ab8500_charger structure | ||
1107 | * @ich: charger current, in mA | ||
1108 | * @reg: select what charger register to set | ||
1109 | * | ||
1110 | * Set charger current. | ||
1111 | * There is no state machine in the AB to step up/down the charger | ||
1112 | * current to avoid dips and spikes on MAIN, VBUS and VBAT when | ||
1113 | * charging is started. Instead we need to implement | ||
1114 | * this charger current step-up/down here. | ||
1115 | * Returns error code in case of failure else 0(on success) | ||
1116 | */ | ||
1117 | static int ab8500_charger_set_current(struct ab8500_charger *di, | ||
1118 | int ich, int reg) | ||
1119 | { | ||
1120 | int ret = 0; | ||
1121 | int auto_curr_index, curr_index, prev_curr_index, shift_value, i; | ||
1122 | u8 reg_value; | ||
1123 | u32 step_udelay; | ||
1124 | bool no_stepping = false; | ||
1125 | |||
1126 | atomic_inc(&di->current_stepping_sessions); | ||
1127 | |||
1128 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1129 | reg, ®_value); | ||
1130 | if (ret < 0) { | ||
1131 | dev_err(di->dev, "%s read failed\n", __func__); | ||
1132 | goto exit_set_current; | ||
1133 | } | ||
1134 | |||
1135 | switch (reg) { | ||
1136 | case AB8500_MCH_IPT_CURLVL_REG: | ||
1137 | shift_value = MAIN_CH_INPUT_CURR_SHIFT; | ||
1138 | prev_curr_index = (reg_value >> shift_value); | ||
1139 | curr_index = ab8500_current_to_regval(ich); | ||
1140 | step_udelay = STEP_UDELAY; | ||
1141 | if (!di->ac.charger_connected) | ||
1142 | no_stepping = true; | ||
1143 | break; | ||
1144 | case AB8500_USBCH_IPT_CRNTLVL_REG: | ||
1145 | shift_value = VBUS_IN_CURR_LIM_SHIFT; | ||
1146 | prev_curr_index = (reg_value >> shift_value); | ||
1147 | curr_index = ab8500_vbus_in_curr_to_regval(ich); | ||
1148 | step_udelay = STEP_UDELAY * 100; | ||
1149 | |||
1150 | ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER, | ||
1151 | AB8500_CH_USBCH_STAT2_REG, ®_value); | ||
1152 | if (ret < 0) { | ||
1153 | dev_err(di->dev, "%s read failed\n", __func__); | ||
1154 | goto exit_set_current; | ||
1155 | } | ||
1156 | auto_curr_index = | ||
1157 | reg_value >> AUTO_VBUS_IN_CURR_LIM_SHIFT; | ||
1158 | |||
1159 | dev_dbg(di->dev, "%s Auto VBUS curr is %d mA\n", | ||
1160 | __func__, | ||
1161 | ab8500_charger_vbus_in_curr_map[auto_curr_index]); | ||
1162 | |||
1163 | prev_curr_index = min(prev_curr_index, auto_curr_index); | ||
1164 | |||
1165 | if (!di->usb.charger_connected) | ||
1166 | no_stepping = true; | ||
1167 | break; | ||
1168 | case AB8500_CH_OPT_CRNTLVL_REG: | ||
1169 | shift_value = 0; | ||
1170 | prev_curr_index = (reg_value >> shift_value); | ||
1171 | curr_index = ab8500_current_to_regval(ich); | ||
1172 | step_udelay = STEP_UDELAY; | ||
1173 | if (curr_index && (curr_index - prev_curr_index) > 1) | ||
1174 | step_udelay *= 100; | ||
1175 | |||
1176 | if (!di->usb.charger_connected && !di->ac.charger_connected) | ||
1177 | no_stepping = true; | ||
1178 | |||
1179 | break; | ||
1180 | default: | ||
1181 | dev_err(di->dev, "%s current register not valid\n", __func__); | ||
1182 | ret = -ENXIO; | ||
1183 | goto exit_set_current; | ||
1184 | } | ||
1185 | |||
1186 | if (curr_index < 0) { | ||
1187 | dev_err(di->dev, "requested current limit out-of-range\n"); | ||
1188 | ret = -ENXIO; | ||
1189 | goto exit_set_current; | ||
1190 | } | ||
1191 | |||
1192 | /* only update current if it's been changed */ | ||
1193 | if (prev_curr_index == curr_index) { | ||
1194 | dev_dbg(di->dev, "%s current not changed for reg: 0x%02x\n", | ||
1195 | __func__, reg); | ||
1196 | ret = 0; | ||
1197 | goto exit_set_current; | ||
1198 | } | ||
1199 | |||
1200 | dev_dbg(di->dev, "%s set charger current: %d mA for reg: 0x%02x\n", | ||
1201 | __func__, ich, reg); | ||
1202 | |||
1203 | if (no_stepping) { | ||
1204 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1205 | reg, (u8)curr_index << shift_value); | ||
1206 | if (ret) | ||
1207 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1208 | } else if (prev_curr_index > curr_index) { | ||
1209 | for (i = prev_curr_index - 1; i >= curr_index; i--) { | ||
1210 | dev_dbg(di->dev, "curr change_1 to: %x for 0x%02x\n", | ||
1211 | (u8) i << shift_value, reg); | ||
1212 | ret = abx500_set_register_interruptible(di->dev, | ||
1213 | AB8500_CHARGER, reg, (u8)i << shift_value); | ||
1214 | if (ret) { | ||
1215 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1216 | goto exit_set_current; | ||
1217 | } | ||
1218 | if (i != curr_index) | ||
1219 | usleep_range(step_udelay, step_udelay * 2); | ||
1220 | } | ||
1221 | } else { | ||
1222 | for (i = prev_curr_index + 1; i <= curr_index; i++) { | ||
1223 | dev_dbg(di->dev, "curr change_2 to: %x for 0x%02x\n", | ||
1224 | (u8)i << shift_value, reg); | ||
1225 | ret = abx500_set_register_interruptible(di->dev, | ||
1226 | AB8500_CHARGER, reg, (u8)i << shift_value); | ||
1227 | if (ret) { | ||
1228 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1229 | goto exit_set_current; | ||
1230 | } | ||
1231 | if (i != curr_index) | ||
1232 | usleep_range(step_udelay, step_udelay * 2); | ||
1233 | } | ||
1234 | } | ||
1235 | |||
1236 | exit_set_current: | ||
1237 | atomic_dec(&di->current_stepping_sessions); | ||
1238 | |||
1239 | return ret; | ||
1240 | } | ||
1241 | |||
1242 | /** | ||
939 | * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit | 1243 | * ab8500_charger_set_vbus_in_curr() - set VBUS input current limit |
940 | * @di: pointer to the ab8500_charger structure | 1244 | * @di: pointer to the ab8500_charger structure |
941 | * @ich_in: charger input current limit | 1245 | * @ich_in: charger input current limit |
@@ -946,12 +1250,11 @@ static int ab8500_charger_get_usb_cur(struct ab8500_charger *di) | |||
946 | static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, | 1250 | static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, |
947 | int ich_in) | 1251 | int ich_in) |
948 | { | 1252 | { |
949 | int ret; | ||
950 | int input_curr_index; | ||
951 | int min_value; | 1253 | int min_value; |
1254 | int ret; | ||
952 | 1255 | ||
953 | /* We should always use to lowest current limit */ | 1256 | /* We should always use to lowest current limit */ |
954 | min_value = min(di->bat->chg_params->usb_curr_max, ich_in); | 1257 | min_value = min(di->bm->chg_params->usb_curr_max, ich_in); |
955 | 1258 | ||
956 | switch (min_value) { | 1259 | switch (min_value) { |
957 | case 100: | 1260 | case 100: |
@@ -966,22 +1269,47 @@ static int ab8500_charger_set_vbus_in_curr(struct ab8500_charger *di, | |||
966 | break; | 1269 | break; |
967 | } | 1270 | } |
968 | 1271 | ||
969 | input_curr_index = ab8500_vbus_in_curr_to_regval(min_value); | 1272 | dev_info(di->dev, "VBUS input current limit set to %d mA\n", min_value); |
970 | if (input_curr_index < 0) { | ||
971 | dev_err(di->dev, "VBUS input current limit too high\n"); | ||
972 | return -ENXIO; | ||
973 | } | ||
974 | 1273 | ||
975 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | 1274 | mutex_lock(&di->usb_ipt_crnt_lock); |
976 | AB8500_USBCH_IPT_CRNTLVL_REG, | 1275 | ret = ab8500_charger_set_current(di, min_value, |
977 | input_curr_index << VBUS_IN_CURR_LIM_SHIFT); | 1276 | AB8500_USBCH_IPT_CRNTLVL_REG); |
978 | if (ret) | 1277 | mutex_unlock(&di->usb_ipt_crnt_lock); |
979 | dev_err(di->dev, "%s write failed\n", __func__); | ||
980 | 1278 | ||
981 | return ret; | 1279 | return ret; |
982 | } | 1280 | } |
983 | 1281 | ||
984 | /** | 1282 | /** |
1283 | * ab8500_charger_set_main_in_curr() - set main charger input current | ||
1284 | * @di: pointer to the ab8500_charger structure | ||
1285 | * @ich_in: input charger current, in mA | ||
1286 | * | ||
1287 | * Set main charger input current. | ||
1288 | * Returns error code in case of failure else 0(on success) | ||
1289 | */ | ||
1290 | static int ab8500_charger_set_main_in_curr(struct ab8500_charger *di, | ||
1291 | int ich_in) | ||
1292 | { | ||
1293 | return ab8500_charger_set_current(di, ich_in, | ||
1294 | AB8500_MCH_IPT_CURLVL_REG); | ||
1295 | } | ||
1296 | |||
1297 | /** | ||
1298 | * ab8500_charger_set_output_curr() - set charger output current | ||
1299 | * @di: pointer to the ab8500_charger structure | ||
1300 | * @ich_out: output charger current, in mA | ||
1301 | * | ||
1302 | * Set charger output current. | ||
1303 | * Returns error code in case of failure else 0(on success) | ||
1304 | */ | ||
1305 | static int ab8500_charger_set_output_curr(struct ab8500_charger *di, | ||
1306 | int ich_out) | ||
1307 | { | ||
1308 | return ab8500_charger_set_current(di, ich_out, | ||
1309 | AB8500_CH_OPT_CRNTLVL_REG); | ||
1310 | } | ||
1311 | |||
1312 | /** | ||
985 | * ab8500_charger_led_en() - turn on/off chargign led | 1313 | * ab8500_charger_led_en() - turn on/off chargign led |
986 | * @di: pointer to the ab8500_charger structure | 1314 | * @di: pointer to the ab8500_charger structure |
987 | * @on: flag to turn on/off the chargign led | 1315 | * @on: flag to turn on/off the chargign led |
@@ -1074,7 +1402,7 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, | |||
1074 | volt_index = ab8500_voltage_to_regval(vset); | 1402 | volt_index = ab8500_voltage_to_regval(vset); |
1075 | curr_index = ab8500_current_to_regval(iset); | 1403 | curr_index = ab8500_current_to_regval(iset); |
1076 | input_curr_index = ab8500_current_to_regval( | 1404 | input_curr_index = ab8500_current_to_regval( |
1077 | di->bat->chg_params->ac_curr_max); | 1405 | di->bm->chg_params->ac_curr_max); |
1078 | if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { | 1406 | if (volt_index < 0 || curr_index < 0 || input_curr_index < 0) { |
1079 | dev_err(di->dev, | 1407 | dev_err(di->dev, |
1080 | "Charger voltage or current too high, " | 1408 | "Charger voltage or current too high, " |
@@ -1090,23 +1418,24 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, | |||
1090 | return ret; | 1418 | return ret; |
1091 | } | 1419 | } |
1092 | /* MainChInputCurr: current that can be drawn from the charger*/ | 1420 | /* MainChInputCurr: current that can be drawn from the charger*/ |
1093 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | 1421 | ret = ab8500_charger_set_main_in_curr(di, |
1094 | AB8500_MCH_IPT_CURLVL_REG, | 1422 | di->bm->chg_params->ac_curr_max); |
1095 | input_curr_index << MAIN_CH_INPUT_CURR_SHIFT); | ||
1096 | if (ret) { | 1423 | if (ret) { |
1097 | dev_err(di->dev, "%s write failed\n", __func__); | 1424 | dev_err(di->dev, "%s Failed to set MainChInputCurr\n", |
1425 | __func__); | ||
1098 | return ret; | 1426 | return ret; |
1099 | } | 1427 | } |
1100 | /* ChOutputCurentLevel: protected output current */ | 1428 | /* ChOutputCurentLevel: protected output current */ |
1101 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | 1429 | ret = ab8500_charger_set_output_curr(di, iset); |
1102 | AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); | ||
1103 | if (ret) { | 1430 | if (ret) { |
1104 | dev_err(di->dev, "%s write failed\n", __func__); | 1431 | dev_err(di->dev, "%s " |
1432 | "Failed to set ChOutputCurentLevel\n", | ||
1433 | __func__); | ||
1105 | return ret; | 1434 | return ret; |
1106 | } | 1435 | } |
1107 | 1436 | ||
1108 | /* Check if VBAT overshoot control should be enabled */ | 1437 | /* Check if VBAT overshoot control should be enabled */ |
1109 | if (!di->bat->enable_overshoot) | 1438 | if (!di->bm->enable_overshoot) |
1110 | overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; | 1439 | overshoot = MAIN_CH_NO_OVERSHOOT_ENA_N; |
1111 | 1440 | ||
1112 | /* Enable Main Charger */ | 1441 | /* Enable Main Charger */ |
@@ -1158,12 +1487,11 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, | |||
1158 | return ret; | 1487 | return ret; |
1159 | } | 1488 | } |
1160 | 1489 | ||
1161 | ret = abx500_set_register_interruptible(di->dev, | 1490 | ret = ab8500_charger_set_output_curr(di, 0); |
1162 | AB8500_CHARGER, | ||
1163 | AB8500_CH_OPT_CRNTLVL_REG, CH_OP_CUR_LVL_0P1); | ||
1164 | if (ret) { | 1491 | if (ret) { |
1165 | dev_err(di->dev, | 1492 | dev_err(di->dev, "%s " |
1166 | "%s write failed\n", __func__); | 1493 | "Failed to set ChOutputCurentLevel\n", |
1494 | __func__); | ||
1167 | return ret; | 1495 | return ret; |
1168 | } | 1496 | } |
1169 | } else { | 1497 | } else { |
@@ -1259,24 +1587,13 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1259 | dev_err(di->dev, "%s write failed\n", __func__); | 1587 | dev_err(di->dev, "%s write failed\n", __func__); |
1260 | return ret; | 1588 | return ret; |
1261 | } | 1589 | } |
1262 | /* USBChInputCurr: current that can be drawn from the usb */ | ||
1263 | ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | ||
1264 | if (ret) { | ||
1265 | dev_err(di->dev, "setting USBChInputCurr failed\n"); | ||
1266 | return ret; | ||
1267 | } | ||
1268 | /* ChOutputCurentLevel: protected output current */ | ||
1269 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1270 | AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); | ||
1271 | if (ret) { | ||
1272 | dev_err(di->dev, "%s write failed\n", __func__); | ||
1273 | return ret; | ||
1274 | } | ||
1275 | /* Check if VBAT overshoot control should be enabled */ | 1590 | /* Check if VBAT overshoot control should be enabled */ |
1276 | if (!di->bat->enable_overshoot) | 1591 | if (!di->bm->enable_overshoot) |
1277 | overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; | 1592 | overshoot = USB_CHG_NO_OVERSHOOT_ENA_N; |
1278 | 1593 | ||
1279 | /* Enable USB Charger */ | 1594 | /* Enable USB Charger */ |
1595 | dev_dbg(di->dev, | ||
1596 | "Enabling USB with write to AB8500_USBCH_CTRL1_REG\n"); | ||
1280 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | 1597 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, |
1281 | AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot); | 1598 | AB8500_USBCH_CTRL1_REG, USB_CH_ENA | overshoot); |
1282 | if (ret) { | 1599 | if (ret) { |
@@ -1289,11 +1606,29 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1289 | if (ret < 0) | 1606 | if (ret < 0) |
1290 | dev_err(di->dev, "failed to enable LED\n"); | 1607 | dev_err(di->dev, "failed to enable LED\n"); |
1291 | 1608 | ||
1609 | di->usb.charger_online = 1; | ||
1610 | |||
1611 | /* USBChInputCurr: current that can be drawn from the usb */ | ||
1612 | ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | ||
1613 | if (ret) { | ||
1614 | dev_err(di->dev, "setting USBChInputCurr failed\n"); | ||
1615 | return ret; | ||
1616 | } | ||
1617 | |||
1618 | /* ChOutputCurentLevel: protected output current */ | ||
1619 | ret = ab8500_charger_set_output_curr(di, ich_out); | ||
1620 | if (ret) { | ||
1621 | dev_err(di->dev, "%s " | ||
1622 | "Failed to set ChOutputCurentLevel\n", | ||
1623 | __func__); | ||
1624 | return ret; | ||
1625 | } | ||
1626 | |||
1292 | queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ); | 1627 | queue_delayed_work(di->charger_wq, &di->check_vbat_work, HZ); |
1293 | 1628 | ||
1294 | di->usb.charger_online = 1; | ||
1295 | } else { | 1629 | } else { |
1296 | /* Disable USB charging */ | 1630 | /* Disable USB charging */ |
1631 | dev_dbg(di->dev, "%s Disabled USB charging\n", __func__); | ||
1297 | ret = abx500_set_register_interruptible(di->dev, | 1632 | ret = abx500_set_register_interruptible(di->dev, |
1298 | AB8500_CHARGER, | 1633 | AB8500_CHARGER, |
1299 | AB8500_USBCH_CTRL1_REG, 0); | 1634 | AB8500_USBCH_CTRL1_REG, 0); |
@@ -1306,7 +1641,21 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1306 | ret = ab8500_charger_led_en(di, false); | 1641 | ret = ab8500_charger_led_en(di, false); |
1307 | if (ret < 0) | 1642 | if (ret < 0) |
1308 | dev_err(di->dev, "failed to disable LED\n"); | 1643 | dev_err(di->dev, "failed to disable LED\n"); |
1644 | /* USBChInputCurr: current that can be drawn from the usb */ | ||
1645 | ret = ab8500_charger_set_vbus_in_curr(di, 0); | ||
1646 | if (ret) { | ||
1647 | dev_err(di->dev, "setting USBChInputCurr failed\n"); | ||
1648 | return ret; | ||
1649 | } | ||
1309 | 1650 | ||
1651 | /* ChOutputCurentLevel: protected output current */ | ||
1652 | ret = ab8500_charger_set_output_curr(di, 0); | ||
1653 | if (ret) { | ||
1654 | dev_err(di->dev, "%s " | ||
1655 | "Failed to reset ChOutputCurentLevel\n", | ||
1656 | __func__); | ||
1657 | return ret; | ||
1658 | } | ||
1310 | di->usb.charger_online = 0; | 1659 | di->usb.charger_online = 0; |
1311 | di->usb.wd_expired = false; | 1660 | di->usb.wd_expired = false; |
1312 | 1661 | ||
@@ -1366,7 +1715,6 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, | |||
1366 | int ich_out) | 1715 | int ich_out) |
1367 | { | 1716 | { |
1368 | int ret; | 1717 | int ret; |
1369 | int curr_index; | ||
1370 | struct ab8500_charger *di; | 1718 | struct ab8500_charger *di; |
1371 | 1719 | ||
1372 | if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) | 1720 | if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) |
@@ -1376,18 +1724,11 @@ static int ab8500_charger_update_charger_current(struct ux500_charger *charger, | |||
1376 | else | 1724 | else |
1377 | return -ENXIO; | 1725 | return -ENXIO; |
1378 | 1726 | ||
1379 | curr_index = ab8500_current_to_regval(ich_out); | 1727 | ret = ab8500_charger_set_output_curr(di, ich_out); |
1380 | if (curr_index < 0) { | ||
1381 | dev_err(di->dev, | ||
1382 | "Charger current too high, " | ||
1383 | "charging not started\n"); | ||
1384 | return -ENXIO; | ||
1385 | } | ||
1386 | |||
1387 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
1388 | AB8500_CH_OPT_CRNTLVL_REG, (u8) curr_index); | ||
1389 | if (ret) { | 1728 | if (ret) { |
1390 | dev_err(di->dev, "%s write failed\n", __func__); | 1729 | dev_err(di->dev, "%s " |
1730 | "Failed to set ChOutputCurentLevel\n", | ||
1731 | __func__); | ||
1391 | return ret; | 1732 | return ret; |
1392 | } | 1733 | } |
1393 | 1734 | ||
@@ -1597,7 +1938,7 @@ static void ab8500_charger_ac_work(struct work_struct *work) | |||
1597 | * synchronously, we have the check if the main charger is | 1938 | * synchronously, we have the check if the main charger is |
1598 | * connected by reading the status register | 1939 | * connected by reading the status register |
1599 | */ | 1940 | */ |
1600 | ret = ab8500_charger_detect_chargers(di); | 1941 | ret = ab8500_charger_detect_chargers(di, false); |
1601 | if (ret < 0) | 1942 | if (ret < 0) |
1602 | return; | 1943 | return; |
1603 | 1944 | ||
@@ -1612,6 +1953,84 @@ static void ab8500_charger_ac_work(struct work_struct *work) | |||
1612 | sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); | 1953 | sysfs_notify(&di->ac_chg.psy.dev->kobj, NULL, "present"); |
1613 | } | 1954 | } |
1614 | 1955 | ||
1956 | static void ab8500_charger_usb_attached_work(struct work_struct *work) | ||
1957 | { | ||
1958 | struct ab8500_charger *di = container_of(work, | ||
1959 | struct ab8500_charger, | ||
1960 | usb_charger_attached_work.work); | ||
1961 | int usbch = (USB_CH_VBUSDROP | USB_CH_VBUSDETDBNC); | ||
1962 | int ret, i; | ||
1963 | u8 statval; | ||
1964 | |||
1965 | for (i = 0; i < 10; i++) { | ||
1966 | ret = abx500_get_register_interruptible(di->dev, | ||
1967 | AB8500_CHARGER, | ||
1968 | AB8500_CH_USBCH_STAT1_REG, | ||
1969 | &statval); | ||
1970 | if (ret < 0) { | ||
1971 | dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); | ||
1972 | goto reschedule; | ||
1973 | } | ||
1974 | if ((statval & usbch) != usbch) | ||
1975 | goto reschedule; | ||
1976 | |||
1977 | msleep(CHARGER_STATUS_POLL); | ||
1978 | } | ||
1979 | |||
1980 | ab8500_charger_usb_en(&di->usb_chg, 0, 0, 0); | ||
1981 | |||
1982 | mutex_lock(&di->charger_attached_mutex); | ||
1983 | mutex_unlock(&di->charger_attached_mutex); | ||
1984 | |||
1985 | return; | ||
1986 | |||
1987 | reschedule: | ||
1988 | queue_delayed_work(di->charger_wq, | ||
1989 | &di->usb_charger_attached_work, | ||
1990 | HZ); | ||
1991 | } | ||
1992 | |||
1993 | static void ab8500_charger_ac_attached_work(struct work_struct *work) | ||
1994 | { | ||
1995 | |||
1996 | struct ab8500_charger *di = container_of(work, | ||
1997 | struct ab8500_charger, | ||
1998 | ac_charger_attached_work.work); | ||
1999 | int mainch = (MAIN_CH_STATUS2_MAINCHGDROP | | ||
2000 | MAIN_CH_STATUS2_MAINCHARGERDETDBNC); | ||
2001 | int ret, i; | ||
2002 | u8 statval; | ||
2003 | |||
2004 | for (i = 0; i < 10; i++) { | ||
2005 | ret = abx500_get_register_interruptible(di->dev, | ||
2006 | AB8500_CHARGER, | ||
2007 | AB8500_CH_STATUS2_REG, | ||
2008 | &statval); | ||
2009 | if (ret < 0) { | ||
2010 | dev_err(di->dev, "ab8500 read failed %d\n", __LINE__); | ||
2011 | goto reschedule; | ||
2012 | } | ||
2013 | |||
2014 | if ((statval & mainch) != mainch) | ||
2015 | goto reschedule; | ||
2016 | |||
2017 | msleep(CHARGER_STATUS_POLL); | ||
2018 | } | ||
2019 | |||
2020 | ab8500_charger_ac_en(&di->ac_chg, 0, 0, 0); | ||
2021 | queue_work(di->charger_wq, &di->ac_work); | ||
2022 | |||
2023 | mutex_lock(&di->charger_attached_mutex); | ||
2024 | mutex_unlock(&di->charger_attached_mutex); | ||
2025 | |||
2026 | return; | ||
2027 | |||
2028 | reschedule: | ||
2029 | queue_delayed_work(di->charger_wq, | ||
2030 | &di->ac_charger_attached_work, | ||
2031 | HZ); | ||
2032 | } | ||
2033 | |||
1615 | /** | 2034 | /** |
1616 | * ab8500_charger_detect_usb_type_work() - work to detect USB type | 2035 | * ab8500_charger_detect_usb_type_work() - work to detect USB type |
1617 | * @work: Pointer to the work_struct structure | 2036 | * @work: Pointer to the work_struct structure |
@@ -1630,16 +2049,18 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work) | |||
1630 | * synchronously, we have the check if is | 2049 | * synchronously, we have the check if is |
1631 | * connected by reading the status register | 2050 | * connected by reading the status register |
1632 | */ | 2051 | */ |
1633 | ret = ab8500_charger_detect_chargers(di); | 2052 | ret = ab8500_charger_detect_chargers(di, false); |
1634 | if (ret < 0) | 2053 | if (ret < 0) |
1635 | return; | 2054 | return; |
1636 | 2055 | ||
1637 | if (!(ret & USB_PW_CONN)) { | 2056 | if (!(ret & USB_PW_CONN)) { |
1638 | di->vbus_detected = 0; | 2057 | dev_dbg(di->dev, "%s di->vbus_detected = false\n", __func__); |
2058 | di->vbus_detected = false; | ||
1639 | ab8500_charger_set_usb_connected(di, false); | 2059 | ab8500_charger_set_usb_connected(di, false); |
1640 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | 2060 | ab8500_power_supply_changed(di, &di->usb_chg.psy); |
1641 | } else { | 2061 | } else { |
1642 | di->vbus_detected = 1; | 2062 | dev_dbg(di->dev, "%s di->vbus_detected = true\n", __func__); |
2063 | di->vbus_detected = true; | ||
1643 | 2064 | ||
1644 | if (is_ab8500_1p1_or_earlier(di->parent)) { | 2065 | if (is_ab8500_1p1_or_earlier(di->parent)) { |
1645 | ret = ab8500_charger_detect_usb_type(di); | 2066 | ret = ab8500_charger_detect_usb_type(di); |
@@ -1649,7 +2070,8 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work) | |||
1649 | &di->usb_chg.psy); | 2070 | &di->usb_chg.psy); |
1650 | } | 2071 | } |
1651 | } else { | 2072 | } else { |
1652 | /* For ABB cut2.0 and onwards we have an IRQ, | 2073 | /* |
2074 | * For ABB cut2.0 and onwards we have an IRQ, | ||
1653 | * USB_LINK_STATUS that will be triggered when the USB | 2075 | * USB_LINK_STATUS that will be triggered when the USB |
1654 | * link status changes. The exception is USB connected | 2076 | * link status changes. The exception is USB connected |
1655 | * during startup. Then we don't get a | 2077 | * during startup. Then we don't get a |
@@ -1670,6 +2092,29 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work) | |||
1670 | } | 2092 | } |
1671 | 2093 | ||
1672 | /** | 2094 | /** |
2095 | * ab8500_charger_usb_link_attach_work() - work to detect USB type | ||
2096 | * @work: pointer to the work_struct structure | ||
2097 | * | ||
2098 | * Detect the type of USB plugged | ||
2099 | */ | ||
2100 | static void ab8500_charger_usb_link_attach_work(struct work_struct *work) | ||
2101 | { | ||
2102 | struct ab8500_charger *di = | ||
2103 | container_of(work, struct ab8500_charger, attach_work.work); | ||
2104 | int ret; | ||
2105 | |||
2106 | /* Update maximum input current if USB enumeration is not detected */ | ||
2107 | if (!di->usb.charger_online) { | ||
2108 | ret = ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | ||
2109 | if (ret) | ||
2110 | return; | ||
2111 | } | ||
2112 | |||
2113 | ab8500_charger_set_usb_connected(di, true); | ||
2114 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | ||
2115 | } | ||
2116 | |||
2117 | /** | ||
1673 | * ab8500_charger_usb_link_status_work() - work to detect USB type | 2118 | * ab8500_charger_usb_link_status_work() - work to detect USB type |
1674 | * @work: pointer to the work_struct structure | 2119 | * @work: pointer to the work_struct structure |
1675 | * | 2120 | * |
@@ -1677,7 +2122,9 @@ static void ab8500_charger_detect_usb_type_work(struct work_struct *work) | |||
1677 | */ | 2122 | */ |
1678 | static void ab8500_charger_usb_link_status_work(struct work_struct *work) | 2123 | static void ab8500_charger_usb_link_status_work(struct work_struct *work) |
1679 | { | 2124 | { |
2125 | int detected_chargers; | ||
1680 | int ret; | 2126 | int ret; |
2127 | u8 val; | ||
1681 | 2128 | ||
1682 | struct ab8500_charger *di = container_of(work, | 2129 | struct ab8500_charger *di = container_of(work, |
1683 | struct ab8500_charger, usb_link_status_work); | 2130 | struct ab8500_charger, usb_link_status_work); |
@@ -1687,31 +2134,95 @@ static void ab8500_charger_usb_link_status_work(struct work_struct *work) | |||
1687 | * synchronously, we have the check if is | 2134 | * synchronously, we have the check if is |
1688 | * connected by reading the status register | 2135 | * connected by reading the status register |
1689 | */ | 2136 | */ |
1690 | ret = ab8500_charger_detect_chargers(di); | 2137 | detected_chargers = ab8500_charger_detect_chargers(di, false); |
1691 | if (ret < 0) | 2138 | if (detected_chargers < 0) |
1692 | return; | 2139 | return; |
1693 | 2140 | ||
1694 | if (!(ret & USB_PW_CONN)) { | 2141 | /* |
1695 | di->vbus_detected = 0; | 2142 | * Some chargers that breaks the USB spec is |
2143 | * identified as invalid by AB8500 and it refuse | ||
2144 | * to start the charging process. but by jumping | ||
2145 | * thru a few hoops it can be forced to start. | ||
2146 | */ | ||
2147 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | ||
2148 | AB8500_USB_LINE_STAT_REG, &val); | ||
2149 | if (ret >= 0) | ||
2150 | dev_dbg(di->dev, "UsbLineStatus register = 0x%02x\n", val); | ||
2151 | else | ||
2152 | dev_dbg(di->dev, "Error reading USB link status\n"); | ||
2153 | |||
2154 | if (detected_chargers & USB_PW_CONN) { | ||
2155 | if (((val & AB8500_USB_LINK_STATUS) >> 3) == USB_STAT_NOT_VALID_LINK && | ||
2156 | di->invalid_charger_detect_state == 0) { | ||
2157 | dev_dbg(di->dev, "Invalid charger detected, state= 0\n"); | ||
2158 | /*Enable charger*/ | ||
2159 | abx500_mask_and_set_register_interruptible(di->dev, | ||
2160 | AB8500_CHARGER, AB8500_USBCH_CTRL1_REG, 0x01, 0x01); | ||
2161 | /*Enable charger detection*/ | ||
2162 | abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB, | ||
2163 | AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x01); | ||
2164 | di->invalid_charger_detect_state = 1; | ||
2165 | /*exit and wait for new link status interrupt.*/ | ||
2166 | return; | ||
2167 | |||
2168 | } | ||
2169 | if (di->invalid_charger_detect_state == 1) { | ||
2170 | dev_dbg(di->dev, "Invalid charger detected, state= 1\n"); | ||
2171 | /*Stop charger detection*/ | ||
2172 | abx500_mask_and_set_register_interruptible(di->dev, AB8500_USB, | ||
2173 | AB8500_MCH_IPT_CURLVL_REG, 0x01, 0x00); | ||
2174 | /*Check link status*/ | ||
2175 | ret = abx500_get_register_interruptible(di->dev, AB8500_USB, | ||
2176 | AB8500_USB_LINE_STAT_REG, &val); | ||
2177 | dev_dbg(di->dev, "USB link status= 0x%02x\n", | ||
2178 | (val & AB8500_USB_LINK_STATUS) >> 3); | ||
2179 | di->invalid_charger_detect_state = 2; | ||
2180 | } | ||
2181 | } else { | ||
2182 | di->invalid_charger_detect_state = 0; | ||
2183 | } | ||
2184 | |||
2185 | if (!(detected_chargers & USB_PW_CONN)) { | ||
2186 | di->vbus_detected = false; | ||
1696 | ab8500_charger_set_usb_connected(di, false); | 2187 | ab8500_charger_set_usb_connected(di, false); |
1697 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | 2188 | ab8500_power_supply_changed(di, &di->usb_chg.psy); |
1698 | } else { | 2189 | return; |
1699 | di->vbus_detected = 1; | 2190 | } |
1700 | ret = ab8500_charger_read_usb_type(di); | ||
1701 | if (!ret) { | ||
1702 | /* Update maximum input current */ | ||
1703 | ret = ab8500_charger_set_vbus_in_curr(di, | ||
1704 | di->max_usb_in_curr); | ||
1705 | if (ret) | ||
1706 | return; | ||
1707 | 2191 | ||
1708 | ab8500_charger_set_usb_connected(di, true); | 2192 | dev_dbg(di->dev,"%s di->vbus_detected = true\n",__func__); |
1709 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | 2193 | di->vbus_detected = true; |
1710 | } else if (ret == -ENXIO) { | 2194 | ret = ab8500_charger_read_usb_type(di); |
2195 | if (ret) { | ||
2196 | if (ret == -ENXIO) { | ||
1711 | /* No valid charger type detected */ | 2197 | /* No valid charger type detected */ |
1712 | ab8500_charger_set_usb_connected(di, false); | 2198 | ab8500_charger_set_usb_connected(di, false); |
1713 | ab8500_power_supply_changed(di, &di->usb_chg.psy); | 2199 | ab8500_power_supply_changed(di, &di->usb_chg.psy); |
1714 | } | 2200 | } |
2201 | return; | ||
2202 | } | ||
2203 | |||
2204 | if (di->usb_device_is_unrecognised) { | ||
2205 | dev_dbg(di->dev, | ||
2206 | "Potential Legacy Charger device. " | ||
2207 | "Delay work for %d msec for USB enum " | ||
2208 | "to finish", | ||
2209 | WAIT_ACA_RID_ENUMERATION); | ||
2210 | queue_delayed_work(di->charger_wq, | ||
2211 | &di->attach_work, | ||
2212 | msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION)); | ||
2213 | } else if (di->is_aca_rid == 1) { | ||
2214 | /* Only wait once */ | ||
2215 | di->is_aca_rid++; | ||
2216 | dev_dbg(di->dev, | ||
2217 | "%s Wait %d msec for USB enum to finish", | ||
2218 | __func__, WAIT_ACA_RID_ENUMERATION); | ||
2219 | queue_delayed_work(di->charger_wq, | ||
2220 | &di->attach_work, | ||
2221 | msecs_to_jiffies(WAIT_ACA_RID_ENUMERATION)); | ||
2222 | } else { | ||
2223 | queue_delayed_work(di->charger_wq, | ||
2224 | &di->attach_work, | ||
2225 | 0); | ||
1715 | } | 2226 | } |
1716 | } | 2227 | } |
1717 | 2228 | ||
@@ -1721,24 +2232,20 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work) | |||
1721 | unsigned long flags; | 2232 | unsigned long flags; |
1722 | 2233 | ||
1723 | struct ab8500_charger *di = container_of(work, | 2234 | struct ab8500_charger *di = container_of(work, |
1724 | struct ab8500_charger, usb_state_changed_work); | 2235 | struct ab8500_charger, usb_state_changed_work.work); |
1725 | 2236 | ||
1726 | if (!di->vbus_detected) | 2237 | if (!di->vbus_detected) { |
2238 | dev_dbg(di->dev, | ||
2239 | "%s !di->vbus_detected\n", | ||
2240 | __func__); | ||
1727 | return; | 2241 | return; |
2242 | } | ||
1728 | 2243 | ||
1729 | spin_lock_irqsave(&di->usb_state.usb_lock, flags); | 2244 | spin_lock_irqsave(&di->usb_state.usb_lock, flags); |
1730 | di->usb_state.usb_changed = false; | 2245 | di->usb_state.state = di->usb_state.state_tmp; |
2246 | di->usb_state.usb_current = di->usb_state.usb_current_tmp; | ||
1731 | spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); | 2247 | spin_unlock_irqrestore(&di->usb_state.usb_lock, flags); |
1732 | 2248 | ||
1733 | /* | ||
1734 | * wait for some time until you get updates from the usb stack | ||
1735 | * and negotiations are completed | ||
1736 | */ | ||
1737 | msleep(250); | ||
1738 | |||
1739 | if (di->usb_state.usb_changed) | ||
1740 | return; | ||
1741 | |||
1742 | dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", | 2249 | dev_dbg(di->dev, "%s USB state: 0x%02x mA: %d\n", |
1743 | __func__, di->usb_state.state, di->usb_state.usb_current); | 2250 | __func__, di->usb_state.state, di->usb_state.usb_current); |
1744 | 2251 | ||
@@ -1892,6 +2399,10 @@ static irqreturn_t ab8500_charger_mainchunplugdet_handler(int irq, void *_di) | |||
1892 | dev_dbg(di->dev, "Main charger unplugged\n"); | 2399 | dev_dbg(di->dev, "Main charger unplugged\n"); |
1893 | queue_work(di->charger_wq, &di->ac_work); | 2400 | queue_work(di->charger_wq, &di->ac_work); |
1894 | 2401 | ||
2402 | cancel_delayed_work_sync(&di->ac_charger_attached_work); | ||
2403 | mutex_lock(&di->charger_attached_mutex); | ||
2404 | mutex_unlock(&di->charger_attached_mutex); | ||
2405 | |||
1895 | return IRQ_HANDLED; | 2406 | return IRQ_HANDLED; |
1896 | } | 2407 | } |
1897 | 2408 | ||
@@ -1909,6 +2420,11 @@ static irqreturn_t ab8500_charger_mainchplugdet_handler(int irq, void *_di) | |||
1909 | dev_dbg(di->dev, "Main charger plugged\n"); | 2420 | dev_dbg(di->dev, "Main charger plugged\n"); |
1910 | queue_work(di->charger_wq, &di->ac_work); | 2421 | queue_work(di->charger_wq, &di->ac_work); |
1911 | 2422 | ||
2423 | mutex_lock(&di->charger_attached_mutex); | ||
2424 | mutex_unlock(&di->charger_attached_mutex); | ||
2425 | queue_delayed_work(di->charger_wq, | ||
2426 | &di->ac_charger_attached_work, | ||
2427 | HZ); | ||
1912 | return IRQ_HANDLED; | 2428 | return IRQ_HANDLED; |
1913 | } | 2429 | } |
1914 | 2430 | ||
@@ -1971,6 +2487,21 @@ static irqreturn_t ab8500_charger_mainchthprotf_handler(int irq, void *_di) | |||
1971 | return IRQ_HANDLED; | 2487 | return IRQ_HANDLED; |
1972 | } | 2488 | } |
1973 | 2489 | ||
2490 | static void ab8500_charger_vbus_drop_end_work(struct work_struct *work) | ||
2491 | { | ||
2492 | struct ab8500_charger *di = container_of(work, | ||
2493 | struct ab8500_charger, vbus_drop_end_work.work); | ||
2494 | |||
2495 | di->flags.vbus_drop_end = false; | ||
2496 | |||
2497 | /* Reset the drop counter */ | ||
2498 | abx500_set_register_interruptible(di->dev, | ||
2499 | AB8500_CHARGER, AB8500_CHARGER_CTRL, 0x01); | ||
2500 | |||
2501 | if (di->usb.charger_connected) | ||
2502 | ab8500_charger_set_vbus_in_curr(di, di->max_usb_in_curr); | ||
2503 | } | ||
2504 | |||
1974 | /** | 2505 | /** |
1975 | * ab8500_charger_vbusdetf_handler() - VBUS falling detected | 2506 | * ab8500_charger_vbusdetf_handler() - VBUS falling detected |
1976 | * @irq: interrupt number | 2507 | * @irq: interrupt number |
@@ -1982,6 +2513,7 @@ static irqreturn_t ab8500_charger_vbusdetf_handler(int irq, void *_di) | |||
1982 | { | 2513 | { |
1983 | struct ab8500_charger *di = _di; | 2514 | struct ab8500_charger *di = _di; |
1984 | 2515 | ||
2516 | di->vbus_detected = false; | ||
1985 | dev_dbg(di->dev, "VBUS falling detected\n"); | 2517 | dev_dbg(di->dev, "VBUS falling detected\n"); |
1986 | queue_work(di->charger_wq, &di->detect_usb_type_work); | 2518 | queue_work(di->charger_wq, &di->detect_usb_type_work); |
1987 | 2519 | ||
@@ -2001,6 +2533,7 @@ static irqreturn_t ab8500_charger_vbusdetr_handler(int irq, void *_di) | |||
2001 | 2533 | ||
2002 | di->vbus_detected = true; | 2534 | di->vbus_detected = true; |
2003 | dev_dbg(di->dev, "VBUS rising detected\n"); | 2535 | dev_dbg(di->dev, "VBUS rising detected\n"); |
2536 | |||
2004 | queue_work(di->charger_wq, &di->detect_usb_type_work); | 2537 | queue_work(di->charger_wq, &di->detect_usb_type_work); |
2005 | 2538 | ||
2006 | return IRQ_HANDLED; | 2539 | return IRQ_HANDLED; |
@@ -2109,6 +2642,25 @@ static irqreturn_t ab8500_charger_chwdexp_handler(int irq, void *_di) | |||
2109 | } | 2642 | } |
2110 | 2643 | ||
2111 | /** | 2644 | /** |
2645 | * ab8500_charger_vbuschdropend_handler() - VBUS drop removed | ||
2646 | * @irq: interrupt number | ||
2647 | * @_di: pointer to the ab8500_charger structure | ||
2648 | * | ||
2649 | * Returns IRQ status(IRQ_HANDLED) | ||
2650 | */ | ||
2651 | static irqreturn_t ab8500_charger_vbuschdropend_handler(int irq, void *_di) | ||
2652 | { | ||
2653 | struct ab8500_charger *di = _di; | ||
2654 | |||
2655 | dev_dbg(di->dev, "VBUS charger drop ended\n"); | ||
2656 | di->flags.vbus_drop_end = true; | ||
2657 | queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, | ||
2658 | round_jiffies(30 * HZ)); | ||
2659 | |||
2660 | return IRQ_HANDLED; | ||
2661 | } | ||
2662 | |||
2663 | /** | ||
2112 | * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected | 2664 | * ab8500_charger_vbusovv_handler() - VBUS overvoltage detected |
2113 | * @irq: interrupt number | 2665 | * @irq: interrupt number |
2114 | * @_di: pointer to the ab8500_charger structure | 2666 | * @_di: pointer to the ab8500_charger structure |
@@ -2148,6 +2700,7 @@ static int ab8500_charger_ac_get_property(struct power_supply *psy, | |||
2148 | union power_supply_propval *val) | 2700 | union power_supply_propval *val) |
2149 | { | 2701 | { |
2150 | struct ab8500_charger *di; | 2702 | struct ab8500_charger *di; |
2703 | int ret; | ||
2151 | 2704 | ||
2152 | di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); | 2705 | di = to_ab8500_charger_ac_device_info(psy_to_ux500_charger(psy)); |
2153 | 2706 | ||
@@ -2169,7 +2722,10 @@ static int ab8500_charger_ac_get_property(struct power_supply *psy, | |||
2169 | val->intval = di->ac.charger_connected; | 2722 | val->intval = di->ac.charger_connected; |
2170 | break; | 2723 | break; |
2171 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 2724 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
2172 | di->ac.charger_voltage = ab8500_charger_get_ac_voltage(di); | 2725 | ret = ab8500_charger_get_ac_voltage(di); |
2726 | if (ret >= 0) | ||
2727 | di->ac.charger_voltage = ret; | ||
2728 | /* On error, use previous value */ | ||
2173 | val->intval = di->ac.charger_voltage * 1000; | 2729 | val->intval = di->ac.charger_voltage * 1000; |
2174 | break; | 2730 | break; |
2175 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | 2731 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
@@ -2181,7 +2737,10 @@ static int ab8500_charger_ac_get_property(struct power_supply *psy, | |||
2181 | val->intval = di->ac.cv_active; | 2737 | val->intval = di->ac.cv_active; |
2182 | break; | 2738 | break; |
2183 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 2739 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
2184 | val->intval = ab8500_charger_get_ac_current(di) * 1000; | 2740 | ret = ab8500_charger_get_ac_current(di); |
2741 | if (ret >= 0) | ||
2742 | di->ac.charger_current = ret; | ||
2743 | val->intval = di->ac.charger_current * 1000; | ||
2185 | break; | 2744 | break; |
2186 | default: | 2745 | default: |
2187 | return -EINVAL; | 2746 | return -EINVAL; |
@@ -2208,6 +2767,7 @@ static int ab8500_charger_usb_get_property(struct power_supply *psy, | |||
2208 | union power_supply_propval *val) | 2767 | union power_supply_propval *val) |
2209 | { | 2768 | { |
2210 | struct ab8500_charger *di; | 2769 | struct ab8500_charger *di; |
2770 | int ret; | ||
2211 | 2771 | ||
2212 | di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); | 2772 | di = to_ab8500_charger_usb_device_info(psy_to_ux500_charger(psy)); |
2213 | 2773 | ||
@@ -2231,7 +2791,9 @@ static int ab8500_charger_usb_get_property(struct power_supply *psy, | |||
2231 | val->intval = di->usb.charger_connected; | 2791 | val->intval = di->usb.charger_connected; |
2232 | break; | 2792 | break; |
2233 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 2793 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
2234 | di->usb.charger_voltage = ab8500_charger_get_vbus_voltage(di); | 2794 | ret = ab8500_charger_get_vbus_voltage(di); |
2795 | if (ret >= 0) | ||
2796 | di->usb.charger_voltage = ret; | ||
2235 | val->intval = di->usb.charger_voltage * 1000; | 2797 | val->intval = di->usb.charger_voltage * 1000; |
2236 | break; | 2798 | break; |
2237 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | 2799 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
@@ -2243,7 +2805,10 @@ static int ab8500_charger_usb_get_property(struct power_supply *psy, | |||
2243 | val->intval = di->usb.cv_active; | 2805 | val->intval = di->usb.cv_active; |
2244 | break; | 2806 | break; |
2245 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 2807 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
2246 | val->intval = ab8500_charger_get_usb_current(di) * 1000; | 2808 | ret = ab8500_charger_get_usb_current(di); |
2809 | if (ret >= 0) | ||
2810 | di->usb.charger_current = ret; | ||
2811 | val->intval = di->usb.charger_current * 1000; | ||
2247 | break; | 2812 | break; |
2248 | case POWER_SUPPLY_PROP_CURRENT_AVG: | 2813 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
2249 | /* | 2814 | /* |
@@ -2293,13 +2858,23 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2293 | } | 2858 | } |
2294 | } | 2859 | } |
2295 | 2860 | ||
2296 | /* VBUS OVV set to 6.3V and enable automatic current limitiation */ | 2861 | if (is_ab9540_2p0(di->parent) || is_ab8505_2p0(di->parent)) |
2297 | ret = abx500_set_register_interruptible(di->dev, | 2862 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
2298 | AB8500_CHARGER, | 2863 | AB8500_CHARGER, |
2299 | AB8500_USBCH_CTRL2_REG, | 2864 | AB8500_USBCH_CTRL2_REG, |
2300 | VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); | 2865 | VBUS_AUTO_IN_CURR_LIM_ENA, |
2866 | VBUS_AUTO_IN_CURR_LIM_ENA); | ||
2867 | else | ||
2868 | /* | ||
2869 | * VBUS OVV set to 6.3V and enable automatic current limitation | ||
2870 | */ | ||
2871 | ret = abx500_set_register_interruptible(di->dev, | ||
2872 | AB8500_CHARGER, | ||
2873 | AB8500_USBCH_CTRL2_REG, | ||
2874 | VBUS_OVV_SELECT_6P3V | VBUS_AUTO_IN_CURR_LIM_ENA); | ||
2301 | if (ret) { | 2875 | if (ret) { |
2302 | dev_err(di->dev, "failed to set VBUS OVV\n"); | 2876 | dev_err(di->dev, |
2877 | "failed to set automatic current limitation\n"); | ||
2303 | goto out; | 2878 | goto out; |
2304 | } | 2879 | } |
2305 | 2880 | ||
@@ -2355,12 +2930,26 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di) | |||
2355 | goto out; | 2930 | goto out; |
2356 | } | 2931 | } |
2357 | 2932 | ||
2933 | /* Set charger watchdog timeout */ | ||
2934 | ret = abx500_set_register_interruptible(di->dev, AB8500_CHARGER, | ||
2935 | AB8500_CH_WD_TIMER_REG, WD_TIMER); | ||
2936 | if (ret) { | ||
2937 | dev_err(di->dev, "failed to set charger watchdog timeout\n"); | ||
2938 | goto out; | ||
2939 | } | ||
2940 | |||
2941 | ret = ab8500_charger_led_en(di, false); | ||
2942 | if (ret < 0) { | ||
2943 | dev_err(di->dev, "failed to disable LED\n"); | ||
2944 | goto out; | ||
2945 | } | ||
2946 | |||
2358 | /* Backup battery voltage and current */ | 2947 | /* Backup battery voltage and current */ |
2359 | ret = abx500_set_register_interruptible(di->dev, | 2948 | ret = abx500_set_register_interruptible(di->dev, |
2360 | AB8500_RTC, | 2949 | AB8500_RTC, |
2361 | AB8500_RTC_BACKUP_CHG_REG, | 2950 | AB8500_RTC_BACKUP_CHG_REG, |
2362 | di->bat->bkup_bat_v | | 2951 | di->bm->bkup_bat_v | |
2363 | di->bat->bkup_bat_i); | 2952 | di->bm->bkup_bat_i); |
2364 | if (ret) { | 2953 | if (ret) { |
2365 | dev_err(di->dev, "failed to setup backup battery charging\n"); | 2954 | dev_err(di->dev, "failed to setup backup battery charging\n"); |
2366 | goto out; | 2955 | goto out; |
@@ -2394,6 +2983,7 @@ static struct ab8500_charger_interrupts ab8500_charger_irq[] = { | |||
2394 | {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, | 2983 | {"USB_CHARGER_NOT_OKR", ab8500_charger_usbchargernotokr_handler}, |
2395 | {"VBUS_OVV", ab8500_charger_vbusovv_handler}, | 2984 | {"VBUS_OVV", ab8500_charger_vbusovv_handler}, |
2396 | {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, | 2985 | {"CH_WD_EXP", ab8500_charger_chwdexp_handler}, |
2986 | {"VBUS_CH_DROP_END", ab8500_charger_vbuschdropend_handler}, | ||
2397 | }; | 2987 | }; |
2398 | 2988 | ||
2399 | static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, | 2989 | static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, |
@@ -2404,6 +2994,9 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, | |||
2404 | enum ab8500_usb_state bm_usb_state; | 2994 | enum ab8500_usb_state bm_usb_state; |
2405 | unsigned mA = *((unsigned *)power); | 2995 | unsigned mA = *((unsigned *)power); |
2406 | 2996 | ||
2997 | if (!di) | ||
2998 | return NOTIFY_DONE; | ||
2999 | |||
2407 | if (event != USB_EVENT_VBUS) { | 3000 | if (event != USB_EVENT_VBUS) { |
2408 | dev_dbg(di->dev, "not a standard host, returning\n"); | 3001 | dev_dbg(di->dev, "not a standard host, returning\n"); |
2409 | return NOTIFY_DONE; | 3002 | return NOTIFY_DONE; |
@@ -2427,13 +3020,15 @@ static int ab8500_charger_usb_notifier_call(struct notifier_block *nb, | |||
2427 | __func__, bm_usb_state, mA); | 3020 | __func__, bm_usb_state, mA); |
2428 | 3021 | ||
2429 | spin_lock(&di->usb_state.usb_lock); | 3022 | spin_lock(&di->usb_state.usb_lock); |
2430 | di->usb_state.usb_changed = true; | 3023 | di->usb_state.state_tmp = bm_usb_state; |
3024 | di->usb_state.usb_current_tmp = mA; | ||
2431 | spin_unlock(&di->usb_state.usb_lock); | 3025 | spin_unlock(&di->usb_state.usb_lock); |
2432 | 3026 | ||
2433 | di->usb_state.state = bm_usb_state; | 3027 | /* |
2434 | di->usb_state.usb_current = mA; | 3028 | * wait for some time until you get updates from the usb stack |
2435 | 3029 | * and negotiations are completed | |
2436 | queue_work(di->charger_wq, &di->usb_state_changed_work); | 3030 | */ |
3031 | queue_delayed_work(di->charger_wq, &di->usb_state_changed_work, HZ/2); | ||
2437 | 3032 | ||
2438 | return NOTIFY_OK; | 3033 | return NOTIFY_OK; |
2439 | } | 3034 | } |
@@ -2473,6 +3068,9 @@ static int ab8500_charger_resume(struct platform_device *pdev) | |||
2473 | &di->check_hw_failure_work, 0); | 3068 | &di->check_hw_failure_work, 0); |
2474 | } | 3069 | } |
2475 | 3070 | ||
3071 | if (di->flags.vbus_drop_end) | ||
3072 | queue_delayed_work(di->charger_wq, &di->vbus_drop_end_work, 0); | ||
3073 | |||
2476 | return 0; | 3074 | return 0; |
2477 | } | 3075 | } |
2478 | 3076 | ||
@@ -2485,6 +3083,23 @@ static int ab8500_charger_suspend(struct platform_device *pdev, | |||
2485 | if (delayed_work_pending(&di->check_hw_failure_work)) | 3083 | if (delayed_work_pending(&di->check_hw_failure_work)) |
2486 | cancel_delayed_work(&di->check_hw_failure_work); | 3084 | cancel_delayed_work(&di->check_hw_failure_work); |
2487 | 3085 | ||
3086 | if (delayed_work_pending(&di->vbus_drop_end_work)) | ||
3087 | cancel_delayed_work(&di->vbus_drop_end_work); | ||
3088 | |||
3089 | flush_delayed_work(&di->attach_work); | ||
3090 | flush_delayed_work(&di->usb_charger_attached_work); | ||
3091 | flush_delayed_work(&di->ac_charger_attached_work); | ||
3092 | flush_delayed_work(&di->check_usbchgnotok_work); | ||
3093 | flush_delayed_work(&di->check_vbat_work); | ||
3094 | flush_delayed_work(&di->kick_wd_work); | ||
3095 | |||
3096 | flush_work(&di->usb_link_status_work); | ||
3097 | flush_work(&di->ac_work); | ||
3098 | flush_work(&di->detect_usb_type_work); | ||
3099 | |||
3100 | if (atomic_read(&di->current_stepping_sessions)) | ||
3101 | return -EAGAIN; | ||
3102 | |||
2488 | return 0; | 3103 | return 0; |
2489 | } | 3104 | } |
2490 | #else | 3105 | #else |
@@ -2509,9 +3124,6 @@ static int ab8500_charger_remove(struct platform_device *pdev) | |||
2509 | free_irq(irq, di); | 3124 | free_irq(irq, di); |
2510 | } | 3125 | } |
2511 | 3126 | ||
2512 | /* disable the regulator */ | ||
2513 | regulator_put(di->regu); | ||
2514 | |||
2515 | /* Backup battery voltage and current disable */ | 3127 | /* Backup battery voltage and current disable */ |
2516 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 3128 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
2517 | AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); | 3129 | AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0); |
@@ -2525,8 +3137,12 @@ static int ab8500_charger_remove(struct platform_device *pdev) | |||
2525 | destroy_workqueue(di->charger_wq); | 3137 | destroy_workqueue(di->charger_wq); |
2526 | 3138 | ||
2527 | flush_scheduled_work(); | 3139 | flush_scheduled_work(); |
2528 | power_supply_unregister(&di->usb_chg.psy); | 3140 | if(di->usb_chg.enabled) |
2529 | power_supply_unregister(&di->ac_chg.psy); | 3141 | power_supply_unregister(&di->usb_chg.psy); |
3142 | #if !defined(CONFIG_CHARGER_PM2301) | ||
3143 | if(di->ac_chg.enabled) | ||
3144 | power_supply_unregister(&di->ac_chg.psy); | ||
3145 | #endif | ||
2530 | platform_set_drvdata(pdev, NULL); | 3146 | platform_set_drvdata(pdev, NULL); |
2531 | 3147 | ||
2532 | return 0; | 3148 | return 0; |
@@ -2541,32 +3157,31 @@ static char *supply_interface[] = { | |||
2541 | static int ab8500_charger_probe(struct platform_device *pdev) | 3157 | static int ab8500_charger_probe(struct platform_device *pdev) |
2542 | { | 3158 | { |
2543 | struct device_node *np = pdev->dev.of_node; | 3159 | struct device_node *np = pdev->dev.of_node; |
3160 | struct abx500_bm_data *plat = pdev->dev.platform_data; | ||
2544 | struct ab8500_charger *di; | 3161 | struct ab8500_charger *di; |
2545 | int irq, i, charger_status, ret = 0; | 3162 | int irq, i, charger_status, ret = 0, ch_stat; |
2546 | 3163 | ||
2547 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | 3164 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); |
2548 | if (!di) { | 3165 | if (!di) { |
2549 | dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); | 3166 | dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); |
2550 | return -ENOMEM; | 3167 | return -ENOMEM; |
2551 | } | 3168 | } |
2552 | di->bat = pdev->mfd_cell->platform_data; | 3169 | |
2553 | if (!di->bat) { | 3170 | if (!plat) { |
2554 | if (np) { | 3171 | dev_err(&pdev->dev, "no battery management data supplied\n"); |
2555 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | 3172 | return -EINVAL; |
2556 | if (ret) { | 3173 | } |
2557 | dev_err(&pdev->dev, | 3174 | di->bm = plat; |
2558 | "failed to get battery information\n"); | 3175 | |
2559 | return ret; | 3176 | if (np) { |
2560 | } | 3177 | ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); |
2561 | di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); | 3178 | if (ret) { |
2562 | } else { | 3179 | dev_err(&pdev->dev, "failed to get battery information\n"); |
2563 | dev_err(&pdev->dev, "missing dt node for ab8500_charger\n"); | 3180 | return ret; |
2564 | return -EINVAL; | ||
2565 | } | 3181 | } |
2566 | } else { | 3182 | di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); |
2567 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | 3183 | } else |
2568 | di->autopower_cfg = false; | 3184 | di->autopower_cfg = false; |
2569 | } | ||
2570 | 3185 | ||
2571 | /* get parent data */ | 3186 | /* get parent data */ |
2572 | di->dev = &pdev->dev; | 3187 | di->dev = &pdev->dev; |
@@ -2575,8 +3190,10 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2575 | 3190 | ||
2576 | /* initialize lock */ | 3191 | /* initialize lock */ |
2577 | spin_lock_init(&di->usb_state.usb_lock); | 3192 | spin_lock_init(&di->usb_state.usb_lock); |
3193 | mutex_init(&di->usb_ipt_crnt_lock); | ||
2578 | 3194 | ||
2579 | di->autopower = false; | 3195 | di->autopower = false; |
3196 | di->invalid_charger_detect_state = 0; | ||
2580 | 3197 | ||
2581 | /* AC supply */ | 3198 | /* AC supply */ |
2582 | /* power_supply base class */ | 3199 | /* power_supply base class */ |
@@ -2595,6 +3212,9 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2595 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; | 3212 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; |
2596 | di->ac_chg.max_out_curr = ab8500_charger_current_map[ | 3213 | di->ac_chg.max_out_curr = ab8500_charger_current_map[ |
2597 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; | 3214 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; |
3215 | di->ac_chg.wdt_refresh = CHG_WD_INTERVAL; | ||
3216 | di->ac_chg.enabled = di->bm->ac_enabled; | ||
3217 | di->ac_chg.external = false; | ||
2598 | 3218 | ||
2599 | /* USB supply */ | 3219 | /* USB supply */ |
2600 | /* power_supply base class */ | 3220 | /* power_supply base class */ |
@@ -2613,7 +3233,9 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2613 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; | 3233 | ARRAY_SIZE(ab8500_charger_voltage_map) - 1]; |
2614 | di->usb_chg.max_out_curr = ab8500_charger_current_map[ | 3234 | di->usb_chg.max_out_curr = ab8500_charger_current_map[ |
2615 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; | 3235 | ARRAY_SIZE(ab8500_charger_current_map) - 1]; |
2616 | 3236 | di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; | |
3237 | di->usb_chg.enabled = di->bm->usb_enabled; | ||
3238 | di->usb_chg.external = false; | ||
2617 | 3239 | ||
2618 | /* Create a work queue for the charger */ | 3240 | /* Create a work queue for the charger */ |
2619 | di->charger_wq = | 3241 | di->charger_wq = |
@@ -2623,12 +3245,19 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2623 | return -ENOMEM; | 3245 | return -ENOMEM; |
2624 | } | 3246 | } |
2625 | 3247 | ||
3248 | mutex_init(&di->charger_attached_mutex); | ||
3249 | |||
2626 | /* Init work for HW failure check */ | 3250 | /* Init work for HW failure check */ |
2627 | INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, | 3251 | INIT_DEFERRABLE_WORK(&di->check_hw_failure_work, |
2628 | ab8500_charger_check_hw_failure_work); | 3252 | ab8500_charger_check_hw_failure_work); |
2629 | INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, | 3253 | INIT_DEFERRABLE_WORK(&di->check_usbchgnotok_work, |
2630 | ab8500_charger_check_usbchargernotok_work); | 3254 | ab8500_charger_check_usbchargernotok_work); |
2631 | 3255 | ||
3256 | INIT_DELAYED_WORK(&di->ac_charger_attached_work, | ||
3257 | ab8500_charger_ac_attached_work); | ||
3258 | INIT_DELAYED_WORK(&di->usb_charger_attached_work, | ||
3259 | ab8500_charger_usb_attached_work); | ||
3260 | |||
2632 | /* | 3261 | /* |
2633 | * For ABB revision 1.0 and 1.1 there is a bug in the watchdog | 3262 | * For ABB revision 1.0 and 1.1 there is a bug in the watchdog |
2634 | * logic. That means we have to continously kick the charger | 3263 | * logic. That means we have to continously kick the charger |
@@ -2644,6 +3273,15 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2644 | INIT_DEFERRABLE_WORK(&di->check_vbat_work, | 3273 | INIT_DEFERRABLE_WORK(&di->check_vbat_work, |
2645 | ab8500_charger_check_vbat_work); | 3274 | ab8500_charger_check_vbat_work); |
2646 | 3275 | ||
3276 | INIT_DELAYED_WORK(&di->attach_work, | ||
3277 | ab8500_charger_usb_link_attach_work); | ||
3278 | |||
3279 | INIT_DELAYED_WORK(&di->usb_state_changed_work, | ||
3280 | ab8500_charger_usb_state_changed_work); | ||
3281 | |||
3282 | INIT_DELAYED_WORK(&di->vbus_drop_end_work, | ||
3283 | ab8500_charger_vbus_drop_end_work); | ||
3284 | |||
2647 | /* Init work for charger detection */ | 3285 | /* Init work for charger detection */ |
2648 | INIT_WORK(&di->usb_link_status_work, | 3286 | INIT_WORK(&di->usb_link_status_work, |
2649 | ab8500_charger_usb_link_status_work); | 3287 | ab8500_charger_usb_link_status_work); |
@@ -2651,9 +3289,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2651 | INIT_WORK(&di->detect_usb_type_work, | 3289 | INIT_WORK(&di->detect_usb_type_work, |
2652 | ab8500_charger_detect_usb_type_work); | 3290 | ab8500_charger_detect_usb_type_work); |
2653 | 3291 | ||
2654 | INIT_WORK(&di->usb_state_changed_work, | ||
2655 | ab8500_charger_usb_state_changed_work); | ||
2656 | |||
2657 | /* Init work for checking HW status */ | 3292 | /* Init work for checking HW status */ |
2658 | INIT_WORK(&di->check_main_thermal_prot_work, | 3293 | INIT_WORK(&di->check_main_thermal_prot_work, |
2659 | ab8500_charger_check_main_thermal_prot_work); | 3294 | ab8500_charger_check_main_thermal_prot_work); |
@@ -2665,7 +3300,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2665 | * is a charger connected to avoid erroneous BTEMP_HIGH/LOW | 3300 | * is a charger connected to avoid erroneous BTEMP_HIGH/LOW |
2666 | * interrupts during charging | 3301 | * interrupts during charging |
2667 | */ | 3302 | */ |
2668 | di->regu = regulator_get(di->dev, "vddadc"); | 3303 | di->regu = devm_regulator_get(di->dev, "vddadc"); |
2669 | if (IS_ERR(di->regu)) { | 3304 | if (IS_ERR(di->regu)) { |
2670 | ret = PTR_ERR(di->regu); | 3305 | ret = PTR_ERR(di->regu); |
2671 | dev_err(di->dev, "failed to get vddadc regulator\n"); | 3306 | dev_err(di->dev, "failed to get vddadc regulator\n"); |
@@ -2677,21 +3312,25 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2677 | ret = ab8500_charger_init_hw_registers(di); | 3312 | ret = ab8500_charger_init_hw_registers(di); |
2678 | if (ret) { | 3313 | if (ret) { |
2679 | dev_err(di->dev, "failed to initialize ABB registers\n"); | 3314 | dev_err(di->dev, "failed to initialize ABB registers\n"); |
2680 | goto free_regulator; | 3315 | goto free_charger_wq; |
2681 | } | 3316 | } |
2682 | 3317 | ||
2683 | /* Register AC charger class */ | 3318 | /* Register AC charger class */ |
2684 | ret = power_supply_register(di->dev, &di->ac_chg.psy); | 3319 | if(di->ac_chg.enabled) { |
2685 | if (ret) { | 3320 | ret = power_supply_register(di->dev, &di->ac_chg.psy); |
2686 | dev_err(di->dev, "failed to register AC charger\n"); | 3321 | if (ret) { |
2687 | goto free_regulator; | 3322 | dev_err(di->dev, "failed to register AC charger\n"); |
3323 | goto free_charger_wq; | ||
3324 | } | ||
2688 | } | 3325 | } |
2689 | 3326 | ||
2690 | /* Register USB charger class */ | 3327 | /* Register USB charger class */ |
2691 | ret = power_supply_register(di->dev, &di->usb_chg.psy); | 3328 | if(di->usb_chg.enabled) { |
2692 | if (ret) { | 3329 | ret = power_supply_register(di->dev, &di->usb_chg.psy); |
2693 | dev_err(di->dev, "failed to register USB charger\n"); | 3330 | if (ret) { |
2694 | goto free_ac; | 3331 | dev_err(di->dev, "failed to register USB charger\n"); |
3332 | goto free_ac; | ||
3333 | } | ||
2695 | } | 3334 | } |
2696 | 3335 | ||
2697 | di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); | 3336 | di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); |
@@ -2708,7 +3347,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2708 | } | 3347 | } |
2709 | 3348 | ||
2710 | /* Identify the connected charger types during startup */ | 3349 | /* Identify the connected charger types during startup */ |
2711 | charger_status = ab8500_charger_detect_chargers(di); | 3350 | charger_status = ab8500_charger_detect_chargers(di, true); |
2712 | if (charger_status & AC_PW_CONN) { | 3351 | if (charger_status & AC_PW_CONN) { |
2713 | di->ac.charger_connected = 1; | 3352 | di->ac.charger_connected = 1; |
2714 | di->ac_conn = true; | 3353 | di->ac_conn = true; |
@@ -2717,7 +3356,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2717 | } | 3356 | } |
2718 | 3357 | ||
2719 | if (charger_status & USB_PW_CONN) { | 3358 | if (charger_status & USB_PW_CONN) { |
2720 | dev_dbg(di->dev, "VBUS Detect during startup\n"); | ||
2721 | di->vbus_detected = true; | 3359 | di->vbus_detected = true; |
2722 | di->vbus_detected_start = true; | 3360 | di->vbus_detected_start = true; |
2723 | queue_work(di->charger_wq, | 3361 | queue_work(di->charger_wq, |
@@ -2742,6 +3380,23 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2742 | 3380 | ||
2743 | platform_set_drvdata(pdev, di); | 3381 | platform_set_drvdata(pdev, di); |
2744 | 3382 | ||
3383 | mutex_lock(&di->charger_attached_mutex); | ||
3384 | |||
3385 | ch_stat = ab8500_charger_detect_chargers(di, false); | ||
3386 | |||
3387 | if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) { | ||
3388 | queue_delayed_work(di->charger_wq, | ||
3389 | &di->ac_charger_attached_work, | ||
3390 | HZ); | ||
3391 | } | ||
3392 | if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) { | ||
3393 | queue_delayed_work(di->charger_wq, | ||
3394 | &di->usb_charger_attached_work, | ||
3395 | HZ); | ||
3396 | } | ||
3397 | |||
3398 | mutex_unlock(&di->charger_attached_mutex); | ||
3399 | |||
2745 | return ret; | 3400 | return ret; |
2746 | 3401 | ||
2747 | free_irq: | 3402 | free_irq: |
@@ -2755,11 +3410,11 @@ free_irq: | |||
2755 | put_usb_phy: | 3410 | put_usb_phy: |
2756 | usb_put_phy(di->usb_phy); | 3411 | usb_put_phy(di->usb_phy); |
2757 | free_usb: | 3412 | free_usb: |
2758 | power_supply_unregister(&di->usb_chg.psy); | 3413 | if(di->usb_chg.enabled) |
3414 | power_supply_unregister(&di->usb_chg.psy); | ||
2759 | free_ac: | 3415 | free_ac: |
2760 | power_supply_unregister(&di->ac_chg.psy); | 3416 | if(di->ac_chg.enabled) |
2761 | free_regulator: | 3417 | power_supply_unregister(&di->ac_chg.psy); |
2762 | regulator_put(di->regu); | ||
2763 | free_charger_wq: | 3418 | free_charger_wq: |
2764 | destroy_workqueue(di->charger_wq); | 3419 | destroy_workqueue(di->charger_wq); |
2765 | return ret; | 3420 | return ret; |
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index b3bf178c3462..25dae4c4b0ef 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mfd/abx500/ab8500.h> | 32 | #include <linux/mfd/abx500/ab8500.h> |
33 | #include <linux/mfd/abx500/ab8500-bm.h> | 33 | #include <linux/mfd/abx500/ab8500-bm.h> |
34 | #include <linux/mfd/abx500/ab8500-gpadc.h> | 34 | #include <linux/mfd/abx500/ab8500-gpadc.h> |
35 | #include <linux/kernel.h> | ||
35 | 36 | ||
36 | #define MILLI_TO_MICRO 1000 | 37 | #define MILLI_TO_MICRO 1000 |
37 | #define FG_LSB_IN_MA 1627 | 38 | #define FG_LSB_IN_MA 1627 |
@@ -42,7 +43,7 @@ | |||
42 | 43 | ||
43 | #define NBR_AVG_SAMPLES 20 | 44 | #define NBR_AVG_SAMPLES 20 |
44 | 45 | ||
45 | #define LOW_BAT_CHECK_INTERVAL (2 * HZ) | 46 | #define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */ |
46 | 47 | ||
47 | #define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */ | 48 | #define VALID_CAPACITY_SEC (45 * 60) /* 45 minutes */ |
48 | #define BATT_OK_MIN 2360 /* mV */ | 49 | #define BATT_OK_MIN 2360 /* mV */ |
@@ -113,6 +114,13 @@ struct ab8500_fg_avg_cap { | |||
113 | int sum; | 114 | int sum; |
114 | }; | 115 | }; |
115 | 116 | ||
117 | struct ab8500_fg_cap_scaling { | ||
118 | bool enable; | ||
119 | int cap_to_scale[2]; | ||
120 | int disable_cap_level; | ||
121 | int scaled_cap; | ||
122 | }; | ||
123 | |||
116 | struct ab8500_fg_battery_capacity { | 124 | struct ab8500_fg_battery_capacity { |
117 | int max_mah_design; | 125 | int max_mah_design; |
118 | int max_mah; | 126 | int max_mah; |
@@ -123,6 +131,7 @@ struct ab8500_fg_battery_capacity { | |||
123 | int prev_percent; | 131 | int prev_percent; |
124 | int prev_level; | 132 | int prev_level; |
125 | int user_mah; | 133 | int user_mah; |
134 | struct ab8500_fg_cap_scaling cap_scale; | ||
126 | }; | 135 | }; |
127 | 136 | ||
128 | struct ab8500_fg_flags { | 137 | struct ab8500_fg_flags { |
@@ -160,6 +169,8 @@ struct inst_curr_result_list { | |||
160 | * @recovery_cnt: Counter for recovery mode | 169 | * @recovery_cnt: Counter for recovery mode |
161 | * @high_curr_cnt: Counter for high current mode | 170 | * @high_curr_cnt: Counter for high current mode |
162 | * @init_cnt: Counter for init mode | 171 | * @init_cnt: Counter for init mode |
172 | * @low_bat_cnt Counter for number of consecutive low battery measures | ||
173 | * @nbr_cceoc_irq_cnt Counter for number of CCEOC irqs received since enabled | ||
163 | * @recovery_needed: Indicate if recovery is needed | 174 | * @recovery_needed: Indicate if recovery is needed |
164 | * @high_curr_mode: Indicate if we're in high current mode | 175 | * @high_curr_mode: Indicate if we're in high current mode |
165 | * @init_capacity: Indicate if initial capacity measuring should be done | 176 | * @init_capacity: Indicate if initial capacity measuring should be done |
@@ -167,13 +178,14 @@ struct inst_curr_result_list { | |||
167 | * @calib_state State during offset calibration | 178 | * @calib_state State during offset calibration |
168 | * @discharge_state: Current discharge state | 179 | * @discharge_state: Current discharge state |
169 | * @charge_state: Current charge state | 180 | * @charge_state: Current charge state |
181 | * @ab8500_fg_started Completion struct used for the instant current start | ||
170 | * @ab8500_fg_complete Completion struct used for the instant current reading | 182 | * @ab8500_fg_complete Completion struct used for the instant current reading |
171 | * @flags: Structure for information about events triggered | 183 | * @flags: Structure for information about events triggered |
172 | * @bat_cap: Structure for battery capacity specific parameters | 184 | * @bat_cap: Structure for battery capacity specific parameters |
173 | * @avg_cap: Average capacity filter | 185 | * @avg_cap: Average capacity filter |
174 | * @parent: Pointer to the struct ab8500 | 186 | * @parent: Pointer to the struct ab8500 |
175 | * @gpadc: Pointer to the struct gpadc | 187 | * @gpadc: Pointer to the struct gpadc |
176 | * @bat: Pointer to the abx500_bm platform data | 188 | * @bm: Platform specific battery management information |
177 | * @fg_psy: Structure that holds the FG specific battery properties | 189 | * @fg_psy: Structure that holds the FG specific battery properties |
178 | * @fg_wq: Work queue for running the FG algorithm | 190 | * @fg_wq: Work queue for running the FG algorithm |
179 | * @fg_periodic_work: Work to run the FG algorithm periodically | 191 | * @fg_periodic_work: Work to run the FG algorithm periodically |
@@ -199,6 +211,8 @@ struct ab8500_fg { | |||
199 | int recovery_cnt; | 211 | int recovery_cnt; |
200 | int high_curr_cnt; | 212 | int high_curr_cnt; |
201 | int init_cnt; | 213 | int init_cnt; |
214 | int low_bat_cnt; | ||
215 | int nbr_cceoc_irq_cnt; | ||
202 | bool recovery_needed; | 216 | bool recovery_needed; |
203 | bool high_curr_mode; | 217 | bool high_curr_mode; |
204 | bool init_capacity; | 218 | bool init_capacity; |
@@ -206,13 +220,14 @@ struct ab8500_fg { | |||
206 | enum ab8500_fg_calibration_state calib_state; | 220 | enum ab8500_fg_calibration_state calib_state; |
207 | enum ab8500_fg_discharge_state discharge_state; | 221 | enum ab8500_fg_discharge_state discharge_state; |
208 | enum ab8500_fg_charge_state charge_state; | 222 | enum ab8500_fg_charge_state charge_state; |
223 | struct completion ab8500_fg_started; | ||
209 | struct completion ab8500_fg_complete; | 224 | struct completion ab8500_fg_complete; |
210 | struct ab8500_fg_flags flags; | 225 | struct ab8500_fg_flags flags; |
211 | struct ab8500_fg_battery_capacity bat_cap; | 226 | struct ab8500_fg_battery_capacity bat_cap; |
212 | struct ab8500_fg_avg_cap avg_cap; | 227 | struct ab8500_fg_avg_cap avg_cap; |
213 | struct ab8500 *parent; | 228 | struct ab8500 *parent; |
214 | struct ab8500_gpadc *gpadc; | 229 | struct ab8500_gpadc *gpadc; |
215 | struct abx500_bm_data *bat; | 230 | struct abx500_bm_data *bm; |
216 | struct power_supply fg_psy; | 231 | struct power_supply fg_psy; |
217 | struct workqueue_struct *fg_wq; | 232 | struct workqueue_struct *fg_wq; |
218 | struct delayed_work fg_periodic_work; | 233 | struct delayed_work fg_periodic_work; |
@@ -355,7 +370,7 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr) | |||
355 | /* | 370 | /* |
356 | * We want to know if we're in low current mode | 371 | * We want to know if we're in low current mode |
357 | */ | 372 | */ |
358 | if (curr > -di->bat->fg_params->high_curr_threshold) | 373 | if (curr > -di->bm->fg_params->high_curr_threshold) |
359 | return true; | 374 | return true; |
360 | else | 375 | else |
361 | return false; | 376 | return false; |
@@ -484,8 +499,9 @@ static int ab8500_fg_coulomb_counter(struct ab8500_fg *di, bool enable) | |||
484 | di->flags.fg_enabled = true; | 499 | di->flags.fg_enabled = true; |
485 | } else { | 500 | } else { |
486 | /* Clear any pending read requests */ | 501 | /* Clear any pending read requests */ |
487 | ret = abx500_set_register_interruptible(di->dev, | 502 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
488 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, 0); | 503 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, |
504 | (RESET_ACCU | READ_REQ), 0); | ||
489 | if (ret) | 505 | if (ret) |
490 | goto cc_err; | 506 | goto cc_err; |
491 | 507 | ||
@@ -523,13 +539,14 @@ cc_err: | |||
523 | * Note: This is part "one" and has to be called before | 539 | * Note: This is part "one" and has to be called before |
524 | * ab8500_fg_inst_curr_finalize() | 540 | * ab8500_fg_inst_curr_finalize() |
525 | */ | 541 | */ |
526 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di) | 542 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di) |
527 | { | 543 | { |
528 | u8 reg_val; | 544 | u8 reg_val; |
529 | int ret; | 545 | int ret; |
530 | 546 | ||
531 | mutex_lock(&di->cc_lock); | 547 | mutex_lock(&di->cc_lock); |
532 | 548 | ||
549 | di->nbr_cceoc_irq_cnt = 0; | ||
533 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, | 550 | ret = abx500_get_register_interruptible(di->dev, AB8500_RTC, |
534 | AB8500_RTC_CC_CONF_REG, ®_val); | 551 | AB8500_RTC_CC_CONF_REG, ®_val); |
535 | if (ret < 0) | 552 | if (ret < 0) |
@@ -557,6 +574,7 @@ cc_err: | |||
557 | } | 574 | } |
558 | 575 | ||
559 | /* Return and WFI */ | 576 | /* Return and WFI */ |
577 | INIT_COMPLETION(di->ab8500_fg_started); | ||
560 | INIT_COMPLETION(di->ab8500_fg_complete); | 578 | INIT_COMPLETION(di->ab8500_fg_complete); |
561 | enable_irq(di->irq); | 579 | enable_irq(di->irq); |
562 | 580 | ||
@@ -568,6 +586,17 @@ fail: | |||
568 | } | 586 | } |
569 | 587 | ||
570 | /** | 588 | /** |
589 | * ab8500_fg_inst_curr_started() - check if fg conversion has started | ||
590 | * @di: pointer to the ab8500_fg structure | ||
591 | * | ||
592 | * Returns 1 if conversion started, 0 if still waiting | ||
593 | */ | ||
594 | int ab8500_fg_inst_curr_started(struct ab8500_fg *di) | ||
595 | { | ||
596 | return completion_done(&di->ab8500_fg_started); | ||
597 | } | ||
598 | |||
599 | /** | ||
571 | * ab8500_fg_inst_curr_done() - check if fg conversion is done | 600 | * ab8500_fg_inst_curr_done() - check if fg conversion is done |
572 | * @di: pointer to the ab8500_fg structure | 601 | * @di: pointer to the ab8500_fg structure |
573 | * | 602 | * |
@@ -595,13 +624,15 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | |||
595 | int timeout; | 624 | int timeout; |
596 | 625 | ||
597 | if (!completion_done(&di->ab8500_fg_complete)) { | 626 | if (!completion_done(&di->ab8500_fg_complete)) { |
598 | timeout = wait_for_completion_timeout(&di->ab8500_fg_complete, | 627 | timeout = wait_for_completion_timeout( |
628 | &di->ab8500_fg_complete, | ||
599 | INS_CURR_TIMEOUT); | 629 | INS_CURR_TIMEOUT); |
600 | dev_dbg(di->dev, "Finalize time: %d ms\n", | 630 | dev_dbg(di->dev, "Finalize time: %d ms\n", |
601 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); | 631 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); |
602 | if (!timeout) { | 632 | if (!timeout) { |
603 | ret = -ETIME; | 633 | ret = -ETIME; |
604 | disable_irq(di->irq); | 634 | disable_irq(di->irq); |
635 | di->nbr_cceoc_irq_cnt = 0; | ||
605 | dev_err(di->dev, "completion timed out [%d]\n", | 636 | dev_err(di->dev, "completion timed out [%d]\n", |
606 | __LINE__); | 637 | __LINE__); |
607 | goto fail; | 638 | goto fail; |
@@ -609,6 +640,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | |||
609 | } | 640 | } |
610 | 641 | ||
611 | disable_irq(di->irq); | 642 | disable_irq(di->irq); |
643 | di->nbr_cceoc_irq_cnt = 0; | ||
612 | 644 | ||
613 | ret = abx500_mask_and_set_register_interruptible(di->dev, | 645 | ret = abx500_mask_and_set_register_interruptible(di->dev, |
614 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, | 646 | AB8500_GAS_GAUGE, AB8500_GASG_CC_CTRL_REG, |
@@ -647,7 +679,7 @@ int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | |||
647 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | 679 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm |
648 | */ | 680 | */ |
649 | val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) / | 681 | val = (val * QLSB_NANO_AMP_HOURS_X10 * 36 * 4) / |
650 | (1000 * di->bat->fg_res); | 682 | (1000 * di->bm->fg_res); |
651 | 683 | ||
652 | if (di->turn_off_fg) { | 684 | if (di->turn_off_fg) { |
653 | dev_dbg(di->dev, "%s Disable FG\n", __func__); | 685 | dev_dbg(di->dev, "%s Disable FG\n", __func__); |
@@ -683,6 +715,7 @@ fail: | |||
683 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) | 715 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) |
684 | { | 716 | { |
685 | int ret; | 717 | int ret; |
718 | int timeout; | ||
686 | int res = 0; | 719 | int res = 0; |
687 | 720 | ||
688 | ret = ab8500_fg_inst_curr_start(di); | 721 | ret = ab8500_fg_inst_curr_start(di); |
@@ -691,13 +724,33 @@ int ab8500_fg_inst_curr_blocking(struct ab8500_fg *di) | |||
691 | return 0; | 724 | return 0; |
692 | } | 725 | } |
693 | 726 | ||
727 | /* Wait for CC to actually start */ | ||
728 | if (!completion_done(&di->ab8500_fg_started)) { | ||
729 | timeout = wait_for_completion_timeout( | ||
730 | &di->ab8500_fg_started, | ||
731 | INS_CURR_TIMEOUT); | ||
732 | dev_dbg(di->dev, "Start time: %d ms\n", | ||
733 | ((INS_CURR_TIMEOUT - timeout) * 1000) / HZ); | ||
734 | if (!timeout) { | ||
735 | ret = -ETIME; | ||
736 | dev_err(di->dev, "completion timed out [%d]\n", | ||
737 | __LINE__); | ||
738 | goto fail; | ||
739 | } | ||
740 | } | ||
741 | |||
694 | ret = ab8500_fg_inst_curr_finalize(di, &res); | 742 | ret = ab8500_fg_inst_curr_finalize(di, &res); |
695 | if (ret) { | 743 | if (ret) { |
696 | dev_err(di->dev, "Failed to finalize fg_inst\n"); | 744 | dev_err(di->dev, "Failed to finalize fg_inst\n"); |
697 | return 0; | 745 | return 0; |
698 | } | 746 | } |
699 | 747 | ||
748 | dev_dbg(di->dev, "%s instant current: %d", __func__, res); | ||
700 | return res; | 749 | return res; |
750 | fail: | ||
751 | disable_irq(di->irq); | ||
752 | mutex_unlock(&di->cc_lock); | ||
753 | return ret; | ||
701 | } | 754 | } |
702 | 755 | ||
703 | /** | 756 | /** |
@@ -750,19 +803,16 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work) | |||
750 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | 803 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm |
751 | */ | 804 | */ |
752 | di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) / | 805 | di->accu_charge = (val * QLSB_NANO_AMP_HOURS_X10) / |
753 | (100 * di->bat->fg_res); | 806 | (100 * di->bm->fg_res); |
754 | 807 | ||
755 | /* | 808 | /* |
756 | * Convert to unit value in mA | 809 | * Convert to unit value in mA |
757 | * Full scale input voltage is | 810 | * by dividing by the conversion |
758 | * 66.660mV => LSB = 66.660mV/(4096*res) = 1.627mA | ||
759 | * Given a 250ms conversion cycle time the LSB corresponds | ||
760 | * to 112.9 nAh. Convert to current by dividing by the conversion | ||
761 | * time in hours (= samples / (3600 * 4)h) | 811 | * time in hours (= samples / (3600 * 4)h) |
762 | * 112.9nAh assumes 10mOhm, but fg_res is in 0.1mOhm | 812 | * and multiply with 1000 |
763 | */ | 813 | */ |
764 | di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) / | 814 | di->avg_curr = (val * QLSB_NANO_AMP_HOURS_X10 * 36) / |
765 | (1000 * di->bat->fg_res * (di->fg_samples / 4)); | 815 | (1000 * di->bm->fg_res * (di->fg_samples / 4)); |
766 | 816 | ||
767 | di->flags.conv_done = true; | 817 | di->flags.conv_done = true; |
768 | 818 | ||
@@ -770,6 +820,8 @@ static void ab8500_fg_acc_cur_work(struct work_struct *work) | |||
770 | 820 | ||
771 | queue_work(di->fg_wq, &di->fg_work); | 821 | queue_work(di->fg_wq, &di->fg_work); |
772 | 822 | ||
823 | dev_dbg(di->dev, "fg_res: %d, fg_samples: %d, gasg: %d, accu_charge: %d \n", | ||
824 | di->bm->fg_res, di->fg_samples, val, di->accu_charge); | ||
773 | return; | 825 | return; |
774 | exit: | 826 | exit: |
775 | dev_err(di->dev, | 827 | dev_err(di->dev, |
@@ -814,8 +866,8 @@ static int ab8500_fg_volt_to_capacity(struct ab8500_fg *di, int voltage) | |||
814 | struct abx500_v_to_cap *tbl; | 866 | struct abx500_v_to_cap *tbl; |
815 | int cap = 0; | 867 | int cap = 0; |
816 | 868 | ||
817 | tbl = di->bat->bat_type[di->bat->batt_id].v_to_cap_tbl, | 869 | tbl = di->bm->bat_type[di->bm->batt_id].v_to_cap_tbl, |
818 | tbl_size = di->bat->bat_type[di->bat->batt_id].n_v_cap_tbl_elements; | 870 | tbl_size = di->bm->bat_type[di->bm->batt_id].n_v_cap_tbl_elements; |
819 | 871 | ||
820 | for (i = 0; i < tbl_size; ++i) { | 872 | for (i = 0; i < tbl_size; ++i) { |
821 | if (voltage > tbl[i].voltage) | 873 | if (voltage > tbl[i].voltage) |
@@ -866,8 +918,8 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di) | |||
866 | struct batres_vs_temp *tbl; | 918 | struct batres_vs_temp *tbl; |
867 | int resist = 0; | 919 | int resist = 0; |
868 | 920 | ||
869 | tbl = di->bat->bat_type[di->bat->batt_id].batres_tbl; | 921 | tbl = di->bm->bat_type[di->bm->batt_id].batres_tbl; |
870 | tbl_size = di->bat->bat_type[di->bat->batt_id].n_batres_tbl_elements; | 922 | tbl_size = di->bm->bat_type[di->bm->batt_id].n_batres_tbl_elements; |
871 | 923 | ||
872 | for (i = 0; i < tbl_size; ++i) { | 924 | for (i = 0; i < tbl_size; ++i) { |
873 | if (di->bat_temp / 10 > tbl[i].temp) | 925 | if (di->bat_temp / 10 > tbl[i].temp) |
@@ -888,11 +940,11 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di) | |||
888 | 940 | ||
889 | dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d" | 941 | dev_dbg(di->dev, "%s Temp: %d battery internal resistance: %d" |
890 | " fg resistance %d, total: %d (mOhm)\n", | 942 | " fg resistance %d, total: %d (mOhm)\n", |
891 | __func__, di->bat_temp, resist, di->bat->fg_res / 10, | 943 | __func__, di->bat_temp, resist, di->bm->fg_res / 10, |
892 | (di->bat->fg_res / 10) + resist); | 944 | (di->bm->fg_res / 10) + resist); |
893 | 945 | ||
894 | /* fg_res variable is in 0.1mOhm */ | 946 | /* fg_res variable is in 0.1mOhm */ |
895 | resist += di->bat->fg_res / 10; | 947 | resist += di->bm->fg_res / 10; |
896 | 948 | ||
897 | return resist; | 949 | return resist; |
898 | } | 950 | } |
@@ -915,7 +967,7 @@ static int ab8500_fg_load_comp_volt_to_capacity(struct ab8500_fg *di) | |||
915 | do { | 967 | do { |
916 | vbat += ab8500_fg_bat_voltage(di); | 968 | vbat += ab8500_fg_bat_voltage(di); |
917 | i++; | 969 | i++; |
918 | msleep(5); | 970 | usleep_range(5000, 6000); |
919 | } while (!ab8500_fg_inst_curr_done(di)); | 971 | } while (!ab8500_fg_inst_curr_done(di)); |
920 | 972 | ||
921 | ab8500_fg_inst_curr_finalize(di, &di->inst_curr); | 973 | ab8500_fg_inst_curr_finalize(di, &di->inst_curr); |
@@ -1108,16 +1160,16 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di) | |||
1108 | { | 1160 | { |
1109 | int ret, percent; | 1161 | int ret, percent; |
1110 | 1162 | ||
1111 | percent = di->bat_cap.permille / 10; | 1163 | percent = DIV_ROUND_CLOSEST(di->bat_cap.permille, 10); |
1112 | 1164 | ||
1113 | if (percent <= di->bat->cap_levels->critical || | 1165 | if (percent <= di->bm->cap_levels->critical || |
1114 | di->flags.low_bat) | 1166 | di->flags.low_bat) |
1115 | ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | 1167 | ret = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; |
1116 | else if (percent <= di->bat->cap_levels->low) | 1168 | else if (percent <= di->bm->cap_levels->low) |
1117 | ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | 1169 | ret = POWER_SUPPLY_CAPACITY_LEVEL_LOW; |
1118 | else if (percent <= di->bat->cap_levels->normal) | 1170 | else if (percent <= di->bm->cap_levels->normal) |
1119 | ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | 1171 | ret = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; |
1120 | else if (percent <= di->bat->cap_levels->high) | 1172 | else if (percent <= di->bm->cap_levels->high) |
1121 | ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; | 1173 | ret = POWER_SUPPLY_CAPACITY_LEVEL_HIGH; |
1122 | else | 1174 | else |
1123 | ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | 1175 | ret = POWER_SUPPLY_CAPACITY_LEVEL_FULL; |
@@ -1126,6 +1178,99 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di) | |||
1126 | } | 1178 | } |
1127 | 1179 | ||
1128 | /** | 1180 | /** |
1181 | * ab8500_fg_calculate_scaled_capacity() - Capacity scaling | ||
1182 | * @di: pointer to the ab8500_fg structure | ||
1183 | * | ||
1184 | * Calculates the capacity to be shown to upper layers. Scales the capacity | ||
1185 | * to have 100% as a reference from the actual capacity upon removal of charger | ||
1186 | * when charging is in maintenance mode. | ||
1187 | */ | ||
1188 | static int ab8500_fg_calculate_scaled_capacity(struct ab8500_fg *di) | ||
1189 | { | ||
1190 | struct ab8500_fg_cap_scaling *cs = &di->bat_cap.cap_scale; | ||
1191 | int capacity = di->bat_cap.prev_percent; | ||
1192 | |||
1193 | if (!cs->enable) | ||
1194 | return capacity; | ||
1195 | |||
1196 | /* | ||
1197 | * As long as we are in fully charge mode scale the capacity | ||
1198 | * to show 100%. | ||
1199 | */ | ||
1200 | if (di->flags.fully_charged) { | ||
1201 | cs->cap_to_scale[0] = 100; | ||
1202 | cs->cap_to_scale[1] = | ||
1203 | max(capacity, di->bm->fg_params->maint_thres); | ||
1204 | dev_dbg(di->dev, "Scale cap with %d/%d\n", | ||
1205 | cs->cap_to_scale[0], cs->cap_to_scale[1]); | ||
1206 | } | ||
1207 | |||
1208 | /* Calculates the scaled capacity. */ | ||
1209 | if ((cs->cap_to_scale[0] != cs->cap_to_scale[1]) | ||
1210 | && (cs->cap_to_scale[1] > 0)) | ||
1211 | capacity = min(100, | ||
1212 | DIV_ROUND_CLOSEST(di->bat_cap.prev_percent * | ||
1213 | cs->cap_to_scale[0], | ||
1214 | cs->cap_to_scale[1])); | ||
1215 | |||
1216 | if (di->flags.charging) { | ||
1217 | if (capacity < cs->disable_cap_level) { | ||
1218 | cs->disable_cap_level = capacity; | ||
1219 | dev_dbg(di->dev, "Cap to stop scale lowered %d%%\n", | ||
1220 | cs->disable_cap_level); | ||
1221 | } else if (!di->flags.fully_charged) { | ||
1222 | if (di->bat_cap.prev_percent >= | ||
1223 | cs->disable_cap_level) { | ||
1224 | dev_dbg(di->dev, "Disabling scaled capacity\n"); | ||
1225 | cs->enable = false; | ||
1226 | capacity = di->bat_cap.prev_percent; | ||
1227 | } else { | ||
1228 | dev_dbg(di->dev, | ||
1229 | "Waiting in cap to level %d%%\n", | ||
1230 | cs->disable_cap_level); | ||
1231 | capacity = cs->disable_cap_level; | ||
1232 | } | ||
1233 | } | ||
1234 | } | ||
1235 | |||
1236 | return capacity; | ||
1237 | } | ||
1238 | |||
1239 | /** | ||
1240 | * ab8500_fg_update_cap_scalers() - Capacity scaling | ||
1241 | * @di: pointer to the ab8500_fg structure | ||
1242 | * | ||
1243 | * To be called when state change from charge<->discharge to update | ||
1244 | * the capacity scalers. | ||
1245 | */ | ||
1246 | static void ab8500_fg_update_cap_scalers(struct ab8500_fg *di) | ||
1247 | { | ||
1248 | struct ab8500_fg_cap_scaling *cs = &di->bat_cap.cap_scale; | ||
1249 | |||
1250 | if (!cs->enable) | ||
1251 | return; | ||
1252 | if (di->flags.charging) { | ||
1253 | di->bat_cap.cap_scale.disable_cap_level = | ||
1254 | di->bat_cap.cap_scale.scaled_cap; | ||
1255 | dev_dbg(di->dev, "Cap to stop scale at charge %d%%\n", | ||
1256 | di->bat_cap.cap_scale.disable_cap_level); | ||
1257 | } else { | ||
1258 | if (cs->scaled_cap != 100) { | ||
1259 | cs->cap_to_scale[0] = cs->scaled_cap; | ||
1260 | cs->cap_to_scale[1] = di->bat_cap.prev_percent; | ||
1261 | } else { | ||
1262 | cs->cap_to_scale[0] = 100; | ||
1263 | cs->cap_to_scale[1] = | ||
1264 | max(di->bat_cap.prev_percent, | ||
1265 | di->bm->fg_params->maint_thres); | ||
1266 | } | ||
1267 | |||
1268 | dev_dbg(di->dev, "Cap to scale at discharge %d/%d\n", | ||
1269 | cs->cap_to_scale[0], cs->cap_to_scale[1]); | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | /** | ||
1129 | * ab8500_fg_check_capacity_limits() - Check if capacity has changed | 1274 | * ab8500_fg_check_capacity_limits() - Check if capacity has changed |
1130 | * @di: pointer to the ab8500_fg structure | 1275 | * @di: pointer to the ab8500_fg structure |
1131 | * @init: capacity is allowed to go up in init mode | 1276 | * @init: capacity is allowed to go up in init mode |
@@ -1136,6 +1281,7 @@ static int ab8500_fg_capacity_level(struct ab8500_fg *di) | |||
1136 | static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | 1281 | static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) |
1137 | { | 1282 | { |
1138 | bool changed = false; | 1283 | bool changed = false; |
1284 | int percent = DIV_ROUND_CLOSEST(di->bat_cap.permille, 10); | ||
1139 | 1285 | ||
1140 | di->bat_cap.level = ab8500_fg_capacity_level(di); | 1286 | di->bat_cap.level = ab8500_fg_capacity_level(di); |
1141 | 1287 | ||
@@ -1167,33 +1313,41 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | |||
1167 | dev_dbg(di->dev, "Battery low, set capacity to 0\n"); | 1313 | dev_dbg(di->dev, "Battery low, set capacity to 0\n"); |
1168 | di->bat_cap.prev_percent = 0; | 1314 | di->bat_cap.prev_percent = 0; |
1169 | di->bat_cap.permille = 0; | 1315 | di->bat_cap.permille = 0; |
1316 | percent = 0; | ||
1170 | di->bat_cap.prev_mah = 0; | 1317 | di->bat_cap.prev_mah = 0; |
1171 | di->bat_cap.mah = 0; | 1318 | di->bat_cap.mah = 0; |
1172 | changed = true; | 1319 | changed = true; |
1173 | } else if (di->flags.fully_charged) { | 1320 | } else if (di->flags.fully_charged) { |
1174 | /* | 1321 | /* |
1175 | * We report 100% if algorithm reported fully charged | 1322 | * We report 100% if algorithm reported fully charged |
1176 | * unless capacity drops too much | 1323 | * and show 100% during maintenance charging (scaling). |
1177 | */ | 1324 | */ |
1178 | if (di->flags.force_full) { | 1325 | if (di->flags.force_full) { |
1179 | di->bat_cap.prev_percent = di->bat_cap.permille / 10; | 1326 | di->bat_cap.prev_percent = percent; |
1180 | di->bat_cap.prev_mah = di->bat_cap.mah; | 1327 | di->bat_cap.prev_mah = di->bat_cap.mah; |
1181 | } else if (!di->flags.force_full && | 1328 | |
1182 | di->bat_cap.prev_percent != | 1329 | changed = true; |
1183 | (di->bat_cap.permille) / 10 && | 1330 | |
1184 | (di->bat_cap.permille / 10) < | 1331 | if (!di->bat_cap.cap_scale.enable && |
1185 | di->bat->fg_params->maint_thres) { | 1332 | di->bm->capacity_scaling) { |
1333 | di->bat_cap.cap_scale.enable = true; | ||
1334 | di->bat_cap.cap_scale.cap_to_scale[0] = 100; | ||
1335 | di->bat_cap.cap_scale.cap_to_scale[1] = | ||
1336 | di->bat_cap.prev_percent; | ||
1337 | di->bat_cap.cap_scale.disable_cap_level = 100; | ||
1338 | } | ||
1339 | } else if (di->bat_cap.prev_percent != percent) { | ||
1186 | dev_dbg(di->dev, | 1340 | dev_dbg(di->dev, |
1187 | "battery reported full " | 1341 | "battery reported full " |
1188 | "but capacity dropping: %d\n", | 1342 | "but capacity dropping: %d\n", |
1189 | di->bat_cap.permille / 10); | 1343 | percent); |
1190 | di->bat_cap.prev_percent = di->bat_cap.permille / 10; | 1344 | di->bat_cap.prev_percent = percent; |
1191 | di->bat_cap.prev_mah = di->bat_cap.mah; | 1345 | di->bat_cap.prev_mah = di->bat_cap.mah; |
1192 | 1346 | ||
1193 | changed = true; | 1347 | changed = true; |
1194 | } | 1348 | } |
1195 | } else if (di->bat_cap.prev_percent != di->bat_cap.permille / 10) { | 1349 | } else if (di->bat_cap.prev_percent != percent) { |
1196 | if (di->bat_cap.permille / 10 == 0) { | 1350 | if (percent == 0) { |
1197 | /* | 1351 | /* |
1198 | * We will not report 0% unless we've got | 1352 | * We will not report 0% unless we've got |
1199 | * the LOW_BAT IRQ, no matter what the FG | 1353 | * the LOW_BAT IRQ, no matter what the FG |
@@ -1203,11 +1357,11 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | |||
1203 | di->bat_cap.permille = 1; | 1357 | di->bat_cap.permille = 1; |
1204 | di->bat_cap.prev_mah = 1; | 1358 | di->bat_cap.prev_mah = 1; |
1205 | di->bat_cap.mah = 1; | 1359 | di->bat_cap.mah = 1; |
1360 | percent = 1; | ||
1206 | 1361 | ||
1207 | changed = true; | 1362 | changed = true; |
1208 | } else if (!(!di->flags.charging && | 1363 | } else if (!(!di->flags.charging && |
1209 | (di->bat_cap.permille / 10) > | 1364 | percent > di->bat_cap.prev_percent) || init) { |
1210 | di->bat_cap.prev_percent) || init) { | ||
1211 | /* | 1365 | /* |
1212 | * We do not allow reported capacity to go up | 1366 | * We do not allow reported capacity to go up |
1213 | * unless we're charging or if we're in init | 1367 | * unless we're charging or if we're in init |
@@ -1215,9 +1369,9 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | |||
1215 | dev_dbg(di->dev, | 1369 | dev_dbg(di->dev, |
1216 | "capacity changed from %d to %d (%d)\n", | 1370 | "capacity changed from %d to %d (%d)\n", |
1217 | di->bat_cap.prev_percent, | 1371 | di->bat_cap.prev_percent, |
1218 | di->bat_cap.permille / 10, | 1372 | percent, |
1219 | di->bat_cap.permille); | 1373 | di->bat_cap.permille); |
1220 | di->bat_cap.prev_percent = di->bat_cap.permille / 10; | 1374 | di->bat_cap.prev_percent = percent; |
1221 | di->bat_cap.prev_mah = di->bat_cap.mah; | 1375 | di->bat_cap.prev_mah = di->bat_cap.mah; |
1222 | 1376 | ||
1223 | changed = true; | 1377 | changed = true; |
@@ -1225,12 +1379,20 @@ static void ab8500_fg_check_capacity_limits(struct ab8500_fg *di, bool init) | |||
1225 | dev_dbg(di->dev, "capacity not allowed to go up since " | 1379 | dev_dbg(di->dev, "capacity not allowed to go up since " |
1226 | "no charger is connected: %d to %d (%d)\n", | 1380 | "no charger is connected: %d to %d (%d)\n", |
1227 | di->bat_cap.prev_percent, | 1381 | di->bat_cap.prev_percent, |
1228 | di->bat_cap.permille / 10, | 1382 | percent, |
1229 | di->bat_cap.permille); | 1383 | di->bat_cap.permille); |
1230 | } | 1384 | } |
1231 | } | 1385 | } |
1232 | 1386 | ||
1233 | if (changed) { | 1387 | if (changed) { |
1388 | if (di->bm->capacity_scaling) { | ||
1389 | di->bat_cap.cap_scale.scaled_cap = | ||
1390 | ab8500_fg_calculate_scaled_capacity(di); | ||
1391 | |||
1392 | dev_info(di->dev, "capacity=%d (%d)\n", | ||
1393 | di->bat_cap.prev_percent, | ||
1394 | di->bat_cap.cap_scale.scaled_cap); | ||
1395 | } | ||
1234 | power_supply_changed(&di->fg_psy); | 1396 | power_supply_changed(&di->fg_psy); |
1235 | if (di->flags.fully_charged && di->flags.force_full) { | 1397 | if (di->flags.fully_charged && di->flags.force_full) { |
1236 | dev_dbg(di->dev, "Battery full, notifying.\n"); | 1398 | dev_dbg(di->dev, "Battery full, notifying.\n"); |
@@ -1284,7 +1446,7 @@ static void ab8500_fg_algorithm_charging(struct ab8500_fg *di) | |||
1284 | switch (di->charge_state) { | 1446 | switch (di->charge_state) { |
1285 | case AB8500_FG_CHARGE_INIT: | 1447 | case AB8500_FG_CHARGE_INIT: |
1286 | di->fg_samples = SEC_TO_SAMPLE( | 1448 | di->fg_samples = SEC_TO_SAMPLE( |
1287 | di->bat->fg_params->accu_charging); | 1449 | di->bm->fg_params->accu_charging); |
1288 | 1450 | ||
1289 | ab8500_fg_coulomb_counter(di, true); | 1451 | ab8500_fg_coulomb_counter(di, true); |
1290 | ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT); | 1452 | ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_READOUT); |
@@ -1296,7 +1458,7 @@ static void ab8500_fg_algorithm_charging(struct ab8500_fg *di) | |||
1296 | * Read the FG and calculate the new capacity | 1458 | * Read the FG and calculate the new capacity |
1297 | */ | 1459 | */ |
1298 | mutex_lock(&di->cc_lock); | 1460 | mutex_lock(&di->cc_lock); |
1299 | if (!di->flags.conv_done) { | 1461 | if (!di->flags.conv_done && !di->flags.force_full) { |
1300 | /* Wasn't the CC IRQ that got us here */ | 1462 | /* Wasn't the CC IRQ that got us here */ |
1301 | mutex_unlock(&di->cc_lock); | 1463 | mutex_unlock(&di->cc_lock); |
1302 | dev_dbg(di->dev, "%s CC conv not done\n", | 1464 | dev_dbg(di->dev, "%s CC conv not done\n", |
@@ -1346,8 +1508,8 @@ static bool check_sysfs_capacity(struct ab8500_fg *di) | |||
1346 | cap_permille = ab8500_fg_convert_mah_to_permille(di, | 1508 | cap_permille = ab8500_fg_convert_mah_to_permille(di, |
1347 | di->bat_cap.user_mah); | 1509 | di->bat_cap.user_mah); |
1348 | 1510 | ||
1349 | lower = di->bat_cap.permille - di->bat->fg_params->user_cap_limit * 10; | 1511 | lower = di->bat_cap.permille - di->bm->fg_params->user_cap_limit * 10; |
1350 | upper = di->bat_cap.permille + di->bat->fg_params->user_cap_limit * 10; | 1512 | upper = di->bat_cap.permille + di->bm->fg_params->user_cap_limit * 10; |
1351 | 1513 | ||
1352 | if (lower < 0) | 1514 | if (lower < 0) |
1353 | lower = 0; | 1515 | lower = 0; |
@@ -1387,7 +1549,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1387 | case AB8500_FG_DISCHARGE_INIT: | 1549 | case AB8500_FG_DISCHARGE_INIT: |
1388 | /* We use the FG IRQ to work on */ | 1550 | /* We use the FG IRQ to work on */ |
1389 | di->init_cnt = 0; | 1551 | di->init_cnt = 0; |
1390 | di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); | 1552 | di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); |
1391 | ab8500_fg_coulomb_counter(di, true); | 1553 | ab8500_fg_coulomb_counter(di, true); |
1392 | ab8500_fg_discharge_state_to(di, | 1554 | ab8500_fg_discharge_state_to(di, |
1393 | AB8500_FG_DISCHARGE_INITMEASURING); | 1555 | AB8500_FG_DISCHARGE_INITMEASURING); |
@@ -1400,18 +1562,17 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1400 | * samples to get an initial capacity. | 1562 | * samples to get an initial capacity. |
1401 | * Then go to READOUT | 1563 | * Then go to READOUT |
1402 | */ | 1564 | */ |
1403 | sleep_time = di->bat->fg_params->init_timer; | 1565 | sleep_time = di->bm->fg_params->init_timer; |
1404 | 1566 | ||
1405 | /* Discard the first [x] seconds */ | 1567 | /* Discard the first [x] seconds */ |
1406 | if (di->init_cnt > | 1568 | if (di->init_cnt > di->bm->fg_params->init_discard_time) { |
1407 | di->bat->fg_params->init_discard_time) { | ||
1408 | ab8500_fg_calc_cap_discharge_voltage(di, true); | 1569 | ab8500_fg_calc_cap_discharge_voltage(di, true); |
1409 | 1570 | ||
1410 | ab8500_fg_check_capacity_limits(di, true); | 1571 | ab8500_fg_check_capacity_limits(di, true); |
1411 | } | 1572 | } |
1412 | 1573 | ||
1413 | di->init_cnt += sleep_time; | 1574 | di->init_cnt += sleep_time; |
1414 | if (di->init_cnt > di->bat->fg_params->init_total_time) | 1575 | if (di->init_cnt > di->bm->fg_params->init_total_time) |
1415 | ab8500_fg_discharge_state_to(di, | 1576 | ab8500_fg_discharge_state_to(di, |
1416 | AB8500_FG_DISCHARGE_READOUT_INIT); | 1577 | AB8500_FG_DISCHARGE_READOUT_INIT); |
1417 | 1578 | ||
@@ -1426,7 +1587,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1426 | /* Intentional fallthrough */ | 1587 | /* Intentional fallthrough */ |
1427 | 1588 | ||
1428 | case AB8500_FG_DISCHARGE_RECOVERY: | 1589 | case AB8500_FG_DISCHARGE_RECOVERY: |
1429 | sleep_time = di->bat->fg_params->recovery_sleep_timer; | 1590 | sleep_time = di->bm->fg_params->recovery_sleep_timer; |
1430 | 1591 | ||
1431 | /* | 1592 | /* |
1432 | * We should check the power consumption | 1593 | * We should check the power consumption |
@@ -1438,9 +1599,9 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1438 | 1599 | ||
1439 | if (ab8500_fg_is_low_curr(di, di->inst_curr)) { | 1600 | if (ab8500_fg_is_low_curr(di, di->inst_curr)) { |
1440 | if (di->recovery_cnt > | 1601 | if (di->recovery_cnt > |
1441 | di->bat->fg_params->recovery_total_time) { | 1602 | di->bm->fg_params->recovery_total_time) { |
1442 | di->fg_samples = SEC_TO_SAMPLE( | 1603 | di->fg_samples = SEC_TO_SAMPLE( |
1443 | di->bat->fg_params->accu_high_curr); | 1604 | di->bm->fg_params->accu_high_curr); |
1444 | ab8500_fg_coulomb_counter(di, true); | 1605 | ab8500_fg_coulomb_counter(di, true); |
1445 | ab8500_fg_discharge_state_to(di, | 1606 | ab8500_fg_discharge_state_to(di, |
1446 | AB8500_FG_DISCHARGE_READOUT); | 1607 | AB8500_FG_DISCHARGE_READOUT); |
@@ -1453,7 +1614,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1453 | di->recovery_cnt += sleep_time; | 1614 | di->recovery_cnt += sleep_time; |
1454 | } else { | 1615 | } else { |
1455 | di->fg_samples = SEC_TO_SAMPLE( | 1616 | di->fg_samples = SEC_TO_SAMPLE( |
1456 | di->bat->fg_params->accu_high_curr); | 1617 | di->bm->fg_params->accu_high_curr); |
1457 | ab8500_fg_coulomb_counter(di, true); | 1618 | ab8500_fg_coulomb_counter(di, true); |
1458 | ab8500_fg_discharge_state_to(di, | 1619 | ab8500_fg_discharge_state_to(di, |
1459 | AB8500_FG_DISCHARGE_READOUT); | 1620 | AB8500_FG_DISCHARGE_READOUT); |
@@ -1462,7 +1623,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1462 | 1623 | ||
1463 | case AB8500_FG_DISCHARGE_READOUT_INIT: | 1624 | case AB8500_FG_DISCHARGE_READOUT_INIT: |
1464 | di->fg_samples = SEC_TO_SAMPLE( | 1625 | di->fg_samples = SEC_TO_SAMPLE( |
1465 | di->bat->fg_params->accu_high_curr); | 1626 | di->bm->fg_params->accu_high_curr); |
1466 | ab8500_fg_coulomb_counter(di, true); | 1627 | ab8500_fg_coulomb_counter(di, true); |
1467 | ab8500_fg_discharge_state_to(di, | 1628 | ab8500_fg_discharge_state_to(di, |
1468 | AB8500_FG_DISCHARGE_READOUT); | 1629 | AB8500_FG_DISCHARGE_READOUT); |
@@ -1480,7 +1641,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1480 | 1641 | ||
1481 | if (di->recovery_needed) { | 1642 | if (di->recovery_needed) { |
1482 | ab8500_fg_discharge_state_to(di, | 1643 | ab8500_fg_discharge_state_to(di, |
1483 | AB8500_FG_DISCHARGE_RECOVERY); | 1644 | AB8500_FG_DISCHARGE_INIT_RECOVERY); |
1484 | 1645 | ||
1485 | queue_delayed_work(di->fg_wq, | 1646 | queue_delayed_work(di->fg_wq, |
1486 | &di->fg_periodic_work, 0); | 1647 | &di->fg_periodic_work, 0); |
@@ -1509,9 +1670,9 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1509 | } | 1670 | } |
1510 | 1671 | ||
1511 | di->high_curr_cnt += | 1672 | di->high_curr_cnt += |
1512 | di->bat->fg_params->accu_high_curr; | 1673 | di->bm->fg_params->accu_high_curr; |
1513 | if (di->high_curr_cnt > | 1674 | if (di->high_curr_cnt > |
1514 | di->bat->fg_params->high_curr_time) | 1675 | di->bm->fg_params->high_curr_time) |
1515 | di->recovery_needed = true; | 1676 | di->recovery_needed = true; |
1516 | 1677 | ||
1517 | ab8500_fg_calc_cap_discharge_fg(di); | 1678 | ab8500_fg_calc_cap_discharge_fg(di); |
@@ -1523,12 +1684,10 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) | |||
1523 | 1684 | ||
1524 | case AB8500_FG_DISCHARGE_WAKEUP: | 1685 | case AB8500_FG_DISCHARGE_WAKEUP: |
1525 | ab8500_fg_coulomb_counter(di, true); | 1686 | ab8500_fg_coulomb_counter(di, true); |
1526 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1527 | |||
1528 | ab8500_fg_calc_cap_discharge_voltage(di, true); | 1687 | ab8500_fg_calc_cap_discharge_voltage(di, true); |
1529 | 1688 | ||
1530 | di->fg_samples = SEC_TO_SAMPLE( | 1689 | di->fg_samples = SEC_TO_SAMPLE( |
1531 | di->bat->fg_params->accu_high_curr); | 1690 | di->bm->fg_params->accu_high_curr); |
1532 | ab8500_fg_coulomb_counter(di, true); | 1691 | ab8500_fg_coulomb_counter(di, true); |
1533 | ab8500_fg_discharge_state_to(di, | 1692 | ab8500_fg_discharge_state_to(di, |
1534 | AB8500_FG_DISCHARGE_READOUT); | 1693 | AB8500_FG_DISCHARGE_READOUT); |
@@ -1641,8 +1800,6 @@ static void ab8500_fg_periodic_work(struct work_struct *work) | |||
1641 | fg_periodic_work.work); | 1800 | fg_periodic_work.work); |
1642 | 1801 | ||
1643 | if (di->init_capacity) { | 1802 | if (di->init_capacity) { |
1644 | /* A dummy read that will return 0 */ | ||
1645 | di->inst_curr = ab8500_fg_inst_curr_blocking(di); | ||
1646 | /* Get an initial capacity calculation */ | 1803 | /* Get an initial capacity calculation */ |
1647 | ab8500_fg_calc_cap_discharge_voltage(di, true); | 1804 | ab8500_fg_calc_cap_discharge_voltage(di, true); |
1648 | ab8500_fg_check_capacity_limits(di, true); | 1805 | ab8500_fg_check_capacity_limits(di, true); |
@@ -1684,24 +1841,26 @@ static void ab8500_fg_check_hw_failure_work(struct work_struct *work) | |||
1684 | * If we have had a battery over-voltage situation, | 1841 | * If we have had a battery over-voltage situation, |
1685 | * check ovv-bit to see if it should be reset. | 1842 | * check ovv-bit to see if it should be reset. |
1686 | */ | 1843 | */ |
1687 | if (di->flags.bat_ovv) { | 1844 | ret = abx500_get_register_interruptible(di->dev, |
1688 | ret = abx500_get_register_interruptible(di->dev, | 1845 | AB8500_CHARGER, AB8500_CH_STAT_REG, |
1689 | AB8500_CHARGER, AB8500_CH_STAT_REG, | 1846 | ®_value); |
1690 | ®_value); | 1847 | if (ret < 0) { |
1691 | if (ret < 0) { | 1848 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); |
1692 | dev_err(di->dev, "%s ab8500 read failed\n", __func__); | 1849 | return; |
1693 | return; | 1850 | } |
1694 | } | 1851 | if ((reg_value & BATT_OVV) == BATT_OVV) { |
1695 | if ((reg_value & BATT_OVV) != BATT_OVV) { | 1852 | if (!di->flags.bat_ovv) { |
1696 | dev_dbg(di->dev, "Battery recovered from OVV\n"); | 1853 | dev_dbg(di->dev, "Battery OVV\n"); |
1697 | di->flags.bat_ovv = false; | 1854 | di->flags.bat_ovv = true; |
1698 | power_supply_changed(&di->fg_psy); | 1855 | power_supply_changed(&di->fg_psy); |
1699 | return; | ||
1700 | } | 1856 | } |
1701 | |||
1702 | /* Not yet recovered from ovv, reschedule this test */ | 1857 | /* Not yet recovered from ovv, reschedule this test */ |
1703 | queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, | 1858 | queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, |
1704 | round_jiffies(HZ)); | 1859 | HZ); |
1860 | } else { | ||
1861 | dev_dbg(di->dev, "Battery recovered from OVV\n"); | ||
1862 | di->flags.bat_ovv = false; | ||
1863 | power_supply_changed(&di->fg_psy); | ||
1705 | } | 1864 | } |
1706 | } | 1865 | } |
1707 | 1866 | ||
@@ -1721,26 +1880,30 @@ static void ab8500_fg_low_bat_work(struct work_struct *work) | |||
1721 | vbat = ab8500_fg_bat_voltage(di); | 1880 | vbat = ab8500_fg_bat_voltage(di); |
1722 | 1881 | ||
1723 | /* Check if LOW_BAT still fulfilled */ | 1882 | /* Check if LOW_BAT still fulfilled */ |
1724 | if (vbat < di->bat->fg_params->lowbat_threshold) { | 1883 | if (vbat < di->bm->fg_params->lowbat_threshold) { |
1725 | di->flags.low_bat = true; | 1884 | /* Is it time to shut down? */ |
1726 | dev_warn(di->dev, "Battery voltage still LOW\n"); | 1885 | if (di->low_bat_cnt < 1) { |
1727 | 1886 | di->flags.low_bat = true; | |
1728 | /* | 1887 | dev_warn(di->dev, "Shut down pending...\n"); |
1729 | * We need to re-schedule this check to be able to detect | 1888 | } else { |
1730 | * if the voltage increases again during charging | 1889 | /* |
1731 | */ | 1890 | * Else we need to re-schedule this check to be able to detect |
1732 | queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, | 1891 | * if the voltage increases again during charging or |
1733 | round_jiffies(LOW_BAT_CHECK_INTERVAL)); | 1892 | * due to decreasing load. |
1893 | */ | ||
1894 | di->low_bat_cnt--; | ||
1895 | dev_warn(di->dev, "Battery voltage still LOW\n"); | ||
1896 | queue_delayed_work(di->fg_wq, &di->fg_low_bat_work, | ||
1897 | round_jiffies(LOW_BAT_CHECK_INTERVAL)); | ||
1898 | } | ||
1734 | } else { | 1899 | } else { |
1735 | di->flags.low_bat = false; | 1900 | di->flags.low_bat_delay = false; |
1901 | di->low_bat_cnt = 10; | ||
1736 | dev_warn(di->dev, "Battery voltage OK again\n"); | 1902 | dev_warn(di->dev, "Battery voltage OK again\n"); |
1737 | } | 1903 | } |
1738 | 1904 | ||
1739 | /* This is needed to dispatch LOW_BAT */ | 1905 | /* This is needed to dispatch LOW_BAT */ |
1740 | ab8500_fg_check_capacity_limits(di, false); | 1906 | ab8500_fg_check_capacity_limits(di, false); |
1741 | |||
1742 | /* Set this flag to check if LOW_BAT IRQ still occurs */ | ||
1743 | di->flags.low_bat_delay = false; | ||
1744 | } | 1907 | } |
1745 | 1908 | ||
1746 | /** | 1909 | /** |
@@ -1779,8 +1942,8 @@ static int ab8500_fg_battok_init_hw_register(struct ab8500_fg *di) | |||
1779 | int ret; | 1942 | int ret; |
1780 | int new_val; | 1943 | int new_val; |
1781 | 1944 | ||
1782 | sel0 = di->bat->fg_params->battok_falling_th_sel0; | 1945 | sel0 = di->bm->fg_params->battok_falling_th_sel0; |
1783 | sel1 = di->bat->fg_params->battok_raising_th_sel1; | 1946 | sel1 = di->bm->fg_params->battok_raising_th_sel1; |
1784 | 1947 | ||
1785 | cbp_sel0 = ab8500_fg_battok_calc(di, sel0); | 1948 | cbp_sel0 = ab8500_fg_battok_calc(di, sel0); |
1786 | cbp_sel1 = ab8500_fg_battok_calc(di, sel1); | 1949 | cbp_sel1 = ab8500_fg_battok_calc(di, sel1); |
@@ -1828,7 +1991,13 @@ static void ab8500_fg_instant_work(struct work_struct *work) | |||
1828 | static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) | 1991 | static irqreturn_t ab8500_fg_cc_data_end_handler(int irq, void *_di) |
1829 | { | 1992 | { |
1830 | struct ab8500_fg *di = _di; | 1993 | struct ab8500_fg *di = _di; |
1831 | complete(&di->ab8500_fg_complete); | 1994 | if (!di->nbr_cceoc_irq_cnt) { |
1995 | di->nbr_cceoc_irq_cnt++; | ||
1996 | complete(&di->ab8500_fg_started); | ||
1997 | } else { | ||
1998 | di->nbr_cceoc_irq_cnt = 0; | ||
1999 | complete(&di->ab8500_fg_complete); | ||
2000 | } | ||
1832 | return IRQ_HANDLED; | 2001 | return IRQ_HANDLED; |
1833 | } | 2002 | } |
1834 | 2003 | ||
@@ -1875,8 +2044,6 @@ static irqreturn_t ab8500_fg_batt_ovv_handler(int irq, void *_di) | |||
1875 | struct ab8500_fg *di = _di; | 2044 | struct ab8500_fg *di = _di; |
1876 | 2045 | ||
1877 | dev_dbg(di->dev, "Battery OVV\n"); | 2046 | dev_dbg(di->dev, "Battery OVV\n"); |
1878 | di->flags.bat_ovv = true; | ||
1879 | power_supply_changed(&di->fg_psy); | ||
1880 | 2047 | ||
1881 | /* Schedule a new HW failure check */ | 2048 | /* Schedule a new HW failure check */ |
1882 | queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, 0); | 2049 | queue_delayed_work(di->fg_wq, &di->fg_check_hw_failure_work, 0); |
@@ -1895,6 +2062,7 @@ static irqreturn_t ab8500_fg_lowbatf_handler(int irq, void *_di) | |||
1895 | { | 2062 | { |
1896 | struct ab8500_fg *di = _di; | 2063 | struct ab8500_fg *di = _di; |
1897 | 2064 | ||
2065 | /* Initiate handling in ab8500_fg_low_bat_work() if not already initiated. */ | ||
1898 | if (!di->flags.low_bat_delay) { | 2066 | if (!di->flags.low_bat_delay) { |
1899 | dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); | 2067 | dev_warn(di->dev, "Battery voltage is below LOW threshold\n"); |
1900 | di->flags.low_bat_delay = true; | 2068 | di->flags.low_bat_delay = true; |
@@ -1963,7 +2131,7 @@ static int ab8500_fg_get_property(struct power_supply *psy, | |||
1963 | di->bat_cap.max_mah); | 2131 | di->bat_cap.max_mah); |
1964 | break; | 2132 | break; |
1965 | case POWER_SUPPLY_PROP_ENERGY_NOW: | 2133 | case POWER_SUPPLY_PROP_ENERGY_NOW: |
1966 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | 2134 | if (di->flags.batt_unknown && !di->bm->chg_unknown_bat && |
1967 | di->flags.batt_id_received) | 2135 | di->flags.batt_id_received) |
1968 | val->intval = ab8500_fg_convert_mah_to_uwh(di, | 2136 | val->intval = ab8500_fg_convert_mah_to_uwh(di, |
1969 | di->bat_cap.max_mah); | 2137 | di->bat_cap.max_mah); |
@@ -1978,21 +2146,23 @@ static int ab8500_fg_get_property(struct power_supply *psy, | |||
1978 | val->intval = di->bat_cap.max_mah; | 2146 | val->intval = di->bat_cap.max_mah; |
1979 | break; | 2147 | break; |
1980 | case POWER_SUPPLY_PROP_CHARGE_NOW: | 2148 | case POWER_SUPPLY_PROP_CHARGE_NOW: |
1981 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | 2149 | if (di->flags.batt_unknown && !di->bm->chg_unknown_bat && |
1982 | di->flags.batt_id_received) | 2150 | di->flags.batt_id_received) |
1983 | val->intval = di->bat_cap.max_mah; | 2151 | val->intval = di->bat_cap.max_mah; |
1984 | else | 2152 | else |
1985 | val->intval = di->bat_cap.prev_mah; | 2153 | val->intval = di->bat_cap.prev_mah; |
1986 | break; | 2154 | break; |
1987 | case POWER_SUPPLY_PROP_CAPACITY: | 2155 | case POWER_SUPPLY_PROP_CAPACITY: |
1988 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | 2156 | if (di->bm->capacity_scaling) |
2157 | val->intval = di->bat_cap.cap_scale.scaled_cap; | ||
2158 | else if (di->flags.batt_unknown && !di->bm->chg_unknown_bat && | ||
1989 | di->flags.batt_id_received) | 2159 | di->flags.batt_id_received) |
1990 | val->intval = 100; | 2160 | val->intval = 100; |
1991 | else | 2161 | else |
1992 | val->intval = di->bat_cap.prev_percent; | 2162 | val->intval = di->bat_cap.prev_percent; |
1993 | break; | 2163 | break; |
1994 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | 2164 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: |
1995 | if (di->flags.batt_unknown && !di->bat->chg_unknown_bat && | 2165 | if (di->flags.batt_unknown && !di->bm->chg_unknown_bat && |
1996 | di->flags.batt_id_received) | 2166 | di->flags.batt_id_received) |
1997 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; | 2167 | val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN; |
1998 | else | 2168 | else |
@@ -2049,6 +2219,8 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) | |||
2049 | break; | 2219 | break; |
2050 | di->flags.charging = false; | 2220 | di->flags.charging = false; |
2051 | di->flags.fully_charged = false; | 2221 | di->flags.fully_charged = false; |
2222 | if (di->bm->capacity_scaling) | ||
2223 | ab8500_fg_update_cap_scalers(di); | ||
2052 | queue_work(di->fg_wq, &di->fg_work); | 2224 | queue_work(di->fg_wq, &di->fg_work); |
2053 | break; | 2225 | break; |
2054 | case POWER_SUPPLY_STATUS_FULL: | 2226 | case POWER_SUPPLY_STATUS_FULL: |
@@ -2061,10 +2233,13 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) | |||
2061 | queue_work(di->fg_wq, &di->fg_work); | 2233 | queue_work(di->fg_wq, &di->fg_work); |
2062 | break; | 2234 | break; |
2063 | case POWER_SUPPLY_STATUS_CHARGING: | 2235 | case POWER_SUPPLY_STATUS_CHARGING: |
2064 | if (di->flags.charging) | 2236 | if (di->flags.charging && |
2237 | !di->flags.fully_charged) | ||
2065 | break; | 2238 | break; |
2066 | di->flags.charging = true; | 2239 | di->flags.charging = true; |
2067 | di->flags.fully_charged = false; | 2240 | di->flags.fully_charged = false; |
2241 | if (di->bm->capacity_scaling) | ||
2242 | ab8500_fg_update_cap_scalers(di); | ||
2068 | queue_work(di->fg_wq, &di->fg_work); | 2243 | queue_work(di->fg_wq, &di->fg_work); |
2069 | break; | 2244 | break; |
2070 | }; | 2245 | }; |
@@ -2075,10 +2250,11 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) | |||
2075 | case POWER_SUPPLY_PROP_TECHNOLOGY: | 2250 | case POWER_SUPPLY_PROP_TECHNOLOGY: |
2076 | switch (ext->type) { | 2251 | switch (ext->type) { |
2077 | case POWER_SUPPLY_TYPE_BATTERY: | 2252 | case POWER_SUPPLY_TYPE_BATTERY: |
2078 | if (!di->flags.batt_id_received) { | 2253 | if (!di->flags.batt_id_received && |
2254 | di->bm->batt_id != BATTERY_UNKNOWN) { | ||
2079 | const struct abx500_battery_type *b; | 2255 | const struct abx500_battery_type *b; |
2080 | 2256 | ||
2081 | b = &(di->bat->bat_type[di->bat->batt_id]); | 2257 | b = &(di->bm->bat_type[di->bm->batt_id]); |
2082 | 2258 | ||
2083 | di->flags.batt_id_received = true; | 2259 | di->flags.batt_id_received = true; |
2084 | 2260 | ||
@@ -2104,8 +2280,8 @@ static int ab8500_fg_get_ext_psy_data(struct device *dev, void *data) | |||
2104 | case POWER_SUPPLY_PROP_TEMP: | 2280 | case POWER_SUPPLY_PROP_TEMP: |
2105 | switch (ext->type) { | 2281 | switch (ext->type) { |
2106 | case POWER_SUPPLY_TYPE_BATTERY: | 2282 | case POWER_SUPPLY_TYPE_BATTERY: |
2107 | if (di->flags.batt_id_received) | 2283 | if (di->flags.batt_id_received) |
2108 | di->bat_temp = ret.intval; | 2284 | di->bat_temp = ret.intval; |
2109 | break; | 2285 | break; |
2110 | default: | 2286 | default: |
2111 | break; | 2287 | break; |
@@ -2155,7 +2331,7 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di) | |||
2155 | AB8500_SYS_CTRL2_BLOCK, | 2331 | AB8500_SYS_CTRL2_BLOCK, |
2156 | AB8500_LOW_BAT_REG, | 2332 | AB8500_LOW_BAT_REG, |
2157 | ab8500_volt_to_regval( | 2333 | ab8500_volt_to_regval( |
2158 | di->bat->fg_params->lowbat_threshold) << 1 | | 2334 | di->bm->fg_params->lowbat_threshold) << 1 | |
2159 | LOW_BAT_ENABLE); | 2335 | LOW_BAT_ENABLE); |
2160 | if (ret) { | 2336 | if (ret) { |
2161 | dev_err(di->dev, "%s write failed\n", __func__); | 2337 | dev_err(di->dev, "%s write failed\n", __func__); |
@@ -2395,6 +2571,11 @@ static int ab8500_fg_suspend(struct platform_device *pdev, | |||
2395 | struct ab8500_fg *di = platform_get_drvdata(pdev); | 2571 | struct ab8500_fg *di = platform_get_drvdata(pdev); |
2396 | 2572 | ||
2397 | flush_delayed_work(&di->fg_periodic_work); | 2573 | flush_delayed_work(&di->fg_periodic_work); |
2574 | flush_work(&di->fg_work); | ||
2575 | flush_work(&di->fg_acc_cur_work); | ||
2576 | flush_delayed_work(&di->fg_reinit_work); | ||
2577 | flush_delayed_work(&di->fg_low_bat_work); | ||
2578 | flush_delayed_work(&di->fg_check_hw_failure_work); | ||
2398 | 2579 | ||
2399 | /* | 2580 | /* |
2400 | * If the FG is enabled we will disable it before going to suspend | 2581 | * If the FG is enabled we will disable it before going to suspend |
@@ -2448,6 +2629,7 @@ static char *supply_interface[] = { | |||
2448 | static int ab8500_fg_probe(struct platform_device *pdev) | 2629 | static int ab8500_fg_probe(struct platform_device *pdev) |
2449 | { | 2630 | { |
2450 | struct device_node *np = pdev->dev.of_node; | 2631 | struct device_node *np = pdev->dev.of_node; |
2632 | struct abx500_bm_data *plat = pdev->dev.platform_data; | ||
2451 | struct ab8500_fg *di; | 2633 | struct ab8500_fg *di; |
2452 | int i, irq; | 2634 | int i, irq; |
2453 | int ret = 0; | 2635 | int ret = 0; |
@@ -2457,21 +2639,19 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2457 | dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); | 2639 | dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); |
2458 | return -ENOMEM; | 2640 | return -ENOMEM; |
2459 | } | 2641 | } |
2460 | di->bat = pdev->mfd_cell->platform_data; | 2642 | |
2461 | if (!di->bat) { | 2643 | if (!plat) { |
2462 | if (np) { | 2644 | dev_err(&pdev->dev, "no battery management data supplied\n"); |
2463 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | 2645 | return -EINVAL; |
2464 | if (ret) { | 2646 | } |
2465 | dev_err(&pdev->dev, | 2647 | di->bm = plat; |
2466 | "failed to get battery information\n"); | 2648 | |
2467 | return ret; | 2649 | if (np) { |
2468 | } | 2650 | ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); |
2469 | } else { | 2651 | if (ret) { |
2470 | dev_err(&pdev->dev, "missing dt node for ab8500_fg\n"); | 2652 | dev_err(&pdev->dev, "failed to get battery information\n"); |
2471 | return -EINVAL; | 2653 | return ret; |
2472 | } | 2654 | } |
2473 | } else { | ||
2474 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
2475 | } | 2655 | } |
2476 | 2656 | ||
2477 | mutex_init(&di->cc_lock); | 2657 | mutex_init(&di->cc_lock); |
@@ -2491,11 +2671,11 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2491 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; | 2671 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; |
2492 | 2672 | ||
2493 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * | 2673 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * |
2494 | di->bat->bat_type[di->bat->batt_id].charge_full_design; | 2674 | di->bm->bat_type[di->bm->batt_id].charge_full_design; |
2495 | 2675 | ||
2496 | di->bat_cap.max_mah = di->bat_cap.max_mah_design; | 2676 | di->bat_cap.max_mah = di->bat_cap.max_mah_design; |
2497 | 2677 | ||
2498 | di->vbat_nom = di->bat->bat_type[di->bat->batt_id].nominal_voltage; | 2678 | di->vbat_nom = di->bm->bat_type[di->bm->batt_id].nominal_voltage; |
2499 | 2679 | ||
2500 | di->init_capacity = true; | 2680 | di->init_capacity = true; |
2501 | 2681 | ||
@@ -2531,6 +2711,12 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2531 | INIT_DEFERRABLE_WORK(&di->fg_check_hw_failure_work, | 2711 | INIT_DEFERRABLE_WORK(&di->fg_check_hw_failure_work, |
2532 | ab8500_fg_check_hw_failure_work); | 2712 | ab8500_fg_check_hw_failure_work); |
2533 | 2713 | ||
2714 | /* Reset battery low voltage flag */ | ||
2715 | di->flags.low_bat = false; | ||
2716 | |||
2717 | /* Initialize low battery counter */ | ||
2718 | di->low_bat_cnt = 10; | ||
2719 | |||
2534 | /* Initialize OVV, and other registers */ | 2720 | /* Initialize OVV, and other registers */ |
2535 | ret = ab8500_fg_init_hw_registers(di); | 2721 | ret = ab8500_fg_init_hw_registers(di); |
2536 | if (ret) { | 2722 | if (ret) { |
@@ -2549,10 +2735,14 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2549 | goto free_inst_curr_wq; | 2735 | goto free_inst_curr_wq; |
2550 | } | 2736 | } |
2551 | 2737 | ||
2552 | di->fg_samples = SEC_TO_SAMPLE(di->bat->fg_params->init_timer); | 2738 | di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer); |
2553 | ab8500_fg_coulomb_counter(di, true); | 2739 | ab8500_fg_coulomb_counter(di, true); |
2554 | 2740 | ||
2555 | /* Initialize completion used to notify completion of inst current */ | 2741 | /* |
2742 | * Initialize completion used to notify completion and start | ||
2743 | * of inst current | ||
2744 | */ | ||
2745 | init_completion(&di->ab8500_fg_started); | ||
2556 | init_completion(&di->ab8500_fg_complete); | 2746 | init_completion(&di->ab8500_fg_complete); |
2557 | 2747 | ||
2558 | /* Register interrupts */ | 2748 | /* Register interrupts */ |
@@ -2572,6 +2762,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2572 | } | 2762 | } |
2573 | di->irq = platform_get_irq_byname(pdev, "CCEOC"); | 2763 | di->irq = platform_get_irq_byname(pdev, "CCEOC"); |
2574 | disable_irq(di->irq); | 2764 | disable_irq(di->irq); |
2765 | di->nbr_cceoc_irq_cnt = 0; | ||
2575 | 2766 | ||
2576 | platform_set_drvdata(pdev, di); | 2767 | platform_set_drvdata(pdev, di); |
2577 | 2768 | ||
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 297089146064..f043c0851a76 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c | |||
@@ -33,9 +33,6 @@ | |||
33 | /* End-of-charge criteria counter */ | 33 | /* End-of-charge criteria counter */ |
34 | #define EOC_COND_CNT 10 | 34 | #define EOC_COND_CNT 10 |
35 | 35 | ||
36 | /* Recharge criteria counter */ | ||
37 | #define RCH_COND_CNT 3 | ||
38 | |||
39 | #define to_abx500_chargalg_device_info(x) container_of((x), \ | 36 | #define to_abx500_chargalg_device_info(x) container_of((x), \ |
40 | struct abx500_chargalg, chargalg_psy); | 37 | struct abx500_chargalg, chargalg_psy); |
41 | 38 | ||
@@ -196,7 +193,6 @@ enum maxim_ret { | |||
196 | * @dev: pointer to the structure device | 193 | * @dev: pointer to the structure device |
197 | * @charge_status: battery operating status | 194 | * @charge_status: battery operating status |
198 | * @eoc_cnt: counter used to determine end-of_charge | 195 | * @eoc_cnt: counter used to determine end-of_charge |
199 | * @rch_cnt: counter used to determine start of recharge | ||
200 | * @maintenance_chg: indicate if maintenance charge is active | 196 | * @maintenance_chg: indicate if maintenance charge is active |
201 | * @t_hyst_norm temperature hysteresis when the temperature has been | 197 | * @t_hyst_norm temperature hysteresis when the temperature has been |
202 | * over or under normal limits | 198 | * over or under normal limits |
@@ -207,7 +203,7 @@ enum maxim_ret { | |||
207 | * @chg_info: information about connected charger types | 203 | * @chg_info: information about connected charger types |
208 | * @batt_data: data of the battery | 204 | * @batt_data: data of the battery |
209 | * @susp_status: current charger suspension status | 205 | * @susp_status: current charger suspension status |
210 | * @bat: pointer to the abx500_bm platform data | 206 | * @bm: Platform specific battery management information |
211 | * @chargalg_psy: structure that holds the battery properties exposed by | 207 | * @chargalg_psy: structure that holds the battery properties exposed by |
212 | * the charging algorithm | 208 | * the charging algorithm |
213 | * @events: structure for information about events triggered | 209 | * @events: structure for information about events triggered |
@@ -223,7 +219,6 @@ struct abx500_chargalg { | |||
223 | struct device *dev; | 219 | struct device *dev; |
224 | int charge_status; | 220 | int charge_status; |
225 | int eoc_cnt; | 221 | int eoc_cnt; |
226 | int rch_cnt; | ||
227 | bool maintenance_chg; | 222 | bool maintenance_chg; |
228 | int t_hyst_norm; | 223 | int t_hyst_norm; |
229 | int t_hyst_lowhigh; | 224 | int t_hyst_lowhigh; |
@@ -232,7 +227,7 @@ struct abx500_chargalg { | |||
232 | struct abx500_chargalg_charger_info chg_info; | 227 | struct abx500_chargalg_charger_info chg_info; |
233 | struct abx500_chargalg_battery_data batt_data; | 228 | struct abx500_chargalg_battery_data batt_data; |
234 | struct abx500_chargalg_suspension_status susp_status; | 229 | struct abx500_chargalg_suspension_status susp_status; |
235 | struct abx500_bm_data *bat; | 230 | struct abx500_bm_data *bm; |
236 | struct power_supply chargalg_psy; | 231 | struct power_supply chargalg_psy; |
237 | struct ux500_charger *ac_chg; | 232 | struct ux500_charger *ac_chg; |
238 | struct ux500_charger *usb_chg; | 233 | struct ux500_charger *usb_chg; |
@@ -367,13 +362,13 @@ static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di) | |||
367 | case AC_CHG: | 362 | case AC_CHG: |
368 | timer_expiration = | 363 | timer_expiration = |
369 | round_jiffies(jiffies + | 364 | round_jiffies(jiffies + |
370 | (di->bat->main_safety_tmr_h * 3600 * HZ)); | 365 | (di->bm->main_safety_tmr_h * 3600 * HZ)); |
371 | break; | 366 | break; |
372 | 367 | ||
373 | case USB_CHG: | 368 | case USB_CHG: |
374 | timer_expiration = | 369 | timer_expiration = |
375 | round_jiffies(jiffies + | 370 | round_jiffies(jiffies + |
376 | (di->bat->usb_safety_tmr_h * 3600 * HZ)); | 371 | (di->bm->usb_safety_tmr_h * 3600 * HZ)); |
377 | break; | 372 | break; |
378 | 373 | ||
379 | default: | 374 | default: |
@@ -450,8 +445,18 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di) | |||
450 | { | 445 | { |
451 | /* Check if charger exists and kick watchdog if charging */ | 446 | /* Check if charger exists and kick watchdog if charging */ |
452 | if (di->ac_chg && di->ac_chg->ops.kick_wd && | 447 | if (di->ac_chg && di->ac_chg->ops.kick_wd && |
453 | di->chg_info.online_chg & AC_CHG) | 448 | di->chg_info.online_chg & AC_CHG) { |
449 | /* | ||
450 | * If AB charger watchdog expired, pm2xxx charging | ||
451 | * gets disabled. To be safe, kick both AB charger watchdog | ||
452 | * and pm2xxx watchdog. | ||
453 | */ | ||
454 | if (di->ac_chg->external && | ||
455 | di->usb_chg && di->usb_chg->ops.kick_wd) | ||
456 | di->usb_chg->ops.kick_wd(di->usb_chg); | ||
457 | |||
454 | return di->ac_chg->ops.kick_wd(di->ac_chg); | 458 | return di->ac_chg->ops.kick_wd(di->ac_chg); |
459 | } | ||
455 | else if (di->usb_chg && di->usb_chg->ops.kick_wd && | 460 | else if (di->usb_chg && di->usb_chg->ops.kick_wd && |
456 | di->chg_info.online_chg & USB_CHG) | 461 | di->chg_info.online_chg & USB_CHG) |
457 | return di->usb_chg->ops.kick_wd(di->usb_chg); | 462 | return di->usb_chg->ops.kick_wd(di->usb_chg); |
@@ -608,6 +613,8 @@ static void abx500_chargalg_hold_charging(struct abx500_chargalg *di) | |||
608 | static void abx500_chargalg_start_charging(struct abx500_chargalg *di, | 613 | static void abx500_chargalg_start_charging(struct abx500_chargalg *di, |
609 | int vset, int iset) | 614 | int vset, int iset) |
610 | { | 615 | { |
616 | bool start_chargalg_wd = true; | ||
617 | |||
611 | switch (di->chg_info.charger_type) { | 618 | switch (di->chg_info.charger_type) { |
612 | case AC_CHG: | 619 | case AC_CHG: |
613 | dev_dbg(di->dev, | 620 | dev_dbg(di->dev, |
@@ -625,8 +632,12 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di, | |||
625 | 632 | ||
626 | default: | 633 | default: |
627 | dev_err(di->dev, "Unknown charger to charge from\n"); | 634 | dev_err(di->dev, "Unknown charger to charge from\n"); |
635 | start_chargalg_wd = false; | ||
628 | break; | 636 | break; |
629 | } | 637 | } |
638 | |||
639 | if (start_chargalg_wd && !delayed_work_pending(&di->chargalg_wd_work)) | ||
640 | queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0); | ||
630 | } | 641 | } |
631 | 642 | ||
632 | /** | 643 | /** |
@@ -638,32 +649,32 @@ static void abx500_chargalg_start_charging(struct abx500_chargalg *di, | |||
638 | */ | 649 | */ |
639 | static void abx500_chargalg_check_temp(struct abx500_chargalg *di) | 650 | static void abx500_chargalg_check_temp(struct abx500_chargalg *di) |
640 | { | 651 | { |
641 | if (di->batt_data.temp > (di->bat->temp_low + di->t_hyst_norm) && | 652 | if (di->batt_data.temp > (di->bm->temp_low + di->t_hyst_norm) && |
642 | di->batt_data.temp < (di->bat->temp_high - di->t_hyst_norm)) { | 653 | di->batt_data.temp < (di->bm->temp_high - di->t_hyst_norm)) { |
643 | /* Temp OK! */ | 654 | /* Temp OK! */ |
644 | di->events.btemp_underover = false; | 655 | di->events.btemp_underover = false; |
645 | di->events.btemp_lowhigh = false; | 656 | di->events.btemp_lowhigh = false; |
646 | di->t_hyst_norm = 0; | 657 | di->t_hyst_norm = 0; |
647 | di->t_hyst_lowhigh = 0; | 658 | di->t_hyst_lowhigh = 0; |
648 | } else { | 659 | } else { |
649 | if (((di->batt_data.temp >= di->bat->temp_high) && | 660 | if (((di->batt_data.temp >= di->bm->temp_high) && |
650 | (di->batt_data.temp < | 661 | (di->batt_data.temp < |
651 | (di->bat->temp_over - di->t_hyst_lowhigh))) || | 662 | (di->bm->temp_over - di->t_hyst_lowhigh))) || |
652 | ((di->batt_data.temp > | 663 | ((di->batt_data.temp > |
653 | (di->bat->temp_under + di->t_hyst_lowhigh)) && | 664 | (di->bm->temp_under + di->t_hyst_lowhigh)) && |
654 | (di->batt_data.temp <= di->bat->temp_low))) { | 665 | (di->batt_data.temp <= di->bm->temp_low))) { |
655 | /* TEMP minor!!!!! */ | 666 | /* TEMP minor!!!!! */ |
656 | di->events.btemp_underover = false; | 667 | di->events.btemp_underover = false; |
657 | di->events.btemp_lowhigh = true; | 668 | di->events.btemp_lowhigh = true; |
658 | di->t_hyst_norm = di->bat->temp_hysteresis; | 669 | di->t_hyst_norm = di->bm->temp_hysteresis; |
659 | di->t_hyst_lowhigh = 0; | 670 | di->t_hyst_lowhigh = 0; |
660 | } else if (di->batt_data.temp <= di->bat->temp_under || | 671 | } else if (di->batt_data.temp <= di->bm->temp_under || |
661 | di->batt_data.temp >= di->bat->temp_over) { | 672 | di->batt_data.temp >= di->bm->temp_over) { |
662 | /* TEMP major!!!!! */ | 673 | /* TEMP major!!!!! */ |
663 | di->events.btemp_underover = true; | 674 | di->events.btemp_underover = true; |
664 | di->events.btemp_lowhigh = false; | 675 | di->events.btemp_lowhigh = false; |
665 | di->t_hyst_norm = 0; | 676 | di->t_hyst_norm = 0; |
666 | di->t_hyst_lowhigh = di->bat->temp_hysteresis; | 677 | di->t_hyst_lowhigh = di->bm->temp_hysteresis; |
667 | } else { | 678 | } else { |
668 | /* Within hysteresis */ | 679 | /* Within hysteresis */ |
669 | dev_dbg(di->dev, "Within hysteresis limit temp: %d " | 680 | dev_dbg(di->dev, "Within hysteresis limit temp: %d " |
@@ -682,12 +693,12 @@ static void abx500_chargalg_check_temp(struct abx500_chargalg *di) | |||
682 | */ | 693 | */ |
683 | static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di) | 694 | static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di) |
684 | { | 695 | { |
685 | if (di->chg_info.usb_volt > di->bat->chg_params->usb_volt_max) | 696 | if (di->chg_info.usb_volt > di->bm->chg_params->usb_volt_max) |
686 | di->chg_info.usb_chg_ok = false; | 697 | di->chg_info.usb_chg_ok = false; |
687 | else | 698 | else |
688 | di->chg_info.usb_chg_ok = true; | 699 | di->chg_info.usb_chg_ok = true; |
689 | 700 | ||
690 | if (di->chg_info.ac_volt > di->bat->chg_params->ac_volt_max) | 701 | if (di->chg_info.ac_volt > di->bm->chg_params->ac_volt_max) |
691 | di->chg_info.ac_chg_ok = false; | 702 | di->chg_info.ac_chg_ok = false; |
692 | else | 703 | else |
693 | di->chg_info.ac_chg_ok = true; | 704 | di->chg_info.ac_chg_ok = true; |
@@ -707,10 +718,10 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di) | |||
707 | if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING && | 718 | if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING && |
708 | di->charge_state == STATE_NORMAL && | 719 | di->charge_state == STATE_NORMAL && |
709 | !di->maintenance_chg && (di->batt_data.volt >= | 720 | !di->maintenance_chg && (di->batt_data.volt >= |
710 | di->bat->bat_type[di->bat->batt_id].termination_vol || | 721 | di->bm->bat_type[di->bm->batt_id].termination_vol || |
711 | di->events.usb_cv_active || di->events.ac_cv_active) && | 722 | di->events.usb_cv_active || di->events.ac_cv_active) && |
712 | di->batt_data.avg_curr < | 723 | di->batt_data.avg_curr < |
713 | di->bat->bat_type[di->bat->batt_id].termination_curr && | 724 | di->bm->bat_type[di->bm->batt_id].termination_curr && |
714 | di->batt_data.avg_curr > 0) { | 725 | di->batt_data.avg_curr > 0) { |
715 | if (++di->eoc_cnt >= EOC_COND_CNT) { | 726 | if (++di->eoc_cnt >= EOC_COND_CNT) { |
716 | di->eoc_cnt = 0; | 727 | di->eoc_cnt = 0; |
@@ -733,12 +744,12 @@ static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di) | |||
733 | static void init_maxim_chg_curr(struct abx500_chargalg *di) | 744 | static void init_maxim_chg_curr(struct abx500_chargalg *di) |
734 | { | 745 | { |
735 | di->ccm.original_iset = | 746 | di->ccm.original_iset = |
736 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; | 747 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl; |
737 | di->ccm.current_iset = | 748 | di->ccm.current_iset = |
738 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl; | 749 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl; |
739 | di->ccm.test_delta_i = di->bat->maxi->charger_curr_step; | 750 | di->ccm.test_delta_i = di->bm->maxi->charger_curr_step; |
740 | di->ccm.max_current = di->bat->maxi->chg_curr; | 751 | di->ccm.max_current = di->bm->maxi->chg_curr; |
741 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | 752 | di->ccm.condition_cnt = di->bm->maxi->wait_cycles; |
742 | di->ccm.level = 0; | 753 | di->ccm.level = 0; |
743 | } | 754 | } |
744 | 755 | ||
@@ -755,7 +766,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) | |||
755 | { | 766 | { |
756 | int delta_i; | 767 | int delta_i; |
757 | 768 | ||
758 | if (!di->bat->maxi->ena_maxi) | 769 | if (!di->bm->maxi->ena_maxi) |
759 | return MAXIM_RET_NOACTION; | 770 | return MAXIM_RET_NOACTION; |
760 | 771 | ||
761 | delta_i = di->ccm.original_iset - di->batt_data.inst_curr; | 772 | delta_i = di->ccm.original_iset - di->batt_data.inst_curr; |
@@ -766,7 +777,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) | |||
766 | if (di->ccm.wait_cnt == 0) { | 777 | if (di->ccm.wait_cnt == 0) { |
767 | dev_dbg(di->dev, "lowering current\n"); | 778 | dev_dbg(di->dev, "lowering current\n"); |
768 | di->ccm.wait_cnt++; | 779 | di->ccm.wait_cnt++; |
769 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | 780 | di->ccm.condition_cnt = di->bm->maxi->wait_cycles; |
770 | di->ccm.max_current = | 781 | di->ccm.max_current = |
771 | di->ccm.current_iset - di->ccm.test_delta_i; | 782 | di->ccm.current_iset - di->ccm.test_delta_i; |
772 | di->ccm.current_iset = di->ccm.max_current; | 783 | di->ccm.current_iset = di->ccm.max_current; |
@@ -791,7 +802,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) | |||
791 | if (di->ccm.current_iset == di->ccm.original_iset) | 802 | if (di->ccm.current_iset == di->ccm.original_iset) |
792 | return MAXIM_RET_NOACTION; | 803 | return MAXIM_RET_NOACTION; |
793 | 804 | ||
794 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | 805 | di->ccm.condition_cnt = di->bm->maxi->wait_cycles; |
795 | di->ccm.current_iset = di->ccm.original_iset; | 806 | di->ccm.current_iset = di->ccm.original_iset; |
796 | di->ccm.level = 0; | 807 | di->ccm.level = 0; |
797 | 808 | ||
@@ -803,7 +814,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) | |||
803 | di->ccm.max_current) { | 814 | di->ccm.max_current) { |
804 | if (di->ccm.condition_cnt-- == 0) { | 815 | if (di->ccm.condition_cnt-- == 0) { |
805 | /* Increse the iset with cco.test_delta_i */ | 816 | /* Increse the iset with cco.test_delta_i */ |
806 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | 817 | di->ccm.condition_cnt = di->bm->maxi->wait_cycles; |
807 | di->ccm.current_iset += di->ccm.test_delta_i; | 818 | di->ccm.current_iset += di->ccm.test_delta_i; |
808 | di->ccm.level++; | 819 | di->ccm.level++; |
809 | dev_dbg(di->dev, " Maximization needed, increase" | 820 | dev_dbg(di->dev, " Maximization needed, increase" |
@@ -818,7 +829,7 @@ static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di) | |||
818 | return MAXIM_RET_NOACTION; | 829 | return MAXIM_RET_NOACTION; |
819 | } | 830 | } |
820 | } else { | 831 | } else { |
821 | di->ccm.condition_cnt = di->bat->maxi->wait_cycles; | 832 | di->ccm.condition_cnt = di->bm->maxi->wait_cycles; |
822 | return MAXIM_RET_NOACTION; | 833 | return MAXIM_RET_NOACTION; |
823 | } | 834 | } |
824 | } | 835 | } |
@@ -838,7 +849,7 @@ static void handle_maxim_chg_curr(struct abx500_chargalg *di) | |||
838 | break; | 849 | break; |
839 | case MAXIM_RET_IBAT_TOO_HIGH: | 850 | case MAXIM_RET_IBAT_TOO_HIGH: |
840 | result = abx500_chargalg_update_chg_curr(di, | 851 | result = abx500_chargalg_update_chg_curr(di, |
841 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); | 852 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); |
842 | if (result) | 853 | if (result) |
843 | dev_err(di->dev, "failed to set chg curr\n"); | 854 | dev_err(di->dev, "failed to set chg curr\n"); |
844 | break; | 855 | break; |
@@ -858,6 +869,7 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data) | |||
858 | union power_supply_propval ret; | 869 | union power_supply_propval ret; |
859 | int i, j; | 870 | int i, j; |
860 | bool psy_found = false; | 871 | bool psy_found = false; |
872 | bool capacity_updated = false; | ||
861 | 873 | ||
862 | psy = (struct power_supply *)data; | 874 | psy = (struct power_supply *)data; |
863 | ext = dev_get_drvdata(dev); | 875 | ext = dev_get_drvdata(dev); |
@@ -870,6 +882,16 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data) | |||
870 | if (!psy_found) | 882 | if (!psy_found) |
871 | return 0; | 883 | return 0; |
872 | 884 | ||
885 | /* | ||
886 | * If external is not registering 'POWER_SUPPLY_PROP_CAPACITY' to its | ||
887 | * property because of handling that sysfs entry on its own, this is | ||
888 | * the place to get the battery capacity. | ||
889 | */ | ||
890 | if (!ext->get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) { | ||
891 | di->batt_data.percent = ret.intval; | ||
892 | capacity_updated = true; | ||
893 | } | ||
894 | |||
873 | /* Go through all properties for the psy */ | 895 | /* Go through all properties for the psy */ |
874 | for (j = 0; j < ext->num_properties; j++) { | 896 | for (j = 0; j < ext->num_properties; j++) { |
875 | enum power_supply_property prop; | 897 | enum power_supply_property prop; |
@@ -1154,7 +1176,8 @@ static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data) | |||
1154 | } | 1176 | } |
1155 | break; | 1177 | break; |
1156 | case POWER_SUPPLY_PROP_CAPACITY: | 1178 | case POWER_SUPPLY_PROP_CAPACITY: |
1157 | di->batt_data.percent = ret.intval; | 1179 | if (!capacity_updated) |
1180 | di->batt_data.percent = ret.intval; | ||
1158 | break; | 1181 | break; |
1159 | default: | 1182 | default: |
1160 | break; | 1183 | break; |
@@ -1210,7 +1233,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1210 | * this way | 1233 | * this way |
1211 | */ | 1234 | */ |
1212 | if (!charger_status || | 1235 | if (!charger_status || |
1213 | (di->events.batt_unknown && !di->bat->chg_unknown_bat)) { | 1236 | (di->events.batt_unknown && !di->bm->chg_unknown_bat)) { |
1214 | if (di->charge_state != STATE_HANDHELD) { | 1237 | if (di->charge_state != STATE_HANDHELD) { |
1215 | di->events.safety_timer_expired = false; | 1238 | di->events.safety_timer_expired = false; |
1216 | abx500_chargalg_state_to(di, STATE_HANDHELD_INIT); | 1239 | abx500_chargalg_state_to(di, STATE_HANDHELD_INIT); |
@@ -1394,8 +1417,8 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1394 | 1417 | ||
1395 | case STATE_NORMAL_INIT: | 1418 | case STATE_NORMAL_INIT: |
1396 | abx500_chargalg_start_charging(di, | 1419 | abx500_chargalg_start_charging(di, |
1397 | di->bat->bat_type[di->bat->batt_id].normal_vol_lvl, | 1420 | di->bm->bat_type[di->bm->batt_id].normal_vol_lvl, |
1398 | di->bat->bat_type[di->bat->batt_id].normal_cur_lvl); | 1421 | di->bm->bat_type[di->bm->batt_id].normal_cur_lvl); |
1399 | abx500_chargalg_state_to(di, STATE_NORMAL); | 1422 | abx500_chargalg_state_to(di, STATE_NORMAL); |
1400 | abx500_chargalg_start_safety_timer(di); | 1423 | abx500_chargalg_start_safety_timer(di); |
1401 | abx500_chargalg_stop_maintenance_timer(di); | 1424 | abx500_chargalg_stop_maintenance_timer(di); |
@@ -1411,7 +1434,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1411 | handle_maxim_chg_curr(di); | 1434 | handle_maxim_chg_curr(di); |
1412 | if (di->charge_status == POWER_SUPPLY_STATUS_FULL && | 1435 | if (di->charge_status == POWER_SUPPLY_STATUS_FULL && |
1413 | di->maintenance_chg) { | 1436 | di->maintenance_chg) { |
1414 | if (di->bat->no_maintenance) | 1437 | if (di->bm->no_maintenance) |
1415 | abx500_chargalg_state_to(di, | 1438 | abx500_chargalg_state_to(di, |
1416 | STATE_WAIT_FOR_RECHARGE_INIT); | 1439 | STATE_WAIT_FOR_RECHARGE_INIT); |
1417 | else | 1440 | else |
@@ -1424,28 +1447,25 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1424 | case STATE_WAIT_FOR_RECHARGE_INIT: | 1447 | case STATE_WAIT_FOR_RECHARGE_INIT: |
1425 | abx500_chargalg_hold_charging(di); | 1448 | abx500_chargalg_hold_charging(di); |
1426 | abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE); | 1449 | abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE); |
1427 | di->rch_cnt = RCH_COND_CNT; | ||
1428 | /* Intentional fallthrough */ | 1450 | /* Intentional fallthrough */ |
1429 | 1451 | ||
1430 | case STATE_WAIT_FOR_RECHARGE: | 1452 | case STATE_WAIT_FOR_RECHARGE: |
1431 | if (di->batt_data.volt <= | 1453 | if (di->batt_data.percent <= |
1432 | di->bat->bat_type[di->bat->batt_id].recharge_vol) { | 1454 | di->bm->bat_type[di->bm->batt_id]. |
1433 | if (di->rch_cnt-- == 0) | 1455 | recharge_cap) |
1434 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); | 1456 | abx500_chargalg_state_to(di, STATE_NORMAL_INIT); |
1435 | } else | ||
1436 | di->rch_cnt = RCH_COND_CNT; | ||
1437 | break; | 1457 | break; |
1438 | 1458 | ||
1439 | case STATE_MAINTENANCE_A_INIT: | 1459 | case STATE_MAINTENANCE_A_INIT: |
1440 | abx500_chargalg_stop_safety_timer(di); | 1460 | abx500_chargalg_stop_safety_timer(di); |
1441 | abx500_chargalg_start_maintenance_timer(di, | 1461 | abx500_chargalg_start_maintenance_timer(di, |
1442 | di->bat->bat_type[ | 1462 | di->bm->bat_type[ |
1443 | di->bat->batt_id].maint_a_chg_timer_h); | 1463 | di->bm->batt_id].maint_a_chg_timer_h); |
1444 | abx500_chargalg_start_charging(di, | 1464 | abx500_chargalg_start_charging(di, |
1445 | di->bat->bat_type[ | 1465 | di->bm->bat_type[ |
1446 | di->bat->batt_id].maint_a_vol_lvl, | 1466 | di->bm->batt_id].maint_a_vol_lvl, |
1447 | di->bat->bat_type[ | 1467 | di->bm->bat_type[ |
1448 | di->bat->batt_id].maint_a_cur_lvl); | 1468 | di->bm->batt_id].maint_a_cur_lvl); |
1449 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_A); | 1469 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_A); |
1450 | power_supply_changed(&di->chargalg_psy); | 1470 | power_supply_changed(&di->chargalg_psy); |
1451 | /* Intentional fallthrough*/ | 1471 | /* Intentional fallthrough*/ |
@@ -1459,13 +1479,13 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1459 | 1479 | ||
1460 | case STATE_MAINTENANCE_B_INIT: | 1480 | case STATE_MAINTENANCE_B_INIT: |
1461 | abx500_chargalg_start_maintenance_timer(di, | 1481 | abx500_chargalg_start_maintenance_timer(di, |
1462 | di->bat->bat_type[ | 1482 | di->bm->bat_type[ |
1463 | di->bat->batt_id].maint_b_chg_timer_h); | 1483 | di->bm->batt_id].maint_b_chg_timer_h); |
1464 | abx500_chargalg_start_charging(di, | 1484 | abx500_chargalg_start_charging(di, |
1465 | di->bat->bat_type[ | 1485 | di->bm->bat_type[ |
1466 | di->bat->batt_id].maint_b_vol_lvl, | 1486 | di->bm->batt_id].maint_b_vol_lvl, |
1467 | di->bat->bat_type[ | 1487 | di->bm->bat_type[ |
1468 | di->bat->batt_id].maint_b_cur_lvl); | 1488 | di->bm->batt_id].maint_b_cur_lvl); |
1469 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_B); | 1489 | abx500_chargalg_state_to(di, STATE_MAINTENANCE_B); |
1470 | power_supply_changed(&di->chargalg_psy); | 1490 | power_supply_changed(&di->chargalg_psy); |
1471 | /* Intentional fallthrough*/ | 1491 | /* Intentional fallthrough*/ |
@@ -1479,10 +1499,10 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) | |||
1479 | 1499 | ||
1480 | case STATE_TEMP_LOWHIGH_INIT: | 1500 | case STATE_TEMP_LOWHIGH_INIT: |
1481 | abx500_chargalg_start_charging(di, | 1501 | abx500_chargalg_start_charging(di, |
1482 | di->bat->bat_type[ | 1502 | di->bm->bat_type[ |
1483 | di->bat->batt_id].low_high_vol_lvl, | 1503 | di->bm->batt_id].low_high_vol_lvl, |
1484 | di->bat->bat_type[ | 1504 | di->bm->bat_type[ |
1485 | di->bat->batt_id].low_high_cur_lvl); | 1505 | di->bm->batt_id].low_high_cur_lvl); |
1486 | abx500_chargalg_stop_maintenance_timer(di); | 1506 | abx500_chargalg_stop_maintenance_timer(di); |
1487 | di->charge_status = POWER_SUPPLY_STATUS_CHARGING; | 1507 | di->charge_status = POWER_SUPPLY_STATUS_CHARGING; |
1488 | abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); | 1508 | abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); |
@@ -1543,11 +1563,11 @@ static void abx500_chargalg_periodic_work(struct work_struct *work) | |||
1543 | if (di->chg_info.conn_chg) | 1563 | if (di->chg_info.conn_chg) |
1544 | queue_delayed_work(di->chargalg_wq, | 1564 | queue_delayed_work(di->chargalg_wq, |
1545 | &di->chargalg_periodic_work, | 1565 | &di->chargalg_periodic_work, |
1546 | di->bat->interval_charging * HZ); | 1566 | di->bm->interval_charging * HZ); |
1547 | else | 1567 | else |
1548 | queue_delayed_work(di->chargalg_wq, | 1568 | queue_delayed_work(di->chargalg_wq, |
1549 | &di->chargalg_periodic_work, | 1569 | &di->chargalg_periodic_work, |
1550 | di->bat->interval_not_charging * HZ); | 1570 | di->bm->interval_not_charging * HZ); |
1551 | } | 1571 | } |
1552 | 1572 | ||
1553 | /** | 1573 | /** |
@@ -1614,10 +1634,13 @@ static int abx500_chargalg_get_property(struct power_supply *psy, | |||
1614 | if (di->events.batt_ovv) { | 1634 | if (di->events.batt_ovv) { |
1615 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | 1635 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; |
1616 | } else if (di->events.btemp_underover) { | 1636 | } else if (di->events.btemp_underover) { |
1617 | if (di->batt_data.temp <= di->bat->temp_under) | 1637 | if (di->batt_data.temp <= di->bm->temp_under) |
1618 | val->intval = POWER_SUPPLY_HEALTH_COLD; | 1638 | val->intval = POWER_SUPPLY_HEALTH_COLD; |
1619 | else | 1639 | else |
1620 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | 1640 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; |
1641 | } else if (di->charge_state == STATE_SAFETY_TIMER_EXPIRED || | ||
1642 | di->charge_state == STATE_SAFETY_TIMER_EXPIRED_INIT) { | ||
1643 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
1621 | } else { | 1644 | } else { |
1622 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | 1645 | val->intval = POWER_SUPPLY_HEALTH_GOOD; |
1623 | } | 1646 | } |
@@ -1631,6 +1654,25 @@ static int abx500_chargalg_get_property(struct power_supply *psy, | |||
1631 | /* Exposure to the sysfs interface */ | 1654 | /* Exposure to the sysfs interface */ |
1632 | 1655 | ||
1633 | /** | 1656 | /** |
1657 | * abx500_chargalg_sysfs_show() - sysfs show operations | ||
1658 | * @kobj: pointer to the struct kobject | ||
1659 | * @attr: pointer to the struct attribute | ||
1660 | * @buf: buffer that holds the parameter to send to userspace | ||
1661 | * | ||
1662 | * Returns a buffer to be displayed in user space | ||
1663 | */ | ||
1664 | static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj, | ||
1665 | struct attribute *attr, char *buf) | ||
1666 | { | ||
1667 | struct abx500_chargalg *di = container_of(kobj, | ||
1668 | struct abx500_chargalg, chargalg_kobject); | ||
1669 | |||
1670 | return sprintf(buf, "%d\n", | ||
1671 | di->susp_status.ac_suspended && | ||
1672 | di->susp_status.usb_suspended); | ||
1673 | } | ||
1674 | |||
1675 | /** | ||
1634 | * abx500_chargalg_sysfs_charger() - sysfs store operations | 1676 | * abx500_chargalg_sysfs_charger() - sysfs store operations |
1635 | * @kobj: pointer to the struct kobject | 1677 | * @kobj: pointer to the struct kobject |
1636 | * @attr: pointer to the struct attribute | 1678 | * @attr: pointer to the struct attribute |
@@ -1698,7 +1740,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, | |||
1698 | static struct attribute abx500_chargalg_en_charger = \ | 1740 | static struct attribute abx500_chargalg_en_charger = \ |
1699 | { | 1741 | { |
1700 | .name = "chargalg", | 1742 | .name = "chargalg", |
1701 | .mode = S_IWUGO, | 1743 | .mode = S_IRUGO | S_IWUSR, |
1702 | }; | 1744 | }; |
1703 | 1745 | ||
1704 | static struct attribute *abx500_chargalg_chg[] = { | 1746 | static struct attribute *abx500_chargalg_chg[] = { |
@@ -1707,6 +1749,7 @@ static struct attribute *abx500_chargalg_chg[] = { | |||
1707 | }; | 1749 | }; |
1708 | 1750 | ||
1709 | static const struct sysfs_ops abx500_chargalg_sysfs_ops = { | 1751 | static const struct sysfs_ops abx500_chargalg_sysfs_ops = { |
1752 | .show = abx500_chargalg_sysfs_show, | ||
1710 | .store = abx500_chargalg_sysfs_charger, | 1753 | .store = abx500_chargalg_sysfs_charger, |
1711 | }; | 1754 | }; |
1712 | 1755 | ||
@@ -1806,6 +1849,7 @@ static char *supply_interface[] = { | |||
1806 | static int abx500_chargalg_probe(struct platform_device *pdev) | 1849 | static int abx500_chargalg_probe(struct platform_device *pdev) |
1807 | { | 1850 | { |
1808 | struct device_node *np = pdev->dev.of_node; | 1851 | struct device_node *np = pdev->dev.of_node; |
1852 | struct abx500_bm_data *plat = pdev->dev.platform_data; | ||
1809 | struct abx500_chargalg *di; | 1853 | struct abx500_chargalg *di; |
1810 | int ret = 0; | 1854 | int ret = 0; |
1811 | 1855 | ||
@@ -1814,21 +1858,19 @@ static int abx500_chargalg_probe(struct platform_device *pdev) | |||
1814 | dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); | 1858 | dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); |
1815 | return -ENOMEM; | 1859 | return -ENOMEM; |
1816 | } | 1860 | } |
1817 | di->bat = pdev->mfd_cell->platform_data; | 1861 | |
1818 | if (!di->bat) { | 1862 | if (!plat) { |
1819 | if (np) { | 1863 | dev_err(&pdev->dev, "no battery management data supplied\n"); |
1820 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | 1864 | return -EINVAL; |
1821 | if (ret) { | 1865 | } |
1822 | dev_err(&pdev->dev, | 1866 | di->bm = plat; |
1823 | "failed to get battery information\n"); | 1867 | |
1824 | return ret; | 1868 | if (np) { |
1825 | } | 1869 | ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm); |
1826 | } else { | 1870 | if (ret) { |
1827 | dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n"); | 1871 | dev_err(&pdev->dev, "failed to get battery information\n"); |
1828 | return -EINVAL; | 1872 | return ret; |
1829 | } | 1873 | } |
1830 | } else { | ||
1831 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
1832 | } | 1874 | } |
1833 | 1875 | ||
1834 | /* get device struct */ | 1876 | /* get device struct */ |
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c index ee842b37f462..ca91396fc48e 100644 --- a/drivers/power/bq2415x_charger.c +++ b/drivers/power/bq2415x_charger.c | |||
@@ -28,7 +28,6 @@ | |||
28 | * http://www.ti.com/product/bq24155 | 28 | * http://www.ti.com/product/bq24155 |
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/version.h> | ||
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
34 | #include <linux/param.h> | 33 | #include <linux/param.h> |
@@ -734,12 +733,10 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode) | |||
734 | int charger = 0; | 733 | int charger = 0; |
735 | int boost = 0; | 734 | int boost = 0; |
736 | 735 | ||
737 | if (mode == BQ2415X_MODE_HOST_CHARGER || | ||
738 | mode == BQ2415X_MODE_DEDICATED_CHARGER) | ||
739 | charger = 1; | ||
740 | |||
741 | if (mode == BQ2415X_MODE_BOOST) | 736 | if (mode == BQ2415X_MODE_BOOST) |
742 | boost = 1; | 737 | boost = 1; |
738 | else if (mode != BQ2415X_MODE_OFF) | ||
739 | charger = 1; | ||
743 | 740 | ||
744 | if (!charger) | 741 | if (!charger) |
745 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE); | 742 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE); |
@@ -751,6 +748,10 @@ static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode) | |||
751 | return ret; | 748 | return ret; |
752 | 749 | ||
753 | switch (mode) { | 750 | switch (mode) { |
751 | case BQ2415X_MODE_OFF: | ||
752 | dev_dbg(bq->dev, "changing mode to: Offline\n"); | ||
753 | ret = bq2415x_set_current_limit(bq, 100); | ||
754 | break; | ||
754 | case BQ2415X_MODE_NONE: | 755 | case BQ2415X_MODE_NONE: |
755 | dev_dbg(bq->dev, "changing mode to: N/A\n"); | 756 | dev_dbg(bq->dev, "changing mode to: N/A\n"); |
756 | ret = bq2415x_set_current_limit(bq, 100); | 757 | ret = bq2415x_set_current_limit(bq, 100); |
@@ -843,7 +844,7 @@ static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg) | |||
843 | dev_err(bq->dev, "%s\n", msg); | 844 | dev_err(bq->dev, "%s\n", msg); |
844 | if (bq->automode > 0) | 845 | if (bq->automode > 0) |
845 | bq->automode = 0; | 846 | bq->automode = 0; |
846 | bq2415x_set_mode(bq, BQ2415X_MODE_NONE); | 847 | bq2415x_set_mode(bq, BQ2415X_MODE_OFF); |
847 | bq2415x_set_autotimer(bq, 0); | 848 | bq2415x_set_autotimer(bq, 0); |
848 | } | 849 | } |
849 | 850 | ||
@@ -1136,6 +1137,10 @@ static ssize_t bq2415x_sysfs_set_mode(struct device *dev, | |||
1136 | return -ENOSYS; | 1137 | return -ENOSYS; |
1137 | bq->automode = 1; | 1138 | bq->automode = 1; |
1138 | mode = bq->reported_mode; | 1139 | mode = bq->reported_mode; |
1140 | } else if (strncmp(buf, "off", 3) == 0) { | ||
1141 | if (bq->automode > 0) | ||
1142 | bq->automode = 0; | ||
1143 | mode = BQ2415X_MODE_OFF; | ||
1139 | } else if (strncmp(buf, "none", 4) == 0) { | 1144 | } else if (strncmp(buf, "none", 4) == 0) { |
1140 | if (bq->automode > 0) | 1145 | if (bq->automode > 0) |
1141 | bq->automode = 0; | 1146 | bq->automode = 0; |
@@ -1183,6 +1188,9 @@ static ssize_t bq2415x_sysfs_show_mode(struct device *dev, | |||
1183 | ret += sprintf(buf+ret, "auto ("); | 1188 | ret += sprintf(buf+ret, "auto ("); |
1184 | 1189 | ||
1185 | switch (bq->mode) { | 1190 | switch (bq->mode) { |
1191 | case BQ2415X_MODE_OFF: | ||
1192 | ret += sprintf(buf+ret, "off"); | ||
1193 | break; | ||
1186 | case BQ2415X_MODE_NONE: | 1194 | case BQ2415X_MODE_NONE: |
1187 | ret += sprintf(buf+ret, "none"); | 1195 | ret += sprintf(buf+ret, "none"); |
1188 | break; | 1196 | break; |
@@ -1217,6 +1225,8 @@ static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev, | |||
1217 | return -EINVAL; | 1225 | return -EINVAL; |
1218 | 1226 | ||
1219 | switch (bq->reported_mode) { | 1227 | switch (bq->reported_mode) { |
1228 | case BQ2415X_MODE_OFF: | ||
1229 | return sprintf(buf, "off\n"); | ||
1220 | case BQ2415X_MODE_NONE: | 1230 | case BQ2415X_MODE_NONE: |
1221 | return sprintf(buf, "none\n"); | 1231 | return sprintf(buf, "none\n"); |
1222 | case BQ2415X_MODE_HOST_CHARGER: | 1232 | case BQ2415X_MODE_HOST_CHARGER: |
@@ -1523,7 +1533,7 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1523 | goto error_1; | 1533 | goto error_1; |
1524 | } | 1534 | } |
1525 | 1535 | ||
1526 | bq = kzalloc(sizeof(*bq), GFP_KERNEL); | 1536 | bq = devm_kzalloc(&client->dev, sizeof(*bq), GFP_KERNEL); |
1527 | if (!bq) { | 1537 | if (!bq) { |
1528 | dev_err(&client->dev, "failed to allocate device data\n"); | 1538 | dev_err(&client->dev, "failed to allocate device data\n"); |
1529 | ret = -ENOMEM; | 1539 | ret = -ENOMEM; |
@@ -1536,8 +1546,8 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1536 | bq->dev = &client->dev; | 1546 | bq->dev = &client->dev; |
1537 | bq->chip = id->driver_data; | 1547 | bq->chip = id->driver_data; |
1538 | bq->name = name; | 1548 | bq->name = name; |
1539 | bq->mode = BQ2415X_MODE_NONE; | 1549 | bq->mode = BQ2415X_MODE_OFF; |
1540 | bq->reported_mode = BQ2415X_MODE_NONE; | 1550 | bq->reported_mode = BQ2415X_MODE_OFF; |
1541 | bq->autotimer = 0; | 1551 | bq->autotimer = 0; |
1542 | bq->automode = 0; | 1552 | bq->automode = 0; |
1543 | 1553 | ||
@@ -1549,19 +1559,19 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1549 | ret = bq2415x_power_supply_init(bq); | 1559 | ret = bq2415x_power_supply_init(bq); |
1550 | if (ret) { | 1560 | if (ret) { |
1551 | dev_err(bq->dev, "failed to register power supply: %d\n", ret); | 1561 | dev_err(bq->dev, "failed to register power supply: %d\n", ret); |
1552 | goto error_3; | 1562 | goto error_2; |
1553 | } | 1563 | } |
1554 | 1564 | ||
1555 | ret = bq2415x_sysfs_init(bq); | 1565 | ret = bq2415x_sysfs_init(bq); |
1556 | if (ret) { | 1566 | if (ret) { |
1557 | dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); | 1567 | dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); |
1558 | goto error_4; | 1568 | goto error_3; |
1559 | } | 1569 | } |
1560 | 1570 | ||
1561 | ret = bq2415x_set_defaults(bq); | 1571 | ret = bq2415x_set_defaults(bq); |
1562 | if (ret) { | 1572 | if (ret) { |
1563 | dev_err(bq->dev, "failed to set default values: %d\n", ret); | 1573 | dev_err(bq->dev, "failed to set default values: %d\n", ret); |
1564 | goto error_5; | 1574 | goto error_4; |
1565 | } | 1575 | } |
1566 | 1576 | ||
1567 | if (bq->init_data.set_mode_hook) { | 1577 | if (bq->init_data.set_mode_hook) { |
@@ -1585,12 +1595,10 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1585 | dev_info(bq->dev, "driver registered\n"); | 1595 | dev_info(bq->dev, "driver registered\n"); |
1586 | return 0; | 1596 | return 0; |
1587 | 1597 | ||
1588 | error_5: | ||
1589 | bq2415x_sysfs_exit(bq); | ||
1590 | error_4: | 1598 | error_4: |
1591 | bq2415x_power_supply_exit(bq); | 1599 | bq2415x_sysfs_exit(bq); |
1592 | error_3: | 1600 | error_3: |
1593 | kfree(bq); | 1601 | bq2415x_power_supply_exit(bq); |
1594 | error_2: | 1602 | error_2: |
1595 | kfree(name); | 1603 | kfree(name); |
1596 | error_1: | 1604 | error_1: |
@@ -1622,7 +1630,6 @@ static int bq2415x_remove(struct i2c_client *client) | |||
1622 | dev_info(bq->dev, "driver unregistered\n"); | 1630 | dev_info(bq->dev, "driver unregistered\n"); |
1623 | 1631 | ||
1624 | kfree(bq->name); | 1632 | kfree(bq->name); |
1625 | kfree(bq); | ||
1626 | 1633 | ||
1627 | return 0; | 1634 | return 0; |
1628 | } | 1635 | } |
@@ -1652,18 +1659,7 @@ static struct i2c_driver bq2415x_driver = { | |||
1652 | .remove = bq2415x_remove, | 1659 | .remove = bq2415x_remove, |
1653 | .id_table = bq2415x_i2c_id_table, | 1660 | .id_table = bq2415x_i2c_id_table, |
1654 | }; | 1661 | }; |
1655 | 1662 | module_i2c_driver(bq2415x_driver); | |
1656 | static int __init bq2415x_init(void) | ||
1657 | { | ||
1658 | return i2c_add_driver(&bq2415x_driver); | ||
1659 | } | ||
1660 | module_init(bq2415x_init); | ||
1661 | |||
1662 | static void __exit bq2415x_exit(void) | ||
1663 | { | ||
1664 | i2c_del_driver(&bq2415x_driver); | ||
1665 | } | ||
1666 | module_exit(bq2415x_exit); | ||
1667 | 1663 | ||
1668 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | 1664 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); |
1669 | MODULE_DESCRIPTION("bq2415x charger driver"); | 1665 | MODULE_DESCRIPTION("bq2415x charger driver"); |
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index 36b34efdafc9..8ccf5d7d0add 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
@@ -299,7 +299,7 @@ static int bq27x00_battery_read_energy(struct bq27x00_device_info *di) | |||
299 | } | 299 | } |
300 | 300 | ||
301 | /* | 301 | /* |
302 | * Return the battery temperature in tenths of degree Celsius | 302 | * Return the battery temperature in tenths of degree Kelvin |
303 | * Or < 0 if something fails. | 303 | * Or < 0 if something fails. |
304 | */ | 304 | */ |
305 | static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di) | 305 | static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di) |
@@ -312,10 +312,8 @@ static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di) | |||
312 | return temp; | 312 | return temp; |
313 | } | 313 | } |
314 | 314 | ||
315 | if (bq27xxx_is_chip_version_higher(di)) | 315 | if (!bq27xxx_is_chip_version_higher(di)) |
316 | temp -= 2731; | 316 | temp = 5 * temp / 2; |
317 | else | ||
318 | temp = ((temp * 5) - 5463) / 2; | ||
319 | 317 | ||
320 | return temp; | 318 | return temp; |
321 | } | 319 | } |
@@ -448,7 +446,6 @@ static void bq27x00_update(struct bq27x00_device_info *di) | |||
448 | cache.temperature = bq27x00_battery_read_temperature(di); | 446 | cache.temperature = bq27x00_battery_read_temperature(di); |
449 | if (!is_bq27425) | 447 | if (!is_bq27425) |
450 | cache.cycle_count = bq27x00_battery_read_cyct(di); | 448 | cache.cycle_count = bq27x00_battery_read_cyct(di); |
451 | cache.cycle_count = bq27x00_battery_read_cyct(di); | ||
452 | cache.power_avg = | 449 | cache.power_avg = |
453 | bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); | 450 | bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); |
454 | 451 | ||
@@ -642,6 +639,8 @@ static int bq27x00_battery_get_property(struct power_supply *psy, | |||
642 | break; | 639 | break; |
643 | case POWER_SUPPLY_PROP_TEMP: | 640 | case POWER_SUPPLY_PROP_TEMP: |
644 | ret = bq27x00_simple_value(di->cache.temperature, val); | 641 | ret = bq27x00_simple_value(di->cache.temperature, val); |
642 | if (ret == 0) | ||
643 | val->intval -= 2731; | ||
645 | break; | 644 | break; |
646 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: | 645 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: |
647 | ret = bq27x00_simple_value(di->cache.time_to_empty, val); | 646 | ret = bq27x00_simple_value(di->cache.time_to_empty, val); |
@@ -696,7 +695,6 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di) | |||
696 | int ret; | 695 | int ret; |
697 | 696 | ||
698 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; | 697 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; |
699 | di->chip = BQ27425; | ||
700 | if (di->chip == BQ27425) { | 698 | if (di->chip == BQ27425) { |
701 | di->bat.properties = bq27425_battery_props; | 699 | di->bat.properties = bq27425_battery_props; |
702 | di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props); | 700 | di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props); |
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 6ba047f5ac2c..8acc3f8d303c 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c | |||
@@ -669,15 +669,21 @@ static void _setup_polling(struct work_struct *work) | |||
669 | WARN(cm_wq == NULL, "charger-manager: workqueue not initialized" | 669 | WARN(cm_wq == NULL, "charger-manager: workqueue not initialized" |
670 | ". try it later. %s\n", __func__); | 670 | ". try it later. %s\n", __func__); |
671 | 671 | ||
672 | /* | ||
673 | * Use mod_delayed_work() iff the next polling interval should | ||
674 | * occur before the currently scheduled one. If @cm_monitor_work | ||
675 | * isn't active, the end result is the same, so no need to worry | ||
676 | * about stale @next_polling. | ||
677 | */ | ||
672 | _next_polling = jiffies + polling_jiffy; | 678 | _next_polling = jiffies + polling_jiffy; |
673 | 679 | ||
674 | if (!delayed_work_pending(&cm_monitor_work) || | 680 | if (time_before(_next_polling, next_polling)) { |
675 | (delayed_work_pending(&cm_monitor_work) && | ||
676 | time_after(next_polling, _next_polling))) { | ||
677 | next_polling = jiffies + polling_jiffy; | ||
678 | mod_delayed_work(cm_wq, &cm_monitor_work, polling_jiffy); | 681 | mod_delayed_work(cm_wq, &cm_monitor_work, polling_jiffy); |
682 | next_polling = _next_polling; | ||
683 | } else { | ||
684 | if (queue_delayed_work(cm_wq, &cm_monitor_work, polling_jiffy)) | ||
685 | next_polling = _next_polling; | ||
679 | } | 686 | } |
680 | |||
681 | out: | 687 | out: |
682 | mutex_unlock(&cm_list_mtx); | 688 | mutex_unlock(&cm_list_mtx); |
683 | } | 689 | } |
@@ -751,8 +757,7 @@ static void misc_event_handler(struct charger_manager *cm, | |||
751 | if (cm_suspended) | 757 | if (cm_suspended) |
752 | device_set_wakeup_capable(cm->dev, true); | 758 | device_set_wakeup_capable(cm->dev, true); |
753 | 759 | ||
754 | if (!delayed_work_pending(&cm_monitor_work) && | 760 | if (is_polling_required(cm) && cm->desc->polling_interval_ms) |
755 | is_polling_required(cm) && cm->desc->polling_interval_ms) | ||
756 | schedule_work(&setup_polling); | 761 | schedule_work(&setup_polling); |
757 | uevent_notify(cm, default_event_names[type]); | 762 | uevent_notify(cm, default_event_names[type]); |
758 | } | 763 | } |
@@ -1170,8 +1175,7 @@ static int charger_extcon_notifier(struct notifier_block *self, | |||
1170 | * when charger cable is attached. | 1175 | * when charger cable is attached. |
1171 | */ | 1176 | */ |
1172 | if (cable->attached && is_polling_required(cable->cm)) { | 1177 | if (cable->attached && is_polling_required(cable->cm)) { |
1173 | if (work_pending(&setup_polling)) | 1178 | cancel_work_sync(&setup_polling); |
1174 | cancel_work_sync(&setup_polling); | ||
1175 | schedule_work(&setup_polling); | 1179 | schedule_work(&setup_polling); |
1176 | } | 1180 | } |
1177 | 1181 | ||
@@ -1215,6 +1219,55 @@ static int charger_extcon_init(struct charger_manager *cm, | |||
1215 | return ret; | 1219 | return ret; |
1216 | } | 1220 | } |
1217 | 1221 | ||
1222 | /** | ||
1223 | * charger_manager_register_extcon - Register extcon device to recevie state | ||
1224 | * of charger cable. | ||
1225 | * @cm: the Charger Manager representing the battery. | ||
1226 | * | ||
1227 | * This function support EXTCON(External Connector) subsystem to detect the | ||
1228 | * state of charger cables for enabling or disabling charger(regulator) and | ||
1229 | * select the charger cable for charging among a number of external cable | ||
1230 | * according to policy of H/W board. | ||
1231 | */ | ||
1232 | static int charger_manager_register_extcon(struct charger_manager *cm) | ||
1233 | { | ||
1234 | struct charger_desc *desc = cm->desc; | ||
1235 | struct charger_regulator *charger; | ||
1236 | int ret = 0; | ||
1237 | int i; | ||
1238 | int j; | ||
1239 | |||
1240 | for (i = 0; i < desc->num_charger_regulators; i++) { | ||
1241 | charger = &desc->charger_regulators[i]; | ||
1242 | |||
1243 | charger->consumer = regulator_get(cm->dev, | ||
1244 | charger->regulator_name); | ||
1245 | if (charger->consumer == NULL) { | ||
1246 | dev_err(cm->dev, "Cannot find charger(%s)n", | ||
1247 | charger->regulator_name); | ||
1248 | ret = -EINVAL; | ||
1249 | goto err; | ||
1250 | } | ||
1251 | charger->cm = cm; | ||
1252 | |||
1253 | for (j = 0; j < charger->num_cables; j++) { | ||
1254 | struct charger_cable *cable = &charger->cables[j]; | ||
1255 | |||
1256 | ret = charger_extcon_init(cm, cable); | ||
1257 | if (ret < 0) { | ||
1258 | dev_err(cm->dev, "Cannot initialize charger(%s)n", | ||
1259 | charger->regulator_name); | ||
1260 | goto err; | ||
1261 | } | ||
1262 | cable->charger = charger; | ||
1263 | cable->cm = cm; | ||
1264 | } | ||
1265 | } | ||
1266 | |||
1267 | err: | ||
1268 | return ret; | ||
1269 | } | ||
1270 | |||
1218 | /* help function of sysfs node to control charger(regulator) */ | 1271 | /* help function of sysfs node to control charger(regulator) */ |
1219 | static ssize_t charger_name_show(struct device *dev, | 1272 | static ssize_t charger_name_show(struct device *dev, |
1220 | struct device_attribute *attr, char *buf) | 1273 | struct device_attribute *attr, char *buf) |
@@ -1274,7 +1327,7 @@ static ssize_t charger_externally_control_store(struct device *dev, | |||
1274 | 1327 | ||
1275 | for (i = 0; i < desc->num_charger_regulators; i++) { | 1328 | for (i = 0; i < desc->num_charger_regulators; i++) { |
1276 | if (&desc->charger_regulators[i] != charger && | 1329 | if (&desc->charger_regulators[i] != charger && |
1277 | !desc->charger_regulators[i].externally_control) { | 1330 | !desc->charger_regulators[i].externally_control) { |
1278 | /* | 1331 | /* |
1279 | * At least, one charger is controlled by | 1332 | * At least, one charger is controlled by |
1280 | * charger-manager | 1333 | * charger-manager |
@@ -1303,13 +1356,107 @@ static ssize_t charger_externally_control_store(struct device *dev, | |||
1303 | return count; | 1356 | return count; |
1304 | } | 1357 | } |
1305 | 1358 | ||
1359 | /** | ||
1360 | * charger_manager_register_sysfs - Register sysfs entry for each charger | ||
1361 | * @cm: the Charger Manager representing the battery. | ||
1362 | * | ||
1363 | * This function add sysfs entry for charger(regulator) to control charger from | ||
1364 | * user-space. If some development board use one more chargers for charging | ||
1365 | * but only need one charger on specific case which is dependent on user | ||
1366 | * scenario or hardware restrictions, the user enter 1 or 0(zero) to '/sys/ | ||
1367 | * class/power_supply/battery/charger.[index]/externally_control'. For example, | ||
1368 | * if user enter 1 to 'sys/class/power_supply/battery/charger.[index]/ | ||
1369 | * externally_control, this charger isn't controlled from charger-manager and | ||
1370 | * always stay off state of regulator. | ||
1371 | */ | ||
1372 | static int charger_manager_register_sysfs(struct charger_manager *cm) | ||
1373 | { | ||
1374 | struct charger_desc *desc = cm->desc; | ||
1375 | struct charger_regulator *charger; | ||
1376 | int chargers_externally_control = 1; | ||
1377 | char buf[11]; | ||
1378 | char *str; | ||
1379 | int ret = 0; | ||
1380 | int i; | ||
1381 | |||
1382 | /* Create sysfs entry to control charger(regulator) */ | ||
1383 | for (i = 0; i < desc->num_charger_regulators; i++) { | ||
1384 | charger = &desc->charger_regulators[i]; | ||
1385 | |||
1386 | snprintf(buf, 10, "charger.%d", i); | ||
1387 | str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); | ||
1388 | if (!str) { | ||
1389 | dev_err(cm->dev, "Cannot allocate memory: %s\n", | ||
1390 | charger->regulator_name); | ||
1391 | ret = -ENOMEM; | ||
1392 | goto err; | ||
1393 | } | ||
1394 | strcpy(str, buf); | ||
1395 | |||
1396 | charger->attrs[0] = &charger->attr_name.attr; | ||
1397 | charger->attrs[1] = &charger->attr_state.attr; | ||
1398 | charger->attrs[2] = &charger->attr_externally_control.attr; | ||
1399 | charger->attrs[3] = NULL; | ||
1400 | charger->attr_g.name = str; | ||
1401 | charger->attr_g.attrs = charger->attrs; | ||
1402 | |||
1403 | sysfs_attr_init(&charger->attr_name.attr); | ||
1404 | charger->attr_name.attr.name = "name"; | ||
1405 | charger->attr_name.attr.mode = 0444; | ||
1406 | charger->attr_name.show = charger_name_show; | ||
1407 | |||
1408 | sysfs_attr_init(&charger->attr_state.attr); | ||
1409 | charger->attr_state.attr.name = "state"; | ||
1410 | charger->attr_state.attr.mode = 0444; | ||
1411 | charger->attr_state.show = charger_state_show; | ||
1412 | |||
1413 | sysfs_attr_init(&charger->attr_externally_control.attr); | ||
1414 | charger->attr_externally_control.attr.name | ||
1415 | = "externally_control"; | ||
1416 | charger->attr_externally_control.attr.mode = 0644; | ||
1417 | charger->attr_externally_control.show | ||
1418 | = charger_externally_control_show; | ||
1419 | charger->attr_externally_control.store | ||
1420 | = charger_externally_control_store; | ||
1421 | |||
1422 | if (!desc->charger_regulators[i].externally_control || | ||
1423 | !chargers_externally_control) | ||
1424 | chargers_externally_control = 0; | ||
1425 | |||
1426 | dev_info(cm->dev, "'%s' regulator's externally_control" | ||
1427 | "is %d\n", charger->regulator_name, | ||
1428 | charger->externally_control); | ||
1429 | |||
1430 | ret = sysfs_create_group(&cm->charger_psy.dev->kobj, | ||
1431 | &charger->attr_g); | ||
1432 | if (ret < 0) { | ||
1433 | dev_err(cm->dev, "Cannot create sysfs entry" | ||
1434 | "of %s regulator\n", | ||
1435 | charger->regulator_name); | ||
1436 | ret = -EINVAL; | ||
1437 | goto err; | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | if (chargers_externally_control) { | ||
1442 | dev_err(cm->dev, "Cannot register regulator because " | ||
1443 | "charger-manager must need at least " | ||
1444 | "one charger for charging battery\n"); | ||
1445 | |||
1446 | ret = -EINVAL; | ||
1447 | goto err; | ||
1448 | } | ||
1449 | |||
1450 | err: | ||
1451 | return ret; | ||
1452 | } | ||
1453 | |||
1306 | static int charger_manager_probe(struct platform_device *pdev) | 1454 | static int charger_manager_probe(struct platform_device *pdev) |
1307 | { | 1455 | { |
1308 | struct charger_desc *desc = dev_get_platdata(&pdev->dev); | 1456 | struct charger_desc *desc = dev_get_platdata(&pdev->dev); |
1309 | struct charger_manager *cm; | 1457 | struct charger_manager *cm; |
1310 | int ret = 0, i = 0; | 1458 | int ret = 0, i = 0; |
1311 | int j = 0; | 1459 | int j = 0; |
1312 | int chargers_externally_control = 1; | ||
1313 | union power_supply_propval val; | 1460 | union power_supply_propval val; |
1314 | 1461 | ||
1315 | if (g_desc && !rtc_dev && g_desc->rtc_name) { | 1462 | if (g_desc && !rtc_dev && g_desc->rtc_name) { |
@@ -1440,11 +1587,10 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1440 | 1587 | ||
1441 | memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); | 1588 | memcpy(&cm->charger_psy, &psy_default, sizeof(psy_default)); |
1442 | 1589 | ||
1443 | if (!desc->psy_name) { | 1590 | if (!desc->psy_name) |
1444 | strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX); | 1591 | strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX); |
1445 | } else { | 1592 | else |
1446 | strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX); | 1593 | strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX); |
1447 | } | ||
1448 | cm->charger_psy.name = cm->psy_name_buf; | 1594 | cm->charger_psy.name = cm->psy_name_buf; |
1449 | 1595 | ||
1450 | /* Allocate for psy properties because they may vary */ | 1596 | /* Allocate for psy properties because they may vary */ |
@@ -1496,105 +1642,19 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1496 | goto err_register; | 1642 | goto err_register; |
1497 | } | 1643 | } |
1498 | 1644 | ||
1499 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | 1645 | /* Register extcon device for charger cable */ |
1500 | struct charger_regulator *charger | 1646 | ret = charger_manager_register_extcon(cm); |
1501 | = &desc->charger_regulators[i]; | 1647 | if (ret < 0) { |
1502 | char buf[11]; | 1648 | dev_err(&pdev->dev, "Cannot initialize extcon device\n"); |
1503 | char *str; | 1649 | goto err_reg_extcon; |
1504 | |||
1505 | charger->consumer = regulator_get(&pdev->dev, | ||
1506 | charger->regulator_name); | ||
1507 | if (charger->consumer == NULL) { | ||
1508 | dev_err(&pdev->dev, "Cannot find charger(%s)n", | ||
1509 | charger->regulator_name); | ||
1510 | ret = -EINVAL; | ||
1511 | goto err_chg_get; | ||
1512 | } | ||
1513 | charger->cm = cm; | ||
1514 | |||
1515 | for (j = 0 ; j < charger->num_cables ; j++) { | ||
1516 | struct charger_cable *cable = &charger->cables[j]; | ||
1517 | |||
1518 | ret = charger_extcon_init(cm, cable); | ||
1519 | if (ret < 0) { | ||
1520 | dev_err(&pdev->dev, "Cannot find charger(%s)n", | ||
1521 | charger->regulator_name); | ||
1522 | goto err_extcon; | ||
1523 | } | ||
1524 | cable->charger = charger; | ||
1525 | cable->cm = cm; | ||
1526 | } | ||
1527 | |||
1528 | /* Create sysfs entry to control charger(regulator) */ | ||
1529 | snprintf(buf, 10, "charger.%d", i); | ||
1530 | str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); | ||
1531 | if (!str) { | ||
1532 | for (i--; i >= 0; i--) { | ||
1533 | charger = &desc->charger_regulators[i]; | ||
1534 | kfree(charger->attr_g.name); | ||
1535 | } | ||
1536 | ret = -ENOMEM; | ||
1537 | |||
1538 | goto err_extcon; | ||
1539 | } | ||
1540 | strcpy(str, buf); | ||
1541 | |||
1542 | charger->attrs[0] = &charger->attr_name.attr; | ||
1543 | charger->attrs[1] = &charger->attr_state.attr; | ||
1544 | charger->attrs[2] = &charger->attr_externally_control.attr; | ||
1545 | charger->attrs[3] = NULL; | ||
1546 | charger->attr_g.name = str; | ||
1547 | charger->attr_g.attrs = charger->attrs; | ||
1548 | |||
1549 | sysfs_attr_init(&charger->attr_name.attr); | ||
1550 | charger->attr_name.attr.name = "name"; | ||
1551 | charger->attr_name.attr.mode = 0444; | ||
1552 | charger->attr_name.show = charger_name_show; | ||
1553 | |||
1554 | sysfs_attr_init(&charger->attr_state.attr); | ||
1555 | charger->attr_state.attr.name = "state"; | ||
1556 | charger->attr_state.attr.mode = 0444; | ||
1557 | charger->attr_state.show = charger_state_show; | ||
1558 | |||
1559 | sysfs_attr_init(&charger->attr_externally_control.attr); | ||
1560 | charger->attr_externally_control.attr.name | ||
1561 | = "externally_control"; | ||
1562 | charger->attr_externally_control.attr.mode = 0644; | ||
1563 | charger->attr_externally_control.show | ||
1564 | = charger_externally_control_show; | ||
1565 | charger->attr_externally_control.store | ||
1566 | = charger_externally_control_store; | ||
1567 | |||
1568 | if (!desc->charger_regulators[i].externally_control || | ||
1569 | !chargers_externally_control) { | ||
1570 | chargers_externally_control = 0; | ||
1571 | } | ||
1572 | dev_info(&pdev->dev, "'%s' regulator's externally_control" | ||
1573 | "is %d\n", charger->regulator_name, | ||
1574 | charger->externally_control); | ||
1575 | |||
1576 | ret = sysfs_create_group(&cm->charger_psy.dev->kobj, | ||
1577 | &charger->attr_g); | ||
1578 | if (ret < 0) { | ||
1579 | dev_info(&pdev->dev, "Cannot create sysfs entry" | ||
1580 | "of %s regulator\n", | ||
1581 | charger->regulator_name); | ||
1582 | } | ||
1583 | } | ||
1584 | |||
1585 | if (chargers_externally_control) { | ||
1586 | dev_err(&pdev->dev, "Cannot register regulator because " | ||
1587 | "charger-manager must need at least " | ||
1588 | "one charger for charging battery\n"); | ||
1589 | |||
1590 | ret = -EINVAL; | ||
1591 | goto err_chg_enable; | ||
1592 | } | 1650 | } |
1593 | 1651 | ||
1594 | ret = try_charger_enable(cm, true); | 1652 | /* Register sysfs entry for charger(regulator) */ |
1595 | if (ret) { | 1653 | ret = charger_manager_register_sysfs(cm); |
1596 | dev_err(&pdev->dev, "Cannot enable charger regulators\n"); | 1654 | if (ret < 0) { |
1597 | goto err_chg_enable; | 1655 | dev_err(&pdev->dev, |
1656 | "Cannot initialize sysfs entry of regulator\n"); | ||
1657 | goto err_reg_sysfs; | ||
1598 | } | 1658 | } |
1599 | 1659 | ||
1600 | /* Add to the list */ | 1660 | /* Add to the list */ |
@@ -1613,27 +1673,28 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1613 | 1673 | ||
1614 | return 0; | 1674 | return 0; |
1615 | 1675 | ||
1616 | err_chg_enable: | 1676 | err_reg_sysfs: |
1617 | for (i = 0; i < desc->num_charger_regulators; i++) { | 1677 | for (i = 0; i < desc->num_charger_regulators; i++) { |
1618 | struct charger_regulator *charger; | 1678 | struct charger_regulator *charger; |
1619 | 1679 | ||
1620 | charger = &desc->charger_regulators[i]; | 1680 | charger = &desc->charger_regulators[i]; |
1621 | sysfs_remove_group(&cm->charger_psy.dev->kobj, | 1681 | sysfs_remove_group(&cm->charger_psy.dev->kobj, |
1622 | &charger->attr_g); | 1682 | &charger->attr_g); |
1683 | |||
1623 | kfree(charger->attr_g.name); | 1684 | kfree(charger->attr_g.name); |
1624 | } | 1685 | } |
1625 | err_extcon: | 1686 | err_reg_extcon: |
1626 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | 1687 | for (i = 0; i < desc->num_charger_regulators; i++) { |
1627 | struct charger_regulator *charger | 1688 | struct charger_regulator *charger; |
1628 | = &desc->charger_regulators[i]; | 1689 | |
1629 | for (j = 0 ; j < charger->num_cables ; j++) { | 1690 | charger = &desc->charger_regulators[i]; |
1691 | for (j = 0; j < charger->num_cables; j++) { | ||
1630 | struct charger_cable *cable = &charger->cables[j]; | 1692 | struct charger_cable *cable = &charger->cables[j]; |
1631 | extcon_unregister_interest(&cable->extcon_dev); | 1693 | extcon_unregister_interest(&cable->extcon_dev); |
1632 | } | 1694 | } |
1633 | } | 1695 | |
1634 | err_chg_get: | ||
1635 | for (i = 0 ; i < desc->num_charger_regulators ; i++) | ||
1636 | regulator_put(desc->charger_regulators[i].consumer); | 1696 | regulator_put(desc->charger_regulators[i].consumer); |
1697 | } | ||
1637 | 1698 | ||
1638 | power_supply_unregister(&cm->charger_psy); | 1699 | power_supply_unregister(&cm->charger_psy); |
1639 | err_register: | 1700 | err_register: |
@@ -1661,10 +1722,8 @@ static int charger_manager_remove(struct platform_device *pdev) | |||
1661 | list_del(&cm->entry); | 1722 | list_del(&cm->entry); |
1662 | mutex_unlock(&cm_list_mtx); | 1723 | mutex_unlock(&cm_list_mtx); |
1663 | 1724 | ||
1664 | if (work_pending(&setup_polling)) | 1725 | cancel_work_sync(&setup_polling); |
1665 | cancel_work_sync(&setup_polling); | 1726 | cancel_delayed_work_sync(&cm_monitor_work); |
1666 | if (delayed_work_pending(&cm_monitor_work)) | ||
1667 | cancel_delayed_work_sync(&cm_monitor_work); | ||
1668 | 1727 | ||
1669 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { | 1728 | for (i = 0 ; i < desc->num_charger_regulators ; i++) { |
1670 | struct charger_regulator *charger | 1729 | struct charger_regulator *charger |
@@ -1733,8 +1792,7 @@ static int cm_suspend_prepare(struct device *dev) | |||
1733 | cm_suspended = true; | 1792 | cm_suspended = true; |
1734 | } | 1793 | } |
1735 | 1794 | ||
1736 | if (delayed_work_pending(&cm->fullbatt_vchk_work)) | 1795 | cancel_delayed_work(&cm->fullbatt_vchk_work); |
1737 | cancel_delayed_work(&cm->fullbatt_vchk_work); | ||
1738 | cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm); | 1796 | cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm); |
1739 | cm->status_save_batt = is_batt_present(cm); | 1797 | cm->status_save_batt = is_batt_present(cm); |
1740 | 1798 | ||
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c index 94762e67e22b..e8c5a391a498 100644 --- a/drivers/power/da9030_battery.c +++ b/drivers/power/da9030_battery.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/debugfs.h> | 23 | #include <linux/debugfs.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/notifier.h> | ||
25 | 26 | ||
26 | #define DA9030_FAULT_LOG 0x0a | 27 | #define DA9030_FAULT_LOG 0x0a |
27 | #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) | 28 | #define DA9030_FAULT_LOG_OVER_TEMP (1 << 7) |
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c index 3c5c2e459d73..08193feb3b08 100644 --- a/drivers/power/da9052-battery.c +++ b/drivers/power/da9052-battery.c | |||
@@ -337,7 +337,7 @@ static unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp) | |||
337 | if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1]) | 337 | if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1]) |
338 | return DA9052_VC_TBL_REF_SZ - 1; | 338 | return DA9052_VC_TBL_REF_SZ - 1; |
339 | 339 | ||
340 | for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) { | 340 | for (i = 0; i < DA9052_VC_TBL_REF_SZ - 1; i++) { |
341 | if ((adc_temp > vc_tbl_ref[i]) && | 341 | if ((adc_temp > vc_tbl_ref[i]) && |
342 | (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))) | 342 | (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))) |
343 | return i; | 343 | return i; |
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 2fa9b6bf1f3f..e7301b3ed623 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c | |||
@@ -7,6 +7,8 @@ | |||
7 | * | 7 | * |
8 | * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il> | 8 | * DS2786 added by Yulia Vilensky <vilensky@compulab.co.il> |
9 | * | 9 | * |
10 | * UEvent sending added by Evgeny Romanov <romanov@neurosoft.ru> | ||
11 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as | 13 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 14 | * published by the Free Software Foundation. |
@@ -19,6 +21,7 @@ | |||
19 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
20 | #include <linux/swab.h> | 22 | #include <linux/swab.h> |
21 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include <linux/delay.h> | ||
22 | #include <linux/idr.h> | 25 | #include <linux/idr.h> |
23 | #include <linux/power_supply.h> | 26 | #include <linux/power_supply.h> |
24 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
@@ -40,6 +43,8 @@ | |||
40 | 43 | ||
41 | #define DS2786_CURRENT_UNITS 25 | 44 | #define DS2786_CURRENT_UNITS 25 |
42 | 45 | ||
46 | #define DS278x_DELAY 1000 | ||
47 | |||
43 | struct ds278x_info; | 48 | struct ds278x_info; |
44 | 49 | ||
45 | struct ds278x_battery_ops { | 50 | struct ds278x_battery_ops { |
@@ -54,8 +59,11 @@ struct ds278x_info { | |||
54 | struct i2c_client *client; | 59 | struct i2c_client *client; |
55 | struct power_supply battery; | 60 | struct power_supply battery; |
56 | struct ds278x_battery_ops *ops; | 61 | struct ds278x_battery_ops *ops; |
62 | struct delayed_work bat_work; | ||
57 | int id; | 63 | int id; |
58 | int rsns; | 64 | int rsns; |
65 | int capacity; | ||
66 | int status; /* State Of Charge */ | ||
59 | }; | 67 | }; |
60 | 68 | ||
61 | static DEFINE_IDR(battery_id); | 69 | static DEFINE_IDR(battery_id); |
@@ -220,6 +228,8 @@ static int ds278x_get_status(struct ds278x_info *info, int *status) | |||
220 | if (err) | 228 | if (err) |
221 | return err; | 229 | return err; |
222 | 230 | ||
231 | info->capacity = capacity; | ||
232 | |||
223 | if (capacity == 100) | 233 | if (capacity == 100) |
224 | *status = POWER_SUPPLY_STATUS_FULL; | 234 | *status = POWER_SUPPLY_STATUS_FULL; |
225 | else if (current_uA == 0) | 235 | else if (current_uA == 0) |
@@ -267,6 +277,27 @@ static int ds278x_battery_get_property(struct power_supply *psy, | |||
267 | return ret; | 277 | return ret; |
268 | } | 278 | } |
269 | 279 | ||
280 | static void ds278x_bat_update(struct ds278x_info *info) | ||
281 | { | ||
282 | int old_status = info->status; | ||
283 | int old_capacity = info->capacity; | ||
284 | |||
285 | ds278x_get_status(info, &info->status); | ||
286 | |||
287 | if ((old_status != info->status) || (old_capacity != info->capacity)) | ||
288 | power_supply_changed(&info->battery); | ||
289 | } | ||
290 | |||
291 | static void ds278x_bat_work(struct work_struct *work) | ||
292 | { | ||
293 | struct ds278x_info *info; | ||
294 | |||
295 | info = container_of(work, struct ds278x_info, bat_work.work); | ||
296 | ds278x_bat_update(info); | ||
297 | |||
298 | schedule_delayed_work(&info->bat_work, DS278x_DELAY); | ||
299 | } | ||
300 | |||
270 | static enum power_supply_property ds278x_battery_props[] = { | 301 | static enum power_supply_property ds278x_battery_props[] = { |
271 | POWER_SUPPLY_PROP_STATUS, | 302 | POWER_SUPPLY_PROP_STATUS, |
272 | POWER_SUPPLY_PROP_CAPACITY, | 303 | POWER_SUPPLY_PROP_CAPACITY, |
@@ -295,10 +326,39 @@ static int ds278x_battery_remove(struct i2c_client *client) | |||
295 | idr_remove(&battery_id, info->id); | 326 | idr_remove(&battery_id, info->id); |
296 | mutex_unlock(&battery_lock); | 327 | mutex_unlock(&battery_lock); |
297 | 328 | ||
329 | cancel_delayed_work(&info->bat_work); | ||
330 | |||
298 | kfree(info); | 331 | kfree(info); |
299 | return 0; | 332 | return 0; |
300 | } | 333 | } |
301 | 334 | ||
335 | #ifdef CONFIG_PM | ||
336 | |||
337 | static int ds278x_suspend(struct i2c_client *client, | ||
338 | pm_message_t state) | ||
339 | { | ||
340 | struct ds278x_info *info = i2c_get_clientdata(client); | ||
341 | |||
342 | cancel_delayed_work(&info->bat_work); | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int ds278x_resume(struct i2c_client *client) | ||
347 | { | ||
348 | struct ds278x_info *info = i2c_get_clientdata(client); | ||
349 | |||
350 | schedule_delayed_work(&info->bat_work, DS278x_DELAY); | ||
351 | return 0; | ||
352 | } | ||
353 | |||
354 | #else | ||
355 | |||
356 | #define ds278x_suspend NULL | ||
357 | #define ds278x_resume NULL | ||
358 | |||
359 | #endif /* CONFIG_PM */ | ||
360 | |||
361 | |||
302 | enum ds278x_num_id { | 362 | enum ds278x_num_id { |
303 | DS2782 = 0, | 363 | DS2782 = 0, |
304 | DS2786, | 364 | DS2786, |
@@ -368,10 +428,17 @@ static int ds278x_battery_probe(struct i2c_client *client, | |||
368 | info->ops = &ds278x_ops[id->driver_data]; | 428 | info->ops = &ds278x_ops[id->driver_data]; |
369 | ds278x_power_supply_init(&info->battery); | 429 | ds278x_power_supply_init(&info->battery); |
370 | 430 | ||
431 | info->capacity = 100; | ||
432 | info->status = POWER_SUPPLY_STATUS_FULL; | ||
433 | |||
434 | INIT_DELAYED_WORK(&info->bat_work, ds278x_bat_work); | ||
435 | |||
371 | ret = power_supply_register(&client->dev, &info->battery); | 436 | ret = power_supply_register(&client->dev, &info->battery); |
372 | if (ret) { | 437 | if (ret) { |
373 | dev_err(&client->dev, "failed to register battery\n"); | 438 | dev_err(&client->dev, "failed to register battery\n"); |
374 | goto fail_register; | 439 | goto fail_register; |
440 | } else { | ||
441 | schedule_delayed_work(&info->bat_work, DS278x_DELAY); | ||
375 | } | 442 | } |
376 | 443 | ||
377 | return 0; | 444 | return 0; |
@@ -401,6 +468,8 @@ static struct i2c_driver ds278x_battery_driver = { | |||
401 | }, | 468 | }, |
402 | .probe = ds278x_battery_probe, | 469 | .probe = ds278x_battery_probe, |
403 | .remove = ds278x_battery_remove, | 470 | .remove = ds278x_battery_remove, |
471 | .suspend = ds278x_suspend, | ||
472 | .resume = ds278x_resume, | ||
404 | .id_table = ds278x_id, | 473 | .id_table = ds278x_id, |
405 | }; | 474 | }; |
406 | module_i2c_driver(ds278x_battery_driver); | 475 | module_i2c_driver(ds278x_battery_driver); |
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c index 32ce17e235c0..836816b82cbc 100644 --- a/drivers/power/generic-adc-battery.c +++ b/drivers/power/generic-adc-battery.c | |||
@@ -263,9 +263,6 @@ static int gab_probe(struct platform_device *pdev) | |||
263 | psy->external_power_changed = gab_ext_power_changed; | 263 | psy->external_power_changed = gab_ext_power_changed; |
264 | adc_bat->pdata = pdata; | 264 | adc_bat->pdata = pdata; |
265 | 265 | ||
266 | /* calculate the total number of channels */ | ||
267 | chan = ARRAY_SIZE(gab_chan_name); | ||
268 | |||
269 | /* | 266 | /* |
270 | * copying the static properties and allocating extra memory for holding | 267 | * copying the static properties and allocating extra memory for holding |
271 | * the extra configurable properties received from platform data. | 268 | * the extra configurable properties received from platform data. |
@@ -291,6 +288,7 @@ static int gab_probe(struct platform_device *pdev) | |||
291 | gab_chan_name[chan]); | 288 | gab_chan_name[chan]); |
292 | if (IS_ERR(adc_bat->channel[chan])) { | 289 | if (IS_ERR(adc_bat->channel[chan])) { |
293 | ret = PTR_ERR(adc_bat->channel[chan]); | 290 | ret = PTR_ERR(adc_bat->channel[chan]); |
291 | adc_bat->channel[chan] = NULL; | ||
294 | } else { | 292 | } else { |
295 | /* copying properties for supported channels only */ | 293 | /* copying properties for supported channels only */ |
296 | memcpy(properties + sizeof(*(psy->properties)) * index, | 294 | memcpy(properties + sizeof(*(psy->properties)) * index, |
@@ -344,8 +342,10 @@ err_gpio: | |||
344 | gpio_req_fail: | 342 | gpio_req_fail: |
345 | power_supply_unregister(psy); | 343 | power_supply_unregister(psy); |
346 | err_reg_fail: | 344 | err_reg_fail: |
347 | for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++) | 345 | for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { |
348 | iio_channel_release(adc_bat->channel[chan]); | 346 | if (adc_bat->channel[chan]) |
347 | iio_channel_release(adc_bat->channel[chan]); | ||
348 | } | ||
349 | second_mem_fail: | 349 | second_mem_fail: |
350 | kfree(psy->properties); | 350 | kfree(psy->properties); |
351 | first_mem_fail: | 351 | first_mem_fail: |
@@ -365,8 +365,10 @@ static int gab_remove(struct platform_device *pdev) | |||
365 | gpio_free(pdata->gpio_charge_finished); | 365 | gpio_free(pdata->gpio_charge_finished); |
366 | } | 366 | } |
367 | 367 | ||
368 | for (chan = 0; ARRAY_SIZE(gab_chan_name); chan++) | 368 | for (chan = 0; chan < ARRAY_SIZE(gab_chan_name); chan++) { |
369 | iio_channel_release(adc_bat->channel[chan]); | 369 | if (adc_bat->channel[chan]) |
370 | iio_channel_release(adc_bat->channel[chan]); | ||
371 | } | ||
370 | 372 | ||
371 | kfree(adc_bat->psy.properties); | 373 | kfree(adc_bat->psy.properties); |
372 | cancel_delayed_work(&adc_bat->bat_work); | 374 | cancel_delayed_work(&adc_bat->bat_work); |
diff --git a/drivers/power/goldfish_battery.c b/drivers/power/goldfish_battery.c new file mode 100644 index 000000000000..c10f460f986f --- /dev/null +++ b/drivers/power/goldfish_battery.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * Power supply driver for the goldfish emulator | ||
3 | * | ||
4 | * Copyright (C) 2008 Google, Inc. | ||
5 | * Copyright (C) 2012 Intel, Inc. | ||
6 | * Copyright (C) 2013 Intel, Inc. | ||
7 | * Author: Mike Lockwood <lockwood@android.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/power_supply.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/io.h> | ||
27 | |||
28 | struct goldfish_battery_data { | ||
29 | void __iomem *reg_base; | ||
30 | int irq; | ||
31 | spinlock_t lock; | ||
32 | |||
33 | struct power_supply battery; | ||
34 | struct power_supply ac; | ||
35 | }; | ||
36 | |||
37 | #define GOLDFISH_BATTERY_READ(data, addr) \ | ||
38 | (readl(data->reg_base + addr)) | ||
39 | #define GOLDFISH_BATTERY_WRITE(data, addr, x) \ | ||
40 | (writel(x, data->reg_base + addr)) | ||
41 | |||
42 | /* | ||
43 | * Temporary variable used between goldfish_battery_probe() and | ||
44 | * goldfish_battery_open(). | ||
45 | */ | ||
46 | static struct goldfish_battery_data *battery_data; | ||
47 | |||
48 | enum { | ||
49 | /* status register */ | ||
50 | BATTERY_INT_STATUS = 0x00, | ||
51 | /* set this to enable IRQ */ | ||
52 | BATTERY_INT_ENABLE = 0x04, | ||
53 | |||
54 | BATTERY_AC_ONLINE = 0x08, | ||
55 | BATTERY_STATUS = 0x0C, | ||
56 | BATTERY_HEALTH = 0x10, | ||
57 | BATTERY_PRESENT = 0x14, | ||
58 | BATTERY_CAPACITY = 0x18, | ||
59 | |||
60 | BATTERY_STATUS_CHANGED = 1U << 0, | ||
61 | AC_STATUS_CHANGED = 1U << 1, | ||
62 | BATTERY_INT_MASK = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED, | ||
63 | }; | ||
64 | |||
65 | |||
66 | static int goldfish_ac_get_property(struct power_supply *psy, | ||
67 | enum power_supply_property psp, | ||
68 | union power_supply_propval *val) | ||
69 | { | ||
70 | struct goldfish_battery_data *data = container_of(psy, | ||
71 | struct goldfish_battery_data, ac); | ||
72 | int ret = 0; | ||
73 | |||
74 | switch (psp) { | ||
75 | case POWER_SUPPLY_PROP_ONLINE: | ||
76 | val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_AC_ONLINE); | ||
77 | break; | ||
78 | default: | ||
79 | ret = -EINVAL; | ||
80 | break; | ||
81 | } | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static int goldfish_battery_get_property(struct power_supply *psy, | ||
86 | enum power_supply_property psp, | ||
87 | union power_supply_propval *val) | ||
88 | { | ||
89 | struct goldfish_battery_data *data = container_of(psy, | ||
90 | struct goldfish_battery_data, battery); | ||
91 | int ret = 0; | ||
92 | |||
93 | switch (psp) { | ||
94 | case POWER_SUPPLY_PROP_STATUS: | ||
95 | val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_STATUS); | ||
96 | break; | ||
97 | case POWER_SUPPLY_PROP_HEALTH: | ||
98 | val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_HEALTH); | ||
99 | break; | ||
100 | case POWER_SUPPLY_PROP_PRESENT: | ||
101 | val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_PRESENT); | ||
102 | break; | ||
103 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
104 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
105 | break; | ||
106 | case POWER_SUPPLY_PROP_CAPACITY: | ||
107 | val->intval = GOLDFISH_BATTERY_READ(data, BATTERY_CAPACITY); | ||
108 | break; | ||
109 | default: | ||
110 | ret = -EINVAL; | ||
111 | break; | ||
112 | } | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static enum power_supply_property goldfish_battery_props[] = { | ||
118 | POWER_SUPPLY_PROP_STATUS, | ||
119 | POWER_SUPPLY_PROP_HEALTH, | ||
120 | POWER_SUPPLY_PROP_PRESENT, | ||
121 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
122 | POWER_SUPPLY_PROP_CAPACITY, | ||
123 | }; | ||
124 | |||
125 | static enum power_supply_property goldfish_ac_props[] = { | ||
126 | POWER_SUPPLY_PROP_ONLINE, | ||
127 | }; | ||
128 | |||
129 | static irqreturn_t goldfish_battery_interrupt(int irq, void *dev_id) | ||
130 | { | ||
131 | unsigned long irq_flags; | ||
132 | struct goldfish_battery_data *data = dev_id; | ||
133 | uint32_t status; | ||
134 | |||
135 | spin_lock_irqsave(&data->lock, irq_flags); | ||
136 | |||
137 | /* read status flags, which will clear the interrupt */ | ||
138 | status = GOLDFISH_BATTERY_READ(data, BATTERY_INT_STATUS); | ||
139 | status &= BATTERY_INT_MASK; | ||
140 | |||
141 | if (status & BATTERY_STATUS_CHANGED) | ||
142 | power_supply_changed(&data->battery); | ||
143 | if (status & AC_STATUS_CHANGED) | ||
144 | power_supply_changed(&data->ac); | ||
145 | |||
146 | spin_unlock_irqrestore(&data->lock, irq_flags); | ||
147 | return status ? IRQ_HANDLED : IRQ_NONE; | ||
148 | } | ||
149 | |||
150 | |||
151 | static int goldfish_battery_probe(struct platform_device *pdev) | ||
152 | { | ||
153 | int ret; | ||
154 | struct resource *r; | ||
155 | struct goldfish_battery_data *data; | ||
156 | |||
157 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
158 | if (data == NULL) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | spin_lock_init(&data->lock); | ||
162 | |||
163 | data->battery.properties = goldfish_battery_props; | ||
164 | data->battery.num_properties = ARRAY_SIZE(goldfish_battery_props); | ||
165 | data->battery.get_property = goldfish_battery_get_property; | ||
166 | data->battery.name = "battery"; | ||
167 | data->battery.type = POWER_SUPPLY_TYPE_BATTERY; | ||
168 | |||
169 | data->ac.properties = goldfish_ac_props; | ||
170 | data->ac.num_properties = ARRAY_SIZE(goldfish_ac_props); | ||
171 | data->ac.get_property = goldfish_ac_get_property; | ||
172 | data->ac.name = "ac"; | ||
173 | data->ac.type = POWER_SUPPLY_TYPE_MAINS; | ||
174 | |||
175 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
176 | if (r == NULL) { | ||
177 | dev_err(&pdev->dev, "platform_get_resource failed\n"); | ||
178 | return -ENODEV; | ||
179 | } | ||
180 | |||
181 | data->reg_base = devm_ioremap(&pdev->dev, r->start, r->end - r->start + 1); | ||
182 | if (data->reg_base == NULL) { | ||
183 | dev_err(&pdev->dev, "unable to remap MMIO\n"); | ||
184 | return -ENOMEM; | ||
185 | } | ||
186 | |||
187 | data->irq = platform_get_irq(pdev, 0); | ||
188 | if (data->irq < 0) { | ||
189 | dev_err(&pdev->dev, "platform_get_irq failed\n"); | ||
190 | return -ENODEV; | ||
191 | } | ||
192 | |||
193 | ret = devm_request_irq(&pdev->dev, data->irq, goldfish_battery_interrupt, | ||
194 | IRQF_SHARED, pdev->name, data); | ||
195 | if (ret) | ||
196 | return ret; | ||
197 | |||
198 | ret = power_supply_register(&pdev->dev, &data->ac); | ||
199 | if (ret) | ||
200 | return ret; | ||
201 | |||
202 | ret = power_supply_register(&pdev->dev, &data->battery); | ||
203 | if (ret) { | ||
204 | power_supply_unregister(&data->ac); | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | platform_set_drvdata(pdev, data); | ||
209 | battery_data = data; | ||
210 | |||
211 | GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK); | ||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int goldfish_battery_remove(struct platform_device *pdev) | ||
216 | { | ||
217 | struct goldfish_battery_data *data = platform_get_drvdata(pdev); | ||
218 | |||
219 | power_supply_unregister(&data->battery); | ||
220 | power_supply_unregister(&data->ac); | ||
221 | battery_data = NULL; | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static struct platform_driver goldfish_battery_device = { | ||
226 | .probe = goldfish_battery_probe, | ||
227 | .remove = goldfish_battery_remove, | ||
228 | .driver = { | ||
229 | .name = "goldfish-battery" | ||
230 | } | ||
231 | }; | ||
232 | module_platform_driver(goldfish_battery_device); | ||
233 | |||
234 | MODULE_AUTHOR("Mike Lockwood lockwood@android.com"); | ||
235 | MODULE_LICENSE("GPL"); | ||
236 | MODULE_DESCRIPTION("Battery driver for the Goldfish emulator"); | ||
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c index 4ee71a90e248..5ef41b819172 100644 --- a/drivers/power/lp8727_charger.c +++ b/drivers/power/lp8727_charger.c | |||
@@ -367,28 +367,28 @@ static int lp8727_battery_get_property(struct power_supply *psy, | |||
367 | return -EINVAL; | 367 | return -EINVAL; |
368 | 368 | ||
369 | if (pdata->get_batt_present) | 369 | if (pdata->get_batt_present) |
370 | val->intval = pchg->pdata->get_batt_present(); | 370 | val->intval = pdata->get_batt_present(); |
371 | break; | 371 | break; |
372 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 372 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
373 | if (!pdata) | 373 | if (!pdata) |
374 | return -EINVAL; | 374 | return -EINVAL; |
375 | 375 | ||
376 | if (pdata->get_batt_level) | 376 | if (pdata->get_batt_level) |
377 | val->intval = pchg->pdata->get_batt_level(); | 377 | val->intval = pdata->get_batt_level(); |
378 | break; | 378 | break; |
379 | case POWER_SUPPLY_PROP_CAPACITY: | 379 | case POWER_SUPPLY_PROP_CAPACITY: |
380 | if (!pdata) | 380 | if (!pdata) |
381 | return -EINVAL; | 381 | return -EINVAL; |
382 | 382 | ||
383 | if (pdata->get_batt_capacity) | 383 | if (pdata->get_batt_capacity) |
384 | val->intval = pchg->pdata->get_batt_capacity(); | 384 | val->intval = pdata->get_batt_capacity(); |
385 | break; | 385 | break; |
386 | case POWER_SUPPLY_PROP_TEMP: | 386 | case POWER_SUPPLY_PROP_TEMP: |
387 | if (!pdata) | 387 | if (!pdata) |
388 | return -EINVAL; | 388 | return -EINVAL; |
389 | 389 | ||
390 | if (pdata->get_batt_temp) | 390 | if (pdata->get_batt_temp) |
391 | val->intval = pchg->pdata->get_batt_temp(); | 391 | val->intval = pdata->get_batt_temp(); |
392 | break; | 392 | break; |
393 | default: | 393 | default: |
394 | break; | 394 | break; |
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c index 22b6407c9ca9..e33d6b2a7a56 100644 --- a/drivers/power/lp8788-charger.c +++ b/drivers/power/lp8788-charger.c | |||
@@ -367,7 +367,8 @@ static inline bool lp8788_is_valid_charger_register(u8 addr) | |||
367 | return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END; | 367 | return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END; |
368 | } | 368 | } |
369 | 369 | ||
370 | static int lp8788_update_charger_params(struct lp8788_charger *pchg) | 370 | static int lp8788_update_charger_params(struct platform_device *pdev, |
371 | struct lp8788_charger *pchg) | ||
371 | { | 372 | { |
372 | struct lp8788 *lp = pchg->lp; | 373 | struct lp8788 *lp = pchg->lp; |
373 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | 374 | struct lp8788_charger_platform_data *pdata = pchg->pdata; |
@@ -376,7 +377,7 @@ static int lp8788_update_charger_params(struct lp8788_charger *pchg) | |||
376 | int ret; | 377 | int ret; |
377 | 378 | ||
378 | if (!pdata || !pdata->chg_params) { | 379 | if (!pdata || !pdata->chg_params) { |
379 | dev_info(lp->dev, "skip updating charger parameters\n"); | 380 | dev_info(&pdev->dev, "skip updating charger parameters\n"); |
380 | return 0; | 381 | return 0; |
381 | } | 382 | } |
382 | 383 | ||
@@ -537,7 +538,6 @@ err_free_irq: | |||
537 | static int lp8788_irq_register(struct platform_device *pdev, | 538 | static int lp8788_irq_register(struct platform_device *pdev, |
538 | struct lp8788_charger *pchg) | 539 | struct lp8788_charger *pchg) |
539 | { | 540 | { |
540 | struct lp8788 *lp = pchg->lp; | ||
541 | const char *name[] = { | 541 | const char *name[] = { |
542 | LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ | 542 | LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ |
543 | }; | 543 | }; |
@@ -550,13 +550,13 @@ static int lp8788_irq_register(struct platform_device *pdev, | |||
550 | for (i = 0; i < ARRAY_SIZE(name); i++) { | 550 | for (i = 0; i < ARRAY_SIZE(name); i++) { |
551 | ret = lp8788_set_irqs(pdev, pchg, name[i]); | 551 | ret = lp8788_set_irqs(pdev, pchg, name[i]); |
552 | if (ret) { | 552 | if (ret) { |
553 | dev_warn(lp->dev, "irq setup failed: %s\n", name[i]); | 553 | dev_warn(&pdev->dev, "irq setup failed: %s\n", name[i]); |
554 | return ret; | 554 | return ret; |
555 | } | 555 | } |
556 | } | 556 | } |
557 | 557 | ||
558 | if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) { | 558 | if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) { |
559 | dev_err(lp->dev, "invalid total number of irqs: %d\n", | 559 | dev_err(&pdev->dev, "invalid total number of irqs: %d\n", |
560 | pchg->num_irqs); | 560 | pchg->num_irqs); |
561 | return -EINVAL; | 561 | return -EINVAL; |
562 | } | 562 | } |
@@ -690,9 +690,10 @@ static int lp8788_charger_probe(struct platform_device *pdev) | |||
690 | { | 690 | { |
691 | struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); | 691 | struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); |
692 | struct lp8788_charger *pchg; | 692 | struct lp8788_charger *pchg; |
693 | struct device *dev = &pdev->dev; | ||
693 | int ret; | 694 | int ret; |
694 | 695 | ||
695 | pchg = devm_kzalloc(lp->dev, sizeof(struct lp8788_charger), GFP_KERNEL); | 696 | pchg = devm_kzalloc(dev, sizeof(struct lp8788_charger), GFP_KERNEL); |
696 | if (!pchg) | 697 | if (!pchg) |
697 | return -ENOMEM; | 698 | return -ENOMEM; |
698 | 699 | ||
@@ -700,7 +701,7 @@ static int lp8788_charger_probe(struct platform_device *pdev) | |||
700 | pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL; | 701 | pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL; |
701 | platform_set_drvdata(pdev, pchg); | 702 | platform_set_drvdata(pdev, pchg); |
702 | 703 | ||
703 | ret = lp8788_update_charger_params(pchg); | 704 | ret = lp8788_update_charger_params(pdev, pchg); |
704 | if (ret) | 705 | if (ret) |
705 | return ret; | 706 | return ret; |
706 | 707 | ||
@@ -718,7 +719,7 @@ static int lp8788_charger_probe(struct platform_device *pdev) | |||
718 | 719 | ||
719 | ret = lp8788_irq_register(pdev, pchg); | 720 | ret = lp8788_irq_register(pdev, pchg); |
720 | if (ret) | 721 | if (ret) |
721 | dev_warn(lp->dev, "failed to register charger irq: %d\n", ret); | 722 | dev_warn(dev, "failed to register charger irq: %d\n", ret); |
722 | 723 | ||
723 | return 0; | 724 | return 0; |
724 | } | 725 | } |
diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c index 22cfe9cc4727..74a0bd9bc162 100644 --- a/drivers/power/max17040_battery.c +++ b/drivers/power/max17040_battery.c | |||
@@ -207,7 +207,7 @@ static int max17040_probe(struct i2c_client *client, | |||
207 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) | 207 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) |
208 | return -EIO; | 208 | return -EIO; |
209 | 209 | ||
210 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 210 | chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); |
211 | if (!chip) | 211 | if (!chip) |
212 | return -ENOMEM; | 212 | return -ENOMEM; |
213 | 213 | ||
@@ -225,7 +225,6 @@ static int max17040_probe(struct i2c_client *client, | |||
225 | ret = power_supply_register(&client->dev, &chip->battery); | 225 | ret = power_supply_register(&client->dev, &chip->battery); |
226 | if (ret) { | 226 | if (ret) { |
227 | dev_err(&client->dev, "failed: power supply register\n"); | 227 | dev_err(&client->dev, "failed: power supply register\n"); |
228 | kfree(chip); | ||
229 | return ret; | 228 | return ret; |
230 | } | 229 | } |
231 | 230 | ||
@@ -244,7 +243,6 @@ static int max17040_remove(struct i2c_client *client) | |||
244 | 243 | ||
245 | power_supply_unregister(&chip->battery); | 244 | power_supply_unregister(&chip->battery); |
246 | cancel_delayed_work(&chip->work); | 245 | cancel_delayed_work(&chip->work); |
247 | kfree(chip); | ||
248 | return 0; | 246 | return 0; |
249 | } | 247 | } |
250 | 248 | ||
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c new file mode 100644 index 000000000000..ed48d75bb786 --- /dev/null +++ b/drivers/power/pm2301_charger.c | |||
@@ -0,0 +1,1088 @@ | |||
1 | /* | ||
2 | * Copyright 2012 ST Ericsson. | ||
3 | * | ||
4 | * Power supply driver for ST Ericsson pm2xxx_charger charger | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/power_supply.h> | ||
19 | #include <linux/completion.h> | ||
20 | #include <linux/regulator/consumer.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/kobject.h> | ||
25 | #include <linux/mfd/abx500.h> | ||
26 | #include <linux/mfd/abx500/ab8500.h> | ||
27 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
28 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
29 | #include <linux/mfd/abx500/ux500_chargalg.h> | ||
30 | #include <linux/pm2301_charger.h> | ||
31 | #include <linux/gpio.h> | ||
32 | |||
33 | #include "pm2301_charger.h" | ||
34 | |||
35 | #define to_pm2xxx_charger_ac_device_info(x) container_of((x), \ | ||
36 | struct pm2xxx_charger, ac_chg) | ||
37 | |||
38 | static int pm2xxx_interrupt_registers[] = { | ||
39 | PM2XXX_REG_INT1, | ||
40 | PM2XXX_REG_INT2, | ||
41 | PM2XXX_REG_INT3, | ||
42 | PM2XXX_REG_INT4, | ||
43 | PM2XXX_REG_INT5, | ||
44 | PM2XXX_REG_INT6, | ||
45 | }; | ||
46 | |||
47 | static enum power_supply_property pm2xxx_charger_ac_props[] = { | ||
48 | POWER_SUPPLY_PROP_HEALTH, | ||
49 | POWER_SUPPLY_PROP_PRESENT, | ||
50 | POWER_SUPPLY_PROP_ONLINE, | ||
51 | POWER_SUPPLY_PROP_VOLTAGE_AVG, | ||
52 | }; | ||
53 | |||
54 | static int pm2xxx_charger_voltage_map[] = { | ||
55 | 3500, | ||
56 | 3525, | ||
57 | 3550, | ||
58 | 3575, | ||
59 | 3600, | ||
60 | 3625, | ||
61 | 3650, | ||
62 | 3675, | ||
63 | 3700, | ||
64 | 3725, | ||
65 | 3750, | ||
66 | 3775, | ||
67 | 3800, | ||
68 | 3825, | ||
69 | 3850, | ||
70 | 3875, | ||
71 | 3900, | ||
72 | 3925, | ||
73 | 3950, | ||
74 | 3975, | ||
75 | 4000, | ||
76 | 4025, | ||
77 | 4050, | ||
78 | 4075, | ||
79 | 4100, | ||
80 | 4125, | ||
81 | 4150, | ||
82 | 4175, | ||
83 | 4200, | ||
84 | 4225, | ||
85 | 4250, | ||
86 | 4275, | ||
87 | 4300, | ||
88 | }; | ||
89 | |||
90 | static int pm2xxx_charger_current_map[] = { | ||
91 | 200, | ||
92 | 200, | ||
93 | 400, | ||
94 | 600, | ||
95 | 800, | ||
96 | 1000, | ||
97 | 1200, | ||
98 | 1400, | ||
99 | 1600, | ||
100 | 1800, | ||
101 | 2000, | ||
102 | 2200, | ||
103 | 2400, | ||
104 | 2600, | ||
105 | 2800, | ||
106 | 3000, | ||
107 | }; | ||
108 | |||
109 | static const struct i2c_device_id pm2xxx_ident[] = { | ||
110 | { "pm2301", 0 }, | ||
111 | { } | ||
112 | }; | ||
113 | |||
114 | static void set_lpn_pin(struct pm2xxx_charger *pm2) | ||
115 | { | ||
116 | if (pm2->ac.charger_connected) | ||
117 | return; | ||
118 | gpio_set_value(pm2->lpn_pin, 1); | ||
119 | |||
120 | return; | ||
121 | } | ||
122 | |||
123 | static void clear_lpn_pin(struct pm2xxx_charger *pm2) | ||
124 | { | ||
125 | if (pm2->ac.charger_connected) | ||
126 | return; | ||
127 | gpio_set_value(pm2->lpn_pin, 0); | ||
128 | |||
129 | return; | ||
130 | } | ||
131 | |||
132 | static int pm2xxx_reg_read(struct pm2xxx_charger *pm2, int reg, u8 *val) | ||
133 | { | ||
134 | int ret; | ||
135 | /* | ||
136 | * When AC adaptor is unplugged, the host | ||
137 | * must put LPN high to be able to | ||
138 | * communicate by I2C with PM2301 | ||
139 | * and receive I2C "acknowledge" from PM2301. | ||
140 | */ | ||
141 | mutex_lock(&pm2->lock); | ||
142 | set_lpn_pin(pm2); | ||
143 | |||
144 | ret = i2c_smbus_read_i2c_block_data(pm2->config.pm2xxx_i2c, reg, | ||
145 | 1, val); | ||
146 | if (ret < 0) | ||
147 | dev_err(pm2->dev, "Error reading register at 0x%x\n", reg); | ||
148 | else | ||
149 | ret = 0; | ||
150 | clear_lpn_pin(pm2); | ||
151 | mutex_unlock(&pm2->lock); | ||
152 | |||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | static int pm2xxx_reg_write(struct pm2xxx_charger *pm2, int reg, u8 val) | ||
157 | { | ||
158 | int ret; | ||
159 | /* | ||
160 | * When AC adaptor is unplugged, the host | ||
161 | * must put LPN high to be able to | ||
162 | * communicate by I2C with PM2301 | ||
163 | * and receive I2C "acknowledge" from PM2301. | ||
164 | */ | ||
165 | mutex_lock(&pm2->lock); | ||
166 | set_lpn_pin(pm2); | ||
167 | |||
168 | ret = i2c_smbus_write_i2c_block_data(pm2->config.pm2xxx_i2c, reg, | ||
169 | 1, &val); | ||
170 | if (ret < 0) | ||
171 | dev_err(pm2->dev, "Error writing register at 0x%x\n", reg); | ||
172 | else | ||
173 | ret = 0; | ||
174 | clear_lpn_pin(pm2); | ||
175 | mutex_unlock(&pm2->lock); | ||
176 | |||
177 | return ret; | ||
178 | } | ||
179 | |||
180 | static int pm2xxx_charging_enable_mngt(struct pm2xxx_charger *pm2) | ||
181 | { | ||
182 | int ret; | ||
183 | |||
184 | /* Enable charging */ | ||
185 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2, | ||
186 | (PM2XXX_CH_AUTO_RESUME_EN | PM2XXX_CHARGER_ENA)); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int pm2xxx_charging_disable_mngt(struct pm2xxx_charger *pm2) | ||
192 | { | ||
193 | int ret; | ||
194 | |||
195 | /* Disable charging */ | ||
196 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG2, | ||
197 | (PM2XXX_CH_AUTO_RESUME_DIS | PM2XXX_CHARGER_DIS)); | ||
198 | |||
199 | return ret; | ||
200 | } | ||
201 | |||
202 | static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val) | ||
203 | { | ||
204 | queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work); | ||
205 | |||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | |||
210 | int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val) | ||
211 | { | ||
212 | queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int pm2xxx_charger_ovv_mngt(struct pm2xxx_charger *pm2, int val) | ||
218 | { | ||
219 | int ret = 0; | ||
220 | |||
221 | pm2->failure_input_ovv++; | ||
222 | if (pm2->failure_input_ovv < 4) { | ||
223 | ret = pm2xxx_charging_enable_mngt(pm2); | ||
224 | goto out; | ||
225 | } else { | ||
226 | pm2->failure_input_ovv = 0; | ||
227 | dev_err(pm2->dev, "Overvoltage detected\n"); | ||
228 | pm2->flags.ovv = true; | ||
229 | power_supply_changed(&pm2->ac_chg.psy); | ||
230 | } | ||
231 | |||
232 | out: | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static int pm2xxx_charger_wd_exp_mngt(struct pm2xxx_charger *pm2, int val) | ||
237 | { | ||
238 | dev_dbg(pm2->dev , "20 minutes watchdog occured\n"); | ||
239 | |||
240 | pm2->ac.wd_expired = true; | ||
241 | power_supply_changed(&pm2->ac_chg.psy); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int pm2xxx_charger_vbat_lsig_mngt(struct pm2xxx_charger *pm2, int val) | ||
247 | { | ||
248 | switch (val) { | ||
249 | case PM2XXX_INT1_ITVBATLOWR: | ||
250 | dev_dbg(pm2->dev, "VBAT grows above VBAT_LOW level\n"); | ||
251 | break; | ||
252 | |||
253 | case PM2XXX_INT1_ITVBATLOWF: | ||
254 | dev_dbg(pm2->dev, "VBAT drops below VBAT_LOW level\n"); | ||
255 | break; | ||
256 | |||
257 | default: | ||
258 | dev_err(pm2->dev, "Unknown VBAT level\n"); | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int pm2xxx_charger_bat_disc_mngt(struct pm2xxx_charger *pm2, int val) | ||
265 | { | ||
266 | dev_dbg(pm2->dev, "battery disconnected\n"); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int pm2xxx_charger_detection(struct pm2xxx_charger *pm2, u8 *val) | ||
272 | { | ||
273 | int ret; | ||
274 | |||
275 | ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT2, val); | ||
276 | |||
277 | if (ret < 0) { | ||
278 | dev_err(pm2->dev, "Charger detection failed\n"); | ||
279 | goto out; | ||
280 | } | ||
281 | |||
282 | *val &= (PM2XXX_INT2_S_ITVPWR1PLUG | PM2XXX_INT2_S_ITVPWR2PLUG); | ||
283 | |||
284 | out: | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | static int pm2xxx_charger_itv_pwr_plug_mngt(struct pm2xxx_charger *pm2, int val) | ||
289 | { | ||
290 | |||
291 | int ret; | ||
292 | u8 read_val; | ||
293 | |||
294 | /* | ||
295 | * Since we can't be sure that the events are received | ||
296 | * synchronously, we have the check if the main charger is | ||
297 | * connected by reading the interrupt source register. | ||
298 | */ | ||
299 | ret = pm2xxx_charger_detection(pm2, &read_val); | ||
300 | |||
301 | if ((ret == 0) && read_val) { | ||
302 | pm2->ac.charger_connected = 1; | ||
303 | pm2->ac_conn = true; | ||
304 | queue_work(pm2->charger_wq, &pm2->ac_work); | ||
305 | } | ||
306 | |||
307 | |||
308 | return ret; | ||
309 | } | ||
310 | |||
311 | static int pm2xxx_charger_itv_pwr_unplug_mngt(struct pm2xxx_charger *pm2, | ||
312 | int val) | ||
313 | { | ||
314 | pm2->ac.charger_connected = 0; | ||
315 | queue_work(pm2->charger_wq, &pm2->ac_work); | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int pm2_int_reg0(void *pm2_data, int val) | ||
321 | { | ||
322 | struct pm2xxx_charger *pm2 = pm2_data; | ||
323 | int ret = 0; | ||
324 | |||
325 | if (val & (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF)) { | ||
326 | ret = pm2xxx_charger_vbat_lsig_mngt(pm2, val & | ||
327 | (PM2XXX_INT1_ITVBATLOWR | PM2XXX_INT1_ITVBATLOWF)); | ||
328 | } | ||
329 | |||
330 | if (val & PM2XXX_INT1_ITVBATDISCONNECT) { | ||
331 | ret = pm2xxx_charger_bat_disc_mngt(pm2, | ||
332 | PM2XXX_INT1_ITVBATDISCONNECT); | ||
333 | } | ||
334 | |||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | static int pm2_int_reg1(void *pm2_data, int val) | ||
339 | { | ||
340 | struct pm2xxx_charger *pm2 = pm2_data; | ||
341 | int ret = 0; | ||
342 | |||
343 | if (val & (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG)) { | ||
344 | dev_dbg(pm2->dev , "Main charger plugged\n"); | ||
345 | ret = pm2xxx_charger_itv_pwr_plug_mngt(pm2, val & | ||
346 | (PM2XXX_INT2_ITVPWR1PLUG | PM2XXX_INT2_ITVPWR2PLUG)); | ||
347 | } | ||
348 | |||
349 | if (val & | ||
350 | (PM2XXX_INT2_ITVPWR1UNPLUG | PM2XXX_INT2_ITVPWR2UNPLUG)) { | ||
351 | dev_dbg(pm2->dev , "Main charger unplugged\n"); | ||
352 | ret = pm2xxx_charger_itv_pwr_unplug_mngt(pm2, val & | ||
353 | (PM2XXX_INT2_ITVPWR1UNPLUG | | ||
354 | PM2XXX_INT2_ITVPWR2UNPLUG)); | ||
355 | } | ||
356 | |||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | static int pm2_int_reg2(void *pm2_data, int val) | ||
361 | { | ||
362 | struct pm2xxx_charger *pm2 = pm2_data; | ||
363 | int ret = 0; | ||
364 | |||
365 | if (val & PM2XXX_INT3_ITAUTOTIMEOUTWD) | ||
366 | ret = pm2xxx_charger_wd_exp_mngt(pm2, val); | ||
367 | |||
368 | if (val & (PM2XXX_INT3_ITCHPRECHARGEWD | | ||
369 | PM2XXX_INT3_ITCHCCWD | PM2XXX_INT3_ITCHCVWD)) { | ||
370 | dev_dbg(pm2->dev, | ||
371 | "Watchdog occured for precharge, CC and CV charge\n"); | ||
372 | } | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | static int pm2_int_reg3(void *pm2_data, int val) | ||
378 | { | ||
379 | struct pm2xxx_charger *pm2 = pm2_data; | ||
380 | int ret = 0; | ||
381 | |||
382 | if (val & (PM2XXX_INT4_ITCHARGINGON)) { | ||
383 | dev_dbg(pm2->dev , | ||
384 | "chargind operation has started\n"); | ||
385 | } | ||
386 | |||
387 | if (val & (PM2XXX_INT4_ITVRESUME)) { | ||
388 | dev_dbg(pm2->dev, | ||
389 | "battery discharged down to VResume threshold\n"); | ||
390 | } | ||
391 | |||
392 | if (val & (PM2XXX_INT4_ITBATTFULL)) { | ||
393 | dev_dbg(pm2->dev , "battery fully detected\n"); | ||
394 | } | ||
395 | |||
396 | if (val & (PM2XXX_INT4_ITCVPHASE)) { | ||
397 | dev_dbg(pm2->dev, "CV phase enter with 0.5C charging\n"); | ||
398 | } | ||
399 | |||
400 | if (val & (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV)) { | ||
401 | pm2->failure_case = VPWR_OVV; | ||
402 | ret = pm2xxx_charger_ovv_mngt(pm2, val & | ||
403 | (PM2XXX_INT4_ITVPWR2OVV | PM2XXX_INT4_ITVPWR1OVV)); | ||
404 | dev_dbg(pm2->dev, "VPWR/VSYSTEM overvoltage detected\n"); | ||
405 | } | ||
406 | |||
407 | if (val & (PM2XXX_INT4_S_ITBATTEMPCOLD | | ||
408 | PM2XXX_INT4_S_ITBATTEMPHOT)) { | ||
409 | ret = pm2xxx_charger_batt_therm_mngt(pm2, val & | ||
410 | (PM2XXX_INT4_S_ITBATTEMPCOLD | | ||
411 | PM2XXX_INT4_S_ITBATTEMPHOT)); | ||
412 | dev_dbg(pm2->dev, "BTEMP is too Low/High\n"); | ||
413 | } | ||
414 | |||
415 | return ret; | ||
416 | } | ||
417 | |||
418 | static int pm2_int_reg4(void *pm2_data, int val) | ||
419 | { | ||
420 | struct pm2xxx_charger *pm2 = pm2_data; | ||
421 | int ret = 0; | ||
422 | |||
423 | if (val & PM2XXX_INT5_ITVSYSTEMOVV) { | ||
424 | pm2->failure_case = VSYSTEM_OVV; | ||
425 | ret = pm2xxx_charger_ovv_mngt(pm2, val & | ||
426 | PM2XXX_INT5_ITVSYSTEMOVV); | ||
427 | dev_dbg(pm2->dev, "VSYSTEM overvoltage detected\n"); | ||
428 | } | ||
429 | |||
430 | if (val & (PM2XXX_INT5_ITTHERMALWARNINGFALL | | ||
431 | PM2XXX_INT5_ITTHERMALWARNINGRISE | | ||
432 | PM2XXX_INT5_ITTHERMALSHUTDOWNFALL | | ||
433 | PM2XXX_INT5_ITTHERMALSHUTDOWNRISE)) { | ||
434 | dev_dbg(pm2->dev, "BTEMP die temperature is too Low/High\n"); | ||
435 | ret = pm2xxx_charger_die_therm_mngt(pm2, val & | ||
436 | (PM2XXX_INT5_ITTHERMALWARNINGFALL | | ||
437 | PM2XXX_INT5_ITTHERMALWARNINGRISE | | ||
438 | PM2XXX_INT5_ITTHERMALSHUTDOWNFALL | | ||
439 | PM2XXX_INT5_ITTHERMALSHUTDOWNRISE)); | ||
440 | } | ||
441 | |||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | static int pm2_int_reg5(void *pm2_data, int val) | ||
446 | { | ||
447 | struct pm2xxx_charger *pm2 = pm2_data; | ||
448 | int ret = 0; | ||
449 | |||
450 | |||
451 | if (val & (PM2XXX_INT6_ITVPWR2DROP | PM2XXX_INT6_ITVPWR1DROP)) { | ||
452 | dev_dbg(pm2->dev, "VMPWR drop to VBAT level\n"); | ||
453 | } | ||
454 | |||
455 | if (val & (PM2XXX_INT6_ITVPWR2VALIDRISE | | ||
456 | PM2XXX_INT6_ITVPWR1VALIDRISE | | ||
457 | PM2XXX_INT6_ITVPWR2VALIDFALL | | ||
458 | PM2XXX_INT6_ITVPWR1VALIDFALL)) { | ||
459 | dev_dbg(pm2->dev, "Falling/Rising edge on WPWR1/2\n"); | ||
460 | } | ||
461 | |||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | static irqreturn_t pm2xxx_irq_int(int irq, void *data) | ||
466 | { | ||
467 | struct pm2xxx_charger *pm2 = data; | ||
468 | struct pm2xxx_interrupts *interrupt = pm2->pm2_int; | ||
469 | int i; | ||
470 | |||
471 | for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { | ||
472 | pm2xxx_reg_read(pm2, | ||
473 | pm2xxx_interrupt_registers[i], | ||
474 | &(interrupt->reg[i])); | ||
475 | |||
476 | if (interrupt->reg[i] > 0) | ||
477 | interrupt->handler[i](pm2, interrupt->reg[i]); | ||
478 | } | ||
479 | |||
480 | return IRQ_HANDLED; | ||
481 | } | ||
482 | |||
483 | static int pm2xxx_charger_get_ac_cv(struct pm2xxx_charger *pm2) | ||
484 | { | ||
485 | int ret = 0; | ||
486 | u8 val; | ||
487 | |||
488 | if (pm2->ac.charger_connected && pm2->ac.charger_online) { | ||
489 | |||
490 | ret = pm2xxx_reg_read(pm2, PM2XXX_SRCE_REG_INT4, &val); | ||
491 | if (ret < 0) { | ||
492 | dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); | ||
493 | goto out; | ||
494 | } | ||
495 | |||
496 | if (val & PM2XXX_INT4_S_ITCVPHASE) | ||
497 | ret = PM2XXX_CONST_VOLT; | ||
498 | else | ||
499 | ret = PM2XXX_CONST_CURR; | ||
500 | } | ||
501 | out: | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static int pm2xxx_current_to_regval(int curr) | ||
506 | { | ||
507 | int i; | ||
508 | |||
509 | if (curr < pm2xxx_charger_current_map[0]) | ||
510 | return 0; | ||
511 | |||
512 | for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_current_map); i++) { | ||
513 | if (curr < pm2xxx_charger_current_map[i]) | ||
514 | return (i - 1); | ||
515 | } | ||
516 | |||
517 | i = ARRAY_SIZE(pm2xxx_charger_current_map) - 1; | ||
518 | if (curr == pm2xxx_charger_current_map[i]) | ||
519 | return i; | ||
520 | else | ||
521 | return -EINVAL; | ||
522 | } | ||
523 | |||
524 | static int pm2xxx_voltage_to_regval(int curr) | ||
525 | { | ||
526 | int i; | ||
527 | |||
528 | if (curr < pm2xxx_charger_voltage_map[0]) | ||
529 | return 0; | ||
530 | |||
531 | for (i = 1; i < ARRAY_SIZE(pm2xxx_charger_voltage_map); i++) { | ||
532 | if (curr < pm2xxx_charger_voltage_map[i]) | ||
533 | return i - 1; | ||
534 | } | ||
535 | |||
536 | i = ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1; | ||
537 | if (curr == pm2xxx_charger_voltage_map[i]) | ||
538 | return i; | ||
539 | else | ||
540 | return -EINVAL; | ||
541 | } | ||
542 | |||
543 | static int pm2xxx_charger_update_charger_current(struct ux500_charger *charger, | ||
544 | int ich_out) | ||
545 | { | ||
546 | int ret; | ||
547 | int curr_index; | ||
548 | struct pm2xxx_charger *pm2; | ||
549 | u8 val; | ||
550 | |||
551 | if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) | ||
552 | pm2 = to_pm2xxx_charger_ac_device_info(charger); | ||
553 | else | ||
554 | return -ENXIO; | ||
555 | |||
556 | curr_index = pm2xxx_current_to_regval(ich_out); | ||
557 | if (curr_index < 0) { | ||
558 | dev_err(pm2->dev, | ||
559 | "Charger current too high, charging not started\n"); | ||
560 | return -ENXIO; | ||
561 | } | ||
562 | |||
563 | ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val); | ||
564 | if (ret >= 0) { | ||
565 | val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK; | ||
566 | val |= curr_index; | ||
567 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val); | ||
568 | if (ret < 0) { | ||
569 | dev_err(pm2->dev, | ||
570 | "%s write failed\n", __func__); | ||
571 | } | ||
572 | } | ||
573 | else | ||
574 | dev_err(pm2->dev, "%s read failed\n", __func__); | ||
575 | |||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int pm2xxx_charger_ac_get_property(struct power_supply *psy, | ||
580 | enum power_supply_property psp, | ||
581 | union power_supply_propval *val) | ||
582 | { | ||
583 | struct pm2xxx_charger *pm2; | ||
584 | |||
585 | pm2 = to_pm2xxx_charger_ac_device_info(psy_to_ux500_charger(psy)); | ||
586 | |||
587 | switch (psp) { | ||
588 | case POWER_SUPPLY_PROP_HEALTH: | ||
589 | if (pm2->flags.mainextchnotok) | ||
590 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
591 | else if (pm2->ac.wd_expired) | ||
592 | val->intval = POWER_SUPPLY_HEALTH_DEAD; | ||
593 | else if (pm2->flags.main_thermal_prot) | ||
594 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
595 | else | ||
596 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
597 | break; | ||
598 | case POWER_SUPPLY_PROP_ONLINE: | ||
599 | val->intval = pm2->ac.charger_online; | ||
600 | break; | ||
601 | case POWER_SUPPLY_PROP_PRESENT: | ||
602 | val->intval = pm2->ac.charger_connected; | ||
603 | break; | ||
604 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | ||
605 | pm2->ac.cv_active = pm2xxx_charger_get_ac_cv(pm2); | ||
606 | val->intval = pm2->ac.cv_active; | ||
607 | break; | ||
608 | default: | ||
609 | return -EINVAL; | ||
610 | } | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static int pm2xxx_charging_init(struct pm2xxx_charger *pm2) | ||
615 | { | ||
616 | int ret = 0; | ||
617 | |||
618 | /* enable CC and CV watchdog */ | ||
619 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG3, | ||
620 | (PM2XXX_CH_WD_CV_PHASE_60MIN | PM2XXX_CH_WD_CC_PHASE_60MIN)); | ||
621 | if( ret < 0) | ||
622 | return ret; | ||
623 | |||
624 | /* enable precharge watchdog */ | ||
625 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG4, | ||
626 | PM2XXX_CH_WD_PRECH_PHASE_60MIN); | ||
627 | |||
628 | /* Disable auto timeout */ | ||
629 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG5, | ||
630 | PM2XXX_CH_WD_AUTO_TIMEOUT_20MIN); | ||
631 | |||
632 | /* | ||
633 | * EOC current level = 100mA | ||
634 | * Precharge current level = 100mA | ||
635 | * CC current level = 1000mA | ||
636 | */ | ||
637 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, | ||
638 | (PM2XXX_DIR_CH_CC_CURRENT_1000MA | | ||
639 | PM2XXX_CH_PRECH_CURRENT_100MA | | ||
640 | PM2XXX_CH_EOC_CURRENT_100MA)); | ||
641 | |||
642 | /* | ||
643 | * recharge threshold = 3.8V | ||
644 | * Precharge to CC threshold = 2.9V | ||
645 | */ | ||
646 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG7, | ||
647 | (PM2XXX_CH_PRECH_VOL_2_9 | PM2XXX_CH_VRESUME_VOL_3_8)); | ||
648 | |||
649 | /* float voltage charger level = 4.2V */ | ||
650 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, | ||
651 | PM2XXX_CH_VOLT_4_2); | ||
652 | |||
653 | /* Voltage drop between VBAT and VSYS in HW charging = 300mV */ | ||
654 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG9, | ||
655 | (PM2XXX_CH_150MV_DROP_300MV | PM2XXX_CHARCHING_INFO_DIS | | ||
656 | PM2XXX_CH_CC_REDUCED_CURRENT_IDENT | | ||
657 | PM2XXX_CH_CC_MODEDROP_DIS)); | ||
658 | |||
659 | /* Input charger level of over voltage = 10V */ | ||
660 | ret = pm2xxx_reg_write(pm2, PM2XXX_INP_VOLT_VPWR2, | ||
661 | PM2XXX_VPWR2_OVV_10); | ||
662 | ret = pm2xxx_reg_write(pm2, PM2XXX_INP_VOLT_VPWR1, | ||
663 | PM2XXX_VPWR1_OVV_10); | ||
664 | |||
665 | /* Input charger drop */ | ||
666 | ret = pm2xxx_reg_write(pm2, PM2XXX_INP_DROP_VPWR2, | ||
667 | (PM2XXX_VPWR2_HW_OPT_DIS | PM2XXX_VPWR2_VALID_DIS | | ||
668 | PM2XXX_VPWR2_DROP_DIS)); | ||
669 | ret = pm2xxx_reg_write(pm2, PM2XXX_INP_DROP_VPWR1, | ||
670 | (PM2XXX_VPWR1_HW_OPT_DIS | PM2XXX_VPWR1_VALID_DIS | | ||
671 | PM2XXX_VPWR1_DROP_DIS)); | ||
672 | |||
673 | /* Disable battery low monitoring */ | ||
674 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_LOW_LEV_COMP_REG, | ||
675 | PM2XXX_VBAT_LOW_MONITORING_ENA); | ||
676 | |||
677 | /* Disable LED */ | ||
678 | ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG, | ||
679 | PM2XXX_LED_SELECT_DIS); | ||
680 | |||
681 | return ret; | ||
682 | } | ||
683 | |||
684 | static int pm2xxx_charger_ac_en(struct ux500_charger *charger, | ||
685 | int enable, int vset, int iset) | ||
686 | { | ||
687 | int ret; | ||
688 | int volt_index; | ||
689 | int curr_index; | ||
690 | u8 val; | ||
691 | |||
692 | struct pm2xxx_charger *pm2 = to_pm2xxx_charger_ac_device_info(charger); | ||
693 | |||
694 | if (enable) { | ||
695 | if (!pm2->ac.charger_connected) { | ||
696 | dev_dbg(pm2->dev, "AC charger not connected\n"); | ||
697 | return -ENXIO; | ||
698 | } | ||
699 | |||
700 | dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset); | ||
701 | if (!pm2->vddadc_en_ac) { | ||
702 | regulator_enable(pm2->regu); | ||
703 | pm2->vddadc_en_ac = true; | ||
704 | } | ||
705 | |||
706 | ret = pm2xxx_charging_init(pm2); | ||
707 | if (ret < 0) { | ||
708 | dev_err(pm2->dev, "%s charging init failed\n", | ||
709 | __func__); | ||
710 | goto error_occured; | ||
711 | } | ||
712 | |||
713 | volt_index = pm2xxx_voltage_to_regval(vset); | ||
714 | curr_index = pm2xxx_current_to_regval(iset); | ||
715 | |||
716 | if (volt_index < 0 || curr_index < 0) { | ||
717 | dev_err(pm2->dev, | ||
718 | "Charger voltage or current too high, " | ||
719 | "charging not started\n"); | ||
720 | return -ENXIO; | ||
721 | } | ||
722 | |||
723 | ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG8, &val); | ||
724 | if (ret < 0) { | ||
725 | dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); | ||
726 | goto error_occured; | ||
727 | } | ||
728 | val &= ~PM2XXX_CH_VOLT_MASK; | ||
729 | val |= volt_index; | ||
730 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG8, val); | ||
731 | if (ret < 0) { | ||
732 | dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); | ||
733 | goto error_occured; | ||
734 | } | ||
735 | |||
736 | ret = pm2xxx_reg_read(pm2, PM2XXX_BATT_CTRL_REG6, &val); | ||
737 | if (ret < 0) { | ||
738 | dev_err(pm2->dev, "%s pm2xxx read failed\n", __func__); | ||
739 | goto error_occured; | ||
740 | } | ||
741 | val &= ~PM2XXX_DIR_CH_CC_CURRENT_MASK; | ||
742 | val |= curr_index; | ||
743 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_CTRL_REG6, val); | ||
744 | if (ret < 0) { | ||
745 | dev_err(pm2->dev, "%s pm2xxx write failed\n", __func__); | ||
746 | goto error_occured; | ||
747 | } | ||
748 | |||
749 | if (!pm2->bat->enable_overshoot) { | ||
750 | ret = pm2xxx_reg_read(pm2, PM2XXX_LED_CTRL_REG, &val); | ||
751 | if (ret < 0) { | ||
752 | dev_err(pm2->dev, "%s pm2xxx read failed\n", | ||
753 | __func__); | ||
754 | goto error_occured; | ||
755 | } | ||
756 | val |= PM2XXX_ANTI_OVERSHOOT_EN; | ||
757 | ret = pm2xxx_reg_write(pm2, PM2XXX_LED_CTRL_REG, val); | ||
758 | if (ret < 0) { | ||
759 | dev_err(pm2->dev, "%s pm2xxx write failed\n", | ||
760 | __func__); | ||
761 | goto error_occured; | ||
762 | } | ||
763 | } | ||
764 | |||
765 | ret = pm2xxx_charging_enable_mngt(pm2); | ||
766 | if (ret < 0) { | ||
767 | dev_err(pm2->dev, "Failed to enable" | ||
768 | "pm2xxx ac charger\n"); | ||
769 | goto error_occured; | ||
770 | } | ||
771 | |||
772 | pm2->ac.charger_online = 1; | ||
773 | } else { | ||
774 | pm2->ac.charger_online = 0; | ||
775 | pm2->ac.wd_expired = false; | ||
776 | |||
777 | /* Disable regulator if enabled */ | ||
778 | if (pm2->vddadc_en_ac) { | ||
779 | regulator_disable(pm2->regu); | ||
780 | pm2->vddadc_en_ac = false; | ||
781 | } | ||
782 | |||
783 | ret = pm2xxx_charging_disable_mngt(pm2); | ||
784 | if (ret < 0) { | ||
785 | dev_err(pm2->dev, "failed to disable" | ||
786 | "pm2xxx ac charger\n"); | ||
787 | goto error_occured; | ||
788 | } | ||
789 | |||
790 | dev_dbg(pm2->dev, "PM2301: " "Disabled AC charging\n"); | ||
791 | } | ||
792 | power_supply_changed(&pm2->ac_chg.psy); | ||
793 | |||
794 | error_occured: | ||
795 | return ret; | ||
796 | } | ||
797 | |||
798 | static int pm2xxx_charger_watchdog_kick(struct ux500_charger *charger) | ||
799 | { | ||
800 | int ret; | ||
801 | struct pm2xxx_charger *pm2; | ||
802 | |||
803 | if (charger->psy.type == POWER_SUPPLY_TYPE_MAINS) | ||
804 | pm2 = to_pm2xxx_charger_ac_device_info(charger); | ||
805 | else | ||
806 | return -ENXIO; | ||
807 | |||
808 | ret = pm2xxx_reg_write(pm2, PM2XXX_BATT_WD_KICK, WD_TIMER); | ||
809 | if (ret) | ||
810 | dev_err(pm2->dev, "Failed to kick WD!\n"); | ||
811 | |||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | static void pm2xxx_charger_ac_work(struct work_struct *work) | ||
816 | { | ||
817 | struct pm2xxx_charger *pm2 = container_of(work, | ||
818 | struct pm2xxx_charger, ac_work); | ||
819 | |||
820 | |||
821 | power_supply_changed(&pm2->ac_chg.psy); | ||
822 | sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present"); | ||
823 | }; | ||
824 | |||
825 | static void pm2xxx_charger_check_main_thermal_prot_work( | ||
826 | struct work_struct *work) | ||
827 | { | ||
828 | }; | ||
829 | |||
830 | static struct pm2xxx_interrupts pm2xxx_int = { | ||
831 | .handler[0] = pm2_int_reg0, | ||
832 | .handler[1] = pm2_int_reg1, | ||
833 | .handler[2] = pm2_int_reg2, | ||
834 | .handler[3] = pm2_int_reg3, | ||
835 | .handler[4] = pm2_int_reg4, | ||
836 | .handler[5] = pm2_int_reg5, | ||
837 | }; | ||
838 | |||
839 | static struct pm2xxx_irq pm2xxx_charger_irq[] = { | ||
840 | {"PM2XXX_IRQ_INT", pm2xxx_irq_int}, | ||
841 | }; | ||
842 | |||
843 | static int pm2xxx_wall_charger_resume(struct i2c_client *i2c_client) | ||
844 | { | ||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client, | ||
849 | pm_message_t state) | ||
850 | { | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | static int __devinit pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | ||
855 | const struct i2c_device_id *id) | ||
856 | { | ||
857 | struct pm2xxx_platform_data *pl_data = i2c_client->dev.platform_data; | ||
858 | struct pm2xxx_charger *pm2; | ||
859 | int ret = 0; | ||
860 | u8 val; | ||
861 | |||
862 | pm2 = kzalloc(sizeof(struct pm2xxx_charger), GFP_KERNEL); | ||
863 | if (!pm2) { | ||
864 | dev_err(pm2->dev, "pm2xxx_charger allocation failed\n"); | ||
865 | return -ENOMEM; | ||
866 | } | ||
867 | |||
868 | /* get parent data */ | ||
869 | pm2->dev = &i2c_client->dev; | ||
870 | pm2->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | ||
871 | |||
872 | pm2->pm2_int = &pm2xxx_int; | ||
873 | |||
874 | /* get charger spcific platform data */ | ||
875 | if (!pl_data->wall_charger) { | ||
876 | dev_err(pm2->dev, "no charger platform data supplied\n"); | ||
877 | ret = -EINVAL; | ||
878 | goto free_device_info; | ||
879 | } | ||
880 | |||
881 | pm2->pdata = pl_data->wall_charger; | ||
882 | |||
883 | /* get battery specific platform data */ | ||
884 | if (!pl_data->battery) { | ||
885 | dev_err(pm2->dev, "no battery platform data supplied\n"); | ||
886 | ret = -EINVAL; | ||
887 | goto free_device_info; | ||
888 | } | ||
889 | |||
890 | pm2->bat = pl_data->battery; | ||
891 | |||
892 | /*get lpn GPIO from platform data*/ | ||
893 | if (!pm2->pdata->lpn_gpio) { | ||
894 | dev_err(pm2->dev, "no lpn gpio data supplied\n"); | ||
895 | ret = -EINVAL; | ||
896 | goto free_device_info; | ||
897 | } | ||
898 | pm2->lpn_pin = pm2->pdata->lpn_gpio; | ||
899 | |||
900 | if (!i2c_check_functionality(i2c_client->adapter, | ||
901 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
902 | I2C_FUNC_SMBUS_READ_WORD_DATA)) { | ||
903 | ret = -ENODEV; | ||
904 | dev_info(pm2->dev, "pm2301 i2c_check_functionality failed\n"); | ||
905 | goto free_device_info; | ||
906 | } | ||
907 | |||
908 | pm2->config.pm2xxx_i2c = i2c_client; | ||
909 | pm2->config.pm2xxx_id = (struct i2c_device_id *) id; | ||
910 | i2c_set_clientdata(i2c_client, pm2); | ||
911 | |||
912 | /* AC supply */ | ||
913 | /* power_supply base class */ | ||
914 | pm2->ac_chg.psy.name = pm2->pdata->label; | ||
915 | pm2->ac_chg.psy.type = POWER_SUPPLY_TYPE_MAINS; | ||
916 | pm2->ac_chg.psy.properties = pm2xxx_charger_ac_props; | ||
917 | pm2->ac_chg.psy.num_properties = ARRAY_SIZE(pm2xxx_charger_ac_props); | ||
918 | pm2->ac_chg.psy.get_property = pm2xxx_charger_ac_get_property; | ||
919 | pm2->ac_chg.psy.supplied_to = pm2->pdata->supplied_to; | ||
920 | pm2->ac_chg.psy.num_supplicants = pm2->pdata->num_supplicants; | ||
921 | /* pm2xxx_charger sub-class */ | ||
922 | pm2->ac_chg.ops.enable = &pm2xxx_charger_ac_en; | ||
923 | pm2->ac_chg.ops.kick_wd = &pm2xxx_charger_watchdog_kick; | ||
924 | pm2->ac_chg.ops.update_curr = &pm2xxx_charger_update_charger_current; | ||
925 | pm2->ac_chg.max_out_volt = pm2xxx_charger_voltage_map[ | ||
926 | ARRAY_SIZE(pm2xxx_charger_voltage_map) - 1]; | ||
927 | pm2->ac_chg.max_out_curr = pm2xxx_charger_current_map[ | ||
928 | ARRAY_SIZE(pm2xxx_charger_current_map) - 1]; | ||
929 | pm2->ac_chg.wdt_refresh = WD_KICK_INTERVAL; | ||
930 | pm2->ac_chg.enabled = true; | ||
931 | pm2->ac_chg.external = true; | ||
932 | |||
933 | /* Create a work queue for the charger */ | ||
934 | pm2->charger_wq = | ||
935 | create_singlethread_workqueue("pm2xxx_charger_wq"); | ||
936 | if (pm2->charger_wq == NULL) { | ||
937 | dev_err(pm2->dev, "failed to create work queue\n"); | ||
938 | goto free_device_info; | ||
939 | } | ||
940 | |||
941 | /* Init work for charger detection */ | ||
942 | INIT_WORK(&pm2->ac_work, pm2xxx_charger_ac_work); | ||
943 | |||
944 | /* Init work for checking HW status */ | ||
945 | INIT_WORK(&pm2->check_main_thermal_prot_work, | ||
946 | pm2xxx_charger_check_main_thermal_prot_work); | ||
947 | |||
948 | /* | ||
949 | * VDD ADC supply needs to be enabled from this driver when there | ||
950 | * is a charger connected to avoid erroneous BTEMP_HIGH/LOW | ||
951 | * interrupts during charging | ||
952 | */ | ||
953 | pm2->regu = regulator_get(pm2->dev, "vddadc"); | ||
954 | if (IS_ERR(pm2->regu)) { | ||
955 | ret = PTR_ERR(pm2->regu); | ||
956 | dev_err(pm2->dev, "failed to get vddadc regulator\n"); | ||
957 | goto free_charger_wq; | ||
958 | } | ||
959 | |||
960 | /* Register AC charger class */ | ||
961 | ret = power_supply_register(pm2->dev, &pm2->ac_chg.psy); | ||
962 | if (ret) { | ||
963 | dev_err(pm2->dev, "failed to register AC charger\n"); | ||
964 | goto free_regulator; | ||
965 | } | ||
966 | |||
967 | /* Register interrupts */ | ||
968 | ret = request_threaded_irq(pm2->pdata->irq_number, NULL, | ||
969 | pm2xxx_charger_irq[0].isr, | ||
970 | pm2->pdata->irq_type, | ||
971 | pm2xxx_charger_irq[0].name, pm2); | ||
972 | |||
973 | if (ret != 0) { | ||
974 | dev_err(pm2->dev, "failed to request %s IRQ %d: %d\n", | ||
975 | pm2xxx_charger_irq[0].name, pm2->pdata->irq_number, ret); | ||
976 | goto unregister_pm2xxx_charger; | ||
977 | } | ||
978 | |||
979 | /*Initialize lock*/ | ||
980 | mutex_init(&pm2->lock); | ||
981 | |||
982 | /* | ||
983 | * Charger detection mechanism requires pulling up the LPN pin | ||
984 | * while i2c communication if Charger is not connected | ||
985 | * LPN pin of PM2301 is GPIO60 of AB9540 | ||
986 | */ | ||
987 | ret = gpio_request(pm2->lpn_pin, "pm2301_lpm_gpio"); | ||
988 | if (ret < 0) { | ||
989 | dev_err(pm2->dev, "pm2301_lpm_gpio request failed\n"); | ||
990 | goto unregister_pm2xxx_charger; | ||
991 | } | ||
992 | ret = gpio_direction_output(pm2->lpn_pin, 0); | ||
993 | if (ret < 0) { | ||
994 | dev_err(pm2->dev, "pm2301_lpm_gpio direction failed\n"); | ||
995 | goto free_gpio; | ||
996 | } | ||
997 | |||
998 | ret = pm2xxx_charger_detection(pm2, &val); | ||
999 | |||
1000 | if ((ret == 0) && val) { | ||
1001 | pm2->ac.charger_connected = 1; | ||
1002 | pm2->ac_conn = true; | ||
1003 | power_supply_changed(&pm2->ac_chg.psy); | ||
1004 | sysfs_notify(&pm2->ac_chg.psy.dev->kobj, NULL, "present"); | ||
1005 | } | ||
1006 | |||
1007 | return 0; | ||
1008 | |||
1009 | free_gpio: | ||
1010 | gpio_free(pm2->lpn_pin); | ||
1011 | unregister_pm2xxx_charger: | ||
1012 | /* unregister power supply */ | ||
1013 | power_supply_unregister(&pm2->ac_chg.psy); | ||
1014 | free_regulator: | ||
1015 | /* disable the regulator */ | ||
1016 | regulator_put(pm2->regu); | ||
1017 | free_charger_wq: | ||
1018 | destroy_workqueue(pm2->charger_wq); | ||
1019 | free_device_info: | ||
1020 | kfree(pm2); | ||
1021 | return ret; | ||
1022 | } | ||
1023 | |||
1024 | static int __devexit pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) | ||
1025 | { | ||
1026 | struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); | ||
1027 | |||
1028 | /* Disable AC charging */ | ||
1029 | pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); | ||
1030 | |||
1031 | /* Disable interrupts */ | ||
1032 | free_irq(pm2->pdata->irq_number, pm2); | ||
1033 | |||
1034 | /* Delete the work queue */ | ||
1035 | destroy_workqueue(pm2->charger_wq); | ||
1036 | |||
1037 | flush_scheduled_work(); | ||
1038 | |||
1039 | /* disable the regulator */ | ||
1040 | regulator_put(pm2->regu); | ||
1041 | |||
1042 | power_supply_unregister(&pm2->ac_chg.psy); | ||
1043 | |||
1044 | /*Free GPIO60*/ | ||
1045 | gpio_free(pm2->lpn_pin); | ||
1046 | |||
1047 | kfree(pm2); | ||
1048 | |||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | static const struct i2c_device_id pm2xxx_id[] = { | ||
1053 | { "pm2301", 0 }, | ||
1054 | { } | ||
1055 | }; | ||
1056 | |||
1057 | MODULE_DEVICE_TABLE(i2c, pm2xxx_id); | ||
1058 | |||
1059 | static struct i2c_driver pm2xxx_charger_driver = { | ||
1060 | .probe = pm2xxx_wall_charger_probe, | ||
1061 | .remove = __devexit_p(pm2xxx_wall_charger_remove), | ||
1062 | .suspend = pm2xxx_wall_charger_suspend, | ||
1063 | .resume = pm2xxx_wall_charger_resume, | ||
1064 | .driver = { | ||
1065 | .name = "pm2xxx-wall_charger", | ||
1066 | .owner = THIS_MODULE, | ||
1067 | }, | ||
1068 | .id_table = pm2xxx_id, | ||
1069 | }; | ||
1070 | |||
1071 | static int __init pm2xxx_charger_init(void) | ||
1072 | { | ||
1073 | return i2c_add_driver(&pm2xxx_charger_driver); | ||
1074 | } | ||
1075 | |||
1076 | static void __exit pm2xxx_charger_exit(void) | ||
1077 | { | ||
1078 | i2c_del_driver(&pm2xxx_charger_driver); | ||
1079 | } | ||
1080 | |||
1081 | subsys_initcall_sync(pm2xxx_charger_init); | ||
1082 | module_exit(pm2xxx_charger_exit); | ||
1083 | |||
1084 | MODULE_LICENSE("GPL v2"); | ||
1085 | MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay"); | ||
1086 | MODULE_ALIAS("platform:pm2xxx-charger"); | ||
1087 | MODULE_DESCRIPTION("PM2xxx charger management driver"); | ||
1088 | |||
diff --git a/drivers/power/pm2301_charger.h b/drivers/power/pm2301_charger.h new file mode 100644 index 000000000000..e6319cdbc94f --- /dev/null +++ b/drivers/power/pm2301_charger.h | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2012 | ||
3 | * | ||
4 | * PM2301 power supply interface | ||
5 | * | ||
6 | * License terms: GNU General Public License (GPL), version 2 | ||
7 | */ | ||
8 | |||
9 | #ifndef PM2301_CHARGER_H | ||
10 | #define PM2301_CHARGER_H | ||
11 | |||
12 | #define MAIN_WDOG_ENA 0x01 | ||
13 | #define MAIN_WDOG_KICK 0x02 | ||
14 | #define MAIN_WDOG_DIS 0x00 | ||
15 | #define CHARG_WD_KICK 0x01 | ||
16 | #define MAIN_CH_ENA 0x01 | ||
17 | #define MAIN_CH_NO_OVERSHOOT_ENA_N 0x02 | ||
18 | #define MAIN_CH_DET 0x01 | ||
19 | #define MAIN_CH_CV_ON 0x04 | ||
20 | #define OTP_ENABLE_WD 0x01 | ||
21 | |||
22 | #define MAIN_CH_INPUT_CURR_SHIFT 4 | ||
23 | |||
24 | #define LED_INDICATOR_PWM_ENA 0x01 | ||
25 | #define LED_INDICATOR_PWM_DIS 0x00 | ||
26 | #define LED_IND_CUR_5MA 0x04 | ||
27 | #define LED_INDICATOR_PWM_DUTY_252_256 0xBF | ||
28 | |||
29 | /* HW failure constants */ | ||
30 | #define MAIN_CH_TH_PROT 0x02 | ||
31 | #define MAIN_CH_NOK 0x01 | ||
32 | |||
33 | /* Watchdog timeout constant */ | ||
34 | #define WD_TIMER 0x30 /* 4min */ | ||
35 | #define WD_KICK_INTERVAL (30 * HZ) | ||
36 | |||
37 | #define PM2XXX_NUM_INT_REG 0x6 | ||
38 | |||
39 | /* Constant voltage/current */ | ||
40 | #define PM2XXX_CONST_CURR 0x0 | ||
41 | #define PM2XXX_CONST_VOLT 0x1 | ||
42 | |||
43 | /* Lowest charger voltage is 3.39V -> 0x4E */ | ||
44 | #define LOW_VOLT_REG 0x4E | ||
45 | |||
46 | #define PM2XXX_BATT_CTRL_REG1 0x00 | ||
47 | #define PM2XXX_BATT_CTRL_REG2 0x01 | ||
48 | #define PM2XXX_BATT_CTRL_REG3 0x02 | ||
49 | #define PM2XXX_BATT_CTRL_REG4 0x03 | ||
50 | #define PM2XXX_BATT_CTRL_REG5 0x04 | ||
51 | #define PM2XXX_BATT_CTRL_REG6 0x05 | ||
52 | #define PM2XXX_BATT_CTRL_REG7 0x06 | ||
53 | #define PM2XXX_BATT_CTRL_REG8 0x07 | ||
54 | #define PM2XXX_NTC_CTRL_REG1 0x08 | ||
55 | #define PM2XXX_NTC_CTRL_REG2 0x09 | ||
56 | #define PM2XXX_BATT_CTRL_REG9 0x0A | ||
57 | #define PM2XXX_BATT_STAT_REG1 0x0B | ||
58 | #define PM2XXX_INP_VOLT_VPWR2 0x11 | ||
59 | #define PM2XXX_INP_DROP_VPWR2 0x13 | ||
60 | #define PM2XXX_INP_VOLT_VPWR1 0x15 | ||
61 | #define PM2XXX_INP_DROP_VPWR1 0x17 | ||
62 | #define PM2XXX_INP_MODE_VPWR 0x18 | ||
63 | #define PM2XXX_BATT_WD_KICK 0x70 | ||
64 | #define PM2XXX_DEV_VER_STAT 0x0C | ||
65 | #define PM2XXX_THERM_WARN_CTRL_REG 0x20 | ||
66 | #define PM2XXX_BATT_DISC_REG 0x21 | ||
67 | #define PM2XXX_BATT_LOW_LEV_COMP_REG 0x22 | ||
68 | #define PM2XXX_BATT_LOW_LEV_VAL_REG 0x23 | ||
69 | #define PM2XXX_I2C_PAD_CTRL_REG 0x24 | ||
70 | #define PM2XXX_SW_CTRL_REG 0x26 | ||
71 | #define PM2XXX_LED_CTRL_REG 0x28 | ||
72 | |||
73 | #define PM2XXX_REG_INT1 0x40 | ||
74 | #define PM2XXX_MASK_REG_INT1 0x50 | ||
75 | #define PM2XXX_SRCE_REG_INT1 0x60 | ||
76 | #define PM2XXX_REG_INT2 0x41 | ||
77 | #define PM2XXX_MASK_REG_INT2 0x51 | ||
78 | #define PM2XXX_SRCE_REG_INT2 0x61 | ||
79 | #define PM2XXX_REG_INT3 0x42 | ||
80 | #define PM2XXX_MASK_REG_INT3 0x52 | ||
81 | #define PM2XXX_SRCE_REG_INT3 0x62 | ||
82 | #define PM2XXX_REG_INT4 0x43 | ||
83 | #define PM2XXX_MASK_REG_INT4 0x53 | ||
84 | #define PM2XXX_SRCE_REG_INT4 0x63 | ||
85 | #define PM2XXX_REG_INT5 0x44 | ||
86 | #define PM2XXX_MASK_REG_INT5 0x54 | ||
87 | #define PM2XXX_SRCE_REG_INT5 0x64 | ||
88 | #define PM2XXX_REG_INT6 0x45 | ||
89 | #define PM2XXX_MASK_REG_INT6 0x55 | ||
90 | #define PM2XXX_SRCE_REG_INT6 0x65 | ||
91 | |||
92 | #define VPWR_OVV 0x0 | ||
93 | #define VSYSTEM_OVV 0x1 | ||
94 | |||
95 | /* control Reg 1 */ | ||
96 | #define PM2XXX_CH_RESUME_EN 0x1 | ||
97 | #define PM2XXX_CH_RESUME_DIS 0x0 | ||
98 | |||
99 | /* control Reg 2 */ | ||
100 | #define PM2XXX_CH_AUTO_RESUME_EN 0X2 | ||
101 | #define PM2XXX_CH_AUTO_RESUME_DIS 0X0 | ||
102 | #define PM2XXX_CHARGER_ENA 0x4 | ||
103 | #define PM2XXX_CHARGER_DIS 0x0 | ||
104 | |||
105 | /* control Reg 3 */ | ||
106 | #define PM2XXX_CH_WD_CC_PHASE_OFF 0x0 | ||
107 | #define PM2XXX_CH_WD_CC_PHASE_5MIN 0x1 | ||
108 | #define PM2XXX_CH_WD_CC_PHASE_10MIN 0x2 | ||
109 | #define PM2XXX_CH_WD_CC_PHASE_30MIN 0x3 | ||
110 | #define PM2XXX_CH_WD_CC_PHASE_60MIN 0x4 | ||
111 | #define PM2XXX_CH_WD_CC_PHASE_120MIN 0x5 | ||
112 | #define PM2XXX_CH_WD_CC_PHASE_240MIN 0x6 | ||
113 | #define PM2XXX_CH_WD_CC_PHASE_360MIN 0x7 | ||
114 | |||
115 | #define PM2XXX_CH_WD_CV_PHASE_OFF (0x0<<3) | ||
116 | #define PM2XXX_CH_WD_CV_PHASE_5MIN (0x1<<3) | ||
117 | #define PM2XXX_CH_WD_CV_PHASE_10MIN (0x2<<3) | ||
118 | #define PM2XXX_CH_WD_CV_PHASE_30MIN (0x3<<3) | ||
119 | #define PM2XXX_CH_WD_CV_PHASE_60MIN (0x4<<3) | ||
120 | #define PM2XXX_CH_WD_CV_PHASE_120MIN (0x5<<3) | ||
121 | #define PM2XXX_CH_WD_CV_PHASE_240MIN (0x6<<3) | ||
122 | #define PM2XXX_CH_WD_CV_PHASE_360MIN (0x7<<3) | ||
123 | |||
124 | /* control Reg 4 */ | ||
125 | #define PM2XXX_CH_WD_PRECH_PHASE_OFF 0x0 | ||
126 | #define PM2XXX_CH_WD_PRECH_PHASE_1MIN 0x1 | ||
127 | #define PM2XXX_CH_WD_PRECH_PHASE_5MIN 0x2 | ||
128 | #define PM2XXX_CH_WD_PRECH_PHASE_10MIN 0x3 | ||
129 | #define PM2XXX_CH_WD_PRECH_PHASE_30MIN 0x4 | ||
130 | #define PM2XXX_CH_WD_PRECH_PHASE_60MIN 0x5 | ||
131 | #define PM2XXX_CH_WD_PRECH_PHASE_120MIN 0x6 | ||
132 | #define PM2XXX_CH_WD_PRECH_PHASE_240MIN 0x7 | ||
133 | |||
134 | /* control Reg 5 */ | ||
135 | #define PM2XXX_CH_WD_AUTO_TIMEOUT_NONE 0x0 | ||
136 | #define PM2XXX_CH_WD_AUTO_TIMEOUT_20MIN 0x1 | ||
137 | |||
138 | /* control Reg 6 */ | ||
139 | #define PM2XXX_DIR_CH_CC_CURRENT_MASK 0x0F | ||
140 | #define PM2XXX_DIR_CH_CC_CURRENT_200MA 0x0 | ||
141 | #define PM2XXX_DIR_CH_CC_CURRENT_400MA 0x2 | ||
142 | #define PM2XXX_DIR_CH_CC_CURRENT_600MA 0x3 | ||
143 | #define PM2XXX_DIR_CH_CC_CURRENT_800MA 0x4 | ||
144 | #define PM2XXX_DIR_CH_CC_CURRENT_1000MA 0x5 | ||
145 | #define PM2XXX_DIR_CH_CC_CURRENT_1200MA 0x6 | ||
146 | #define PM2XXX_DIR_CH_CC_CURRENT_1400MA 0x7 | ||
147 | #define PM2XXX_DIR_CH_CC_CURRENT_1600MA 0x8 | ||
148 | #define PM2XXX_DIR_CH_CC_CURRENT_1800MA 0x9 | ||
149 | #define PM2XXX_DIR_CH_CC_CURRENT_2000MA 0xA | ||
150 | #define PM2XXX_DIR_CH_CC_CURRENT_2200MA 0xB | ||
151 | #define PM2XXX_DIR_CH_CC_CURRENT_2400MA 0xC | ||
152 | #define PM2XXX_DIR_CH_CC_CURRENT_2600MA 0xD | ||
153 | #define PM2XXX_DIR_CH_CC_CURRENT_2800MA 0xE | ||
154 | #define PM2XXX_DIR_CH_CC_CURRENT_3000MA 0xF | ||
155 | |||
156 | #define PM2XXX_CH_PRECH_CURRENT_MASK 0x30 | ||
157 | #define PM2XXX_CH_PRECH_CURRENT_25MA (0x0<<4) | ||
158 | #define PM2XXX_CH_PRECH_CURRENT_50MA (0x1<<4) | ||
159 | #define PM2XXX_CH_PRECH_CURRENT_75MA (0x2<<4) | ||
160 | #define PM2XXX_CH_PRECH_CURRENT_100MA (0x3<<4) | ||
161 | |||
162 | #define PM2XXX_CH_EOC_CURRENT_MASK 0xC0 | ||
163 | #define PM2XXX_CH_EOC_CURRENT_100MA (0x0<<6) | ||
164 | #define PM2XXX_CH_EOC_CURRENT_150MA (0x1<<6) | ||
165 | #define PM2XXX_CH_EOC_CURRENT_300MA (0x2<<6) | ||
166 | #define PM2XXX_CH_EOC_CURRENT_400MA (0x3<<6) | ||
167 | |||
168 | /* control Reg 7 */ | ||
169 | #define PM2XXX_CH_PRECH_VOL_2_5 0x0 | ||
170 | #define PM2XXX_CH_PRECH_VOL_2_7 0x1 | ||
171 | #define PM2XXX_CH_PRECH_VOL_2_9 0x2 | ||
172 | #define PM2XXX_CH_PRECH_VOL_3_1 0x3 | ||
173 | |||
174 | #define PM2XXX_CH_VRESUME_VOL_3_2 (0x0<<2) | ||
175 | #define PM2XXX_CH_VRESUME_VOL_3_4 (0x1<<2) | ||
176 | #define PM2XXX_CH_VRESUME_VOL_3_6 (0x2<<2) | ||
177 | #define PM2XXX_CH_VRESUME_VOL_3_8 (0x3<<2) | ||
178 | |||
179 | /* control Reg 8 */ | ||
180 | #define PM2XXX_CH_VOLT_MASK 0x3F | ||
181 | #define PM2XXX_CH_VOLT_3_5 0x0 | ||
182 | #define PM2XXX_CH_VOLT_3_5225 0x1 | ||
183 | #define PM2XXX_CH_VOLT_3_6 0x4 | ||
184 | #define PM2XXX_CH_VOLT_3_7 0x8 | ||
185 | #define PM2XXX_CH_VOLT_4_0 0x14 | ||
186 | #define PM2XXX_CH_VOLT_4_175 0x1B | ||
187 | #define PM2XXX_CH_VOLT_4_2 0x1C | ||
188 | #define PM2XXX_CH_VOLT_4_275 0x1F | ||
189 | #define PM2XXX_CH_VOLT_4_3 0x20 | ||
190 | |||
191 | /*NTC control register 1*/ | ||
192 | #define PM2XXX_BTEMP_HIGH_TH_45 0x0 | ||
193 | #define PM2XXX_BTEMP_HIGH_TH_50 0x1 | ||
194 | #define PM2XXX_BTEMP_HIGH_TH_55 0x2 | ||
195 | #define PM2XXX_BTEMP_HIGH_TH_60 0x3 | ||
196 | #define PM2XXX_BTEMP_HIGH_TH_65 0x4 | ||
197 | |||
198 | #define PM2XXX_BTEMP_LOW_TH_N5 (0x0<<3) | ||
199 | #define PM2XXX_BTEMP_LOW_TH_0 (0x1<<3) | ||
200 | #define PM2XXX_BTEMP_LOW_TH_5 (0x2<<3) | ||
201 | #define PM2XXX_BTEMP_LOW_TH_10 (0x3<<3) | ||
202 | |||
203 | /*NTC control register 2*/ | ||
204 | #define PM2XXX_NTC_BETA_COEFF_3477 0x0 | ||
205 | #define PM2XXX_NTC_BETA_COEFF_3964 0x1 | ||
206 | |||
207 | #define PM2XXX_NTC_RES_10K (0x0<<2) | ||
208 | #define PM2XXX_NTC_RES_47K (0x1<<2) | ||
209 | #define PM2XXX_NTC_RES_100K (0x2<<2) | ||
210 | #define PM2XXX_NTC_RES_NO_NTC (0x3<<2) | ||
211 | |||
212 | /* control Reg 9 */ | ||
213 | #define PM2XXX_CH_CC_MODEDROP_EN 1 | ||
214 | #define PM2XXX_CH_CC_MODEDROP_DIS 0 | ||
215 | |||
216 | #define PM2XXX_CH_CC_REDUCED_CURRENT_100MA (0x0<<1) | ||
217 | #define PM2XXX_CH_CC_REDUCED_CURRENT_200MA (0x1<<1) | ||
218 | #define PM2XXX_CH_CC_REDUCED_CURRENT_400MA (0x2<<1) | ||
219 | #define PM2XXX_CH_CC_REDUCED_CURRENT_IDENT (0x3<<1) | ||
220 | |||
221 | #define PM2XXX_CHARCHING_INFO_DIS (0<<3) | ||
222 | #define PM2XXX_CHARCHING_INFO_EN (1<<3) | ||
223 | |||
224 | #define PM2XXX_CH_150MV_DROP_300MV (0<<4) | ||
225 | #define PM2XXX_CH_150MV_DROP_150MV (1<<4) | ||
226 | |||
227 | |||
228 | /* charger status register */ | ||
229 | #define PM2XXX_CHG_STATUS_OFF 0x0 | ||
230 | #define PM2XXX_CHG_STATUS_ON 0x1 | ||
231 | #define PM2XXX_CHG_STATUS_FULL 0x2 | ||
232 | #define PM2XXX_CHG_STATUS_ERR 0x3 | ||
233 | #define PM2XXX_CHG_STATUS_WAIT 0x4 | ||
234 | #define PM2XXX_CHG_STATUS_NOBAT 0x5 | ||
235 | |||
236 | /* Input charger voltage VPWR2 */ | ||
237 | #define PM2XXX_VPWR2_OVV_6_0 0x0 | ||
238 | #define PM2XXX_VPWR2_OVV_6_3 0x1 | ||
239 | #define PM2XXX_VPWR2_OVV_10 0x2 | ||
240 | #define PM2XXX_VPWR2_OVV_NONE 0x3 | ||
241 | |||
242 | /* Input charger drop VPWR2 */ | ||
243 | #define PM2XXX_VPWR2_HW_OPT_EN (0x1<<4) | ||
244 | #define PM2XXX_VPWR2_HW_OPT_DIS (0x0<<4) | ||
245 | |||
246 | #define PM2XXX_VPWR2_VALID_EN (0x1<<3) | ||
247 | #define PM2XXX_VPWR2_VALID_DIS (0x0<<3) | ||
248 | |||
249 | #define PM2XXX_VPWR2_DROP_EN (0x1<<2) | ||
250 | #define PM2XXX_VPWR2_DROP_DIS (0x0<<2) | ||
251 | |||
252 | /* Input charger voltage VPWR1 */ | ||
253 | #define PM2XXX_VPWR1_OVV_6_0 0x0 | ||
254 | #define PM2XXX_VPWR1_OVV_6_3 0x1 | ||
255 | #define PM2XXX_VPWR1_OVV_10 0x2 | ||
256 | #define PM2XXX_VPWR1_OVV_NONE 0x3 | ||
257 | |||
258 | /* Input charger drop VPWR1 */ | ||
259 | #define PM2XXX_VPWR1_HW_OPT_EN (0x1<<4) | ||
260 | #define PM2XXX_VPWR1_HW_OPT_DIS (0x0<<4) | ||
261 | |||
262 | #define PM2XXX_VPWR1_VALID_EN (0x1<<3) | ||
263 | #define PM2XXX_VPWR1_VALID_DIS (0x0<<3) | ||
264 | |||
265 | #define PM2XXX_VPWR1_DROP_EN (0x1<<2) | ||
266 | #define PM2XXX_VPWR1_DROP_DIS (0x0<<2) | ||
267 | |||
268 | /* Battery low level comparator control register */ | ||
269 | #define PM2XXX_VBAT_LOW_MONITORING_DIS 0x0 | ||
270 | #define PM2XXX_VBAT_LOW_MONITORING_ENA 0x1 | ||
271 | |||
272 | /* Battery low level value control register */ | ||
273 | #define PM2XXX_VBAT_LOW_LEVEL_2_3 0x0 | ||
274 | #define PM2XXX_VBAT_LOW_LEVEL_2_4 0x1 | ||
275 | #define PM2XXX_VBAT_LOW_LEVEL_2_5 0x2 | ||
276 | #define PM2XXX_VBAT_LOW_LEVEL_2_6 0x3 | ||
277 | #define PM2XXX_VBAT_LOW_LEVEL_2_7 0x4 | ||
278 | #define PM2XXX_VBAT_LOW_LEVEL_2_8 0x5 | ||
279 | #define PM2XXX_VBAT_LOW_LEVEL_2_9 0x6 | ||
280 | #define PM2XXX_VBAT_LOW_LEVEL_3_0 0x7 | ||
281 | #define PM2XXX_VBAT_LOW_LEVEL_3_1 0x8 | ||
282 | #define PM2XXX_VBAT_LOW_LEVEL_3_2 0x9 | ||
283 | #define PM2XXX_VBAT_LOW_LEVEL_3_3 0xA | ||
284 | #define PM2XXX_VBAT_LOW_LEVEL_3_4 0xB | ||
285 | #define PM2XXX_VBAT_LOW_LEVEL_3_5 0xC | ||
286 | #define PM2XXX_VBAT_LOW_LEVEL_3_6 0xD | ||
287 | #define PM2XXX_VBAT_LOW_LEVEL_3_7 0xE | ||
288 | #define PM2XXX_VBAT_LOW_LEVEL_3_8 0xF | ||
289 | #define PM2XXX_VBAT_LOW_LEVEL_3_9 0x10 | ||
290 | #define PM2XXX_VBAT_LOW_LEVEL_4_0 0x11 | ||
291 | #define PM2XXX_VBAT_LOW_LEVEL_4_1 0x12 | ||
292 | #define PM2XXX_VBAT_LOW_LEVEL_4_2 0x13 | ||
293 | |||
294 | /* SW CTRL */ | ||
295 | #define PM2XXX_SWCTRL_HW 0x0 | ||
296 | #define PM2XXX_SWCTRL_SW 0x1 | ||
297 | |||
298 | |||
299 | /* LED Driver Control */ | ||
300 | #define PM2XXX_LED_CURRENT_MASK 0x0C | ||
301 | #define PM2XXX_LED_CURRENT_2_5MA (0X0<<2) | ||
302 | #define PM2XXX_LED_CURRENT_1MA (0X1<<2) | ||
303 | #define PM2XXX_LED_CURRENT_5MA (0X2<<2) | ||
304 | #define PM2XXX_LED_CURRENT_10MA (0X3<<2) | ||
305 | |||
306 | #define PM2XXX_LED_SELECT_MASK 0x02 | ||
307 | #define PM2XXX_LED_SELECT_EN (0X0<<1) | ||
308 | #define PM2XXX_LED_SELECT_DIS (0X1<<1) | ||
309 | |||
310 | #define PM2XXX_ANTI_OVERSHOOT_MASK 0x01 | ||
311 | #define PM2XXX_ANTI_OVERSHOOT_DIS 0X0 | ||
312 | #define PM2XXX_ANTI_OVERSHOOT_EN 0X1 | ||
313 | |||
314 | enum pm2xxx_reg_int1 { | ||
315 | PM2XXX_INT1_ITVBATDISCONNECT = 0x02, | ||
316 | PM2XXX_INT1_ITVBATLOWR = 0x04, | ||
317 | PM2XXX_INT1_ITVBATLOWF = 0x08, | ||
318 | }; | ||
319 | |||
320 | enum pm2xxx_mask_reg_int1 { | ||
321 | PM2XXX_INT1_M_ITVBATDISCONNECT = 0x02, | ||
322 | PM2XXX_INT1_M_ITVBATLOWR = 0x04, | ||
323 | PM2XXX_INT1_M_ITVBATLOWF = 0x08, | ||
324 | }; | ||
325 | |||
326 | enum pm2xxx_source_reg_int1 { | ||
327 | PM2XXX_INT1_S_ITVBATDISCONNECT = 0x02, | ||
328 | PM2XXX_INT1_S_ITVBATLOWR = 0x04, | ||
329 | PM2XXX_INT1_S_ITVBATLOWF = 0x08, | ||
330 | }; | ||
331 | |||
332 | enum pm2xxx_reg_int2 { | ||
333 | PM2XXX_INT2_ITVPWR2PLUG = 0x01, | ||
334 | PM2XXX_INT2_ITVPWR2UNPLUG = 0x02, | ||
335 | PM2XXX_INT2_ITVPWR1PLUG = 0x04, | ||
336 | PM2XXX_INT2_ITVPWR1UNPLUG = 0x08, | ||
337 | }; | ||
338 | |||
339 | enum pm2xxx_mask_reg_int2 { | ||
340 | PM2XXX_INT2_M_ITVPWR2PLUG = 0x01, | ||
341 | PM2XXX_INT2_M_ITVPWR2UNPLUG = 0x02, | ||
342 | PM2XXX_INT2_M_ITVPWR1PLUG = 0x04, | ||
343 | PM2XXX_INT2_M_ITVPWR1UNPLUG = 0x08, | ||
344 | }; | ||
345 | |||
346 | enum pm2xxx_source_reg_int2 { | ||
347 | PM2XXX_INT2_S_ITVPWR2PLUG = 0x03, | ||
348 | PM2XXX_INT2_S_ITVPWR1PLUG = 0x0c, | ||
349 | }; | ||
350 | |||
351 | enum pm2xxx_reg_int3 { | ||
352 | PM2XXX_INT3_ITCHPRECHARGEWD = 0x01, | ||
353 | PM2XXX_INT3_ITCHCCWD = 0x02, | ||
354 | PM2XXX_INT3_ITCHCVWD = 0x04, | ||
355 | PM2XXX_INT3_ITAUTOTIMEOUTWD = 0x08, | ||
356 | }; | ||
357 | |||
358 | enum pm2xxx_mask_reg_int3 { | ||
359 | PM2XXX_INT3_M_ITCHPRECHARGEWD = 0x01, | ||
360 | PM2XXX_INT3_M_ITCHCCWD = 0x02, | ||
361 | PM2XXX_INT3_M_ITCHCVWD = 0x04, | ||
362 | PM2XXX_INT3_M_ITAUTOTIMEOUTWD = 0x08, | ||
363 | }; | ||
364 | |||
365 | enum pm2xxx_source_reg_int3 { | ||
366 | PM2XXX_INT3_S_ITCHPRECHARGEWD = 0x01, | ||
367 | PM2XXX_INT3_S_ITCHCCWD = 0x02, | ||
368 | PM2XXX_INT3_S_ITCHCVWD = 0x04, | ||
369 | PM2XXX_INT3_S_ITAUTOTIMEOUTWD = 0x08, | ||
370 | }; | ||
371 | |||
372 | enum pm2xxx_reg_int4 { | ||
373 | PM2XXX_INT4_ITBATTEMPCOLD = 0x01, | ||
374 | PM2XXX_INT4_ITBATTEMPHOT = 0x02, | ||
375 | PM2XXX_INT4_ITVPWR2OVV = 0x04, | ||
376 | PM2XXX_INT4_ITVPWR1OVV = 0x08, | ||
377 | PM2XXX_INT4_ITCHARGINGON = 0x10, | ||
378 | PM2XXX_INT4_ITVRESUME = 0x20, | ||
379 | PM2XXX_INT4_ITBATTFULL = 0x40, | ||
380 | PM2XXX_INT4_ITCVPHASE = 0x80, | ||
381 | }; | ||
382 | |||
383 | enum pm2xxx_mask_reg_int4 { | ||
384 | PM2XXX_INT4_M_ITBATTEMPCOLD = 0x01, | ||
385 | PM2XXX_INT4_M_ITBATTEMPHOT = 0x02, | ||
386 | PM2XXX_INT4_M_ITVPWR2OVV = 0x04, | ||
387 | PM2XXX_INT4_M_ITVPWR1OVV = 0x08, | ||
388 | PM2XXX_INT4_M_ITCHARGINGON = 0x10, | ||
389 | PM2XXX_INT4_M_ITVRESUME = 0x20, | ||
390 | PM2XXX_INT4_M_ITBATTFULL = 0x40, | ||
391 | PM2XXX_INT4_M_ITCVPHASE = 0x80, | ||
392 | }; | ||
393 | |||
394 | enum pm2xxx_source_reg_int4 { | ||
395 | PM2XXX_INT4_S_ITBATTEMPCOLD = 0x01, | ||
396 | PM2XXX_INT4_S_ITBATTEMPHOT = 0x02, | ||
397 | PM2XXX_INT4_S_ITVPWR2OVV = 0x04, | ||
398 | PM2XXX_INT4_S_ITVPWR1OVV = 0x08, | ||
399 | PM2XXX_INT4_S_ITCHARGINGON = 0x10, | ||
400 | PM2XXX_INT4_S_ITVRESUME = 0x20, | ||
401 | PM2XXX_INT4_S_ITBATTFULL = 0x40, | ||
402 | PM2XXX_INT4_S_ITCVPHASE = 0x80, | ||
403 | }; | ||
404 | |||
405 | enum pm2xxx_reg_int5 { | ||
406 | PM2XXX_INT5_ITTHERMALSHUTDOWNRISE = 0x01, | ||
407 | PM2XXX_INT5_ITTHERMALSHUTDOWNFALL = 0x02, | ||
408 | PM2XXX_INT5_ITTHERMALWARNINGRISE = 0x04, | ||
409 | PM2XXX_INT5_ITTHERMALWARNINGFALL = 0x08, | ||
410 | PM2XXX_INT5_ITVSYSTEMOVV = 0x10, | ||
411 | }; | ||
412 | |||
413 | enum pm2xxx_mask_reg_int5 { | ||
414 | PM2XXX_INT5_M_ITTHERMALSHUTDOWNRISE = 0x01, | ||
415 | PM2XXX_INT5_M_ITTHERMALSHUTDOWNFALL = 0x02, | ||
416 | PM2XXX_INT5_M_ITTHERMALWARNINGRISE = 0x04, | ||
417 | PM2XXX_INT5_M_ITTHERMALWARNINGFALL = 0x08, | ||
418 | PM2XXX_INT5_M_ITVSYSTEMOVV = 0x10, | ||
419 | }; | ||
420 | |||
421 | enum pm2xxx_source_reg_int5 { | ||
422 | PM2XXX_INT5_S_ITTHERMALSHUTDOWNRISE = 0x01, | ||
423 | PM2XXX_INT5_S_ITTHERMALSHUTDOWNFALL = 0x02, | ||
424 | PM2XXX_INT5_S_ITTHERMALWARNINGRISE = 0x04, | ||
425 | PM2XXX_INT5_S_ITTHERMALWARNINGFALL = 0x08, | ||
426 | PM2XXX_INT5_S_ITVSYSTEMOVV = 0x10, | ||
427 | }; | ||
428 | |||
429 | enum pm2xxx_reg_int6 { | ||
430 | PM2XXX_INT6_ITVPWR2DROP = 0x01, | ||
431 | PM2XXX_INT6_ITVPWR1DROP = 0x02, | ||
432 | PM2XXX_INT6_ITVPWR2VALIDRISE = 0x04, | ||
433 | PM2XXX_INT6_ITVPWR2VALIDFALL = 0x08, | ||
434 | PM2XXX_INT6_ITVPWR1VALIDRISE = 0x10, | ||
435 | PM2XXX_INT6_ITVPWR1VALIDFALL = 0x20, | ||
436 | }; | ||
437 | |||
438 | enum pm2xxx_mask_reg_int6 { | ||
439 | PM2XXX_INT6_M_ITVPWR2DROP = 0x01, | ||
440 | PM2XXX_INT6_M_ITVPWR1DROP = 0x02, | ||
441 | PM2XXX_INT6_M_ITVPWR2VALIDRISE = 0x04, | ||
442 | PM2XXX_INT6_M_ITVPWR2VALIDFALL = 0x08, | ||
443 | PM2XXX_INT6_M_ITVPWR1VALIDRISE = 0x10, | ||
444 | PM2XXX_INT6_M_ITVPWR1VALIDFALL = 0x20, | ||
445 | }; | ||
446 | |||
447 | enum pm2xxx_source_reg_int6 { | ||
448 | PM2XXX_INT6_S_ITVPWR2DROP = 0x01, | ||
449 | PM2XXX_INT6_S_ITVPWR1DROP = 0x02, | ||
450 | PM2XXX_INT6_S_ITVPWR2VALIDRISE = 0x04, | ||
451 | PM2XXX_INT6_S_ITVPWR2VALIDFALL = 0x08, | ||
452 | PM2XXX_INT6_S_ITVPWR1VALIDRISE = 0x10, | ||
453 | PM2XXX_INT6_S_ITVPWR1VALIDFALL = 0x20, | ||
454 | }; | ||
455 | |||
456 | struct pm2xxx_charger_info { | ||
457 | int charger_connected; | ||
458 | int charger_online; | ||
459 | int cv_active; | ||
460 | bool wd_expired; | ||
461 | }; | ||
462 | |||
463 | struct pm2xxx_charger_event_flags { | ||
464 | bool mainextchnotok; | ||
465 | bool main_thermal_prot; | ||
466 | bool ovv; | ||
467 | bool chgwdexp; | ||
468 | }; | ||
469 | |||
470 | struct pm2xxx_interrupts { | ||
471 | u8 reg[PM2XXX_NUM_INT_REG]; | ||
472 | int (*handler[PM2XXX_NUM_INT_REG])(void *, int); | ||
473 | }; | ||
474 | |||
475 | struct pm2xxx_config { | ||
476 | struct i2c_client *pm2xxx_i2c; | ||
477 | struct i2c_device_id *pm2xxx_id; | ||
478 | }; | ||
479 | |||
480 | struct pm2xxx_irq { | ||
481 | char *name; | ||
482 | irqreturn_t (*isr)(int irq, void *data); | ||
483 | }; | ||
484 | |||
485 | struct pm2xxx_charger { | ||
486 | struct device *dev; | ||
487 | u8 chip_id; | ||
488 | bool vddadc_en_ac; | ||
489 | struct pm2xxx_config config; | ||
490 | bool ac_conn; | ||
491 | unsigned int gpio_irq; | ||
492 | int vbat; | ||
493 | int old_vbat; | ||
494 | int failure_case; | ||
495 | int failure_input_ovv; | ||
496 | unsigned int lpn_pin; | ||
497 | struct pm2xxx_interrupts *pm2_int; | ||
498 | struct ab8500_gpadc *gpadc; | ||
499 | struct regulator *regu; | ||
500 | struct pm2xxx_bm_data *bat; | ||
501 | struct mutex lock; | ||
502 | struct ab8500 *parent; | ||
503 | struct pm2xxx_charger_info ac; | ||
504 | struct pm2xxx_charger_platform_data *pdata; | ||
505 | struct workqueue_struct *charger_wq; | ||
506 | struct delayed_work check_vbat_work; | ||
507 | struct work_struct ac_work; | ||
508 | struct work_struct check_main_thermal_prot_work; | ||
509 | struct ux500_charger ac_chg; | ||
510 | struct pm2xxx_charger_event_flags flags; | ||
511 | }; | ||
512 | |||
513 | #endif /* PM2301_CHARGER_H */ | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 40fa3b7cae54..29178f78d73c 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -55,7 +55,8 @@ static ssize_t power_supply_show_property(struct device *dev, | |||
55 | }; | 55 | }; |
56 | static char *health_text[] = { | 56 | static char *health_text[] = { |
57 | "Unknown", "Good", "Overheat", "Dead", "Over voltage", | 57 | "Unknown", "Good", "Overheat", "Dead", "Over voltage", |
58 | "Unspecified failure", "Cold", | 58 | "Unspecified failure", "Cold", "Watchdog timer expire", |
59 | "Safety timer expire" | ||
59 | }; | 60 | }; |
60 | static char *technology_text[] = { | 61 | static char *technology_text[] = { |
61 | "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", | 62 | "Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd", |
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 6461b489fb09..1ae65b822864 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig | |||
@@ -13,3 +13,20 @@ config POWER_RESET_GPIO | |||
13 | This driver supports turning off your board via a GPIO line. | 13 | This driver supports turning off your board via a GPIO line. |
14 | If your board needs a GPIO high/low to power down, say Y and | 14 | If your board needs a GPIO high/low to power down, say Y and |
15 | create a binding in your devicetree. | 15 | create a binding in your devicetree. |
16 | |||
17 | config POWER_RESET_QNAP | ||
18 | bool "QNAP power-off driver" | ||
19 | depends on OF_GPIO && POWER_RESET && PLAT_ORION | ||
20 | help | ||
21 | This driver supports turning off QNAP NAS devices by sending | ||
22 | commands to the microcontroller which controls the main power. | ||
23 | |||
24 | Say Y if you have a QNAP NAS. | ||
25 | |||
26 | config POWER_RESET_RESTART | ||
27 | bool "Restart power-off driver" | ||
28 | depends on ARM | ||
29 | help | ||
30 | Some boards don't actually have the ability to power off. | ||
31 | Instead they restart, and u-boot holds the SoC until the | ||
32 | user presses a key. u-boot then boots into Linux. | ||
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index 751488a4a0c5..0f317f50c56f 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o | 1 | obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o |
2 | obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o | ||
3 | obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o \ No newline at end of file | ||
diff --git a/drivers/power/reset/qnap-poweroff.c b/drivers/power/reset/qnap-poweroff.c new file mode 100644 index 000000000000..37f56f7ee926 --- /dev/null +++ b/drivers/power/reset/qnap-poweroff.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * QNAP Turbo NAS Board power off | ||
3 | * | ||
4 | * Copyright (C) 2012 Andrew Lunn <andrew@lunn.ch> | ||
5 | * | ||
6 | * Based on the code from: | ||
7 | * | ||
8 | * Copyright (C) 2009 Martin Michlmayr <tbm@cyrius.com> | ||
9 | * Copyright (C) 2008 Byron Bradley <byron.bbradley@gmail.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/serial_reg.h> | ||
21 | #include <linux/kallsyms.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/clk.h> | ||
25 | |||
26 | #define UART1_REG(x) (base + ((UART_##x) << 2)) | ||
27 | |||
28 | static void __iomem *base; | ||
29 | static unsigned long tclk; | ||
30 | |||
31 | static void qnap_power_off(void) | ||
32 | { | ||
33 | /* 19200 baud divisor */ | ||
34 | const unsigned divisor = ((tclk + (8 * 19200)) / (16 * 19200)); | ||
35 | |||
36 | pr_err("%s: triggering power-off...\n", __func__); | ||
37 | |||
38 | /* hijack UART1 and reset into sane state (19200,8n1) */ | ||
39 | writel(0x83, UART1_REG(LCR)); | ||
40 | writel(divisor & 0xff, UART1_REG(DLL)); | ||
41 | writel((divisor >> 8) & 0xff, UART1_REG(DLM)); | ||
42 | writel(0x03, UART1_REG(LCR)); | ||
43 | writel(0x00, UART1_REG(IER)); | ||
44 | writel(0x00, UART1_REG(FCR)); | ||
45 | writel(0x00, UART1_REG(MCR)); | ||
46 | |||
47 | /* send the power-off command 'A' to PIC */ | ||
48 | writel('A', UART1_REG(TX)); | ||
49 | } | ||
50 | |||
51 | static int qnap_power_off_probe(struct platform_device *pdev) | ||
52 | { | ||
53 | struct resource *res; | ||
54 | struct clk *clk; | ||
55 | char symname[KSYM_NAME_LEN]; | ||
56 | |||
57 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
58 | if (!res) { | ||
59 | dev_err(&pdev->dev, "Missing resource"); | ||
60 | return -EINVAL; | ||
61 | } | ||
62 | |||
63 | base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
64 | if (!base) { | ||
65 | dev_err(&pdev->dev, "Unable to map resource"); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | /* We need to know tclk in order to calculate the UART divisor */ | ||
70 | clk = devm_clk_get(&pdev->dev, NULL); | ||
71 | if (IS_ERR(clk)) { | ||
72 | dev_err(&pdev->dev, "Clk missing"); | ||
73 | return PTR_ERR(clk); | ||
74 | } | ||
75 | |||
76 | tclk = clk_get_rate(clk); | ||
77 | |||
78 | /* Check that nothing else has already setup a handler */ | ||
79 | if (pm_power_off) { | ||
80 | lookup_symbol_name((ulong)pm_power_off, symname); | ||
81 | dev_err(&pdev->dev, | ||
82 | "pm_power_off already claimed %p %s", | ||
83 | pm_power_off, symname); | ||
84 | return -EBUSY; | ||
85 | } | ||
86 | pm_power_off = qnap_power_off; | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int qnap_power_off_remove(struct platform_device *pdev) | ||
92 | { | ||
93 | pm_power_off = NULL; | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static const struct of_device_id qnap_power_off_of_match_table[] = { | ||
98 | { .compatible = "qnap,power-off", }, | ||
99 | {} | ||
100 | }; | ||
101 | MODULE_DEVICE_TABLE(of, qnap_power_off_of_match_table); | ||
102 | |||
103 | static struct platform_driver qnap_power_off_driver = { | ||
104 | .probe = qnap_power_off_probe, | ||
105 | .remove = qnap_power_off_remove, | ||
106 | .driver = { | ||
107 | .owner = THIS_MODULE, | ||
108 | .name = "qnap_power_off", | ||
109 | .of_match_table = of_match_ptr(qnap_power_off_of_match_table), | ||
110 | }, | ||
111 | }; | ||
112 | module_platform_driver(qnap_power_off_driver); | ||
113 | |||
114 | MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>"); | ||
115 | MODULE_DESCRIPTION("QNAP Power off driver"); | ||
116 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/reset/restart-poweroff.c b/drivers/power/reset/restart-poweroff.c new file mode 100644 index 000000000000..059cd1501e2a --- /dev/null +++ b/drivers/power/reset/restart-poweroff.c | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * Power off by restarting and let u-boot keep hold of the machine | ||
3 | * until the user presses a button for example. | ||
4 | * | ||
5 | * Andrew Lunn <andrew@lunn.ch> | ||
6 | * | ||
7 | * Copyright (C) 2012 Andrew Lunn | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <asm/system_misc.h> | ||
19 | |||
20 | static void restart_poweroff_do_poweroff(void) | ||
21 | { | ||
22 | arm_pm_restart('h', NULL); | ||
23 | } | ||
24 | |||
25 | static int restart_poweroff_probe(struct platform_device *pdev) | ||
26 | { | ||
27 | /* If a pm_power_off function has already been added, leave it alone */ | ||
28 | if (pm_power_off != NULL) { | ||
29 | dev_err(&pdev->dev, | ||
30 | "pm_power_off function already registered"); | ||
31 | return -EBUSY; | ||
32 | } | ||
33 | |||
34 | pm_power_off = &restart_poweroff_do_poweroff; | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static int restart_poweroff_remove(struct platform_device *pdev) | ||
39 | { | ||
40 | if (pm_power_off == &restart_poweroff_do_poweroff) | ||
41 | pm_power_off = NULL; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static const struct of_device_id of_restart_poweroff_match[] = { | ||
47 | { .compatible = "restart-poweroff", }, | ||
48 | {}, | ||
49 | }; | ||
50 | |||
51 | static struct platform_driver restart_poweroff_driver = { | ||
52 | .probe = restart_poweroff_probe, | ||
53 | .remove = restart_poweroff_remove, | ||
54 | .driver = { | ||
55 | .name = "poweroff-restart", | ||
56 | .owner = THIS_MODULE, | ||
57 | .of_match_table = of_restart_poweroff_match, | ||
58 | }, | ||
59 | }; | ||
60 | module_platform_driver(restart_poweroff_driver); | ||
61 | |||
62 | MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch"); | ||
63 | MODULE_DESCRIPTION("restart poweroff driver"); | ||
64 | MODULE_LICENSE("GPLv2"); | ||
65 | MODULE_ALIAS("platform:poweroff-restart"); | ||
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index e53dcfeaee69..80e3b8683a84 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h | |||
@@ -131,7 +131,7 @@ struct abx500_maxim_parameters { | |||
131 | * @nominal_voltage: Nominal voltage of the battery in mV | 131 | * @nominal_voltage: Nominal voltage of the battery in mV |
132 | * @termination_vol: max voltage upto which battery can be charged | 132 | * @termination_vol: max voltage upto which battery can be charged |
133 | * @termination_curr battery charging termination current in mA | 133 | * @termination_curr battery charging termination current in mA |
134 | * @recharge_vol battery voltage limit that will trigger a new | 134 | * @recharge_cap battery capacity limit that will trigger a new |
135 | * full charging cycle in the case where maintenan- | 135 | * full charging cycle in the case where maintenan- |
136 | * -ce charging has been disabled | 136 | * -ce charging has been disabled |
137 | * @normal_cur_lvl: charger current in normal state in mA | 137 | * @normal_cur_lvl: charger current in normal state in mA |
@@ -160,7 +160,7 @@ struct abx500_battery_type { | |||
160 | int nominal_voltage; | 160 | int nominal_voltage; |
161 | int termination_vol; | 161 | int termination_vol; |
162 | int termination_curr; | 162 | int termination_curr; |
163 | int recharge_vol; | 163 | int recharge_cap; |
164 | int normal_cur_lvl; | 164 | int normal_cur_lvl; |
165 | int normal_vol_lvl; | 165 | int normal_vol_lvl; |
166 | int maint_a_cur_lvl; | 166 | int maint_a_cur_lvl; |
@@ -224,6 +224,7 @@ struct abx500_bm_charger_parameters { | |||
224 | * @bkup_bat_v voltage which we charge the backup battery with | 224 | * @bkup_bat_v voltage which we charge the backup battery with |
225 | * @bkup_bat_i current which we charge the backup battery with | 225 | * @bkup_bat_i current which we charge the backup battery with |
226 | * @no_maintenance indicates that maintenance charging is disabled | 226 | * @no_maintenance indicates that maintenance charging is disabled |
227 | * @capacity_scaling indicates whether capacity scaling is to be used | ||
227 | * @abx500_adc_therm placement of thermistor, batctrl or battemp adc | 228 | * @abx500_adc_therm placement of thermistor, batctrl or battemp adc |
228 | * @chg_unknown_bat flag to enable charging of unknown batteries | 229 | * @chg_unknown_bat flag to enable charging of unknown batteries |
229 | * @enable_overshoot flag to enable VBAT overshoot control | 230 | * @enable_overshoot flag to enable VBAT overshoot control |
@@ -253,7 +254,11 @@ struct abx500_bm_data { | |||
253 | int usb_safety_tmr_h; | 254 | int usb_safety_tmr_h; |
254 | int bkup_bat_v; | 255 | int bkup_bat_v; |
255 | int bkup_bat_i; | 256 | int bkup_bat_i; |
257 | bool autopower_cfg; | ||
258 | bool ac_enabled; | ||
259 | bool usb_enabled; | ||
256 | bool no_maintenance; | 260 | bool no_maintenance; |
261 | bool capacity_scaling; | ||
257 | bool chg_unknown_bat; | 262 | bool chg_unknown_bat; |
258 | bool enable_overshoot; | 263 | bool enable_overshoot; |
259 | bool auto_trig; | 264 | bool auto_trig; |
@@ -277,9 +282,9 @@ enum { | |||
277 | NTC_INTERNAL, | 282 | NTC_INTERNAL, |
278 | }; | 283 | }; |
279 | 284 | ||
280 | int bmdevs_of_probe(struct device *dev, | 285 | int ab8500_bm_of_probe(struct device *dev, |
281 | struct device_node *np, | 286 | struct device_node *np, |
282 | struct abx500_bm_data **battery); | 287 | struct abx500_bm_data *bm); |
283 | 288 | ||
284 | int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | 289 | int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, |
285 | u8 value); | 290 | u8 value); |
diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h index 9bd037df97d9..8d35bfe164c8 100644 --- a/include/linux/mfd/abx500/ab8500-bm.h +++ b/include/linux/mfd/abx500/ab8500-bm.h | |||
@@ -23,6 +23,7 @@ | |||
23 | * Bank : 0x5 | 23 | * Bank : 0x5 |
24 | */ | 24 | */ |
25 | #define AB8500_USB_LINE_STAT_REG 0x80 | 25 | #define AB8500_USB_LINE_STAT_REG 0x80 |
26 | #define AB8500_USB_LINK1_STAT_REG 0x94 | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * Charger / status register offfsets | 29 | * Charger / status register offfsets |
@@ -225,6 +226,8 @@ | |||
225 | /* BatCtrl Current Source Constants */ | 226 | /* BatCtrl Current Source Constants */ |
226 | #define BAT_CTRL_7U_ENA 0x01 | 227 | #define BAT_CTRL_7U_ENA 0x01 |
227 | #define BAT_CTRL_20U_ENA 0x02 | 228 | #define BAT_CTRL_20U_ENA 0x02 |
229 | #define BAT_CTRL_18U_ENA 0x01 | ||
230 | #define BAT_CTRL_16U_ENA 0x02 | ||
228 | #define BAT_CTRL_CMP_ENA 0x04 | 231 | #define BAT_CTRL_CMP_ENA 0x04 |
229 | #define FORCE_BAT_CTRL_CMP_HIGH 0x08 | 232 | #define FORCE_BAT_CTRL_CMP_HIGH 0x08 |
230 | #define BAT_CTRL_PULL_UP_ENA 0x10 | 233 | #define BAT_CTRL_PULL_UP_ENA 0x10 |
@@ -355,6 +358,7 @@ struct ab8500_bm_charger_parameters { | |||
355 | * @bkup_bat_v voltage which we charge the backup battery with | 358 | * @bkup_bat_v voltage which we charge the backup battery with |
356 | * @bkup_bat_i current which we charge the backup battery with | 359 | * @bkup_bat_i current which we charge the backup battery with |
357 | * @no_maintenance indicates that maintenance charging is disabled | 360 | * @no_maintenance indicates that maintenance charging is disabled |
361 | * @capacity_scaling indicates whether capacity scaling is to be used | ||
358 | * @adc_therm placement of thermistor, batctrl or battemp adc | 362 | * @adc_therm placement of thermistor, batctrl or battemp adc |
359 | * @chg_unknown_bat flag to enable charging of unknown batteries | 363 | * @chg_unknown_bat flag to enable charging of unknown batteries |
360 | * @enable_overshoot flag to enable VBAT overshoot control | 364 | * @enable_overshoot flag to enable VBAT overshoot control |
@@ -383,6 +387,7 @@ struct ab8500_bm_data { | |||
383 | int bkup_bat_v; | 387 | int bkup_bat_v; |
384 | int bkup_bat_i; | 388 | int bkup_bat_i; |
385 | bool no_maintenance; | 389 | bool no_maintenance; |
390 | bool capacity_scaling; | ||
386 | bool chg_unknown_bat; | 391 | bool chg_unknown_bat; |
387 | bool enable_overshoot; | 392 | bool enable_overshoot; |
388 | enum abx500_adc_therm adc_therm; | 393 | enum abx500_adc_therm adc_therm; |
@@ -399,26 +404,6 @@ struct ab8500_bm_data { | |||
399 | const struct ab8500_fg_parameters *fg_params; | 404 | const struct ab8500_fg_parameters *fg_params; |
400 | }; | 405 | }; |
401 | 406 | ||
402 | struct ab8500_charger_platform_data { | ||
403 | char **supplied_to; | ||
404 | size_t num_supplicants; | ||
405 | bool autopower_cfg; | ||
406 | }; | ||
407 | |||
408 | struct ab8500_btemp_platform_data { | ||
409 | char **supplied_to; | ||
410 | size_t num_supplicants; | ||
411 | }; | ||
412 | |||
413 | struct ab8500_fg_platform_data { | ||
414 | char **supplied_to; | ||
415 | size_t num_supplicants; | ||
416 | }; | ||
417 | |||
418 | struct ab8500_chargalg_platform_data { | ||
419 | char **supplied_to; | ||
420 | size_t num_supplicants; | ||
421 | }; | ||
422 | struct ab8500_btemp; | 407 | struct ab8500_btemp; |
423 | struct ab8500_gpadc; | 408 | struct ab8500_gpadc; |
424 | struct ab8500_fg; | 409 | struct ab8500_fg; |
@@ -434,20 +419,10 @@ struct ab8500_fg *ab8500_fg_get(void); | |||
434 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev); | 419 | int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev); |
435 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di); | 420 | int ab8500_fg_inst_curr_start(struct ab8500_fg *di); |
436 | int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res); | 421 | int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res); |
422 | int ab8500_fg_inst_curr_started(struct ab8500_fg *di); | ||
437 | int ab8500_fg_inst_curr_done(struct ab8500_fg *di); | 423 | int ab8500_fg_inst_curr_done(struct ab8500_fg *di); |
438 | 424 | ||
439 | #else | 425 | #else |
440 | static struct abx500_bm_data ab8500_bm_data; | 426 | static struct abx500_bm_data ab8500_bm_data; |
441 | |||
442 | static inline int ab8500_fg_inst_curr_start(struct ab8500_fg *di) | ||
443 | { | ||
444 | return -ENODEV; | ||
445 | } | ||
446 | |||
447 | static inline int ab8500_fg_inst_curr_finalize(struct ab8500_fg *di, int *res) | ||
448 | { | ||
449 | return -ENODEV; | ||
450 | } | ||
451 | |||
452 | #endif | 427 | #endif |
453 | #endif /* _AB8500_BM_H */ | 428 | #endif /* _AB8500_BM_H */ |
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h index 9b07725750c9..d43ac0f35526 100644 --- a/include/linux/mfd/abx500/ux500_chargalg.h +++ b/include/linux/mfd/abx500/ux500_chargalg.h | |||
@@ -27,12 +27,17 @@ struct ux500_charger_ops { | |||
27 | * @ops ux500 charger operations | 27 | * @ops ux500 charger operations |
28 | * @max_out_volt maximum output charger voltage in mV | 28 | * @max_out_volt maximum output charger voltage in mV |
29 | * @max_out_curr maximum output charger current in mA | 29 | * @max_out_curr maximum output charger current in mA |
30 | * @enabled indicates if this charger is used or not | ||
31 | * @external external charger unit (pm2xxx) | ||
30 | */ | 32 | */ |
31 | struct ux500_charger { | 33 | struct ux500_charger { |
32 | struct power_supply psy; | 34 | struct power_supply psy; |
33 | struct ux500_charger_ops ops; | 35 | struct ux500_charger_ops ops; |
34 | int max_out_volt; | 36 | int max_out_volt; |
35 | int max_out_curr; | 37 | int max_out_curr; |
38 | int wdt_refresh; | ||
39 | bool enabled; | ||
40 | bool external; | ||
36 | }; | 41 | }; |
37 | 42 | ||
38 | #endif | 43 | #endif |
diff --git a/include/linux/pm2301_charger.h b/include/linux/pm2301_charger.h new file mode 100644 index 000000000000..fc3f026922ae --- /dev/null +++ b/include/linux/pm2301_charger.h | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * PM2301 charger driver. | ||
3 | * | ||
4 | * Copyright (C) 2012 ST Ericsson Corporation | ||
5 | * | ||
6 | * Contact: Olivier LAUNAY (olivier.launay@stericsson.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #ifndef __LINUX_PM2301_H | ||
24 | #define __LINUX_PM2301_H | ||
25 | |||
26 | /** | ||
27 | * struct pm2xxx_bm_charger_parameters - Charger specific parameters | ||
28 | * @ac_volt_max: maximum allowed AC charger voltage in mV | ||
29 | * @ac_curr_max: maximum allowed AC charger current in mA | ||
30 | */ | ||
31 | struct pm2xxx_bm_charger_parameters { | ||
32 | int ac_volt_max; | ||
33 | int ac_curr_max; | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * struct pm2xxx_bm_data - pm2xxx battery management data | ||
38 | * @enable_overshoot flag to enable VBAT overshoot control | ||
39 | * @chg_params charger parameters | ||
40 | */ | ||
41 | struct pm2xxx_bm_data { | ||
42 | bool enable_overshoot; | ||
43 | const struct pm2xxx_bm_charger_parameters *chg_params; | ||
44 | }; | ||
45 | |||
46 | struct pm2xxx_charger_platform_data { | ||
47 | char **supplied_to; | ||
48 | size_t num_supplicants; | ||
49 | int i2c_bus; | ||
50 | const char *label; | ||
51 | int irq_number; | ||
52 | unsigned int lpn_gpio; | ||
53 | int irq_type; | ||
54 | }; | ||
55 | |||
56 | struct pm2xxx_platform_data { | ||
57 | struct pm2xxx_charger_platform_data *wall_charger; | ||
58 | struct pm2xxx_bm_data *battery; | ||
59 | }; | ||
60 | |||
61 | #endif /* __LINUX_PM2301_H */ | ||
diff --git a/include/linux/power/bq2415x_charger.h b/include/linux/power/bq2415x_charger.h index 97a1665eaeaf..8dcc0f46fc0a 100644 --- a/include/linux/power/bq2415x_charger.h +++ b/include/linux/power/bq2415x_charger.h | |||
@@ -75,7 +75,8 @@ | |||
75 | 75 | ||
76 | /* Supported modes with maximal current limit */ | 76 | /* Supported modes with maximal current limit */ |
77 | enum bq2415x_mode { | 77 | enum bq2415x_mode { |
78 | BQ2415X_MODE_NONE, /* unknown or no charger (100mA) */ | 78 | BQ2415X_MODE_OFF, /* offline mode (charger disabled) */ |
79 | BQ2415X_MODE_NONE, /* unknown charger (100mA) */ | ||
79 | BQ2415X_MODE_HOST_CHARGER, /* usb host/hub charger (500mA) */ | 80 | BQ2415X_MODE_HOST_CHARGER, /* usb host/hub charger (500mA) */ |
80 | BQ2415X_MODE_DEDICATED_CHARGER, /* dedicated charger (unlimited) */ | 81 | BQ2415X_MODE_DEDICATED_CHARGER, /* dedicated charger (unlimited) */ |
81 | BQ2415X_MODE_BOOST, /* boost mode (charging disabled) */ | 82 | BQ2415X_MODE_BOOST, /* boost mode (charging disabled) */ |
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 1f0ab90aff00..25c0982eb9b1 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h | |||
@@ -54,6 +54,8 @@ enum { | |||
54 | POWER_SUPPLY_HEALTH_OVERVOLTAGE, | 54 | POWER_SUPPLY_HEALTH_OVERVOLTAGE, |
55 | POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, | 55 | POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, |
56 | POWER_SUPPLY_HEALTH_COLD, | 56 | POWER_SUPPLY_HEALTH_COLD, |
57 | POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE, | ||
58 | POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | enum { | 61 | enum { |