diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 15:28:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 15:28:15 -0500 |
commit | 400c5bd5a5b1faf3089322ace58b974446a8ddc3 (patch) | |
tree | 78594fc5e426c68b322adc11bd62a417267811eb /drivers/power | |
parent | 9bd9fa6c147e68fc4dc3b35893979720ba7d0321 (diff) | |
parent | 6bd03ce3c12a22d86f59070f1da15aaa2bde8a51 (diff) |
Merge tag 'for-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel:
- new AXP20X USB Power driver
- new Qualcomm SMBB driver
- new TPS65217 Charger driver
- BQ24257: add BQ24250/BQ24251 support
- overhaul bq27x00 battery driver, rename to bq27xxx
- misc fixes and cleanups
* tag 'for-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (54 commits)
power: bq27xxx_battery: Remove unneeded dependency in Kconfig
power: bq27xxx_battery: move irq handler to i2c section
power: bq27xxx_battery: fix platform probe
twl4030_charger: add missing iio dependency
power_supply: charger-manager: add missing of_node_put
Documentation: power: bq24257: Document exported sysfs entries
power: bq24257: Add various device-specific sysfs properties
power: bq24257: Allow input current limit sysfs access
power: bq24257: Add input DPM voltage threshold setting support
power: bq24257: Add over voltage protection setting support
power: bq24257: Add SW-based approach for Power Good determination
power: bq24257: Allow manual setting of input current limit
power: bq24257: Add bit definition for temp sense enable
power: bq24257: Add basic support for bq24250/bq24251
dt: power: bq24257-charger: Cover additional devices
power: bq24257: Simplify bq24257_power_supply_init()
power: bq24257: Use managed power supply register
power: bq24257: Streamline input current limit setup
power: bq24257: Remove IRQ config through stat-gpios
power: bq27xxx_battery: fix signedness bug in bq27xxx_battery_read_health()
...
Diffstat (limited to 'drivers/power')
25 files changed, 3467 insertions, 1440 deletions
diff --git a/drivers/power/88pm860x_battery.c b/drivers/power/88pm860x_battery.c index d49579b227ec..63c57dc82ac1 100644 --- a/drivers/power/88pm860x_battery.c +++ b/drivers/power/88pm860x_battery.c | |||
@@ -954,47 +954,33 @@ static int pm860x_battery_probe(struct platform_device *pdev) | |||
954 | else | 954 | else |
955 | info->resistor = 300; /* set default internal resistor */ | 955 | info->resistor = 300; /* set default internal resistor */ |
956 | 956 | ||
957 | info->battery = power_supply_register(&pdev->dev, &pm860x_battery_desc, | 957 | info->battery = devm_power_supply_register(&pdev->dev, |
958 | NULL); | 958 | &pm860x_battery_desc, |
959 | NULL); | ||
959 | if (IS_ERR(info->battery)) | 960 | if (IS_ERR(info->battery)) |
960 | return PTR_ERR(info->battery); | 961 | return PTR_ERR(info->battery); |
961 | info->battery->dev.parent = &pdev->dev; | 962 | info->battery->dev.parent = &pdev->dev; |
962 | 963 | ||
963 | ret = request_threaded_irq(info->irq_cc, NULL, | 964 | ret = devm_request_threaded_irq(chip->dev, info->irq_cc, NULL, |
964 | pm860x_coulomb_handler, IRQF_ONESHOT, | 965 | pm860x_coulomb_handler, IRQF_ONESHOT, |
965 | "coulomb", info); | 966 | "coulomb", info); |
966 | if (ret < 0) { | 967 | if (ret < 0) { |
967 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | 968 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", |
968 | info->irq_cc, ret); | 969 | info->irq_cc, ret); |
969 | goto out_reg; | 970 | return ret; |
970 | } | 971 | } |
971 | 972 | ||
972 | ret = request_threaded_irq(info->irq_batt, NULL, pm860x_batt_handler, | 973 | ret = devm_request_threaded_irq(chip->dev, info->irq_batt, NULL, |
973 | IRQF_ONESHOT, "battery", info); | 974 | pm860x_batt_handler, |
975 | IRQF_ONESHOT, "battery", info); | ||
974 | if (ret < 0) { | 976 | if (ret < 0) { |
975 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | 977 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", |
976 | info->irq_batt, ret); | 978 | info->irq_batt, ret); |
977 | goto out_coulomb; | 979 | return ret; |
978 | } | 980 | } |
979 | 981 | ||
980 | 982 | ||
981 | return 0; | 983 | return 0; |
982 | |||
983 | out_coulomb: | ||
984 | free_irq(info->irq_cc, info); | ||
985 | out_reg: | ||
986 | power_supply_unregister(info->battery); | ||
987 | return ret; | ||
988 | } | ||
989 | |||
990 | static int pm860x_battery_remove(struct platform_device *pdev) | ||
991 | { | ||
992 | struct pm860x_battery_info *info = platform_get_drvdata(pdev); | ||
993 | |||
994 | free_irq(info->irq_batt, info); | ||
995 | free_irq(info->irq_cc, info); | ||
996 | power_supply_unregister(info->battery); | ||
997 | return 0; | ||
998 | } | 984 | } |
999 | 985 | ||
1000 | #ifdef CONFIG_PM_SLEEP | 986 | #ifdef CONFIG_PM_SLEEP |
@@ -1028,7 +1014,6 @@ static struct platform_driver pm860x_battery_driver = { | |||
1028 | .pm = &pm860x_battery_pm_ops, | 1014 | .pm = &pm860x_battery_pm_ops, |
1029 | }, | 1015 | }, |
1030 | .probe = pm860x_battery_probe, | 1016 | .probe = pm860x_battery_probe, |
1031 | .remove = pm860x_battery_remove, | ||
1032 | }; | 1017 | }; |
1033 | module_platform_driver(pm860x_battery_driver); | 1018 | module_platform_driver(pm860x_battery_driver); |
1034 | 1019 | ||
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f8758d6febf8..02b3b313809a 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -157,26 +157,25 @@ config BATTERY_SBS | |||
157 | Say Y to include support for SBS battery driver for SBS-compliant | 157 | Say Y to include support for SBS battery driver for SBS-compliant |
158 | gas gauges. | 158 | gas gauges. |
159 | 159 | ||
160 | config BATTERY_BQ27x00 | 160 | config BATTERY_BQ27XXX |
161 | tristate "BQ27x00 battery driver" | 161 | tristate "BQ27xxx battery driver" |
162 | depends on I2C || I2C=n | ||
163 | help | 162 | help |
164 | Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips. | 163 | Say Y here to enable support for batteries with BQ27xxx (I2C/HDQ) chips. |
165 | 164 | ||
166 | config BATTERY_BQ27X00_I2C | 165 | config BATTERY_BQ27XXX_I2C |
167 | bool "BQ27200/BQ27500 support" | 166 | bool "BQ27xxx I2C support" |
168 | depends on BATTERY_BQ27x00 | 167 | depends on BATTERY_BQ27XXX |
169 | depends on I2C | 168 | depends on I2C |
170 | default y | 169 | default y |
171 | help | 170 | help |
172 | Say Y here to enable support for batteries with BQ27x00 (I2C) chips. | 171 | Say Y here to enable support for batteries with BQ27xxx (I2C) chips. |
173 | 172 | ||
174 | config BATTERY_BQ27X00_PLATFORM | 173 | config BATTERY_BQ27XXX_PLATFORM |
175 | bool "BQ27000 support" | 174 | bool "BQ27xxx HDQ support" |
176 | depends on BATTERY_BQ27x00 | 175 | depends on BATTERY_BQ27XXX |
177 | default y | 176 | default y |
178 | help | 177 | help |
179 | Say Y here to enable support for batteries with BQ27000 (HDQ) chips. | 178 | Say Y here to enable support for batteries with BQ27xxx (HDQ) chips. |
180 | 179 | ||
181 | config BATTERY_DA9030 | 180 | config BATTERY_DA9030 |
182 | tristate "DA9030 battery driver" | 181 | tristate "DA9030 battery driver" |
@@ -313,7 +312,7 @@ config CHARGER_MAX8903 | |||
313 | 312 | ||
314 | config CHARGER_TWL4030 | 313 | config CHARGER_TWL4030 |
315 | tristate "OMAP TWL4030 BCI charger driver" | 314 | tristate "OMAP TWL4030 BCI charger driver" |
316 | depends on TWL4030_CORE | 315 | depends on IIO && TWL4030_CORE |
317 | help | 316 | help |
318 | Say Y here to enable support for TWL4030 Battery Charge Interface. | 317 | Say Y here to enable support for TWL4030 Battery Charge Interface. |
319 | 318 | ||
@@ -379,6 +378,18 @@ config CHARGER_MAX8998 | |||
379 | Say Y to enable support for the battery charger control sysfs and | 378 | Say Y to enable support for the battery charger control sysfs and |
380 | platform data of MAX8998/LP3974 PMICs. | 379 | platform data of MAX8998/LP3974 PMICs. |
381 | 380 | ||
381 | config CHARGER_QCOM_SMBB | ||
382 | tristate "Qualcomm Switch-Mode Battery Charger and Boost" | ||
383 | depends on MFD_SPMI_PMIC || COMPILE_TEST | ||
384 | depends on OF | ||
385 | help | ||
386 | Say Y to include support for the Switch-Mode Battery Charger and | ||
387 | Boost (SMBB) hardware found in Qualcomm PM8941 PMICs. The charger | ||
388 | is an integrated, single-cell lithium-ion battery charger. DT | ||
389 | configuration is required for loading, see the devicetree | ||
390 | documentation for more detail. The base name for this driver is | ||
391 | 'pm8941_charger'. | ||
392 | |||
382 | config CHARGER_BQ2415X | 393 | config CHARGER_BQ2415X |
383 | tristate "TI BQ2415x battery charger driver" | 394 | tristate "TI BQ2415x battery charger driver" |
384 | depends on I2C | 395 | depends on I2C |
@@ -397,12 +408,13 @@ config CHARGER_BQ24190 | |||
397 | Say Y to enable support for the TI BQ24190 battery charger. | 408 | Say Y to enable support for the TI BQ24190 battery charger. |
398 | 409 | ||
399 | config CHARGER_BQ24257 | 410 | config CHARGER_BQ24257 |
400 | tristate "TI BQ24257 battery charger driver" | 411 | tristate "TI BQ24250/24251/24257 battery charger driver" |
401 | depends on I2C | 412 | depends on I2C |
402 | depends on GPIOLIB || COMPILE_TEST | 413 | depends on GPIOLIB || COMPILE_TEST |
403 | depends on REGMAP_I2C | 414 | depends on REGMAP_I2C |
404 | help | 415 | help |
405 | Say Y to enable support for the TI BQ24257 battery charger. | 416 | Say Y to enable support for the TI BQ24250, BQ24251, and BQ24257 battery |
417 | chargers. | ||
406 | 418 | ||
407 | config CHARGER_BQ24735 | 419 | config CHARGER_BQ24735 |
408 | tristate "TI BQ24735 battery charger support" | 420 | tristate "TI BQ24735 battery charger support" |
@@ -434,6 +446,13 @@ config CHARGER_TPS65090 | |||
434 | Say Y here to enable support for battery charging with TPS65090 | 446 | Say Y here to enable support for battery charging with TPS65090 |
435 | PMIC chips. | 447 | PMIC chips. |
436 | 448 | ||
449 | config CHARGER_TPS65217 | ||
450 | tristate "TPS65217 battery charger driver" | ||
451 | depends on MFD_TPS65217 | ||
452 | help | ||
453 | Say Y here to enable support for battery charging with TPS65217 | ||
454 | PMIC chips. | ||
455 | |||
437 | config BATTERY_GAUGE_LTC2941 | 456 | config BATTERY_GAUGE_LTC2941 |
438 | tristate "LTC2941/LTC2943 Battery Gauge Driver" | 457 | tristate "LTC2941/LTC2943 Battery Gauge Driver" |
439 | depends on I2C | 458 | depends on I2C |
@@ -472,6 +491,13 @@ config CHARGER_RT9455 | |||
472 | help | 491 | help |
473 | Say Y to enable support for Richtek RT9455 battery charger. | 492 | Say Y to enable support for Richtek RT9455 battery charger. |
474 | 493 | ||
494 | config AXP20X_POWER | ||
495 | tristate "AXP20x power supply driver" | ||
496 | depends on MFD_AXP20X | ||
497 | help | ||
498 | This driver provides support for the power supply features of | ||
499 | AXP20x PMIC. | ||
500 | |||
475 | source "drivers/power/reset/Kconfig" | 501 | source "drivers/power/reset/Kconfig" |
476 | 502 | ||
477 | endif # POWER_SUPPLY | 503 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 5752ce818f51..b0e1bf190e3d 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o | |||
9 | 9 | ||
10 | obj-$(CONFIG_PDA_POWER) += pda_power.o | 10 | obj-$(CONFIG_PDA_POWER) += pda_power.o |
11 | obj-$(CONFIG_APM_POWER) += apm_power.o | 11 | obj-$(CONFIG_APM_POWER) += apm_power.o |
12 | obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o | ||
12 | obj-$(CONFIG_MAX8925_POWER) += max8925_power.o | 13 | obj-$(CONFIG_MAX8925_POWER) += max8925_power.o |
13 | obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o | 14 | obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o |
14 | obj-$(CONFIG_WM831X_POWER) += wm831x_power.o | 15 | obj-$(CONFIG_WM831X_POWER) += wm831x_power.o |
@@ -29,7 +30,7 @@ obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o | |||
29 | obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o | 30 | obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o |
30 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o | 31 | obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o |
31 | obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o | 32 | obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o |
32 | obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o | 33 | obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o |
33 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o | 34 | obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o |
34 | obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o | 35 | obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o |
35 | obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o | 36 | obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o |
@@ -57,6 +58,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o | |||
57 | obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o | 58 | obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o |
58 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 59 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
59 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 60 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
61 | obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o | ||
60 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 62 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o |
61 | obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o | 63 | obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o |
62 | obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o | 64 | obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o |
@@ -65,6 +67,7 @@ obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o | |||
65 | obj-$(CONFIG_POWER_AVS) += avs/ | 67 | obj-$(CONFIG_POWER_AVS) += avs/ |
66 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o | 68 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o |
67 | obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o | 69 | obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o |
70 | obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o | ||
68 | obj-$(CONFIG_POWER_RESET) += reset/ | 71 | obj-$(CONFIG_POWER_RESET) += reset/ |
69 | obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o | 72 | obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o |
70 | obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o | 73 | obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o |
diff --git a/drivers/power/axp20x_usb_power.c b/drivers/power/axp20x_usb_power.c new file mode 100644 index 000000000000..421a90b83567 --- /dev/null +++ b/drivers/power/axp20x_usb_power.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * AXP20x PMIC USB power supply status driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com> | ||
5 | * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mfd/axp20x.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/power_supply.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | #define DRVNAME "axp20x-usb-power-supply" | ||
26 | |||
27 | #define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5) | ||
28 | #define AXP20X_PWR_STATUS_VBUS_USED BIT(4) | ||
29 | |||
30 | #define AXP20X_USB_STATUS_VBUS_VALID BIT(2) | ||
31 | |||
32 | #define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000) | ||
33 | #define AXP20X_VBUS_CLIMIT_MASK 3 | ||
34 | #define AXP20X_VBUC_CLIMIT_900mA 0 | ||
35 | #define AXP20X_VBUC_CLIMIT_500mA 1 | ||
36 | #define AXP20X_VBUC_CLIMIT_100mA 2 | ||
37 | #define AXP20X_VBUC_CLIMIT_NONE 3 | ||
38 | |||
39 | #define AXP20X_ADC_EN1_VBUS_CURR BIT(2) | ||
40 | #define AXP20X_ADC_EN1_VBUS_VOLT BIT(3) | ||
41 | |||
42 | #define AXP20X_VBUS_MON_VBUS_VALID BIT(3) | ||
43 | |||
44 | struct axp20x_usb_power { | ||
45 | struct regmap *regmap; | ||
46 | struct power_supply *supply; | ||
47 | }; | ||
48 | |||
49 | static irqreturn_t axp20x_usb_power_irq(int irq, void *devid) | ||
50 | { | ||
51 | struct axp20x_usb_power *power = devid; | ||
52 | |||
53 | power_supply_changed(power->supply); | ||
54 | |||
55 | return IRQ_HANDLED; | ||
56 | } | ||
57 | |||
58 | static int axp20x_usb_power_get_property(struct power_supply *psy, | ||
59 | enum power_supply_property psp, union power_supply_propval *val) | ||
60 | { | ||
61 | struct axp20x_usb_power *power = power_supply_get_drvdata(psy); | ||
62 | unsigned int input, v; | ||
63 | int ret; | ||
64 | |||
65 | switch (psp) { | ||
66 | case POWER_SUPPLY_PROP_VOLTAGE_MIN: | ||
67 | ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); | ||
68 | if (ret) | ||
69 | return ret; | ||
70 | |||
71 | val->intval = AXP20X_VBUS_VHOLD_uV(v); | ||
72 | return 0; | ||
73 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
74 | ret = axp20x_read_variable_width(power->regmap, | ||
75 | AXP20X_VBUS_V_ADC_H, 12); | ||
76 | if (ret < 0) | ||
77 | return ret; | ||
78 | |||
79 | val->intval = ret * 1700; /* 1 step = 1.7 mV */ | ||
80 | return 0; | ||
81 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
82 | ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | switch (v & AXP20X_VBUS_CLIMIT_MASK) { | ||
87 | case AXP20X_VBUC_CLIMIT_100mA: | ||
88 | val->intval = 100000; | ||
89 | break; | ||
90 | case AXP20X_VBUC_CLIMIT_500mA: | ||
91 | val->intval = 500000; | ||
92 | break; | ||
93 | case AXP20X_VBUC_CLIMIT_900mA: | ||
94 | val->intval = 900000; | ||
95 | break; | ||
96 | case AXP20X_VBUC_CLIMIT_NONE: | ||
97 | val->intval = -1; | ||
98 | break; | ||
99 | } | ||
100 | return 0; | ||
101 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
102 | ret = axp20x_read_variable_width(power->regmap, | ||
103 | AXP20X_VBUS_I_ADC_H, 12); | ||
104 | if (ret < 0) | ||
105 | return ret; | ||
106 | |||
107 | val->intval = ret * 375; /* 1 step = 0.375 mA */ | ||
108 | return 0; | ||
109 | default: | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | /* All the properties below need the input-status reg value */ | ||
114 | ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input); | ||
115 | if (ret) | ||
116 | return ret; | ||
117 | |||
118 | switch (psp) { | ||
119 | case POWER_SUPPLY_PROP_HEALTH: | ||
120 | if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) { | ||
121 | val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) { | ||
130 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
131 | break; | ||
132 | } | ||
133 | |||
134 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
135 | break; | ||
136 | case POWER_SUPPLY_PROP_PRESENT: | ||
137 | val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT); | ||
138 | break; | ||
139 | case POWER_SUPPLY_PROP_ONLINE: | ||
140 | val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED); | ||
141 | break; | ||
142 | default: | ||
143 | return -EINVAL; | ||
144 | } | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static enum power_supply_property axp20x_usb_power_properties[] = { | ||
150 | POWER_SUPPLY_PROP_HEALTH, | ||
151 | POWER_SUPPLY_PROP_PRESENT, | ||
152 | POWER_SUPPLY_PROP_ONLINE, | ||
153 | POWER_SUPPLY_PROP_VOLTAGE_MIN, | ||
154 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
155 | POWER_SUPPLY_PROP_CURRENT_MAX, | ||
156 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
157 | }; | ||
158 | |||
159 | static const struct power_supply_desc axp20x_usb_power_desc = { | ||
160 | .name = "axp20x-usb", | ||
161 | .type = POWER_SUPPLY_TYPE_USB, | ||
162 | .properties = axp20x_usb_power_properties, | ||
163 | .num_properties = ARRAY_SIZE(axp20x_usb_power_properties), | ||
164 | .get_property = axp20x_usb_power_get_property, | ||
165 | }; | ||
166 | |||
167 | static int axp20x_usb_power_probe(struct platform_device *pdev) | ||
168 | { | ||
169 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); | ||
170 | struct power_supply_config psy_cfg = {}; | ||
171 | struct axp20x_usb_power *power; | ||
172 | static const char * const irq_names[] = { "VBUS_PLUGIN", | ||
173 | "VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" }; | ||
174 | int i, irq, ret; | ||
175 | |||
176 | if (!of_device_is_available(pdev->dev.of_node)) | ||
177 | return -ENODEV; | ||
178 | |||
179 | if (!axp20x) { | ||
180 | dev_err(&pdev->dev, "Parent drvdata not set\n"); | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | |||
184 | power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL); | ||
185 | if (!power) | ||
186 | return -ENOMEM; | ||
187 | |||
188 | power->regmap = axp20x->regmap; | ||
189 | |||
190 | /* Enable vbus valid checking */ | ||
191 | ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON, | ||
192 | AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID); | ||
193 | if (ret) | ||
194 | return ret; | ||
195 | |||
196 | /* Enable vbus voltage and current measurement */ | ||
197 | ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1, | ||
198 | AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT, | ||
199 | AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | |||
203 | psy_cfg.of_node = pdev->dev.of_node; | ||
204 | psy_cfg.drv_data = power; | ||
205 | |||
206 | power->supply = devm_power_supply_register(&pdev->dev, | ||
207 | &axp20x_usb_power_desc, &psy_cfg); | ||
208 | if (IS_ERR(power->supply)) | ||
209 | return PTR_ERR(power->supply); | ||
210 | |||
211 | /* Request irqs after registering, as irqs may trigger immediately */ | ||
212 | for (i = 0; i < ARRAY_SIZE(irq_names); i++) { | ||
213 | irq = platform_get_irq_byname(pdev, irq_names[i]); | ||
214 | if (irq < 0) { | ||
215 | dev_warn(&pdev->dev, "No IRQ for %s: %d\n", | ||
216 | irq_names[i], irq); | ||
217 | continue; | ||
218 | } | ||
219 | irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq); | ||
220 | ret = devm_request_any_context_irq(&pdev->dev, irq, | ||
221 | axp20x_usb_power_irq, 0, DRVNAME, power); | ||
222 | if (ret < 0) | ||
223 | dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n", | ||
224 | irq_names[i], ret); | ||
225 | } | ||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static const struct of_device_id axp20x_usb_power_match[] = { | ||
231 | { .compatible = "x-powers,axp202-usb-power-supply" }, | ||
232 | { } | ||
233 | }; | ||
234 | MODULE_DEVICE_TABLE(of, axp20x_usb_power_match); | ||
235 | |||
236 | static struct platform_driver axp20x_usb_power_driver = { | ||
237 | .probe = axp20x_usb_power_probe, | ||
238 | .driver = { | ||
239 | .name = DRVNAME, | ||
240 | .of_match_table = axp20x_usb_power_match, | ||
241 | }, | ||
242 | }; | ||
243 | |||
244 | module_platform_driver(axp20x_usb_power_driver); | ||
245 | |||
246 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | ||
247 | MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver"); | ||
248 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c index ec212b5be755..4afd76848bce 100644 --- a/drivers/power/bq2415x_charger.c +++ b/drivers/power/bq2415x_charger.c | |||
@@ -1704,7 +1704,7 @@ error_4: | |||
1704 | error_3: | 1704 | error_3: |
1705 | bq2415x_power_supply_exit(bq); | 1705 | bq2415x_power_supply_exit(bq); |
1706 | error_2: | 1706 | error_2: |
1707 | if (bq->notify_node) | 1707 | if (bq && bq->notify_node) |
1708 | of_node_put(bq->notify_node); | 1708 | of_node_put(bq->notify_node); |
1709 | kfree(name); | 1709 | kfree(name); |
1710 | error_1: | 1710 | error_1: |
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c index 469a452cbe10..f5746b9f4e83 100644 --- a/drivers/power/bq24190_charger.c +++ b/drivers/power/bq24190_charger.c | |||
@@ -1543,5 +1543,4 @@ module_i2c_driver(bq24190_driver); | |||
1543 | 1543 | ||
1544 | MODULE_LICENSE("GPL"); | 1544 | MODULE_LICENSE("GPL"); |
1545 | MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>"); | 1545 | MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>"); |
1546 | MODULE_ALIAS("i2c:bq24190-charger"); | ||
1547 | MODULE_DESCRIPTION("TI BQ24190 Charger Driver"); | 1546 | MODULE_DESCRIPTION("TI BQ24190 Charger Driver"); |
diff --git a/drivers/power/bq24257_charger.c b/drivers/power/bq24257_charger.c index 5859bc7c1616..1fea2c7ef97f 100644 --- a/drivers/power/bq24257_charger.c +++ b/drivers/power/bq24257_charger.c | |||
@@ -13,6 +13,10 @@ | |||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * Datasheets: | ||
17 | * http://www.ti.com/product/bq24250 | ||
18 | * http://www.ti.com/product/bq24251 | ||
19 | * http://www.ti.com/product/bq24257 | ||
16 | */ | 20 | */ |
17 | 21 | ||
18 | #include <linux/module.h> | 22 | #include <linux/module.h> |
@@ -36,18 +40,33 @@ | |||
36 | #define BQ24257_REG_7 0x06 | 40 | #define BQ24257_REG_7 0x06 |
37 | 41 | ||
38 | #define BQ24257_MANUFACTURER "Texas Instruments" | 42 | #define BQ24257_MANUFACTURER "Texas Instruments" |
39 | #define BQ24257_STAT_IRQ "stat" | ||
40 | #define BQ24257_PG_GPIO "pg" | 43 | #define BQ24257_PG_GPIO "pg" |
41 | 44 | ||
42 | #define BQ24257_ILIM_SET_DELAY 1000 /* msec */ | 45 | #define BQ24257_ILIM_SET_DELAY 1000 /* msec */ |
43 | 46 | ||
47 | /* | ||
48 | * When adding support for new devices make sure that enum bq2425x_chip and | ||
49 | * bq2425x_chip_name[] always stay in sync! | ||
50 | */ | ||
51 | enum bq2425x_chip { | ||
52 | BQ24250, | ||
53 | BQ24251, | ||
54 | BQ24257, | ||
55 | }; | ||
56 | |||
57 | static const char *const bq2425x_chip_name[] = { | ||
58 | "bq24250", | ||
59 | "bq24251", | ||
60 | "bq24257", | ||
61 | }; | ||
62 | |||
44 | enum bq24257_fields { | 63 | enum bq24257_fields { |
45 | F_WD_FAULT, F_WD_EN, F_STAT, F_FAULT, /* REG 1 */ | 64 | F_WD_FAULT, F_WD_EN, F_STAT, F_FAULT, /* REG 1 */ |
46 | F_RESET, F_IILIMIT, F_EN_STAT, F_EN_TERM, F_CE, F_HZ_MODE, /* REG 2 */ | 65 | F_RESET, F_IILIMIT, F_EN_STAT, F_EN_TERM, F_CE, F_HZ_MODE, /* REG 2 */ |
47 | F_VBAT, F_USB_DET, /* REG 3 */ | 66 | F_VBAT, F_USB_DET, /* REG 3 */ |
48 | F_ICHG, F_ITERM, /* REG 4 */ | 67 | F_ICHG, F_ITERM, /* REG 4 */ |
49 | F_LOOP_STATUS, F_LOW_CHG, F_DPDM_EN, F_CE_STATUS, F_VINDPM, /* REG 5 */ | 68 | F_LOOP_STATUS, F_LOW_CHG, F_DPDM_EN, F_CE_STATUS, F_VINDPM, /* REG 5 */ |
50 | F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_STAT, /* REG 6 */ | 69 | F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_EN, F_TS_STAT, /* REG 6 */ |
51 | F_VOVP, F_CLR_VDP, F_FORCE_BATDET, F_FORCE_PTM, /* REG 7 */ | 70 | F_VOVP, F_CLR_VDP, F_FORCE_BATDET, F_FORCE_PTM, /* REG 7 */ |
52 | 71 | ||
53 | F_MAX_FIELDS | 72 | F_MAX_FIELDS |
@@ -58,6 +77,9 @@ struct bq24257_init_data { | |||
58 | u8 ichg; /* charge current */ | 77 | u8 ichg; /* charge current */ |
59 | u8 vbat; /* regulation voltage */ | 78 | u8 vbat; /* regulation voltage */ |
60 | u8 iterm; /* termination current */ | 79 | u8 iterm; /* termination current */ |
80 | u8 iilimit; /* input current limit */ | ||
81 | u8 vovp; /* over voltage protection voltage */ | ||
82 | u8 vindpm; /* VDMP input threshold voltage */ | ||
61 | }; | 83 | }; |
62 | 84 | ||
63 | struct bq24257_state { | 85 | struct bq24257_state { |
@@ -71,6 +93,8 @@ struct bq24257_device { | |||
71 | struct device *dev; | 93 | struct device *dev; |
72 | struct power_supply *charger; | 94 | struct power_supply *charger; |
73 | 95 | ||
96 | enum bq2425x_chip chip; | ||
97 | |||
74 | struct regmap *rmap; | 98 | struct regmap *rmap; |
75 | struct regmap_field *rmap_fields[F_MAX_FIELDS]; | 99 | struct regmap_field *rmap_fields[F_MAX_FIELDS]; |
76 | 100 | ||
@@ -82,6 +106,8 @@ struct bq24257_device { | |||
82 | struct bq24257_state state; | 106 | struct bq24257_state state; |
83 | 107 | ||
84 | struct mutex lock; /* protect state data */ | 108 | struct mutex lock; /* protect state data */ |
109 | |||
110 | bool iilimit_autoset_enable; | ||
85 | }; | 111 | }; |
86 | 112 | ||
87 | static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg) | 113 | static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg) |
@@ -135,6 +161,7 @@ static const struct reg_field bq24257_reg_fields[] = { | |||
135 | [F_X2_TMR_EN] = REG_FIELD(BQ24257_REG_6, 7, 7), | 161 | [F_X2_TMR_EN] = REG_FIELD(BQ24257_REG_6, 7, 7), |
136 | [F_TMR] = REG_FIELD(BQ24257_REG_6, 5, 6), | 162 | [F_TMR] = REG_FIELD(BQ24257_REG_6, 5, 6), |
137 | [F_SYSOFF] = REG_FIELD(BQ24257_REG_6, 4, 4), | 163 | [F_SYSOFF] = REG_FIELD(BQ24257_REG_6, 4, 4), |
164 | [F_TS_EN] = REG_FIELD(BQ24257_REG_6, 3, 3), | ||
138 | [F_TS_STAT] = REG_FIELD(BQ24257_REG_6, 0, 2), | 165 | [F_TS_STAT] = REG_FIELD(BQ24257_REG_6, 0, 2), |
139 | /* REG 7 */ | 166 | /* REG 7 */ |
140 | [F_VOVP] = REG_FIELD(BQ24257_REG_7, 5, 7), | 167 | [F_VOVP] = REG_FIELD(BQ24257_REG_7, 5, 7), |
@@ -169,6 +196,26 @@ static const u32 bq24257_iterm_map[] = { | |||
169 | 196 | ||
170 | #define BQ24257_ITERM_MAP_SIZE ARRAY_SIZE(bq24257_iterm_map) | 197 | #define BQ24257_ITERM_MAP_SIZE ARRAY_SIZE(bq24257_iterm_map) |
171 | 198 | ||
199 | static const u32 bq24257_iilimit_map[] = { | ||
200 | 100000, 150000, 500000, 900000, 1500000, 2000000 | ||
201 | }; | ||
202 | |||
203 | #define BQ24257_IILIMIT_MAP_SIZE ARRAY_SIZE(bq24257_iilimit_map) | ||
204 | |||
205 | static const u32 bq24257_vovp_map[] = { | ||
206 | 6000000, 6500000, 7000000, 8000000, 9000000, 9500000, 10000000, | ||
207 | 10500000 | ||
208 | }; | ||
209 | |||
210 | #define BQ24257_VOVP_MAP_SIZE ARRAY_SIZE(bq24257_vovp_map) | ||
211 | |||
212 | static const u32 bq24257_vindpm_map[] = { | ||
213 | 4200000, 4280000, 4360000, 4440000, 4520000, 4600000, 4680000, | ||
214 | 4760000 | ||
215 | }; | ||
216 | |||
217 | #define BQ24257_VINDPM_MAP_SIZE ARRAY_SIZE(bq24257_vindpm_map) | ||
218 | |||
172 | static int bq24257_field_read(struct bq24257_device *bq, | 219 | static int bq24257_field_read(struct bq24257_device *bq, |
173 | enum bq24257_fields field_id) | 220 | enum bq24257_fields field_id) |
174 | { | 221 | { |
@@ -220,6 +267,47 @@ enum bq24257_fault { | |||
220 | FAULT_INPUT_LDO_LOW, | 267 | FAULT_INPUT_LDO_LOW, |
221 | }; | 268 | }; |
222 | 269 | ||
270 | static int bq24257_get_input_current_limit(struct bq24257_device *bq, | ||
271 | union power_supply_propval *val) | ||
272 | { | ||
273 | int ret; | ||
274 | |||
275 | ret = bq24257_field_read(bq, F_IILIMIT); | ||
276 | if (ret < 0) | ||
277 | return ret; | ||
278 | |||
279 | /* | ||
280 | * The "External ILIM" and "Production & Test" modes are not exposed | ||
281 | * through this driver and not being covered by the lookup table. | ||
282 | * Should such a mode have become active let's return an error rather | ||
283 | * than exceeding the bounds of the lookup table and returning | ||
284 | * garbage. | ||
285 | */ | ||
286 | if (ret >= BQ24257_IILIMIT_MAP_SIZE) | ||
287 | return -ENODATA; | ||
288 | |||
289 | val->intval = bq24257_iilimit_map[ret]; | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int bq24257_set_input_current_limit(struct bq24257_device *bq, | ||
295 | const union power_supply_propval *val) | ||
296 | { | ||
297 | /* | ||
298 | * Address the case where the user manually sets an input current limit | ||
299 | * while the charger auto-detection mechanism is is active. In this | ||
300 | * case we want to abort and go straight to the user-specified value. | ||
301 | */ | ||
302 | if (bq->iilimit_autoset_enable) | ||
303 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
304 | |||
305 | return bq24257_field_write(bq, F_IILIMIT, | ||
306 | bq24257_find_idx(val->intval, | ||
307 | bq24257_iilimit_map, | ||
308 | BQ24257_IILIMIT_MAP_SIZE)); | ||
309 | } | ||
310 | |||
223 | static int bq24257_power_supply_get_property(struct power_supply *psy, | 311 | static int bq24257_power_supply_get_property(struct power_supply *psy, |
224 | enum power_supply_property psp, | 312 | enum power_supply_property psp, |
225 | union power_supply_propval *val) | 313 | union power_supply_propval *val) |
@@ -249,6 +337,10 @@ static int bq24257_power_supply_get_property(struct power_supply *psy, | |||
249 | val->strval = BQ24257_MANUFACTURER; | 337 | val->strval = BQ24257_MANUFACTURER; |
250 | break; | 338 | break; |
251 | 339 | ||
340 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
341 | val->strval = bq2425x_chip_name[bq->chip]; | ||
342 | break; | ||
343 | |||
252 | case POWER_SUPPLY_PROP_ONLINE: | 344 | case POWER_SUPPLY_PROP_ONLINE: |
253 | val->intval = state.power_good; | 345 | val->intval = state.power_good; |
254 | break; | 346 | break; |
@@ -300,6 +392,9 @@ static int bq24257_power_supply_get_property(struct power_supply *psy, | |||
300 | val->intval = bq24257_iterm_map[bq->init_data.iterm]; | 392 | val->intval = bq24257_iterm_map[bq->init_data.iterm]; |
301 | break; | 393 | break; |
302 | 394 | ||
395 | case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: | ||
396 | return bq24257_get_input_current_limit(bq, val); | ||
397 | |||
303 | default: | 398 | default: |
304 | return -EINVAL; | 399 | return -EINVAL; |
305 | } | 400 | } |
@@ -307,6 +402,31 @@ static int bq24257_power_supply_get_property(struct power_supply *psy, | |||
307 | return 0; | 402 | return 0; |
308 | } | 403 | } |
309 | 404 | ||
405 | static int bq24257_power_supply_set_property(struct power_supply *psy, | ||
406 | enum power_supply_property prop, | ||
407 | const union power_supply_propval *val) | ||
408 | { | ||
409 | struct bq24257_device *bq = power_supply_get_drvdata(psy); | ||
410 | |||
411 | switch (prop) { | ||
412 | case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: | ||
413 | return bq24257_set_input_current_limit(bq, val); | ||
414 | default: | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | static int bq24257_power_supply_property_is_writeable(struct power_supply *psy, | ||
420 | enum power_supply_property psp) | ||
421 | { | ||
422 | switch (psp) { | ||
423 | case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT: | ||
424 | return true; | ||
425 | default: | ||
426 | return false; | ||
427 | } | ||
428 | } | ||
429 | |||
310 | static int bq24257_get_chip_state(struct bq24257_device *bq, | 430 | static int bq24257_get_chip_state(struct bq24257_device *bq, |
311 | struct bq24257_state *state) | 431 | struct bq24257_state *state) |
312 | { | 432 | { |
@@ -324,7 +444,26 @@ static int bq24257_get_chip_state(struct bq24257_device *bq, | |||
324 | 444 | ||
325 | state->fault = ret; | 445 | state->fault = ret; |
326 | 446 | ||
327 | state->power_good = !gpiod_get_value_cansleep(bq->pg); | 447 | if (bq->pg) |
448 | state->power_good = !gpiod_get_value_cansleep(bq->pg); | ||
449 | else | ||
450 | /* | ||
451 | * If we have a chip without a dedicated power-good GPIO or | ||
452 | * some other explicit bit that would provide this information | ||
453 | * assume the power is good if there is no supply related | ||
454 | * fault - and not good otherwise. There is a possibility for | ||
455 | * other errors to mask that power in fact is not good but this | ||
456 | * is probably the best we can do here. | ||
457 | */ | ||
458 | switch (state->fault) { | ||
459 | case FAULT_INPUT_OVP: | ||
460 | case FAULT_INPUT_UVLO: | ||
461 | case FAULT_INPUT_LDO_LOW: | ||
462 | state->power_good = false; | ||
463 | break; | ||
464 | default: | ||
465 | state->power_good = true; | ||
466 | } | ||
328 | 467 | ||
329 | return 0; | 468 | return 0; |
330 | } | 469 | } |
@@ -361,6 +500,28 @@ enum bq24257_in_ilimit { | |||
361 | IILIMIT_NONE, | 500 | IILIMIT_NONE, |
362 | }; | 501 | }; |
363 | 502 | ||
503 | enum bq24257_vovp { | ||
504 | VOVP_6000, | ||
505 | VOVP_6500, | ||
506 | VOVP_7000, | ||
507 | VOVP_8000, | ||
508 | VOVP_9000, | ||
509 | VOVP_9500, | ||
510 | VOVP_10000, | ||
511 | VOVP_10500 | ||
512 | }; | ||
513 | |||
514 | enum bq24257_vindpm { | ||
515 | VINDPM_4200, | ||
516 | VINDPM_4280, | ||
517 | VINDPM_4360, | ||
518 | VINDPM_4440, | ||
519 | VINDPM_4520, | ||
520 | VINDPM_4600, | ||
521 | VINDPM_4680, | ||
522 | VINDPM_4760 | ||
523 | }; | ||
524 | |||
364 | enum bq24257_port_type { | 525 | enum bq24257_port_type { |
365 | PORT_TYPE_DCP, /* Dedicated Charging Port */ | 526 | PORT_TYPE_DCP, /* Dedicated Charging Port */ |
366 | PORT_TYPE_CDP, /* Charging Downstream Port */ | 527 | PORT_TYPE_CDP, /* Charging Downstream Port */ |
@@ -449,41 +610,43 @@ static void bq24257_handle_state_change(struct bq24257_device *bq, | |||
449 | { | 610 | { |
450 | int ret; | 611 | int ret; |
451 | struct bq24257_state old_state; | 612 | struct bq24257_state old_state; |
452 | bool reset_iilimit = false; | ||
453 | bool config_iilimit = false; | ||
454 | 613 | ||
455 | mutex_lock(&bq->lock); | 614 | mutex_lock(&bq->lock); |
456 | old_state = bq->state; | 615 | old_state = bq->state; |
457 | mutex_unlock(&bq->lock); | 616 | mutex_unlock(&bq->lock); |
458 | 617 | ||
459 | if (!new_state->power_good) { /* power removed */ | 618 | /* |
460 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | 619 | * Handle BQ2425x state changes observing whether the D+/D- based input |
461 | 620 | * current limit autoset functionality is enabled. | |
462 | /* activate D+/D- port detection algorithm */ | 621 | */ |
463 | ret = bq24257_field_write(bq, F_DPDM_EN, 1); | 622 | if (!new_state->power_good) { |
623 | dev_dbg(bq->dev, "Power removed\n"); | ||
624 | if (bq->iilimit_autoset_enable) { | ||
625 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
626 | |||
627 | /* activate D+/D- port detection algorithm */ | ||
628 | ret = bq24257_field_write(bq, F_DPDM_EN, 1); | ||
629 | if (ret < 0) | ||
630 | goto error; | ||
631 | } | ||
632 | /* | ||
633 | * When power is removed always return to the default input | ||
634 | * current limit as configured during probe. | ||
635 | */ | ||
636 | ret = bq24257_field_write(bq, F_IILIMIT, bq->init_data.iilimit); | ||
464 | if (ret < 0) | 637 | if (ret < 0) |
465 | goto error; | 638 | goto error; |
639 | } else if (!old_state.power_good) { | ||
640 | dev_dbg(bq->dev, "Power inserted\n"); | ||
466 | 641 | ||
467 | reset_iilimit = true; | 642 | if (bq->iilimit_autoset_enable) |
468 | } else if (!old_state.power_good) { /* power inserted */ | 643 | /* configure input current limit */ |
469 | config_iilimit = true; | 644 | schedule_delayed_work(&bq->iilimit_setup_work, |
470 | } else if (new_state->fault == FAULT_NO_BAT) { /* battery removed */ | ||
471 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
472 | |||
473 | reset_iilimit = true; | ||
474 | } else if (old_state.fault == FAULT_NO_BAT) { /* battery connected */ | ||
475 | config_iilimit = true; | ||
476 | } else if (new_state->fault == FAULT_TIMER) { /* safety timer expired */ | ||
477 | dev_err(bq->dev, "Safety timer expired! Battery dead?\n"); | ||
478 | } | ||
479 | |||
480 | if (reset_iilimit) { | ||
481 | ret = bq24257_field_write(bq, F_IILIMIT, IILIMIT_500); | ||
482 | if (ret < 0) | ||
483 | goto error; | ||
484 | } else if (config_iilimit) { | ||
485 | schedule_delayed_work(&bq->iilimit_setup_work, | ||
486 | msecs_to_jiffies(BQ24257_ILIM_SET_DELAY)); | 645 | msecs_to_jiffies(BQ24257_ILIM_SET_DELAY)); |
646 | } else if (new_state->fault == FAULT_NO_BAT) { | ||
647 | dev_warn(bq->dev, "Battery removed\n"); | ||
648 | } else if (new_state->fault == FAULT_TIMER) { | ||
649 | dev_err(bq->dev, "Safety timer expired! Battery dead?\n"); | ||
487 | } | 650 | } |
488 | 651 | ||
489 | return; | 652 | return; |
@@ -531,7 +694,9 @@ static int bq24257_hw_init(struct bq24257_device *bq) | |||
531 | } init_data[] = { | 694 | } init_data[] = { |
532 | {F_ICHG, bq->init_data.ichg}, | 695 | {F_ICHG, bq->init_data.ichg}, |
533 | {F_VBAT, bq->init_data.vbat}, | 696 | {F_VBAT, bq->init_data.vbat}, |
534 | {F_ITERM, bq->init_data.iterm} | 697 | {F_ITERM, bq->init_data.iterm}, |
698 | {F_VOVP, bq->init_data.vovp}, | ||
699 | {F_VINDPM, bq->init_data.vindpm}, | ||
535 | }; | 700 | }; |
536 | 701 | ||
537 | /* | 702 | /* |
@@ -558,7 +723,16 @@ static int bq24257_hw_init(struct bq24257_device *bq) | |||
558 | bq->state = state; | 723 | bq->state = state; |
559 | mutex_unlock(&bq->lock); | 724 | mutex_unlock(&bq->lock); |
560 | 725 | ||
561 | if (!state.power_good) | 726 | if (!bq->iilimit_autoset_enable) { |
727 | dev_dbg(bq->dev, "manually setting iilimit = %u\n", | ||
728 | bq->init_data.iilimit); | ||
729 | |||
730 | /* program fixed input current limit */ | ||
731 | ret = bq24257_field_write(bq, F_IILIMIT, | ||
732 | bq->init_data.iilimit); | ||
733 | if (ret < 0) | ||
734 | return ret; | ||
735 | } else if (!state.power_good) | ||
562 | /* activate D+/D- detection algorithm */ | 736 | /* activate D+/D- detection algorithm */ |
563 | ret = bq24257_field_write(bq, F_DPDM_EN, 1); | 737 | ret = bq24257_field_write(bq, F_DPDM_EN, 1); |
564 | else if (state.fault != FAULT_NO_BAT) | 738 | else if (state.fault != FAULT_NO_BAT) |
@@ -569,6 +743,7 @@ static int bq24257_hw_init(struct bq24257_device *bq) | |||
569 | 743 | ||
570 | static enum power_supply_property bq24257_power_supply_props[] = { | 744 | static enum power_supply_property bq24257_power_supply_props[] = { |
571 | POWER_SUPPLY_PROP_MANUFACTURER, | 745 | POWER_SUPPLY_PROP_MANUFACTURER, |
746 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
572 | POWER_SUPPLY_PROP_STATUS, | 747 | POWER_SUPPLY_PROP_STATUS, |
573 | POWER_SUPPLY_PROP_ONLINE, | 748 | POWER_SUPPLY_PROP_ONLINE, |
574 | POWER_SUPPLY_PROP_HEALTH, | 749 | POWER_SUPPLY_PROP_HEALTH, |
@@ -577,6 +752,7 @@ static enum power_supply_property bq24257_power_supply_props[] = { | |||
577 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | 752 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, |
578 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | 753 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, |
579 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, | 754 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, |
755 | POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, | ||
580 | }; | 756 | }; |
581 | 757 | ||
582 | static char *bq24257_charger_supplied_to[] = { | 758 | static char *bq24257_charger_supplied_to[] = { |
@@ -589,45 +765,127 @@ static const struct power_supply_desc bq24257_power_supply_desc = { | |||
589 | .properties = bq24257_power_supply_props, | 765 | .properties = bq24257_power_supply_props, |
590 | .num_properties = ARRAY_SIZE(bq24257_power_supply_props), | 766 | .num_properties = ARRAY_SIZE(bq24257_power_supply_props), |
591 | .get_property = bq24257_power_supply_get_property, | 767 | .get_property = bq24257_power_supply_get_property, |
768 | .set_property = bq24257_power_supply_set_property, | ||
769 | .property_is_writeable = bq24257_power_supply_property_is_writeable, | ||
592 | }; | 770 | }; |
593 | 771 | ||
594 | static int bq24257_power_supply_init(struct bq24257_device *bq) | 772 | static ssize_t bq24257_show_ovp_voltage(struct device *dev, |
773 | struct device_attribute *attr, | ||
774 | char *buf) | ||
595 | { | 775 | { |
596 | struct power_supply_config psy_cfg = { .drv_data = bq, }; | 776 | struct power_supply *psy = dev_get_drvdata(dev); |
777 | struct bq24257_device *bq = power_supply_get_drvdata(psy); | ||
597 | 778 | ||
598 | psy_cfg.supplied_to = bq24257_charger_supplied_to; | 779 | return scnprintf(buf, PAGE_SIZE, "%u\n", |
599 | psy_cfg.num_supplicants = ARRAY_SIZE(bq24257_charger_supplied_to); | 780 | bq24257_vovp_map[bq->init_data.vovp]); |
781 | } | ||
600 | 782 | ||
601 | bq->charger = power_supply_register(bq->dev, &bq24257_power_supply_desc, | 783 | static ssize_t bq24257_show_in_dpm_voltage(struct device *dev, |
602 | &psy_cfg); | 784 | struct device_attribute *attr, |
603 | if (IS_ERR(bq->charger)) | 785 | char *buf) |
604 | return PTR_ERR(bq->charger); | 786 | { |
787 | struct power_supply *psy = dev_get_drvdata(dev); | ||
788 | struct bq24257_device *bq = power_supply_get_drvdata(psy); | ||
605 | 789 | ||
606 | return 0; | 790 | return scnprintf(buf, PAGE_SIZE, "%u\n", |
791 | bq24257_vindpm_map[bq->init_data.vindpm]); | ||
607 | } | 792 | } |
608 | 793 | ||
609 | static int bq24257_irq_probe(struct bq24257_device *bq) | 794 | static ssize_t bq24257_sysfs_show_enable(struct device *dev, |
795 | struct device_attribute *attr, | ||
796 | char *buf) | ||
610 | { | 797 | { |
611 | struct gpio_desc *stat_irq; | 798 | struct power_supply *psy = dev_get_drvdata(dev); |
799 | struct bq24257_device *bq = power_supply_get_drvdata(psy); | ||
800 | int ret; | ||
612 | 801 | ||
613 | stat_irq = devm_gpiod_get_index(bq->dev, BQ24257_STAT_IRQ, 0, GPIOD_IN); | 802 | if (strcmp(attr->attr.name, "high_impedance_enable") == 0) |
614 | if (IS_ERR(stat_irq)) { | 803 | ret = bq24257_field_read(bq, F_HZ_MODE); |
615 | dev_err(bq->dev, "could not probe stat_irq pin\n"); | 804 | else if (strcmp(attr->attr.name, "sysoff_enable") == 0) |
616 | return PTR_ERR(stat_irq); | 805 | ret = bq24257_field_read(bq, F_SYSOFF); |
617 | } | 806 | else |
807 | return -EINVAL; | ||
618 | 808 | ||
619 | return gpiod_to_irq(stat_irq); | 809 | if (ret < 0) |
810 | return ret; | ||
811 | |||
812 | return scnprintf(buf, PAGE_SIZE, "%d\n", ret); | ||
620 | } | 813 | } |
621 | 814 | ||
622 | static int bq24257_pg_gpio_probe(struct bq24257_device *bq) | 815 | static ssize_t bq24257_sysfs_set_enable(struct device *dev, |
816 | struct device_attribute *attr, | ||
817 | const char *buf, | ||
818 | size_t count) | ||
623 | { | 819 | { |
624 | bq->pg = devm_gpiod_get_index(bq->dev, BQ24257_PG_GPIO, 0, GPIOD_IN); | 820 | struct power_supply *psy = dev_get_drvdata(dev); |
625 | if (IS_ERR(bq->pg)) { | 821 | struct bq24257_device *bq = power_supply_get_drvdata(psy); |
626 | dev_err(bq->dev, "could not probe PG pin\n"); | 822 | long val; |
627 | return PTR_ERR(bq->pg); | 823 | int ret; |
824 | |||
825 | if (kstrtol(buf, 10, &val) < 0) | ||
826 | return -EINVAL; | ||
827 | |||
828 | if (strcmp(attr->attr.name, "high_impedance_enable") == 0) | ||
829 | ret = bq24257_field_write(bq, F_HZ_MODE, (bool)val); | ||
830 | else if (strcmp(attr->attr.name, "sysoff_enable") == 0) | ||
831 | ret = bq24257_field_write(bq, F_SYSOFF, (bool)val); | ||
832 | else | ||
833 | return -EINVAL; | ||
834 | |||
835 | if (ret < 0) | ||
836 | return ret; | ||
837 | |||
838 | return count; | ||
839 | } | ||
840 | |||
841 | static DEVICE_ATTR(ovp_voltage, S_IRUGO, bq24257_show_ovp_voltage, NULL); | ||
842 | static DEVICE_ATTR(in_dpm_voltage, S_IRUGO, bq24257_show_in_dpm_voltage, NULL); | ||
843 | static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO, | ||
844 | bq24257_sysfs_show_enable, bq24257_sysfs_set_enable); | ||
845 | static DEVICE_ATTR(sysoff_enable, S_IWUSR | S_IRUGO, | ||
846 | bq24257_sysfs_show_enable, bq24257_sysfs_set_enable); | ||
847 | |||
848 | static struct attribute *bq24257_charger_attr[] = { | ||
849 | &dev_attr_ovp_voltage.attr, | ||
850 | &dev_attr_in_dpm_voltage.attr, | ||
851 | &dev_attr_high_impedance_enable.attr, | ||
852 | &dev_attr_sysoff_enable.attr, | ||
853 | NULL, | ||
854 | }; | ||
855 | |||
856 | static const struct attribute_group bq24257_attr_group = { | ||
857 | .attrs = bq24257_charger_attr, | ||
858 | }; | ||
859 | |||
860 | static int bq24257_power_supply_init(struct bq24257_device *bq) | ||
861 | { | ||
862 | struct power_supply_config psy_cfg = { .drv_data = bq, }; | ||
863 | |||
864 | psy_cfg.supplied_to = bq24257_charger_supplied_to; | ||
865 | psy_cfg.num_supplicants = ARRAY_SIZE(bq24257_charger_supplied_to); | ||
866 | |||
867 | bq->charger = devm_power_supply_register(bq->dev, | ||
868 | &bq24257_power_supply_desc, | ||
869 | &psy_cfg); | ||
870 | |||
871 | return PTR_ERR_OR_ZERO(bq->charger); | ||
872 | } | ||
873 | |||
874 | static void bq24257_pg_gpio_probe(struct bq24257_device *bq) | ||
875 | { | ||
876 | bq->pg = devm_gpiod_get_optional(bq->dev, BQ24257_PG_GPIO, GPIOD_IN); | ||
877 | |||
878 | if (PTR_ERR(bq->pg) == -EPROBE_DEFER) { | ||
879 | dev_info(bq->dev, "probe retry requested for PG pin\n"); | ||
880 | return; | ||
881 | } else if (IS_ERR(bq->pg)) { | ||
882 | dev_err(bq->dev, "error probing PG pin\n"); | ||
883 | bq->pg = NULL; | ||
884 | return; | ||
628 | } | 885 | } |
629 | 886 | ||
630 | return 0; | 887 | if (bq->pg) |
888 | dev_dbg(bq->dev, "probed PG pin = %d\n", desc_to_gpio(bq->pg)); | ||
631 | } | 889 | } |
632 | 890 | ||
633 | static int bq24257_fw_probe(struct bq24257_device *bq) | 891 | static int bq24257_fw_probe(struct bq24257_device *bq) |
@@ -635,6 +893,7 @@ static int bq24257_fw_probe(struct bq24257_device *bq) | |||
635 | int ret; | 893 | int ret; |
636 | u32 property; | 894 | u32 property; |
637 | 895 | ||
896 | /* Required properties */ | ||
638 | ret = device_property_read_u32(bq->dev, "ti,charge-current", &property); | 897 | ret = device_property_read_u32(bq->dev, "ti,charge-current", &property); |
639 | if (ret < 0) | 898 | if (ret < 0) |
640 | return ret; | 899 | return ret; |
@@ -658,6 +917,43 @@ static int bq24257_fw_probe(struct bq24257_device *bq) | |||
658 | bq->init_data.iterm = bq24257_find_idx(property, bq24257_iterm_map, | 917 | bq->init_data.iterm = bq24257_find_idx(property, bq24257_iterm_map, |
659 | BQ24257_ITERM_MAP_SIZE); | 918 | BQ24257_ITERM_MAP_SIZE); |
660 | 919 | ||
920 | /* Optional properties. If not provided use reasonable default. */ | ||
921 | ret = device_property_read_u32(bq->dev, "ti,current-limit", | ||
922 | &property); | ||
923 | if (ret < 0) { | ||
924 | bq->iilimit_autoset_enable = true; | ||
925 | |||
926 | /* | ||
927 | * Explicitly set a default value which will be needed for | ||
928 | * devices that don't support the automatic setting of the input | ||
929 | * current limit through the charger type detection mechanism. | ||
930 | */ | ||
931 | bq->init_data.iilimit = IILIMIT_500; | ||
932 | } else | ||
933 | bq->init_data.iilimit = | ||
934 | bq24257_find_idx(property, | ||
935 | bq24257_iilimit_map, | ||
936 | BQ24257_IILIMIT_MAP_SIZE); | ||
937 | |||
938 | ret = device_property_read_u32(bq->dev, "ti,ovp-voltage", | ||
939 | &property); | ||
940 | if (ret < 0) | ||
941 | bq->init_data.vovp = VOVP_6500; | ||
942 | else | ||
943 | bq->init_data.vovp = bq24257_find_idx(property, | ||
944 | bq24257_vovp_map, | ||
945 | BQ24257_VOVP_MAP_SIZE); | ||
946 | |||
947 | ret = device_property_read_u32(bq->dev, "ti,in-dpm-voltage", | ||
948 | &property); | ||
949 | if (ret < 0) | ||
950 | bq->init_data.vindpm = VINDPM_4360; | ||
951 | else | ||
952 | bq->init_data.vindpm = | ||
953 | bq24257_find_idx(property, | ||
954 | bq24257_vindpm_map, | ||
955 | BQ24257_VINDPM_MAP_SIZE); | ||
956 | |||
661 | return 0; | 957 | return 0; |
662 | } | 958 | } |
663 | 959 | ||
@@ -666,6 +962,7 @@ static int bq24257_probe(struct i2c_client *client, | |||
666 | { | 962 | { |
667 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 963 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
668 | struct device *dev = &client->dev; | 964 | struct device *dev = &client->dev; |
965 | const struct acpi_device_id *acpi_id; | ||
669 | struct bq24257_device *bq; | 966 | struct bq24257_device *bq; |
670 | int ret; | 967 | int ret; |
671 | int i; | 968 | int i; |
@@ -682,6 +979,18 @@ static int bq24257_probe(struct i2c_client *client, | |||
682 | bq->client = client; | 979 | bq->client = client; |
683 | bq->dev = dev; | 980 | bq->dev = dev; |
684 | 981 | ||
982 | if (ACPI_HANDLE(dev)) { | ||
983 | acpi_id = acpi_match_device(dev->driver->acpi_match_table, | ||
984 | &client->dev); | ||
985 | if (!acpi_id) { | ||
986 | dev_err(dev, "Failed to match ACPI device\n"); | ||
987 | return -ENODEV; | ||
988 | } | ||
989 | bq->chip = (enum bq2425x_chip)acpi_id->driver_data; | ||
990 | } else { | ||
991 | bq->chip = (enum bq2425x_chip)id->driver_data; | ||
992 | } | ||
993 | |||
685 | mutex_init(&bq->lock); | 994 | mutex_init(&bq->lock); |
686 | 995 | ||
687 | bq->rmap = devm_regmap_init_i2c(client, &bq24257_regmap_config); | 996 | bq->rmap = devm_regmap_init_i2c(client, &bq24257_regmap_config); |
@@ -703,8 +1012,6 @@ static int bq24257_probe(struct i2c_client *client, | |||
703 | 1012 | ||
704 | i2c_set_clientdata(client, bq); | 1013 | i2c_set_clientdata(client, bq); |
705 | 1014 | ||
706 | INIT_DELAYED_WORK(&bq->iilimit_setup_work, bq24257_iilimit_setup_work); | ||
707 | |||
708 | if (!dev->platform_data) { | 1015 | if (!dev->platform_data) { |
709 | ret = bq24257_fw_probe(bq); | 1016 | ret = bq24257_fw_probe(bq); |
710 | if (ret < 0) { | 1017 | if (ret < 0) { |
@@ -715,10 +1022,31 @@ static int bq24257_probe(struct i2c_client *client, | |||
715 | return -ENODEV; | 1022 | return -ENODEV; |
716 | } | 1023 | } |
717 | 1024 | ||
718 | /* we can only check Power Good status by probing the PG pin */ | 1025 | /* |
719 | ret = bq24257_pg_gpio_probe(bq); | 1026 | * The BQ24250 doesn't support the D+/D- based charger type detection |
720 | if (ret < 0) | 1027 | * used for the automatic setting of the input current limit setting so |
721 | return ret; | 1028 | * explicitly disable that feature. |
1029 | */ | ||
1030 | if (bq->chip == BQ24250) | ||
1031 | bq->iilimit_autoset_enable = false; | ||
1032 | |||
1033 | if (bq->iilimit_autoset_enable) | ||
1034 | INIT_DELAYED_WORK(&bq->iilimit_setup_work, | ||
1035 | bq24257_iilimit_setup_work); | ||
1036 | |||
1037 | /* | ||
1038 | * The BQ24250 doesn't have a dedicated Power Good (PG) pin so let's | ||
1039 | * not probe for it and instead use a SW-based approach to determine | ||
1040 | * the PG state. We also use a SW-based approach for all other devices | ||
1041 | * if the PG pin is either not defined or can't be probed. | ||
1042 | */ | ||
1043 | if (bq->chip != BQ24250) | ||
1044 | bq24257_pg_gpio_probe(bq); | ||
1045 | |||
1046 | if (PTR_ERR(bq->pg) == -EPROBE_DEFER) | ||
1047 | return PTR_ERR(bq->pg); | ||
1048 | else if (!bq->pg) | ||
1049 | dev_info(bq->dev, "using SW-based power-good detection\n"); | ||
722 | 1050 | ||
723 | /* reset all registers to defaults */ | 1051 | /* reset all registers to defaults */ |
724 | ret = bq24257_field_write(bq, F_RESET, 1); | 1052 | ret = bq24257_field_write(bq, F_RESET, 1); |
@@ -740,36 +1068,39 @@ static int bq24257_probe(struct i2c_client *client, | |||
740 | return ret; | 1068 | return ret; |
741 | } | 1069 | } |
742 | 1070 | ||
743 | if (client->irq <= 0) | ||
744 | client->irq = bq24257_irq_probe(bq); | ||
745 | |||
746 | if (client->irq < 0) { | ||
747 | dev_err(dev, "no irq resource found\n"); | ||
748 | return client->irq; | ||
749 | } | ||
750 | |||
751 | ret = devm_request_threaded_irq(dev, client->irq, NULL, | 1071 | ret = devm_request_threaded_irq(dev, client->irq, NULL, |
752 | bq24257_irq_handler_thread, | 1072 | bq24257_irq_handler_thread, |
753 | IRQF_TRIGGER_FALLING | | 1073 | IRQF_TRIGGER_FALLING | |
754 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | 1074 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
755 | BQ24257_STAT_IRQ, bq); | 1075 | bq2425x_chip_name[bq->chip], bq); |
756 | if (ret) | 1076 | if (ret) { |
1077 | dev_err(dev, "Failed to request IRQ #%d\n", client->irq); | ||
757 | return ret; | 1078 | return ret; |
1079 | } | ||
758 | 1080 | ||
759 | ret = bq24257_power_supply_init(bq); | 1081 | ret = bq24257_power_supply_init(bq); |
760 | if (ret < 0) | 1082 | if (ret < 0) { |
761 | dev_err(dev, "Failed to register power supply\n"); | 1083 | dev_err(dev, "Failed to register power supply\n"); |
1084 | return ret; | ||
1085 | } | ||
762 | 1086 | ||
763 | return ret; | 1087 | ret = sysfs_create_group(&bq->charger->dev.kobj, &bq24257_attr_group); |
1088 | if (ret < 0) { | ||
1089 | dev_err(dev, "Can't create sysfs entries\n"); | ||
1090 | return ret; | ||
1091 | } | ||
1092 | |||
1093 | return 0; | ||
764 | } | 1094 | } |
765 | 1095 | ||
766 | static int bq24257_remove(struct i2c_client *client) | 1096 | static int bq24257_remove(struct i2c_client *client) |
767 | { | 1097 | { |
768 | struct bq24257_device *bq = i2c_get_clientdata(client); | 1098 | struct bq24257_device *bq = i2c_get_clientdata(client); |
769 | 1099 | ||
770 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | 1100 | if (bq->iilimit_autoset_enable) |
1101 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
771 | 1102 | ||
772 | power_supply_unregister(bq->charger); | 1103 | sysfs_remove_group(&bq->charger->dev.kobj, &bq24257_attr_group); |
773 | 1104 | ||
774 | bq24257_field_write(bq, F_RESET, 1); /* reset to defaults */ | 1105 | bq24257_field_write(bq, F_RESET, 1); /* reset to defaults */ |
775 | 1106 | ||
@@ -782,7 +1113,8 @@ static int bq24257_suspend(struct device *dev) | |||
782 | struct bq24257_device *bq = dev_get_drvdata(dev); | 1113 | struct bq24257_device *bq = dev_get_drvdata(dev); |
783 | int ret = 0; | 1114 | int ret = 0; |
784 | 1115 | ||
785 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | 1116 | if (bq->iilimit_autoset_enable) |
1117 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
786 | 1118 | ||
787 | /* reset all registers to default (and activate standalone mode) */ | 1119 | /* reset all registers to default (and activate standalone mode) */ |
788 | ret = bq24257_field_write(bq, F_RESET, 1); | 1120 | ret = bq24257_field_write(bq, F_RESET, 1); |
@@ -823,19 +1155,25 @@ static const struct dev_pm_ops bq24257_pm = { | |||
823 | }; | 1155 | }; |
824 | 1156 | ||
825 | static const struct i2c_device_id bq24257_i2c_ids[] = { | 1157 | static const struct i2c_device_id bq24257_i2c_ids[] = { |
826 | { "bq24257", 0 }, | 1158 | { "bq24250", BQ24250 }, |
1159 | { "bq24251", BQ24251 }, | ||
1160 | { "bq24257", BQ24257 }, | ||
827 | {}, | 1161 | {}, |
828 | }; | 1162 | }; |
829 | MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids); | 1163 | MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids); |
830 | 1164 | ||
831 | static const struct of_device_id bq24257_of_match[] = { | 1165 | static const struct of_device_id bq24257_of_match[] = { |
1166 | { .compatible = "ti,bq24250", }, | ||
1167 | { .compatible = "ti,bq24251", }, | ||
832 | { .compatible = "ti,bq24257", }, | 1168 | { .compatible = "ti,bq24257", }, |
833 | { }, | 1169 | { }, |
834 | }; | 1170 | }; |
835 | MODULE_DEVICE_TABLE(of, bq24257_of_match); | 1171 | MODULE_DEVICE_TABLE(of, bq24257_of_match); |
836 | 1172 | ||
837 | static const struct acpi_device_id bq24257_acpi_match[] = { | 1173 | static const struct acpi_device_id bq24257_acpi_match[] = { |
838 | {"BQ242570", 0}, | 1174 | { "BQ242500", BQ24250 }, |
1175 | { "BQ242510", BQ24251 }, | ||
1176 | { "BQ242570", BQ24257 }, | ||
839 | {}, | 1177 | {}, |
840 | }; | 1178 | }; |
841 | MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match); | 1179 | MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match); |
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c deleted file mode 100644 index 8287261fd978..000000000000 --- a/drivers/power/bq27x00_battery.c +++ /dev/null | |||
@@ -1,1129 +0,0 @@ | |||
1 | /* | ||
2 | * BQ27x00 battery driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com> | ||
8 | * | ||
9 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. | ||
10 | * | ||
11 | * This package is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
17 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | * | ||
19 | * Datasheets: | ||
20 | * http://focus.ti.com/docs/prod/folders/print/bq27000.html | ||
21 | * http://focus.ti.com/docs/prod/folders/print/bq27500.html | ||
22 | * http://www.ti.com/product/bq27425-g1 | ||
23 | * http://www.ti.com/product/BQ27742-G1 | ||
24 | * http://www.ti.com/product/BQ27510-G3 | ||
25 | */ | ||
26 | |||
27 | #include <linux/device.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/param.h> | ||
30 | #include <linux/jiffies.h> | ||
31 | #include <linux/workqueue.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/power_supply.h> | ||
35 | #include <linux/idr.h> | ||
36 | #include <linux/i2c.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <asm/unaligned.h> | ||
39 | |||
40 | #include <linux/power/bq27x00_battery.h> | ||
41 | |||
42 | #define DRIVER_VERSION "1.2.0" | ||
43 | |||
44 | #define BQ27XXX_MANUFACTURER "Texas Instruments" | ||
45 | |||
46 | #define BQ27x00_REG_TEMP 0x06 | ||
47 | #define BQ27x00_REG_VOLT 0x08 | ||
48 | #define BQ27x00_REG_AI 0x14 | ||
49 | #define BQ27x00_REG_FLAGS 0x0A | ||
50 | #define BQ27x00_REG_TTE 0x16 | ||
51 | #define BQ27x00_REG_TTF 0x18 | ||
52 | #define BQ27x00_REG_TTECP 0x26 | ||
53 | #define BQ27x00_REG_NAC 0x0C /* Nominal available capacity */ | ||
54 | #define BQ27x00_REG_LMD 0x12 /* Last measured discharge */ | ||
55 | #define BQ27x00_REG_CYCT 0x2A /* Cycle count total */ | ||
56 | #define BQ27x00_REG_AE 0x22 /* Available energy */ | ||
57 | #define BQ27x00_POWER_AVG 0x24 | ||
58 | |||
59 | #define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */ | ||
60 | #define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */ | ||
61 | #define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */ | ||
62 | #define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */ | ||
63 | #define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */ | ||
64 | #define BQ27000_FLAG_FC BIT(5) | ||
65 | #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */ | ||
66 | |||
67 | #define BQ27500_REG_SOC 0x2C | ||
68 | #define BQ27500_REG_DCAP 0x3C /* Design capacity */ | ||
69 | #define BQ27500_FLAG_DSC BIT(0) | ||
70 | #define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ | ||
71 | #define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ | ||
72 | #define BQ27500_FLAG_FC BIT(9) | ||
73 | #define BQ27500_FLAG_OTC BIT(15) | ||
74 | |||
75 | #define BQ27742_POWER_AVG 0x76 | ||
76 | |||
77 | #define BQ27510_REG_SOC 0x20 | ||
78 | #define BQ27510_REG_DCAP 0x2E /* Design capacity */ | ||
79 | #define BQ27510_REG_CYCT 0x1E /* Cycle count total */ | ||
80 | |||
81 | /* bq27425 register addresses are same as bq27x00 addresses minus 4 */ | ||
82 | #define BQ27425_REG_OFFSET 0x04 | ||
83 | #define BQ27425_REG_SOC (0x1C + BQ27425_REG_OFFSET) | ||
84 | #define BQ27425_REG_DCAP (0x3C + BQ27425_REG_OFFSET) | ||
85 | |||
86 | #define BQ27000_RS 20 /* Resistor sense */ | ||
87 | #define BQ27x00_POWER_CONSTANT (256 * 29200 / 1000) | ||
88 | |||
89 | struct bq27x00_device_info; | ||
90 | struct bq27x00_access_methods { | ||
91 | int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); | ||
92 | }; | ||
93 | |||
94 | enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742, BQ27510}; | ||
95 | |||
96 | struct bq27x00_reg_cache { | ||
97 | int temperature; | ||
98 | int time_to_empty; | ||
99 | int time_to_empty_avg; | ||
100 | int time_to_full; | ||
101 | int charge_full; | ||
102 | int cycle_count; | ||
103 | int capacity; | ||
104 | int energy; | ||
105 | int flags; | ||
106 | int power_avg; | ||
107 | int health; | ||
108 | }; | ||
109 | |||
110 | struct bq27x00_device_info { | ||
111 | struct device *dev; | ||
112 | int id; | ||
113 | enum bq27x00_chip chip; | ||
114 | |||
115 | struct bq27x00_reg_cache cache; | ||
116 | int charge_design_full; | ||
117 | |||
118 | unsigned long last_update; | ||
119 | struct delayed_work work; | ||
120 | |||
121 | struct power_supply *bat; | ||
122 | |||
123 | struct bq27x00_access_methods bus; | ||
124 | |||
125 | struct mutex lock; | ||
126 | }; | ||
127 | |||
128 | static enum power_supply_property bq27x00_battery_props[] = { | ||
129 | POWER_SUPPLY_PROP_STATUS, | ||
130 | POWER_SUPPLY_PROP_PRESENT, | ||
131 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
132 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
133 | POWER_SUPPLY_PROP_CAPACITY, | ||
134 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
135 | POWER_SUPPLY_PROP_TEMP, | ||
136 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
137 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | ||
138 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, | ||
139 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
140 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
141 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
142 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
143 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
144 | POWER_SUPPLY_PROP_ENERGY_NOW, | ||
145 | POWER_SUPPLY_PROP_POWER_AVG, | ||
146 | POWER_SUPPLY_PROP_HEALTH, | ||
147 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
148 | }; | ||
149 | |||
150 | static enum power_supply_property bq27425_battery_props[] = { | ||
151 | POWER_SUPPLY_PROP_STATUS, | ||
152 | POWER_SUPPLY_PROP_PRESENT, | ||
153 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
154 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
155 | POWER_SUPPLY_PROP_CAPACITY, | ||
156 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
157 | POWER_SUPPLY_PROP_TEMP, | ||
158 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
159 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
160 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
161 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
162 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
163 | }; | ||
164 | |||
165 | static enum power_supply_property bq27742_battery_props[] = { | ||
166 | POWER_SUPPLY_PROP_STATUS, | ||
167 | POWER_SUPPLY_PROP_PRESENT, | ||
168 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
169 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
170 | POWER_SUPPLY_PROP_CAPACITY, | ||
171 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
172 | POWER_SUPPLY_PROP_TEMP, | ||
173 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
174 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
175 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
176 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
177 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
178 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
179 | POWER_SUPPLY_PROP_POWER_AVG, | ||
180 | POWER_SUPPLY_PROP_HEALTH, | ||
181 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
182 | }; | ||
183 | |||
184 | static enum power_supply_property bq27510_battery_props[] = { | ||
185 | POWER_SUPPLY_PROP_STATUS, | ||
186 | POWER_SUPPLY_PROP_PRESENT, | ||
187 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
188 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
189 | POWER_SUPPLY_PROP_CAPACITY, | ||
190 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
191 | POWER_SUPPLY_PROP_TEMP, | ||
192 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
193 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
194 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
195 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
196 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
197 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
198 | POWER_SUPPLY_PROP_POWER_AVG, | ||
199 | POWER_SUPPLY_PROP_HEALTH, | ||
200 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
201 | }; | ||
202 | |||
203 | static unsigned int poll_interval = 360; | ||
204 | module_param(poll_interval, uint, 0644); | ||
205 | MODULE_PARM_DESC(poll_interval, | ||
206 | "battery poll interval in seconds - 0 disables polling"); | ||
207 | |||
208 | /* | ||
209 | * Common code for BQ27x00 devices | ||
210 | */ | ||
211 | |||
212 | static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg, | ||
213 | bool single) | ||
214 | { | ||
215 | if (di->chip == BQ27425) | ||
216 | return di->bus.read(di, reg - BQ27425_REG_OFFSET, single); | ||
217 | return di->bus.read(di, reg, single); | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * Higher versions of the chip like BQ27425 and BQ27500 | ||
222 | * differ from BQ27000 and BQ27200 in calculation of certain | ||
223 | * parameters. Hence we need to check for the chip type. | ||
224 | */ | ||
225 | static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) | ||
226 | { | ||
227 | if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742 | ||
228 | || di->chip == BQ27510) | ||
229 | return true; | ||
230 | return false; | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Return the battery Relative State-of-Charge | ||
235 | * Or < 0 if something fails. | ||
236 | */ | ||
237 | static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di) | ||
238 | { | ||
239 | int rsoc; | ||
240 | |||
241 | if (di->chip == BQ27500 || di->chip == BQ27742) | ||
242 | rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); | ||
243 | else if (di->chip == BQ27510) | ||
244 | rsoc = bq27x00_read(di, BQ27510_REG_SOC, false); | ||
245 | else if (di->chip == BQ27425) | ||
246 | rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); | ||
247 | else | ||
248 | rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true); | ||
249 | |||
250 | if (rsoc < 0) | ||
251 | dev_dbg(di->dev, "error reading relative State-of-Charge\n"); | ||
252 | |||
253 | return rsoc; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Return a battery charge value in µAh | ||
258 | * Or < 0 if something fails. | ||
259 | */ | ||
260 | static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg) | ||
261 | { | ||
262 | int charge; | ||
263 | |||
264 | charge = bq27x00_read(di, reg, false); | ||
265 | if (charge < 0) { | ||
266 | dev_dbg(di->dev, "error reading charge register %02x: %d\n", | ||
267 | reg, charge); | ||
268 | return charge; | ||
269 | } | ||
270 | |||
271 | if (bq27xxx_is_chip_version_higher(di)) | ||
272 | charge *= 1000; | ||
273 | else | ||
274 | charge = charge * 3570 / BQ27000_RS; | ||
275 | |||
276 | return charge; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Return the battery Nominal available capaciy in µAh | ||
281 | * Or < 0 if something fails. | ||
282 | */ | ||
283 | static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di) | ||
284 | { | ||
285 | int flags; | ||
286 | bool is_bq27500 = di->chip == BQ27500; | ||
287 | bool is_bq27742 = di->chip == BQ27742; | ||
288 | bool is_higher = bq27xxx_is_chip_version_higher(di); | ||
289 | bool flags_1b = !(is_bq27500 || is_bq27742); | ||
290 | |||
291 | flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b); | ||
292 | if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI)) | ||
293 | return -ENODATA; | ||
294 | |||
295 | return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC); | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Return the battery Last measured discharge in µAh | ||
300 | * Or < 0 if something fails. | ||
301 | */ | ||
302 | static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di) | ||
303 | { | ||
304 | return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD); | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Return the battery Initial last measured discharge in µAh | ||
309 | * Or < 0 if something fails. | ||
310 | */ | ||
311 | static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di) | ||
312 | { | ||
313 | int ilmd; | ||
314 | |||
315 | if (bq27xxx_is_chip_version_higher(di)) { | ||
316 | if (di->chip == BQ27425) | ||
317 | ilmd = bq27x00_read(di, BQ27425_REG_DCAP, false); | ||
318 | else if (di->chip == BQ27510) | ||
319 | ilmd = bq27x00_read(di, BQ27510_REG_DCAP, false); | ||
320 | else | ||
321 | ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false); | ||
322 | } else { | ||
323 | ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true); | ||
324 | } | ||
325 | |||
326 | if (ilmd < 0) { | ||
327 | dev_dbg(di->dev, "error reading initial last measured discharge\n"); | ||
328 | return ilmd; | ||
329 | } | ||
330 | |||
331 | if (bq27xxx_is_chip_version_higher(di)) | ||
332 | ilmd *= 1000; | ||
333 | else | ||
334 | ilmd = ilmd * 256 * 3570 / BQ27000_RS; | ||
335 | |||
336 | return ilmd; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * Return the battery Available energy in µWh | ||
341 | * Or < 0 if something fails. | ||
342 | */ | ||
343 | static int bq27x00_battery_read_energy(struct bq27x00_device_info *di) | ||
344 | { | ||
345 | int ae; | ||
346 | |||
347 | ae = bq27x00_read(di, BQ27x00_REG_AE, false); | ||
348 | if (ae < 0) { | ||
349 | dev_dbg(di->dev, "error reading available energy\n"); | ||
350 | return ae; | ||
351 | } | ||
352 | |||
353 | if (di->chip == BQ27500) | ||
354 | ae *= 1000; | ||
355 | else | ||
356 | ae = ae * 29200 / BQ27000_RS; | ||
357 | |||
358 | return ae; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * Return the battery temperature in tenths of degree Kelvin | ||
363 | * Or < 0 if something fails. | ||
364 | */ | ||
365 | static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di) | ||
366 | { | ||
367 | int temp; | ||
368 | |||
369 | temp = bq27x00_read(di, BQ27x00_REG_TEMP, false); | ||
370 | if (temp < 0) { | ||
371 | dev_err(di->dev, "error reading temperature\n"); | ||
372 | return temp; | ||
373 | } | ||
374 | |||
375 | if (!bq27xxx_is_chip_version_higher(di)) | ||
376 | temp = 5 * temp / 2; | ||
377 | |||
378 | return temp; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * Return the battery Cycle count total | ||
383 | * Or < 0 if something fails. | ||
384 | */ | ||
385 | static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di) | ||
386 | { | ||
387 | int cyct; | ||
388 | |||
389 | if (di->chip == BQ27510) | ||
390 | cyct = bq27x00_read(di, BQ27510_REG_CYCT, false); | ||
391 | else | ||
392 | cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false); | ||
393 | if (cyct < 0) | ||
394 | dev_err(di->dev, "error reading cycle count total\n"); | ||
395 | |||
396 | return cyct; | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | * Read a time register. | ||
401 | * Return < 0 if something fails. | ||
402 | */ | ||
403 | static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg) | ||
404 | { | ||
405 | int tval; | ||
406 | |||
407 | tval = bq27x00_read(di, reg, false); | ||
408 | if (tval < 0) { | ||
409 | dev_dbg(di->dev, "error reading time register %02x: %d\n", | ||
410 | reg, tval); | ||
411 | return tval; | ||
412 | } | ||
413 | |||
414 | if (tval == 65535) | ||
415 | return -ENODATA; | ||
416 | |||
417 | return tval * 60; | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * Read a power avg register. | ||
422 | * Return < 0 if something fails. | ||
423 | */ | ||
424 | static int bq27x00_battery_read_pwr_avg(struct bq27x00_device_info *di, u8 reg) | ||
425 | { | ||
426 | int tval; | ||
427 | |||
428 | tval = bq27x00_read(di, reg, false); | ||
429 | if (tval < 0) { | ||
430 | dev_err(di->dev, "error reading power avg rgister %02x: %d\n", | ||
431 | reg, tval); | ||
432 | return tval; | ||
433 | } | ||
434 | |||
435 | if (di->chip == BQ27500) | ||
436 | return tval; | ||
437 | else | ||
438 | return (tval * BQ27x00_POWER_CONSTANT) / BQ27000_RS; | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Read flag register. | ||
443 | * Return < 0 if something fails. | ||
444 | */ | ||
445 | static int bq27x00_battery_read_health(struct bq27x00_device_info *di) | ||
446 | { | ||
447 | int tval; | ||
448 | |||
449 | tval = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | ||
450 | if (tval < 0) { | ||
451 | dev_err(di->dev, "error reading flag register:%d\n", tval); | ||
452 | return tval; | ||
453 | } | ||
454 | |||
455 | if (di->chip == BQ27500) { | ||
456 | if (tval & BQ27500_FLAG_SOCF) | ||
457 | tval = POWER_SUPPLY_HEALTH_DEAD; | ||
458 | else if (tval & BQ27500_FLAG_OTC) | ||
459 | tval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
460 | else | ||
461 | tval = POWER_SUPPLY_HEALTH_GOOD; | ||
462 | return tval; | ||
463 | } else if (di->chip == BQ27510) { | ||
464 | if (tval & BQ27500_FLAG_OTC) | ||
465 | return POWER_SUPPLY_HEALTH_OVERHEAT; | ||
466 | return POWER_SUPPLY_HEALTH_GOOD; | ||
467 | } else { | ||
468 | if (tval & BQ27000_FLAG_EDV1) | ||
469 | tval = POWER_SUPPLY_HEALTH_DEAD; | ||
470 | else | ||
471 | tval = POWER_SUPPLY_HEALTH_GOOD; | ||
472 | return tval; | ||
473 | } | ||
474 | |||
475 | return -1; | ||
476 | } | ||
477 | |||
478 | static void bq27x00_update(struct bq27x00_device_info *di) | ||
479 | { | ||
480 | struct bq27x00_reg_cache cache = {0, }; | ||
481 | bool is_bq27500 = di->chip == BQ27500; | ||
482 | bool is_bq27510 = di->chip == BQ27510; | ||
483 | bool is_bq27425 = di->chip == BQ27425; | ||
484 | bool is_bq27742 = di->chip == BQ27742; | ||
485 | bool flags_1b = !(is_bq27500 || is_bq27742); | ||
486 | |||
487 | cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b); | ||
488 | if ((cache.flags & 0xff) == 0xff) | ||
489 | /* read error */ | ||
490 | cache.flags = -1; | ||
491 | if (cache.flags >= 0) { | ||
492 | if (!is_bq27500 && !is_bq27425 && !is_bq27742 && !is_bq27510 | ||
493 | && (cache.flags & BQ27000_FLAG_CI)) { | ||
494 | dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); | ||
495 | cache.capacity = -ENODATA; | ||
496 | cache.energy = -ENODATA; | ||
497 | cache.time_to_empty = -ENODATA; | ||
498 | cache.time_to_empty_avg = -ENODATA; | ||
499 | cache.time_to_full = -ENODATA; | ||
500 | cache.charge_full = -ENODATA; | ||
501 | cache.health = -ENODATA; | ||
502 | } else { | ||
503 | cache.capacity = bq27x00_battery_read_rsoc(di); | ||
504 | if (is_bq27742 || is_bq27510) | ||
505 | cache.time_to_empty = | ||
506 | bq27x00_battery_read_time(di, | ||
507 | BQ27x00_REG_TTE); | ||
508 | else if (!is_bq27425) { | ||
509 | cache.energy = bq27x00_battery_read_energy(di); | ||
510 | cache.time_to_empty = | ||
511 | bq27x00_battery_read_time(di, | ||
512 | BQ27x00_REG_TTE); | ||
513 | cache.time_to_empty_avg = | ||
514 | bq27x00_battery_read_time(di, | ||
515 | BQ27x00_REG_TTECP); | ||
516 | cache.time_to_full = | ||
517 | bq27x00_battery_read_time(di, | ||
518 | BQ27x00_REG_TTF); | ||
519 | } | ||
520 | cache.charge_full = bq27x00_battery_read_lmd(di); | ||
521 | cache.health = bq27x00_battery_read_health(di); | ||
522 | } | ||
523 | cache.temperature = bq27x00_battery_read_temperature(di); | ||
524 | if (!is_bq27425) | ||
525 | cache.cycle_count = bq27x00_battery_read_cyct(di); | ||
526 | if (is_bq27742) | ||
527 | cache.power_avg = | ||
528 | bq27x00_battery_read_pwr_avg(di, | ||
529 | BQ27742_POWER_AVG); | ||
530 | else | ||
531 | cache.power_avg = | ||
532 | bq27x00_battery_read_pwr_avg(di, | ||
533 | BQ27x00_POWER_AVG); | ||
534 | |||
535 | /* We only have to read charge design full once */ | ||
536 | if (di->charge_design_full <= 0) | ||
537 | di->charge_design_full = bq27x00_battery_read_ilmd(di); | ||
538 | } | ||
539 | |||
540 | if (di->cache.capacity != cache.capacity) | ||
541 | power_supply_changed(di->bat); | ||
542 | |||
543 | if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) | ||
544 | di->cache = cache; | ||
545 | |||
546 | di->last_update = jiffies; | ||
547 | } | ||
548 | |||
549 | static void bq27x00_battery_poll(struct work_struct *work) | ||
550 | { | ||
551 | struct bq27x00_device_info *di = | ||
552 | container_of(work, struct bq27x00_device_info, work.work); | ||
553 | |||
554 | bq27x00_update(di); | ||
555 | |||
556 | if (poll_interval > 0) { | ||
557 | /* The timer does not have to be accurate. */ | ||
558 | set_timer_slack(&di->work.timer, poll_interval * HZ / 4); | ||
559 | schedule_delayed_work(&di->work, poll_interval * HZ); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | /* | ||
564 | * Return the battery average current in µA | ||
565 | * Note that current can be negative signed as well | ||
566 | * Or 0 if something fails. | ||
567 | */ | ||
568 | static int bq27x00_battery_current(struct bq27x00_device_info *di, | ||
569 | union power_supply_propval *val) | ||
570 | { | ||
571 | int curr; | ||
572 | int flags; | ||
573 | |||
574 | curr = bq27x00_read(di, BQ27x00_REG_AI, false); | ||
575 | if (curr < 0) { | ||
576 | dev_err(di->dev, "error reading current\n"); | ||
577 | return curr; | ||
578 | } | ||
579 | |||
580 | if (bq27xxx_is_chip_version_higher(di)) { | ||
581 | /* bq27500 returns signed value */ | ||
582 | val->intval = (int)((s16)curr) * 1000; | ||
583 | } else { | ||
584 | flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false); | ||
585 | if (flags & BQ27000_FLAG_CHGS) { | ||
586 | dev_dbg(di->dev, "negative current!\n"); | ||
587 | curr = -curr; | ||
588 | } | ||
589 | |||
590 | val->intval = curr * 3570 / BQ27000_RS; | ||
591 | } | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int bq27x00_battery_status(struct bq27x00_device_info *di, | ||
597 | union power_supply_propval *val) | ||
598 | { | ||
599 | int status; | ||
600 | |||
601 | if (bq27xxx_is_chip_version_higher(di)) { | ||
602 | if (di->cache.flags & BQ27500_FLAG_FC) | ||
603 | status = POWER_SUPPLY_STATUS_FULL; | ||
604 | else if (di->cache.flags & BQ27500_FLAG_DSC) | ||
605 | status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
606 | else | ||
607 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
608 | } else { | ||
609 | if (di->cache.flags & BQ27000_FLAG_FC) | ||
610 | status = POWER_SUPPLY_STATUS_FULL; | ||
611 | else if (di->cache.flags & BQ27000_FLAG_CHGS) | ||
612 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
613 | else if (power_supply_am_i_supplied(di->bat)) | ||
614 | status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
615 | else | ||
616 | status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
617 | } | ||
618 | |||
619 | val->intval = status; | ||
620 | |||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di, | ||
625 | union power_supply_propval *val) | ||
626 | { | ||
627 | int level; | ||
628 | |||
629 | if (bq27xxx_is_chip_version_higher(di)) { | ||
630 | if (di->cache.flags & BQ27500_FLAG_FC) | ||
631 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | ||
632 | else if (di->cache.flags & BQ27500_FLAG_SOC1) | ||
633 | level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
634 | else if (di->cache.flags & BQ27500_FLAG_SOCF) | ||
635 | level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
636 | else | ||
637 | level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
638 | } else { | ||
639 | if (di->cache.flags & BQ27000_FLAG_FC) | ||
640 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | ||
641 | else if (di->cache.flags & BQ27000_FLAG_EDV1) | ||
642 | level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
643 | else if (di->cache.flags & BQ27000_FLAG_EDVF) | ||
644 | level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
645 | else | ||
646 | level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
647 | } | ||
648 | |||
649 | val->intval = level; | ||
650 | |||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Return the battery Voltage in millivolts | ||
656 | * Or < 0 if something fails. | ||
657 | */ | ||
658 | static int bq27x00_battery_voltage(struct bq27x00_device_info *di, | ||
659 | union power_supply_propval *val) | ||
660 | { | ||
661 | int volt; | ||
662 | |||
663 | volt = bq27x00_read(di, BQ27x00_REG_VOLT, false); | ||
664 | if (volt < 0) { | ||
665 | dev_err(di->dev, "error reading voltage\n"); | ||
666 | return volt; | ||
667 | } | ||
668 | |||
669 | val->intval = volt * 1000; | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int bq27x00_simple_value(int value, | ||
675 | union power_supply_propval *val) | ||
676 | { | ||
677 | if (value < 0) | ||
678 | return value; | ||
679 | |||
680 | val->intval = value; | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | static int bq27x00_battery_get_property(struct power_supply *psy, | ||
686 | enum power_supply_property psp, | ||
687 | union power_supply_propval *val) | ||
688 | { | ||
689 | int ret = 0; | ||
690 | struct bq27x00_device_info *di = power_supply_get_drvdata(psy); | ||
691 | |||
692 | mutex_lock(&di->lock); | ||
693 | if (time_is_before_jiffies(di->last_update + 5 * HZ)) { | ||
694 | cancel_delayed_work_sync(&di->work); | ||
695 | bq27x00_battery_poll(&di->work.work); | ||
696 | } | ||
697 | mutex_unlock(&di->lock); | ||
698 | |||
699 | if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) | ||
700 | return -ENODEV; | ||
701 | |||
702 | switch (psp) { | ||
703 | case POWER_SUPPLY_PROP_STATUS: | ||
704 | ret = bq27x00_battery_status(di, val); | ||
705 | break; | ||
706 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
707 | ret = bq27x00_battery_voltage(di, val); | ||
708 | break; | ||
709 | case POWER_SUPPLY_PROP_PRESENT: | ||
710 | val->intval = di->cache.flags < 0 ? 0 : 1; | ||
711 | break; | ||
712 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
713 | ret = bq27x00_battery_current(di, val); | ||
714 | break; | ||
715 | case POWER_SUPPLY_PROP_CAPACITY: | ||
716 | ret = bq27x00_simple_value(di->cache.capacity, val); | ||
717 | break; | ||
718 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | ||
719 | ret = bq27x00_battery_capacity_level(di, val); | ||
720 | break; | ||
721 | case POWER_SUPPLY_PROP_TEMP: | ||
722 | ret = bq27x00_simple_value(di->cache.temperature, val); | ||
723 | if (ret == 0) | ||
724 | val->intval -= 2731; | ||
725 | break; | ||
726 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: | ||
727 | ret = bq27x00_simple_value(di->cache.time_to_empty, val); | ||
728 | break; | ||
729 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | ||
730 | ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val); | ||
731 | break; | ||
732 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: | ||
733 | ret = bq27x00_simple_value(di->cache.time_to_full, val); | ||
734 | break; | ||
735 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
736 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
737 | break; | ||
738 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
739 | ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val); | ||
740 | break; | ||
741 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
742 | ret = bq27x00_simple_value(di->cache.charge_full, val); | ||
743 | break; | ||
744 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
745 | ret = bq27x00_simple_value(di->charge_design_full, val); | ||
746 | break; | ||
747 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | ||
748 | ret = bq27x00_simple_value(di->cache.cycle_count, val); | ||
749 | break; | ||
750 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
751 | ret = bq27x00_simple_value(di->cache.energy, val); | ||
752 | break; | ||
753 | case POWER_SUPPLY_PROP_POWER_AVG: | ||
754 | ret = bq27x00_simple_value(di->cache.power_avg, val); | ||
755 | break; | ||
756 | case POWER_SUPPLY_PROP_HEALTH: | ||
757 | ret = bq27x00_simple_value(di->cache.health, val); | ||
758 | break; | ||
759 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
760 | val->strval = BQ27XXX_MANUFACTURER; | ||
761 | break; | ||
762 | default: | ||
763 | return -EINVAL; | ||
764 | } | ||
765 | |||
766 | return ret; | ||
767 | } | ||
768 | |||
769 | static void bq27x00_external_power_changed(struct power_supply *psy) | ||
770 | { | ||
771 | struct bq27x00_device_info *di = power_supply_get_drvdata(psy); | ||
772 | |||
773 | cancel_delayed_work_sync(&di->work); | ||
774 | schedule_delayed_work(&di->work, 0); | ||
775 | } | ||
776 | |||
777 | static int bq27x00_powersupply_init(struct bq27x00_device_info *di, | ||
778 | const char *name) | ||
779 | { | ||
780 | int ret; | ||
781 | struct power_supply_desc *psy_desc; | ||
782 | struct power_supply_config psy_cfg = { .drv_data = di, }; | ||
783 | |||
784 | psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL); | ||
785 | if (!psy_desc) | ||
786 | return -ENOMEM; | ||
787 | |||
788 | psy_desc->name = name; | ||
789 | psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; | ||
790 | if (di->chip == BQ27425) { | ||
791 | psy_desc->properties = bq27425_battery_props; | ||
792 | psy_desc->num_properties = ARRAY_SIZE(bq27425_battery_props); | ||
793 | } else if (di->chip == BQ27742) { | ||
794 | psy_desc->properties = bq27742_battery_props; | ||
795 | psy_desc->num_properties = ARRAY_SIZE(bq27742_battery_props); | ||
796 | } else if (di->chip == BQ27510) { | ||
797 | psy_desc->properties = bq27510_battery_props; | ||
798 | psy_desc->num_properties = ARRAY_SIZE(bq27510_battery_props); | ||
799 | } else { | ||
800 | psy_desc->properties = bq27x00_battery_props; | ||
801 | psy_desc->num_properties = ARRAY_SIZE(bq27x00_battery_props); | ||
802 | } | ||
803 | psy_desc->get_property = bq27x00_battery_get_property; | ||
804 | psy_desc->external_power_changed = bq27x00_external_power_changed; | ||
805 | |||
806 | INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll); | ||
807 | mutex_init(&di->lock); | ||
808 | |||
809 | di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); | ||
810 | if (IS_ERR(di->bat)) { | ||
811 | ret = PTR_ERR(di->bat); | ||
812 | dev_err(di->dev, "failed to register battery: %d\n", ret); | ||
813 | return ret; | ||
814 | } | ||
815 | |||
816 | dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); | ||
817 | |||
818 | bq27x00_update(di); | ||
819 | |||
820 | return 0; | ||
821 | } | ||
822 | |||
823 | static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di) | ||
824 | { | ||
825 | /* | ||
826 | * power_supply_unregister call bq27x00_battery_get_property which | ||
827 | * call bq27x00_battery_poll. | ||
828 | * Make sure that bq27x00_battery_poll will not call | ||
829 | * schedule_delayed_work again after unregister (which cause OOPS). | ||
830 | */ | ||
831 | poll_interval = 0; | ||
832 | |||
833 | cancel_delayed_work_sync(&di->work); | ||
834 | |||
835 | power_supply_unregister(di->bat); | ||
836 | |||
837 | mutex_destroy(&di->lock); | ||
838 | } | ||
839 | |||
840 | /* i2c specific code */ | ||
841 | #ifdef CONFIG_BATTERY_BQ27X00_I2C | ||
842 | |||
843 | /* If the system has several batteries we need a different name for each | ||
844 | * of them... | ||
845 | */ | ||
846 | static DEFINE_IDR(battery_id); | ||
847 | static DEFINE_MUTEX(battery_mutex); | ||
848 | |||
849 | static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single) | ||
850 | { | ||
851 | struct i2c_client *client = to_i2c_client(di->dev); | ||
852 | struct i2c_msg msg[2]; | ||
853 | unsigned char data[2]; | ||
854 | int ret; | ||
855 | |||
856 | if (!client->adapter) | ||
857 | return -ENODEV; | ||
858 | |||
859 | msg[0].addr = client->addr; | ||
860 | msg[0].flags = 0; | ||
861 | msg[0].buf = ® | ||
862 | msg[0].len = sizeof(reg); | ||
863 | msg[1].addr = client->addr; | ||
864 | msg[1].flags = I2C_M_RD; | ||
865 | msg[1].buf = data; | ||
866 | if (single) | ||
867 | msg[1].len = 1; | ||
868 | else | ||
869 | msg[1].len = 2; | ||
870 | |||
871 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
872 | if (ret < 0) | ||
873 | return ret; | ||
874 | |||
875 | if (!single) | ||
876 | ret = get_unaligned_le16(data); | ||
877 | else | ||
878 | ret = data[0]; | ||
879 | |||
880 | return ret; | ||
881 | } | ||
882 | |||
883 | static int bq27x00_battery_probe(struct i2c_client *client, | ||
884 | const struct i2c_device_id *id) | ||
885 | { | ||
886 | char *name; | ||
887 | struct bq27x00_device_info *di; | ||
888 | int num; | ||
889 | int retval = 0; | ||
890 | |||
891 | /* Get new ID for the new battery device */ | ||
892 | mutex_lock(&battery_mutex); | ||
893 | num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); | ||
894 | mutex_unlock(&battery_mutex); | ||
895 | if (num < 0) | ||
896 | return num; | ||
897 | |||
898 | name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); | ||
899 | if (!name) { | ||
900 | retval = -ENOMEM; | ||
901 | goto batt_failed; | ||
902 | } | ||
903 | |||
904 | di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); | ||
905 | if (!di) { | ||
906 | retval = -ENOMEM; | ||
907 | goto batt_failed; | ||
908 | } | ||
909 | |||
910 | di->id = num; | ||
911 | di->dev = &client->dev; | ||
912 | di->chip = id->driver_data; | ||
913 | di->bus.read = &bq27x00_read_i2c; | ||
914 | |||
915 | retval = bq27x00_powersupply_init(di, name); | ||
916 | if (retval) | ||
917 | goto batt_failed; | ||
918 | |||
919 | i2c_set_clientdata(client, di); | ||
920 | |||
921 | return 0; | ||
922 | |||
923 | batt_failed: | ||
924 | mutex_lock(&battery_mutex); | ||
925 | idr_remove(&battery_id, num); | ||
926 | mutex_unlock(&battery_mutex); | ||
927 | |||
928 | return retval; | ||
929 | } | ||
930 | |||
931 | static int bq27x00_battery_remove(struct i2c_client *client) | ||
932 | { | ||
933 | struct bq27x00_device_info *di = i2c_get_clientdata(client); | ||
934 | |||
935 | bq27x00_powersupply_unregister(di); | ||
936 | |||
937 | mutex_lock(&battery_mutex); | ||
938 | idr_remove(&battery_id, di->id); | ||
939 | mutex_unlock(&battery_mutex); | ||
940 | |||
941 | return 0; | ||
942 | } | ||
943 | |||
944 | static const struct i2c_device_id bq27x00_id[] = { | ||
945 | { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ | ||
946 | { "bq27500", BQ27500 }, | ||
947 | { "bq27425", BQ27425 }, | ||
948 | { "bq27742", BQ27742 }, | ||
949 | { "bq27510", BQ27510 }, | ||
950 | {}, | ||
951 | }; | ||
952 | MODULE_DEVICE_TABLE(i2c, bq27x00_id); | ||
953 | |||
954 | static struct i2c_driver bq27x00_battery_driver = { | ||
955 | .driver = { | ||
956 | .name = "bq27x00-battery", | ||
957 | }, | ||
958 | .probe = bq27x00_battery_probe, | ||
959 | .remove = bq27x00_battery_remove, | ||
960 | .id_table = bq27x00_id, | ||
961 | }; | ||
962 | |||
963 | static inline int bq27x00_battery_i2c_init(void) | ||
964 | { | ||
965 | int ret = i2c_add_driver(&bq27x00_battery_driver); | ||
966 | |||
967 | if (ret) | ||
968 | pr_err("Unable to register BQ27x00 i2c driver\n"); | ||
969 | |||
970 | return ret; | ||
971 | } | ||
972 | |||
973 | static inline void bq27x00_battery_i2c_exit(void) | ||
974 | { | ||
975 | i2c_del_driver(&bq27x00_battery_driver); | ||
976 | } | ||
977 | |||
978 | #else | ||
979 | |||
980 | static inline int bq27x00_battery_i2c_init(void) { return 0; } | ||
981 | static inline void bq27x00_battery_i2c_exit(void) {}; | ||
982 | |||
983 | #endif | ||
984 | |||
985 | /* platform specific code */ | ||
986 | #ifdef CONFIG_BATTERY_BQ27X00_PLATFORM | ||
987 | |||
988 | static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg, | ||
989 | bool single) | ||
990 | { | ||
991 | struct device *dev = di->dev; | ||
992 | struct bq27000_platform_data *pdata = dev->platform_data; | ||
993 | unsigned int timeout = 3; | ||
994 | int upper, lower; | ||
995 | int temp; | ||
996 | |||
997 | if (!single) { | ||
998 | /* Make sure the value has not changed in between reading the | ||
999 | * lower and the upper part */ | ||
1000 | upper = pdata->read(dev, reg + 1); | ||
1001 | do { | ||
1002 | temp = upper; | ||
1003 | if (upper < 0) | ||
1004 | return upper; | ||
1005 | |||
1006 | lower = pdata->read(dev, reg); | ||
1007 | if (lower < 0) | ||
1008 | return lower; | ||
1009 | |||
1010 | upper = pdata->read(dev, reg + 1); | ||
1011 | } while (temp != upper && --timeout); | ||
1012 | |||
1013 | if (timeout == 0) | ||
1014 | return -EIO; | ||
1015 | |||
1016 | return (upper << 8) | lower; | ||
1017 | } | ||
1018 | |||
1019 | return pdata->read(dev, reg); | ||
1020 | } | ||
1021 | |||
1022 | static int bq27000_battery_probe(struct platform_device *pdev) | ||
1023 | { | ||
1024 | struct bq27x00_device_info *di; | ||
1025 | struct bq27000_platform_data *pdata = pdev->dev.platform_data; | ||
1026 | const char *name; | ||
1027 | |||
1028 | if (!pdata) { | ||
1029 | dev_err(&pdev->dev, "no platform_data supplied\n"); | ||
1030 | return -EINVAL; | ||
1031 | } | ||
1032 | |||
1033 | if (!pdata->read) { | ||
1034 | dev_err(&pdev->dev, "no hdq read callback supplied\n"); | ||
1035 | return -EINVAL; | ||
1036 | } | ||
1037 | |||
1038 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | ||
1039 | if (!di) | ||
1040 | return -ENOMEM; | ||
1041 | |||
1042 | platform_set_drvdata(pdev, di); | ||
1043 | |||
1044 | di->dev = &pdev->dev; | ||
1045 | di->chip = BQ27000; | ||
1046 | |||
1047 | name = pdata->name ?: dev_name(&pdev->dev); | ||
1048 | di->bus.read = &bq27000_read_platform; | ||
1049 | |||
1050 | return bq27x00_powersupply_init(di, name); | ||
1051 | } | ||
1052 | |||
1053 | static int bq27000_battery_remove(struct platform_device *pdev) | ||
1054 | { | ||
1055 | struct bq27x00_device_info *di = platform_get_drvdata(pdev); | ||
1056 | |||
1057 | bq27x00_powersupply_unregister(di); | ||
1058 | |||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static struct platform_driver bq27000_battery_driver = { | ||
1063 | .probe = bq27000_battery_probe, | ||
1064 | .remove = bq27000_battery_remove, | ||
1065 | .driver = { | ||
1066 | .name = "bq27000-battery", | ||
1067 | }, | ||
1068 | }; | ||
1069 | |||
1070 | static inline int bq27x00_battery_platform_init(void) | ||
1071 | { | ||
1072 | int ret = platform_driver_register(&bq27000_battery_driver); | ||
1073 | |||
1074 | if (ret) | ||
1075 | pr_err("Unable to register BQ27000 platform driver\n"); | ||
1076 | |||
1077 | return ret; | ||
1078 | } | ||
1079 | |||
1080 | static inline void bq27x00_battery_platform_exit(void) | ||
1081 | { | ||
1082 | platform_driver_unregister(&bq27000_battery_driver); | ||
1083 | } | ||
1084 | |||
1085 | #else | ||
1086 | |||
1087 | static inline int bq27x00_battery_platform_init(void) { return 0; } | ||
1088 | static inline void bq27x00_battery_platform_exit(void) {}; | ||
1089 | |||
1090 | #endif | ||
1091 | |||
1092 | /* | ||
1093 | * Module stuff | ||
1094 | */ | ||
1095 | |||
1096 | static int __init bq27x00_battery_init(void) | ||
1097 | { | ||
1098 | int ret; | ||
1099 | |||
1100 | ret = bq27x00_battery_i2c_init(); | ||
1101 | if (ret) | ||
1102 | return ret; | ||
1103 | |||
1104 | ret = bq27x00_battery_platform_init(); | ||
1105 | if (ret) | ||
1106 | bq27x00_battery_i2c_exit(); | ||
1107 | |||
1108 | return ret; | ||
1109 | } | ||
1110 | module_init(bq27x00_battery_init); | ||
1111 | |||
1112 | static void __exit bq27x00_battery_exit(void) | ||
1113 | { | ||
1114 | bq27x00_battery_platform_exit(); | ||
1115 | bq27x00_battery_i2c_exit(); | ||
1116 | } | ||
1117 | module_exit(bq27x00_battery_exit); | ||
1118 | |||
1119 | #ifdef CONFIG_BATTERY_BQ27X00_PLATFORM | ||
1120 | MODULE_ALIAS("platform:bq27000-battery"); | ||
1121 | #endif | ||
1122 | |||
1123 | #ifdef CONFIG_BATTERY_BQ27X00_I2C | ||
1124 | MODULE_ALIAS("i2c:bq27000-battery"); | ||
1125 | #endif | ||
1126 | |||
1127 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
1128 | MODULE_DESCRIPTION("BQ27x00 battery monitor driver"); | ||
1129 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/bq27xxx_battery.c b/drivers/power/bq27xxx_battery.c new file mode 100644 index 000000000000..880233ce9343 --- /dev/null +++ b/drivers/power/bq27xxx_battery.c | |||
@@ -0,0 +1,1375 @@ | |||
1 | /* | ||
2 | * BQ27xxx battery driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it> | ||
5 | * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it> | ||
6 | * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de> | ||
7 | * Copyright (C) 2011 Pali Rohár <pali.rohar@gmail.com> | ||
8 | * | ||
9 | * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc. | ||
10 | * | ||
11 | * This package is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | ||
17 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | * | ||
19 | * Datasheets: | ||
20 | * http://www.ti.com/product/bq27000 | ||
21 | * http://www.ti.com/product/bq27200 | ||
22 | * http://www.ti.com/product/bq27010 | ||
23 | * http://www.ti.com/product/bq27210 | ||
24 | * http://www.ti.com/product/bq27500 | ||
25 | * http://www.ti.com/product/bq27510-g3 | ||
26 | * http://www.ti.com/product/bq27520-g4 | ||
27 | * http://www.ti.com/product/bq27530-g1 | ||
28 | * http://www.ti.com/product/bq27531-g1 | ||
29 | * http://www.ti.com/product/bq27541-g1 | ||
30 | * http://www.ti.com/product/bq27542-g1 | ||
31 | * http://www.ti.com/product/bq27546-g1 | ||
32 | * http://www.ti.com/product/bq27742-g1 | ||
33 | * http://www.ti.com/product/bq27545-g1 | ||
34 | * http://www.ti.com/product/bq27421-g1 | ||
35 | * http://www.ti.com/product/bq27425-g1 | ||
36 | * http://www.ti.com/product/bq27411-g1 | ||
37 | * http://www.ti.com/product/bq27621-g1 | ||
38 | */ | ||
39 | |||
40 | #include <linux/device.h> | ||
41 | #include <linux/module.h> | ||
42 | #include <linux/param.h> | ||
43 | #include <linux/jiffies.h> | ||
44 | #include <linux/workqueue.h> | ||
45 | #include <linux/delay.h> | ||
46 | #include <linux/platform_device.h> | ||
47 | #include <linux/power_supply.h> | ||
48 | #include <linux/idr.h> | ||
49 | #include <linux/i2c.h> | ||
50 | #include <linux/slab.h> | ||
51 | #include <linux/interrupt.h> | ||
52 | #include <asm/unaligned.h> | ||
53 | |||
54 | #include <linux/power/bq27xxx_battery.h> | ||
55 | |||
56 | #define DRIVER_VERSION "1.2.0" | ||
57 | |||
58 | #define BQ27XXX_MANUFACTURER "Texas Instruments" | ||
59 | |||
60 | /* BQ27XXX Flags */ | ||
61 | #define BQ27XXX_FLAG_DSC BIT(0) | ||
62 | #define BQ27XXX_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ | ||
63 | #define BQ27XXX_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ | ||
64 | #define BQ27XXX_FLAG_FC BIT(9) | ||
65 | #define BQ27XXX_FLAG_OTD BIT(14) | ||
66 | #define BQ27XXX_FLAG_OTC BIT(15) | ||
67 | #define BQ27XXX_FLAG_UT BIT(14) | ||
68 | #define BQ27XXX_FLAG_OT BIT(15) | ||
69 | |||
70 | /* BQ27000 has different layout for Flags register */ | ||
71 | #define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */ | ||
72 | #define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */ | ||
73 | #define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */ | ||
74 | #define BQ27000_FLAG_FC BIT(5) | ||
75 | #define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */ | ||
76 | |||
77 | #define BQ27XXX_RS (20) /* Resistor sense mOhm */ | ||
78 | #define BQ27XXX_POWER_CONSTANT (29200) /* 29.2 µV^2 * 1000 */ | ||
79 | #define BQ27XXX_CURRENT_CONSTANT (3570) /* 3.57 µV * 1000 */ | ||
80 | |||
81 | struct bq27xxx_device_info; | ||
82 | struct bq27xxx_access_methods { | ||
83 | int (*read)(struct bq27xxx_device_info *di, u8 reg, bool single); | ||
84 | }; | ||
85 | |||
86 | #define INVALID_REG_ADDR 0xff | ||
87 | |||
88 | /* | ||
89 | * bq27xxx_reg_index - Register names | ||
90 | * | ||
91 | * These are indexes into a device's register mapping array. | ||
92 | */ | ||
93 | enum bq27xxx_reg_index { | ||
94 | BQ27XXX_REG_CTRL = 0, /* Control */ | ||
95 | BQ27XXX_REG_TEMP, /* Temperature */ | ||
96 | BQ27XXX_REG_INT_TEMP, /* Internal Temperature */ | ||
97 | BQ27XXX_REG_VOLT, /* Voltage */ | ||
98 | BQ27XXX_REG_AI, /* Average Current */ | ||
99 | BQ27XXX_REG_FLAGS, /* Flags */ | ||
100 | BQ27XXX_REG_TTE, /* Time-to-Empty */ | ||
101 | BQ27XXX_REG_TTF, /* Time-to-Full */ | ||
102 | BQ27XXX_REG_TTES, /* Time-to-Empty Standby */ | ||
103 | BQ27XXX_REG_TTECP, /* Time-to-Empty at Constant Power */ | ||
104 | BQ27XXX_REG_NAC, /* Nominal Available Capacity */ | ||
105 | BQ27XXX_REG_FCC, /* Full Charge Capacity */ | ||
106 | BQ27XXX_REG_CYCT, /* Cycle Count */ | ||
107 | BQ27XXX_REG_AE, /* Available Energy */ | ||
108 | BQ27XXX_REG_SOC, /* State-of-Charge */ | ||
109 | BQ27XXX_REG_DCAP, /* Design Capacity */ | ||
110 | BQ27XXX_REG_AP, /* Average Power */ | ||
111 | }; | ||
112 | |||
113 | struct bq27xxx_reg_cache { | ||
114 | int temperature; | ||
115 | int time_to_empty; | ||
116 | int time_to_empty_avg; | ||
117 | int time_to_full; | ||
118 | int charge_full; | ||
119 | int cycle_count; | ||
120 | int capacity; | ||
121 | int energy; | ||
122 | int flags; | ||
123 | int power_avg; | ||
124 | int health; | ||
125 | }; | ||
126 | |||
127 | struct bq27xxx_device_info { | ||
128 | struct device *dev; | ||
129 | int id; | ||
130 | enum bq27xxx_chip chip; | ||
131 | |||
132 | struct bq27xxx_reg_cache cache; | ||
133 | int charge_design_full; | ||
134 | |||
135 | unsigned long last_update; | ||
136 | struct delayed_work work; | ||
137 | |||
138 | struct power_supply *bat; | ||
139 | |||
140 | struct bq27xxx_access_methods bus; | ||
141 | |||
142 | struct mutex lock; | ||
143 | |||
144 | u8 *regs; | ||
145 | }; | ||
146 | |||
147 | /* Register mappings */ | ||
148 | static u8 bq27000_regs[] = { | ||
149 | 0x00, /* CONTROL */ | ||
150 | 0x06, /* TEMP */ | ||
151 | INVALID_REG_ADDR, /* INT TEMP - NA*/ | ||
152 | 0x08, /* VOLT */ | ||
153 | 0x14, /* AVG CURR */ | ||
154 | 0x0a, /* FLAGS */ | ||
155 | 0x16, /* TTE */ | ||
156 | 0x18, /* TTF */ | ||
157 | 0x1c, /* TTES */ | ||
158 | 0x26, /* TTECP */ | ||
159 | 0x0c, /* NAC */ | ||
160 | 0x12, /* LMD(FCC) */ | ||
161 | 0x2a, /* CYCT */ | ||
162 | 0x22, /* AE */ | ||
163 | 0x0b, /* SOC(RSOC) */ | ||
164 | 0x76, /* DCAP(ILMD) */ | ||
165 | 0x24, /* AP */ | ||
166 | }; | ||
167 | |||
168 | static u8 bq27010_regs[] = { | ||
169 | 0x00, /* CONTROL */ | ||
170 | 0x06, /* TEMP */ | ||
171 | INVALID_REG_ADDR, /* INT TEMP - NA*/ | ||
172 | 0x08, /* VOLT */ | ||
173 | 0x14, /* AVG CURR */ | ||
174 | 0x0a, /* FLAGS */ | ||
175 | 0x16, /* TTE */ | ||
176 | 0x18, /* TTF */ | ||
177 | 0x1c, /* TTES */ | ||
178 | 0x26, /* TTECP */ | ||
179 | 0x0c, /* NAC */ | ||
180 | 0x12, /* LMD(FCC) */ | ||
181 | 0x2a, /* CYCT */ | ||
182 | INVALID_REG_ADDR, /* AE - NA */ | ||
183 | 0x0b, /* SOC(RSOC) */ | ||
184 | 0x76, /* DCAP(ILMD) */ | ||
185 | INVALID_REG_ADDR, /* AP - NA */ | ||
186 | }; | ||
187 | |||
188 | static u8 bq27500_regs[] = { | ||
189 | 0x00, /* CONTROL */ | ||
190 | 0x06, /* TEMP */ | ||
191 | 0x28, /* INT TEMP */ | ||
192 | 0x08, /* VOLT */ | ||
193 | 0x14, /* AVG CURR */ | ||
194 | 0x0a, /* FLAGS */ | ||
195 | 0x16, /* TTE */ | ||
196 | INVALID_REG_ADDR, /* TTF - NA */ | ||
197 | 0x1a, /* TTES */ | ||
198 | INVALID_REG_ADDR, /* TTECP - NA */ | ||
199 | 0x0c, /* NAC */ | ||
200 | 0x12, /* LMD(FCC) */ | ||
201 | 0x1e, /* CYCT */ | ||
202 | INVALID_REG_ADDR, /* AE - NA */ | ||
203 | 0x20, /* SOC(RSOC) */ | ||
204 | 0x2e, /* DCAP(ILMD) */ | ||
205 | INVALID_REG_ADDR, /* AP - NA */ | ||
206 | }; | ||
207 | |||
208 | static u8 bq27530_regs[] = { | ||
209 | 0x00, /* CONTROL */ | ||
210 | 0x06, /* TEMP */ | ||
211 | 0x32, /* INT TEMP */ | ||
212 | 0x08, /* VOLT */ | ||
213 | 0x14, /* AVG CURR */ | ||
214 | 0x0a, /* FLAGS */ | ||
215 | 0x16, /* TTE */ | ||
216 | INVALID_REG_ADDR, /* TTF - NA */ | ||
217 | INVALID_REG_ADDR, /* TTES - NA */ | ||
218 | INVALID_REG_ADDR, /* TTECP - NA */ | ||
219 | 0x0c, /* NAC */ | ||
220 | 0x12, /* LMD(FCC) */ | ||
221 | 0x2a, /* CYCT */ | ||
222 | INVALID_REG_ADDR, /* AE - NA */ | ||
223 | 0x2c, /* SOC(RSOC) */ | ||
224 | INVALID_REG_ADDR, /* DCAP - NA */ | ||
225 | 0x24, /* AP */ | ||
226 | }; | ||
227 | |||
228 | static u8 bq27541_regs[] = { | ||
229 | 0x00, /* CONTROL */ | ||
230 | 0x06, /* TEMP */ | ||
231 | 0x28, /* INT TEMP */ | ||
232 | 0x08, /* VOLT */ | ||
233 | 0x14, /* AVG CURR */ | ||
234 | 0x0a, /* FLAGS */ | ||
235 | 0x16, /* TTE */ | ||
236 | INVALID_REG_ADDR, /* TTF - NA */ | ||
237 | INVALID_REG_ADDR, /* TTES - NA */ | ||
238 | INVALID_REG_ADDR, /* TTECP - NA */ | ||
239 | 0x0c, /* NAC */ | ||
240 | 0x12, /* LMD(FCC) */ | ||
241 | 0x2a, /* CYCT */ | ||
242 | INVALID_REG_ADDR, /* AE - NA */ | ||
243 | 0x2c, /* SOC(RSOC) */ | ||
244 | 0x3c, /* DCAP */ | ||
245 | 0x76, /* AP */ | ||
246 | }; | ||
247 | |||
248 | static u8 bq27545_regs[] = { | ||
249 | 0x00, /* CONTROL */ | ||
250 | 0x06, /* TEMP */ | ||
251 | 0x28, /* INT TEMP */ | ||
252 | 0x08, /* VOLT */ | ||
253 | 0x14, /* AVG CURR */ | ||
254 | 0x0a, /* FLAGS */ | ||
255 | 0x16, /* TTE */ | ||
256 | INVALID_REG_ADDR, /* TTF - NA */ | ||
257 | INVALID_REG_ADDR, /* TTES - NA */ | ||
258 | INVALID_REG_ADDR, /* TTECP - NA */ | ||
259 | 0x0c, /* NAC */ | ||
260 | 0x12, /* LMD(FCC) */ | ||
261 | 0x2a, /* CYCT */ | ||
262 | INVALID_REG_ADDR, /* AE - NA */ | ||
263 | 0x2c, /* SOC(RSOC) */ | ||
264 | INVALID_REG_ADDR, /* DCAP - NA */ | ||
265 | 0x24, /* AP */ | ||
266 | }; | ||
267 | |||
268 | static u8 bq27421_regs[] = { | ||
269 | 0x00, /* CONTROL */ | ||
270 | 0x02, /* TEMP */ | ||
271 | 0x1e, /* INT TEMP */ | ||
272 | 0x04, /* VOLT */ | ||
273 | 0x10, /* AVG CURR */ | ||
274 | 0x06, /* FLAGS */ | ||
275 | INVALID_REG_ADDR, /* TTE - NA */ | ||
276 | INVALID_REG_ADDR, /* TTF - NA */ | ||
277 | INVALID_REG_ADDR, /* TTES - NA */ | ||
278 | INVALID_REG_ADDR, /* TTECP - NA */ | ||
279 | 0x08, /* NAC */ | ||
280 | 0x0e, /* FCC */ | ||
281 | INVALID_REG_ADDR, /* CYCT - NA */ | ||
282 | INVALID_REG_ADDR, /* AE - NA */ | ||
283 | 0x1c, /* SOC */ | ||
284 | 0x3c, /* DCAP */ | ||
285 | 0x18, /* AP */ | ||
286 | }; | ||
287 | |||
288 | static u8 *bq27xxx_regs[] = { | ||
289 | [BQ27000] = bq27000_regs, | ||
290 | [BQ27010] = bq27010_regs, | ||
291 | [BQ27500] = bq27500_regs, | ||
292 | [BQ27530] = bq27530_regs, | ||
293 | [BQ27541] = bq27541_regs, | ||
294 | [BQ27545] = bq27545_regs, | ||
295 | [BQ27421] = bq27421_regs, | ||
296 | }; | ||
297 | |||
298 | static enum power_supply_property bq27000_battery_props[] = { | ||
299 | POWER_SUPPLY_PROP_STATUS, | ||
300 | POWER_SUPPLY_PROP_PRESENT, | ||
301 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
302 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
303 | POWER_SUPPLY_PROP_CAPACITY, | ||
304 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
305 | POWER_SUPPLY_PROP_TEMP, | ||
306 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
307 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | ||
308 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, | ||
309 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
310 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
311 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
312 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
313 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
314 | POWER_SUPPLY_PROP_ENERGY_NOW, | ||
315 | POWER_SUPPLY_PROP_POWER_AVG, | ||
316 | POWER_SUPPLY_PROP_HEALTH, | ||
317 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
318 | }; | ||
319 | |||
320 | static enum power_supply_property bq27010_battery_props[] = { | ||
321 | POWER_SUPPLY_PROP_STATUS, | ||
322 | POWER_SUPPLY_PROP_PRESENT, | ||
323 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
324 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
325 | POWER_SUPPLY_PROP_CAPACITY, | ||
326 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
327 | POWER_SUPPLY_PROP_TEMP, | ||
328 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
329 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, | ||
330 | POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, | ||
331 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
332 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
333 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
334 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
335 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
336 | POWER_SUPPLY_PROP_HEALTH, | ||
337 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
338 | }; | ||
339 | |||
340 | static enum power_supply_property bq27500_battery_props[] = { | ||
341 | POWER_SUPPLY_PROP_STATUS, | ||
342 | POWER_SUPPLY_PROP_PRESENT, | ||
343 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
344 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
345 | POWER_SUPPLY_PROP_CAPACITY, | ||
346 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
347 | POWER_SUPPLY_PROP_TEMP, | ||
348 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
349 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
350 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
351 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
352 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
353 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
354 | POWER_SUPPLY_PROP_HEALTH, | ||
355 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
356 | }; | ||
357 | |||
358 | static enum power_supply_property bq27530_battery_props[] = { | ||
359 | POWER_SUPPLY_PROP_STATUS, | ||
360 | POWER_SUPPLY_PROP_PRESENT, | ||
361 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
362 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
363 | POWER_SUPPLY_PROP_CAPACITY, | ||
364 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
365 | POWER_SUPPLY_PROP_TEMP, | ||
366 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
367 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
368 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
369 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
370 | POWER_SUPPLY_PROP_POWER_AVG, | ||
371 | POWER_SUPPLY_PROP_HEALTH, | ||
372 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
373 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
374 | }; | ||
375 | |||
376 | static enum power_supply_property bq27541_battery_props[] = { | ||
377 | POWER_SUPPLY_PROP_STATUS, | ||
378 | POWER_SUPPLY_PROP_PRESENT, | ||
379 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
380 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
381 | POWER_SUPPLY_PROP_CAPACITY, | ||
382 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
383 | POWER_SUPPLY_PROP_TEMP, | ||
384 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
385 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
386 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
387 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
388 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
389 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
390 | POWER_SUPPLY_PROP_POWER_AVG, | ||
391 | POWER_SUPPLY_PROP_HEALTH, | ||
392 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
393 | }; | ||
394 | |||
395 | static enum power_supply_property bq27545_battery_props[] = { | ||
396 | POWER_SUPPLY_PROP_STATUS, | ||
397 | POWER_SUPPLY_PROP_PRESENT, | ||
398 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
399 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
400 | POWER_SUPPLY_PROP_CAPACITY, | ||
401 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
402 | POWER_SUPPLY_PROP_TEMP, | ||
403 | POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, | ||
404 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
405 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
406 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
407 | POWER_SUPPLY_PROP_HEALTH, | ||
408 | POWER_SUPPLY_PROP_CYCLE_COUNT, | ||
409 | POWER_SUPPLY_PROP_POWER_AVG, | ||
410 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
411 | }; | ||
412 | |||
413 | static enum power_supply_property bq27421_battery_props[] = { | ||
414 | POWER_SUPPLY_PROP_STATUS, | ||
415 | POWER_SUPPLY_PROP_PRESENT, | ||
416 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
417 | POWER_SUPPLY_PROP_CURRENT_NOW, | ||
418 | POWER_SUPPLY_PROP_CAPACITY, | ||
419 | POWER_SUPPLY_PROP_CAPACITY_LEVEL, | ||
420 | POWER_SUPPLY_PROP_TEMP, | ||
421 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
422 | POWER_SUPPLY_PROP_CHARGE_FULL, | ||
423 | POWER_SUPPLY_PROP_CHARGE_NOW, | ||
424 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
425 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
426 | }; | ||
427 | |||
428 | #define BQ27XXX_PROP(_id, _prop) \ | ||
429 | [_id] = { \ | ||
430 | .props = _prop, \ | ||
431 | .size = ARRAY_SIZE(_prop), \ | ||
432 | } | ||
433 | |||
434 | static struct { | ||
435 | enum power_supply_property *props; | ||
436 | size_t size; | ||
437 | } bq27xxx_battery_props[] = { | ||
438 | BQ27XXX_PROP(BQ27000, bq27000_battery_props), | ||
439 | BQ27XXX_PROP(BQ27010, bq27010_battery_props), | ||
440 | BQ27XXX_PROP(BQ27500, bq27500_battery_props), | ||
441 | BQ27XXX_PROP(BQ27530, bq27530_battery_props), | ||
442 | BQ27XXX_PROP(BQ27541, bq27541_battery_props), | ||
443 | BQ27XXX_PROP(BQ27545, bq27545_battery_props), | ||
444 | BQ27XXX_PROP(BQ27421, bq27421_battery_props), | ||
445 | }; | ||
446 | |||
447 | static unsigned int poll_interval = 360; | ||
448 | module_param(poll_interval, uint, 0644); | ||
449 | MODULE_PARM_DESC(poll_interval, | ||
450 | "battery poll interval in seconds - 0 disables polling"); | ||
451 | |||
452 | /* | ||
453 | * Common code for BQ27xxx devices | ||
454 | */ | ||
455 | |||
456 | static inline int bq27xxx_read(struct bq27xxx_device_info *di, int reg_index, | ||
457 | bool single) | ||
458 | { | ||
459 | /* Reports EINVAL for invalid/missing registers */ | ||
460 | if (!di || di->regs[reg_index] == INVALID_REG_ADDR) | ||
461 | return -EINVAL; | ||
462 | |||
463 | return di->bus.read(di, di->regs[reg_index], single); | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Return the battery State-of-Charge | ||
468 | * Or < 0 if something fails. | ||
469 | */ | ||
470 | static int bq27xxx_battery_read_soc(struct bq27xxx_device_info *di) | ||
471 | { | ||
472 | int soc; | ||
473 | |||
474 | soc = bq27xxx_read(di, BQ27XXX_REG_SOC, false); | ||
475 | |||
476 | if (soc < 0) | ||
477 | dev_dbg(di->dev, "error reading State-of-Charge\n"); | ||
478 | |||
479 | return soc; | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * Return a battery charge value in µAh | ||
484 | * Or < 0 if something fails. | ||
485 | */ | ||
486 | static int bq27xxx_battery_read_charge(struct bq27xxx_device_info *di, u8 reg) | ||
487 | { | ||
488 | int charge; | ||
489 | |||
490 | charge = bq27xxx_read(di, reg, false); | ||
491 | if (charge < 0) { | ||
492 | dev_dbg(di->dev, "error reading charge register %02x: %d\n", | ||
493 | reg, charge); | ||
494 | return charge; | ||
495 | } | ||
496 | |||
497 | if (di->chip == BQ27000 || di->chip == BQ27010) | ||
498 | charge *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; | ||
499 | else | ||
500 | charge *= 1000; | ||
501 | |||
502 | return charge; | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * Return the battery Nominal available capacity in µAh | ||
507 | * Or < 0 if something fails. | ||
508 | */ | ||
509 | static inline int bq27xxx_battery_read_nac(struct bq27xxx_device_info *di) | ||
510 | { | ||
511 | int flags; | ||
512 | |||
513 | if (di->chip == BQ27000 || di->chip == BQ27010) { | ||
514 | flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, true); | ||
515 | if (flags >= 0 && (flags & BQ27000_FLAG_CI)) | ||
516 | return -ENODATA; | ||
517 | } | ||
518 | |||
519 | return bq27xxx_battery_read_charge(di, BQ27XXX_REG_NAC); | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * Return the battery Full Charge Capacity in µAh | ||
524 | * Or < 0 if something fails. | ||
525 | */ | ||
526 | static inline int bq27xxx_battery_read_fcc(struct bq27xxx_device_info *di) | ||
527 | { | ||
528 | return bq27xxx_battery_read_charge(di, BQ27XXX_REG_FCC); | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Return the Design Capacity in µAh | ||
533 | * Or < 0 if something fails. | ||
534 | */ | ||
535 | static int bq27xxx_battery_read_dcap(struct bq27xxx_device_info *di) | ||
536 | { | ||
537 | int dcap; | ||
538 | |||
539 | dcap = bq27xxx_read(di, BQ27XXX_REG_DCAP, false); | ||
540 | |||
541 | if (dcap < 0) { | ||
542 | dev_dbg(di->dev, "error reading initial last measured discharge\n"); | ||
543 | return dcap; | ||
544 | } | ||
545 | |||
546 | if (di->chip == BQ27000 || di->chip == BQ27010) | ||
547 | dcap *= BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; | ||
548 | else | ||
549 | dcap *= 1000; | ||
550 | |||
551 | return dcap; | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Return the battery Available energy in µWh | ||
556 | * Or < 0 if something fails. | ||
557 | */ | ||
558 | static int bq27xxx_battery_read_energy(struct bq27xxx_device_info *di) | ||
559 | { | ||
560 | int ae; | ||
561 | |||
562 | ae = bq27xxx_read(di, BQ27XXX_REG_AE, false); | ||
563 | if (ae < 0) { | ||
564 | dev_dbg(di->dev, "error reading available energy\n"); | ||
565 | return ae; | ||
566 | } | ||
567 | |||
568 | if (di->chip == BQ27000 || di->chip == BQ27010) | ||
569 | ae *= BQ27XXX_POWER_CONSTANT / BQ27XXX_RS; | ||
570 | else | ||
571 | ae *= 1000; | ||
572 | |||
573 | return ae; | ||
574 | } | ||
575 | |||
576 | /* | ||
577 | * Return the battery temperature in tenths of degree Kelvin | ||
578 | * Or < 0 if something fails. | ||
579 | */ | ||
580 | static int bq27xxx_battery_read_temperature(struct bq27xxx_device_info *di) | ||
581 | { | ||
582 | int temp; | ||
583 | |||
584 | temp = bq27xxx_read(di, BQ27XXX_REG_TEMP, false); | ||
585 | if (temp < 0) { | ||
586 | dev_err(di->dev, "error reading temperature\n"); | ||
587 | return temp; | ||
588 | } | ||
589 | |||
590 | if (di->chip == BQ27000 || di->chip == BQ27010) | ||
591 | temp = 5 * temp / 2; | ||
592 | |||
593 | return temp; | ||
594 | } | ||
595 | |||
596 | /* | ||
597 | * Return the battery Cycle count total | ||
598 | * Or < 0 if something fails. | ||
599 | */ | ||
600 | static int bq27xxx_battery_read_cyct(struct bq27xxx_device_info *di) | ||
601 | { | ||
602 | int cyct; | ||
603 | |||
604 | cyct = bq27xxx_read(di, BQ27XXX_REG_CYCT, false); | ||
605 | if (cyct < 0) | ||
606 | dev_err(di->dev, "error reading cycle count total\n"); | ||
607 | |||
608 | return cyct; | ||
609 | } | ||
610 | |||
611 | /* | ||
612 | * Read a time register. | ||
613 | * Return < 0 if something fails. | ||
614 | */ | ||
615 | static int bq27xxx_battery_read_time(struct bq27xxx_device_info *di, u8 reg) | ||
616 | { | ||
617 | int tval; | ||
618 | |||
619 | tval = bq27xxx_read(di, reg, false); | ||
620 | if (tval < 0) { | ||
621 | dev_dbg(di->dev, "error reading time register %02x: %d\n", | ||
622 | reg, tval); | ||
623 | return tval; | ||
624 | } | ||
625 | |||
626 | if (tval == 65535) | ||
627 | return -ENODATA; | ||
628 | |||
629 | return tval * 60; | ||
630 | } | ||
631 | |||
632 | /* | ||
633 | * Read an average power register. | ||
634 | * Return < 0 if something fails. | ||
635 | */ | ||
636 | static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di) | ||
637 | { | ||
638 | int tval; | ||
639 | |||
640 | tval = bq27xxx_read(di, BQ27XXX_REG_AP, false); | ||
641 | if (tval < 0) { | ||
642 | dev_err(di->dev, "error reading average power register %02x: %d\n", | ||
643 | BQ27XXX_REG_AP, tval); | ||
644 | return tval; | ||
645 | } | ||
646 | |||
647 | if (di->chip == BQ27000 || di->chip == BQ27010) | ||
648 | return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS; | ||
649 | else | ||
650 | return tval; | ||
651 | } | ||
652 | |||
653 | /* | ||
654 | * Returns true if a battery over temperature condition is detected | ||
655 | */ | ||
656 | static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags) | ||
657 | { | ||
658 | if (di->chip == BQ27500 || di->chip == BQ27541 || di->chip == BQ27545) | ||
659 | return flags & (BQ27XXX_FLAG_OTC | BQ27XXX_FLAG_OTD); | ||
660 | if (di->chip == BQ27530 || di->chip == BQ27421) | ||
661 | return flags & BQ27XXX_FLAG_OT; | ||
662 | |||
663 | return false; | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * Returns true if a battery under temperature condition is detected | ||
668 | */ | ||
669 | static bool bq27xxx_battery_undertemp(struct bq27xxx_device_info *di, u16 flags) | ||
670 | { | ||
671 | if (di->chip == BQ27530 || di->chip == BQ27421) | ||
672 | return flags & BQ27XXX_FLAG_UT; | ||
673 | |||
674 | return false; | ||
675 | } | ||
676 | |||
677 | /* | ||
678 | * Returns true if a low state of charge condition is detected | ||
679 | */ | ||
680 | static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags) | ||
681 | { | ||
682 | if (di->chip == BQ27000 || di->chip == BQ27010) | ||
683 | return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF); | ||
684 | else | ||
685 | return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF); | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * Read flag register. | ||
690 | * Return < 0 if something fails. | ||
691 | */ | ||
692 | static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di) | ||
693 | { | ||
694 | int flags; | ||
695 | |||
696 | flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); | ||
697 | if (flags < 0) { | ||
698 | dev_err(di->dev, "error reading flag register:%d\n", flags); | ||
699 | return flags; | ||
700 | } | ||
701 | |||
702 | /* Unlikely but important to return first */ | ||
703 | if (unlikely(bq27xxx_battery_overtemp(di, flags))) | ||
704 | return POWER_SUPPLY_HEALTH_OVERHEAT; | ||
705 | if (unlikely(bq27xxx_battery_undertemp(di, flags))) | ||
706 | return POWER_SUPPLY_HEALTH_COLD; | ||
707 | if (unlikely(bq27xxx_battery_dead(di, flags))) | ||
708 | return POWER_SUPPLY_HEALTH_DEAD; | ||
709 | |||
710 | return POWER_SUPPLY_HEALTH_GOOD; | ||
711 | } | ||
712 | |||
713 | static void bq27xxx_battery_update(struct bq27xxx_device_info *di) | ||
714 | { | ||
715 | struct bq27xxx_reg_cache cache = {0, }; | ||
716 | bool has_ci_flag = di->chip == BQ27000 || di->chip == BQ27010; | ||
717 | bool has_singe_flag = di->chip == BQ27000 || di->chip == BQ27010; | ||
718 | |||
719 | cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); | ||
720 | if ((cache.flags & 0xff) == 0xff) | ||
721 | cache.flags = -1; /* read error */ | ||
722 | if (cache.flags >= 0) { | ||
723 | cache.temperature = bq27xxx_battery_read_temperature(di); | ||
724 | if (has_ci_flag && (cache.flags & BQ27000_FLAG_CI)) { | ||
725 | dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); | ||
726 | cache.capacity = -ENODATA; | ||
727 | cache.energy = -ENODATA; | ||
728 | cache.time_to_empty = -ENODATA; | ||
729 | cache.time_to_empty_avg = -ENODATA; | ||
730 | cache.time_to_full = -ENODATA; | ||
731 | cache.charge_full = -ENODATA; | ||
732 | cache.health = -ENODATA; | ||
733 | } else { | ||
734 | if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) | ||
735 | cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); | ||
736 | if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) | ||
737 | cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); | ||
738 | if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) | ||
739 | cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); | ||
740 | cache.charge_full = bq27xxx_battery_read_fcc(di); | ||
741 | cache.capacity = bq27xxx_battery_read_soc(di); | ||
742 | if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) | ||
743 | cache.energy = bq27xxx_battery_read_energy(di); | ||
744 | cache.health = bq27xxx_battery_read_health(di); | ||
745 | } | ||
746 | if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) | ||
747 | cache.cycle_count = bq27xxx_battery_read_cyct(di); | ||
748 | if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR) | ||
749 | cache.power_avg = bq27xxx_battery_read_pwr_avg(di); | ||
750 | |||
751 | /* We only have to read charge design full once */ | ||
752 | if (di->charge_design_full <= 0) | ||
753 | di->charge_design_full = bq27xxx_battery_read_dcap(di); | ||
754 | } | ||
755 | |||
756 | if (di->cache.capacity != cache.capacity) | ||
757 | power_supply_changed(di->bat); | ||
758 | |||
759 | if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) | ||
760 | di->cache = cache; | ||
761 | |||
762 | di->last_update = jiffies; | ||
763 | } | ||
764 | |||
765 | static void bq27xxx_battery_poll(struct work_struct *work) | ||
766 | { | ||
767 | struct bq27xxx_device_info *di = | ||
768 | container_of(work, struct bq27xxx_device_info, | ||
769 | work.work); | ||
770 | |||
771 | bq27xxx_battery_update(di); | ||
772 | |||
773 | if (poll_interval > 0) { | ||
774 | /* The timer does not have to be accurate. */ | ||
775 | set_timer_slack(&di->work.timer, poll_interval * HZ / 4); | ||
776 | schedule_delayed_work(&di->work, poll_interval * HZ); | ||
777 | } | ||
778 | } | ||
779 | |||
780 | /* | ||
781 | * Return the battery average current in µA | ||
782 | * Note that current can be negative signed as well | ||
783 | * Or 0 if something fails. | ||
784 | */ | ||
785 | static int bq27xxx_battery_current(struct bq27xxx_device_info *di, | ||
786 | union power_supply_propval *val) | ||
787 | { | ||
788 | int curr; | ||
789 | int flags; | ||
790 | |||
791 | curr = bq27xxx_read(di, BQ27XXX_REG_AI, false); | ||
792 | if (curr < 0) { | ||
793 | dev_err(di->dev, "error reading current\n"); | ||
794 | return curr; | ||
795 | } | ||
796 | |||
797 | if (di->chip == BQ27000 || di->chip == BQ27010) { | ||
798 | flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, false); | ||
799 | if (flags & BQ27000_FLAG_CHGS) { | ||
800 | dev_dbg(di->dev, "negative current!\n"); | ||
801 | curr = -curr; | ||
802 | } | ||
803 | |||
804 | val->intval = curr * BQ27XXX_CURRENT_CONSTANT / BQ27XXX_RS; | ||
805 | } else { | ||
806 | /* Other gauges return signed value */ | ||
807 | val->intval = (int)((s16)curr) * 1000; | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | static int bq27xxx_battery_status(struct bq27xxx_device_info *di, | ||
814 | union power_supply_propval *val) | ||
815 | { | ||
816 | int status; | ||
817 | |||
818 | if (di->chip == BQ27000 || di->chip == BQ27010) { | ||
819 | if (di->cache.flags & BQ27000_FLAG_FC) | ||
820 | status = POWER_SUPPLY_STATUS_FULL; | ||
821 | else if (di->cache.flags & BQ27000_FLAG_CHGS) | ||
822 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
823 | else if (power_supply_am_i_supplied(di->bat)) | ||
824 | status = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
825 | else | ||
826 | status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
827 | } else { | ||
828 | if (di->cache.flags & BQ27XXX_FLAG_FC) | ||
829 | status = POWER_SUPPLY_STATUS_FULL; | ||
830 | else if (di->cache.flags & BQ27XXX_FLAG_DSC) | ||
831 | status = POWER_SUPPLY_STATUS_DISCHARGING; | ||
832 | else | ||
833 | status = POWER_SUPPLY_STATUS_CHARGING; | ||
834 | } | ||
835 | |||
836 | val->intval = status; | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di, | ||
842 | union power_supply_propval *val) | ||
843 | { | ||
844 | int level; | ||
845 | |||
846 | if (di->chip == BQ27000 || di->chip == BQ27010) { | ||
847 | if (di->cache.flags & BQ27000_FLAG_FC) | ||
848 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | ||
849 | else if (di->cache.flags & BQ27000_FLAG_EDV1) | ||
850 | level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
851 | else if (di->cache.flags & BQ27000_FLAG_EDVF) | ||
852 | level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
853 | else | ||
854 | level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
855 | } else { | ||
856 | if (di->cache.flags & BQ27XXX_FLAG_FC) | ||
857 | level = POWER_SUPPLY_CAPACITY_LEVEL_FULL; | ||
858 | else if (di->cache.flags & BQ27XXX_FLAG_SOC1) | ||
859 | level = POWER_SUPPLY_CAPACITY_LEVEL_LOW; | ||
860 | else if (di->cache.flags & BQ27XXX_FLAG_SOCF) | ||
861 | level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL; | ||
862 | else | ||
863 | level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL; | ||
864 | } | ||
865 | |||
866 | val->intval = level; | ||
867 | |||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | /* | ||
872 | * Return the battery Voltage in millivolts | ||
873 | * Or < 0 if something fails. | ||
874 | */ | ||
875 | static int bq27xxx_battery_voltage(struct bq27xxx_device_info *di, | ||
876 | union power_supply_propval *val) | ||
877 | { | ||
878 | int volt; | ||
879 | |||
880 | volt = bq27xxx_read(di, BQ27XXX_REG_VOLT, false); | ||
881 | if (volt < 0) { | ||
882 | dev_err(di->dev, "error reading voltage\n"); | ||
883 | return volt; | ||
884 | } | ||
885 | |||
886 | val->intval = volt * 1000; | ||
887 | |||
888 | return 0; | ||
889 | } | ||
890 | |||
891 | static int bq27xxx_simple_value(int value, | ||
892 | union power_supply_propval *val) | ||
893 | { | ||
894 | if (value < 0) | ||
895 | return value; | ||
896 | |||
897 | val->intval = value; | ||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | static int bq27xxx_battery_get_property(struct power_supply *psy, | ||
903 | enum power_supply_property psp, | ||
904 | union power_supply_propval *val) | ||
905 | { | ||
906 | int ret = 0; | ||
907 | struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); | ||
908 | |||
909 | mutex_lock(&di->lock); | ||
910 | if (time_is_before_jiffies(di->last_update + 5 * HZ)) { | ||
911 | cancel_delayed_work_sync(&di->work); | ||
912 | bq27xxx_battery_poll(&di->work.work); | ||
913 | } | ||
914 | mutex_unlock(&di->lock); | ||
915 | |||
916 | if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) | ||
917 | return -ENODEV; | ||
918 | |||
919 | switch (psp) { | ||
920 | case POWER_SUPPLY_PROP_STATUS: | ||
921 | ret = bq27xxx_battery_status(di, val); | ||
922 | break; | ||
923 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
924 | ret = bq27xxx_battery_voltage(di, val); | ||
925 | break; | ||
926 | case POWER_SUPPLY_PROP_PRESENT: | ||
927 | val->intval = di->cache.flags < 0 ? 0 : 1; | ||
928 | break; | ||
929 | case POWER_SUPPLY_PROP_CURRENT_NOW: | ||
930 | ret = bq27xxx_battery_current(di, val); | ||
931 | break; | ||
932 | case POWER_SUPPLY_PROP_CAPACITY: | ||
933 | ret = bq27xxx_simple_value(di->cache.capacity, val); | ||
934 | break; | ||
935 | case POWER_SUPPLY_PROP_CAPACITY_LEVEL: | ||
936 | ret = bq27xxx_battery_capacity_level(di, val); | ||
937 | break; | ||
938 | case POWER_SUPPLY_PROP_TEMP: | ||
939 | ret = bq27xxx_simple_value(di->cache.temperature, val); | ||
940 | if (ret == 0) | ||
941 | val->intval -= 2731; /* convert decidegree k to c */ | ||
942 | break; | ||
943 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW: | ||
944 | ret = bq27xxx_simple_value(di->cache.time_to_empty, val); | ||
945 | break; | ||
946 | case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: | ||
947 | ret = bq27xxx_simple_value(di->cache.time_to_empty_avg, val); | ||
948 | break; | ||
949 | case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW: | ||
950 | ret = bq27xxx_simple_value(di->cache.time_to_full, val); | ||
951 | break; | ||
952 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
953 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
954 | break; | ||
955 | case POWER_SUPPLY_PROP_CHARGE_NOW: | ||
956 | ret = bq27xxx_simple_value(bq27xxx_battery_read_nac(di), val); | ||
957 | break; | ||
958 | case POWER_SUPPLY_PROP_CHARGE_FULL: | ||
959 | ret = bq27xxx_simple_value(di->cache.charge_full, val); | ||
960 | break; | ||
961 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
962 | ret = bq27xxx_simple_value(di->charge_design_full, val); | ||
963 | break; | ||
964 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | ||
965 | ret = bq27xxx_simple_value(di->cache.cycle_count, val); | ||
966 | break; | ||
967 | case POWER_SUPPLY_PROP_ENERGY_NOW: | ||
968 | ret = bq27xxx_simple_value(di->cache.energy, val); | ||
969 | break; | ||
970 | case POWER_SUPPLY_PROP_POWER_AVG: | ||
971 | ret = bq27xxx_simple_value(di->cache.power_avg, val); | ||
972 | break; | ||
973 | case POWER_SUPPLY_PROP_HEALTH: | ||
974 | ret = bq27xxx_simple_value(di->cache.health, val); | ||
975 | break; | ||
976 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
977 | val->strval = BQ27XXX_MANUFACTURER; | ||
978 | break; | ||
979 | default: | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | return ret; | ||
984 | } | ||
985 | |||
986 | static void bq27xxx_external_power_changed(struct power_supply *psy) | ||
987 | { | ||
988 | struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); | ||
989 | |||
990 | cancel_delayed_work_sync(&di->work); | ||
991 | schedule_delayed_work(&di->work, 0); | ||
992 | } | ||
993 | |||
994 | static int bq27xxx_powersupply_init(struct bq27xxx_device_info *di, | ||
995 | const char *name) | ||
996 | { | ||
997 | int ret; | ||
998 | struct power_supply_desc *psy_desc; | ||
999 | struct power_supply_config psy_cfg = { .drv_data = di, }; | ||
1000 | |||
1001 | psy_desc = devm_kzalloc(di->dev, sizeof(*psy_desc), GFP_KERNEL); | ||
1002 | if (!psy_desc) | ||
1003 | return -ENOMEM; | ||
1004 | |||
1005 | psy_desc->name = name; | ||
1006 | psy_desc->type = POWER_SUPPLY_TYPE_BATTERY; | ||
1007 | psy_desc->properties = bq27xxx_battery_props[di->chip].props; | ||
1008 | psy_desc->num_properties = bq27xxx_battery_props[di->chip].size; | ||
1009 | psy_desc->get_property = bq27xxx_battery_get_property; | ||
1010 | psy_desc->external_power_changed = bq27xxx_external_power_changed; | ||
1011 | |||
1012 | INIT_DELAYED_WORK(&di->work, bq27xxx_battery_poll); | ||
1013 | mutex_init(&di->lock); | ||
1014 | |||
1015 | di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg); | ||
1016 | if (IS_ERR(di->bat)) { | ||
1017 | ret = PTR_ERR(di->bat); | ||
1018 | dev_err(di->dev, "failed to register battery: %d\n", ret); | ||
1019 | return ret; | ||
1020 | } | ||
1021 | |||
1022 | dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION); | ||
1023 | |||
1024 | bq27xxx_battery_update(di); | ||
1025 | |||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | static void bq27xxx_powersupply_unregister(struct bq27xxx_device_info *di) | ||
1030 | { | ||
1031 | /* | ||
1032 | * power_supply_unregister call bq27xxx_battery_get_property which | ||
1033 | * call bq27xxx_battery_poll. | ||
1034 | * Make sure that bq27xxx_battery_poll will not call | ||
1035 | * schedule_delayed_work again after unregister (which cause OOPS). | ||
1036 | */ | ||
1037 | poll_interval = 0; | ||
1038 | |||
1039 | cancel_delayed_work_sync(&di->work); | ||
1040 | |||
1041 | power_supply_unregister(di->bat); | ||
1042 | |||
1043 | mutex_destroy(&di->lock); | ||
1044 | } | ||
1045 | |||
1046 | /* i2c specific code */ | ||
1047 | #ifdef CONFIG_BATTERY_BQ27XXX_I2C | ||
1048 | |||
1049 | /* If the system has several batteries we need a different name for each | ||
1050 | * of them... | ||
1051 | */ | ||
1052 | static DEFINE_IDR(battery_id); | ||
1053 | static DEFINE_MUTEX(battery_mutex); | ||
1054 | |||
1055 | static irqreturn_t bq27xxx_battery_irq_handler_thread(int irq, void *data) | ||
1056 | { | ||
1057 | struct bq27xxx_device_info *di = data; | ||
1058 | |||
1059 | bq27xxx_battery_update(di); | ||
1060 | |||
1061 | return IRQ_HANDLED; | ||
1062 | } | ||
1063 | |||
1064 | static int bq27xxx_battery_i2c_read(struct bq27xxx_device_info *di, u8 reg, | ||
1065 | bool single) | ||
1066 | { | ||
1067 | struct i2c_client *client = to_i2c_client(di->dev); | ||
1068 | struct i2c_msg msg[2]; | ||
1069 | unsigned char data[2]; | ||
1070 | int ret; | ||
1071 | |||
1072 | if (!client->adapter) | ||
1073 | return -ENODEV; | ||
1074 | |||
1075 | msg[0].addr = client->addr; | ||
1076 | msg[0].flags = 0; | ||
1077 | msg[0].buf = ® | ||
1078 | msg[0].len = sizeof(reg); | ||
1079 | msg[1].addr = client->addr; | ||
1080 | msg[1].flags = I2C_M_RD; | ||
1081 | msg[1].buf = data; | ||
1082 | if (single) | ||
1083 | msg[1].len = 1; | ||
1084 | else | ||
1085 | msg[1].len = 2; | ||
1086 | |||
1087 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
1088 | if (ret < 0) | ||
1089 | return ret; | ||
1090 | |||
1091 | if (!single) | ||
1092 | ret = get_unaligned_le16(data); | ||
1093 | else | ||
1094 | ret = data[0]; | ||
1095 | |||
1096 | return ret; | ||
1097 | } | ||
1098 | |||
1099 | static int bq27xxx_battery_i2c_probe(struct i2c_client *client, | ||
1100 | const struct i2c_device_id *id) | ||
1101 | { | ||
1102 | char *name; | ||
1103 | struct bq27xxx_device_info *di; | ||
1104 | int num; | ||
1105 | int retval = 0; | ||
1106 | |||
1107 | /* Get new ID for the new battery device */ | ||
1108 | mutex_lock(&battery_mutex); | ||
1109 | num = idr_alloc(&battery_id, client, 0, 0, GFP_KERNEL); | ||
1110 | mutex_unlock(&battery_mutex); | ||
1111 | if (num < 0) | ||
1112 | return num; | ||
1113 | |||
1114 | name = devm_kasprintf(&client->dev, GFP_KERNEL, "%s-%d", id->name, num); | ||
1115 | if (!name) { | ||
1116 | retval = -ENOMEM; | ||
1117 | goto batt_failed; | ||
1118 | } | ||
1119 | |||
1120 | di = devm_kzalloc(&client->dev, sizeof(*di), GFP_KERNEL); | ||
1121 | if (!di) { | ||
1122 | retval = -ENOMEM; | ||
1123 | goto batt_failed; | ||
1124 | } | ||
1125 | |||
1126 | di->id = num; | ||
1127 | di->dev = &client->dev; | ||
1128 | di->chip = id->driver_data; | ||
1129 | di->bus.read = &bq27xxx_battery_i2c_read; | ||
1130 | di->regs = bq27xxx_regs[di->chip]; | ||
1131 | |||
1132 | retval = bq27xxx_powersupply_init(di, name); | ||
1133 | if (retval) | ||
1134 | goto batt_failed; | ||
1135 | |||
1136 | /* Schedule a polling after about 1 min */ | ||
1137 | schedule_delayed_work(&di->work, 60 * HZ); | ||
1138 | |||
1139 | i2c_set_clientdata(client, di); | ||
1140 | |||
1141 | if (client->irq) { | ||
1142 | retval = devm_request_threaded_irq(&client->dev, client->irq, | ||
1143 | NULL, bq27xxx_battery_irq_handler_thread, | ||
1144 | IRQF_ONESHOT, | ||
1145 | name, di); | ||
1146 | if (retval) { | ||
1147 | dev_err(&client->dev, | ||
1148 | "Unable to register IRQ %d error %d\n", | ||
1149 | client->irq, retval); | ||
1150 | return retval; | ||
1151 | } | ||
1152 | } | ||
1153 | |||
1154 | return 0; | ||
1155 | |||
1156 | batt_failed: | ||
1157 | mutex_lock(&battery_mutex); | ||
1158 | idr_remove(&battery_id, num); | ||
1159 | mutex_unlock(&battery_mutex); | ||
1160 | |||
1161 | return retval; | ||
1162 | } | ||
1163 | |||
1164 | static int bq27xxx_battery_i2c_remove(struct i2c_client *client) | ||
1165 | { | ||
1166 | struct bq27xxx_device_info *di = i2c_get_clientdata(client); | ||
1167 | |||
1168 | bq27xxx_powersupply_unregister(di); | ||
1169 | |||
1170 | mutex_lock(&battery_mutex); | ||
1171 | idr_remove(&battery_id, di->id); | ||
1172 | mutex_unlock(&battery_mutex); | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | static const struct i2c_device_id bq27xxx_id[] = { | ||
1178 | { "bq27200", BQ27000 }, | ||
1179 | { "bq27210", BQ27010 }, | ||
1180 | { "bq27500", BQ27500 }, | ||
1181 | { "bq27510", BQ27500 }, | ||
1182 | { "bq27520", BQ27500 }, | ||
1183 | { "bq27530", BQ27530 }, | ||
1184 | { "bq27531", BQ27530 }, | ||
1185 | { "bq27541", BQ27541 }, | ||
1186 | { "bq27542", BQ27541 }, | ||
1187 | { "bq27546", BQ27541 }, | ||
1188 | { "bq27742", BQ27541 }, | ||
1189 | { "bq27545", BQ27545 }, | ||
1190 | { "bq27421", BQ27421 }, | ||
1191 | { "bq27425", BQ27421 }, | ||
1192 | { "bq27441", BQ27421 }, | ||
1193 | { "bq27621", BQ27421 }, | ||
1194 | {}, | ||
1195 | }; | ||
1196 | MODULE_DEVICE_TABLE(i2c, bq27xxx_id); | ||
1197 | |||
1198 | static struct i2c_driver bq27xxx_battery_i2c_driver = { | ||
1199 | .driver = { | ||
1200 | .name = "bq27xxx-battery", | ||
1201 | }, | ||
1202 | .probe = bq27xxx_battery_i2c_probe, | ||
1203 | .remove = bq27xxx_battery_i2c_remove, | ||
1204 | .id_table = bq27xxx_id, | ||
1205 | }; | ||
1206 | |||
1207 | static inline int bq27xxx_battery_i2c_init(void) | ||
1208 | { | ||
1209 | int ret = i2c_add_driver(&bq27xxx_battery_i2c_driver); | ||
1210 | |||
1211 | if (ret) | ||
1212 | pr_err("Unable to register BQ27xxx i2c driver\n"); | ||
1213 | |||
1214 | return ret; | ||
1215 | } | ||
1216 | |||
1217 | static inline void bq27xxx_battery_i2c_exit(void) | ||
1218 | { | ||
1219 | i2c_del_driver(&bq27xxx_battery_i2c_driver); | ||
1220 | } | ||
1221 | |||
1222 | #else | ||
1223 | |||
1224 | static inline int bq27xxx_battery_i2c_init(void) { return 0; } | ||
1225 | static inline void bq27xxx_battery_i2c_exit(void) {}; | ||
1226 | |||
1227 | #endif | ||
1228 | |||
1229 | /* platform specific code */ | ||
1230 | #ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM | ||
1231 | |||
1232 | static int bq27xxx_battery_platform_read(struct bq27xxx_device_info *di, u8 reg, | ||
1233 | bool single) | ||
1234 | { | ||
1235 | struct device *dev = di->dev; | ||
1236 | struct bq27xxx_platform_data *pdata = dev->platform_data; | ||
1237 | unsigned int timeout = 3; | ||
1238 | int upper, lower; | ||
1239 | int temp; | ||
1240 | |||
1241 | if (!single) { | ||
1242 | /* Make sure the value has not changed in between reading the | ||
1243 | * lower and the upper part */ | ||
1244 | upper = pdata->read(dev, reg + 1); | ||
1245 | do { | ||
1246 | temp = upper; | ||
1247 | if (upper < 0) | ||
1248 | return upper; | ||
1249 | |||
1250 | lower = pdata->read(dev, reg); | ||
1251 | if (lower < 0) | ||
1252 | return lower; | ||
1253 | |||
1254 | upper = pdata->read(dev, reg + 1); | ||
1255 | } while (temp != upper && --timeout); | ||
1256 | |||
1257 | if (timeout == 0) | ||
1258 | return -EIO; | ||
1259 | |||
1260 | return (upper << 8) | lower; | ||
1261 | } | ||
1262 | |||
1263 | return pdata->read(dev, reg); | ||
1264 | } | ||
1265 | |||
1266 | static int bq27xxx_battery_platform_probe(struct platform_device *pdev) | ||
1267 | { | ||
1268 | struct bq27xxx_device_info *di; | ||
1269 | struct bq27xxx_platform_data *pdata = pdev->dev.platform_data; | ||
1270 | const char *name; | ||
1271 | |||
1272 | if (!pdata) { | ||
1273 | dev_err(&pdev->dev, "no platform_data supplied\n"); | ||
1274 | return -EINVAL; | ||
1275 | } | ||
1276 | |||
1277 | if (!pdata->read) { | ||
1278 | dev_err(&pdev->dev, "no hdq read callback supplied\n"); | ||
1279 | return -EINVAL; | ||
1280 | } | ||
1281 | |||
1282 | if (!pdata->chip) { | ||
1283 | dev_err(&pdev->dev, "no device supplied\n"); | ||
1284 | return -EINVAL; | ||
1285 | } | ||
1286 | |||
1287 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); | ||
1288 | if (!di) | ||
1289 | return -ENOMEM; | ||
1290 | |||
1291 | platform_set_drvdata(pdev, di); | ||
1292 | |||
1293 | di->dev = &pdev->dev; | ||
1294 | di->chip = pdata->chip; | ||
1295 | di->regs = bq27xxx_regs[di->chip]; | ||
1296 | |||
1297 | name = pdata->name ?: dev_name(&pdev->dev); | ||
1298 | di->bus.read = &bq27xxx_battery_platform_read; | ||
1299 | |||
1300 | return bq27xxx_powersupply_init(di, name); | ||
1301 | } | ||
1302 | |||
1303 | static int bq27xxx_battery_platform_remove(struct platform_device *pdev) | ||
1304 | { | ||
1305 | struct bq27xxx_device_info *di = platform_get_drvdata(pdev); | ||
1306 | |||
1307 | bq27xxx_powersupply_unregister(di); | ||
1308 | |||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | static struct platform_driver bq27xxx_battery_platform_driver = { | ||
1313 | .probe = bq27xxx_battery_platform_probe, | ||
1314 | .remove = bq27xxx_battery_platform_remove, | ||
1315 | .driver = { | ||
1316 | .name = "bq27000-battery", | ||
1317 | }, | ||
1318 | }; | ||
1319 | |||
1320 | static inline int bq27xxx_battery_platform_init(void) | ||
1321 | { | ||
1322 | int ret = platform_driver_register(&bq27xxx_battery_platform_driver); | ||
1323 | |||
1324 | if (ret) | ||
1325 | pr_err("Unable to register BQ27xxx platform driver\n"); | ||
1326 | |||
1327 | return ret; | ||
1328 | } | ||
1329 | |||
1330 | static inline void bq27xxx_battery_platform_exit(void) | ||
1331 | { | ||
1332 | platform_driver_unregister(&bq27xxx_battery_platform_driver); | ||
1333 | } | ||
1334 | |||
1335 | #else | ||
1336 | |||
1337 | static inline int bq27xxx_battery_platform_init(void) { return 0; } | ||
1338 | static inline void bq27xxx_battery_platform_exit(void) {}; | ||
1339 | |||
1340 | #endif | ||
1341 | |||
1342 | /* | ||
1343 | * Module stuff | ||
1344 | */ | ||
1345 | |||
1346 | static int __init bq27xxx_battery_init(void) | ||
1347 | { | ||
1348 | int ret; | ||
1349 | |||
1350 | ret = bq27xxx_battery_i2c_init(); | ||
1351 | if (ret) | ||
1352 | return ret; | ||
1353 | |||
1354 | ret = bq27xxx_battery_platform_init(); | ||
1355 | if (ret) | ||
1356 | bq27xxx_battery_i2c_exit(); | ||
1357 | |||
1358 | return ret; | ||
1359 | } | ||
1360 | module_init(bq27xxx_battery_init); | ||
1361 | |||
1362 | static void __exit bq27xxx_battery_exit(void) | ||
1363 | { | ||
1364 | bq27xxx_battery_platform_exit(); | ||
1365 | bq27xxx_battery_i2c_exit(); | ||
1366 | } | ||
1367 | module_exit(bq27xxx_battery_exit); | ||
1368 | |||
1369 | #ifdef CONFIG_BATTERY_BQ27XXX_PLATFORM | ||
1370 | MODULE_ALIAS("platform:bq27000-battery"); | ||
1371 | #endif | ||
1372 | |||
1373 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
1374 | MODULE_DESCRIPTION("BQ27xxx battery monitor driver"); | ||
1375 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 907293e6f2a4..1ea5d1aa268b 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c | |||
@@ -1581,8 +1581,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev) | |||
1581 | cables = devm_kzalloc(dev, sizeof(*cables) | 1581 | cables = devm_kzalloc(dev, sizeof(*cables) |
1582 | * chg_regs->num_cables, | 1582 | * chg_regs->num_cables, |
1583 | GFP_KERNEL); | 1583 | GFP_KERNEL); |
1584 | if (!cables) | 1584 | if (!cables) { |
1585 | of_node_put(child); | ||
1585 | return ERR_PTR(-ENOMEM); | 1586 | return ERR_PTR(-ENOMEM); |
1587 | } | ||
1586 | 1588 | ||
1587 | chg_regs->cables = cables; | 1589 | chg_regs->cables = cables; |
1588 | 1590 | ||
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c index 7e741f1d3cd5..042fb3dacb46 100644 --- a/drivers/power/lp8727_charger.c +++ b/drivers/power/lp8727_charger.c | |||
@@ -508,23 +508,23 @@ out: | |||
508 | return param; | 508 | return param; |
509 | } | 509 | } |
510 | 510 | ||
511 | static int lp8727_parse_dt(struct device *dev) | 511 | static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev) |
512 | { | 512 | { |
513 | struct device_node *np = dev->of_node; | 513 | struct device_node *np = dev->of_node; |
514 | struct device_node *child; | 514 | struct device_node *child; |
515 | struct lp8727_platform_data *pdata; | 515 | struct lp8727_platform_data *pdata; |
516 | const char *type; | 516 | const char *type; |
517 | 517 | ||
518 | /* If charging parameter is not defined, just skip parsing the dt */ | ||
519 | if (of_get_child_count(np) == 0) | ||
520 | goto out; | ||
521 | |||
522 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 518 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
523 | if (!pdata) | 519 | if (!pdata) |
524 | return -ENOMEM; | 520 | return ERR_PTR(-ENOMEM); |
525 | 521 | ||
526 | of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec); | 522 | of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec); |
527 | 523 | ||
524 | /* If charging parameter is not defined, just skip parsing the dt */ | ||
525 | if (of_get_child_count(np) == 0) | ||
526 | return pdata; | ||
527 | |||
528 | for_each_child_of_node(np, child) { | 528 | for_each_child_of_node(np, child) { |
529 | of_property_read_string(child, "charger-type", &type); | 529 | of_property_read_string(child, "charger-type", &type); |
530 | 530 | ||
@@ -535,29 +535,30 @@ static int lp8727_parse_dt(struct device *dev) | |||
535 | pdata->usb = lp8727_parse_charge_pdata(dev, child); | 535 | pdata->usb = lp8727_parse_charge_pdata(dev, child); |
536 | } | 536 | } |
537 | 537 | ||
538 | dev->platform_data = pdata; | 538 | return pdata; |
539 | out: | ||
540 | return 0; | ||
541 | } | 539 | } |
542 | #else | 540 | #else |
543 | static int lp8727_parse_dt(struct device *dev) | 541 | static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev) |
544 | { | 542 | { |
545 | return 0; | 543 | return NULL; |
546 | } | 544 | } |
547 | #endif | 545 | #endif |
548 | 546 | ||
549 | static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) | 547 | static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) |
550 | { | 548 | { |
551 | struct lp8727_chg *pchg; | 549 | struct lp8727_chg *pchg; |
550 | struct lp8727_platform_data *pdata; | ||
552 | int ret; | 551 | int ret; |
553 | 552 | ||
554 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) | 553 | if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
555 | return -EIO; | 554 | return -EIO; |
556 | 555 | ||
557 | if (cl->dev.of_node) { | 556 | if (cl->dev.of_node) { |
558 | ret = lp8727_parse_dt(&cl->dev); | 557 | pdata = lp8727_parse_dt(&cl->dev); |
559 | if (ret) | 558 | if (IS_ERR(pdata)) |
560 | return ret; | 559 | return PTR_ERR(pdata); |
560 | } else { | ||
561 | pdata = dev_get_platdata(&cl->dev); | ||
561 | } | 562 | } |
562 | 563 | ||
563 | pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL); | 564 | pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL); |
@@ -566,7 +567,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |||
566 | 567 | ||
567 | pchg->client = cl; | 568 | pchg->client = cl; |
568 | pchg->dev = &cl->dev; | 569 | pchg->dev = &cl->dev; |
569 | pchg->pdata = cl->dev.platform_data; | 570 | pchg->pdata = pdata; |
570 | i2c_set_clientdata(cl, pchg); | 571 | i2c_set_clientdata(cl, pchg); |
571 | 572 | ||
572 | mutex_init(&pchg->xfer_lock); | 573 | mutex_init(&pchg->xfer_lock); |
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index e89255764745..9c65f134d447 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
@@ -909,18 +909,21 @@ static int max17042_probe(struct i2c_client *client, | |||
909 | regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007); | 909 | regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007); |
910 | } | 910 | } |
911 | 911 | ||
912 | chip->battery = power_supply_register(&client->dev, max17042_desc, | 912 | chip->battery = devm_power_supply_register(&client->dev, max17042_desc, |
913 | &psy_cfg); | 913 | &psy_cfg); |
914 | if (IS_ERR(chip->battery)) { | 914 | if (IS_ERR(chip->battery)) { |
915 | dev_err(&client->dev, "failed: power supply register\n"); | 915 | dev_err(&client->dev, "failed: power supply register\n"); |
916 | return PTR_ERR(chip->battery); | 916 | return PTR_ERR(chip->battery); |
917 | } | 917 | } |
918 | 918 | ||
919 | if (client->irq) { | 919 | if (client->irq) { |
920 | ret = request_threaded_irq(client->irq, NULL, | 920 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
921 | max17042_thread_handler, | 921 | NULL, |
922 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 922 | max17042_thread_handler, |
923 | chip->battery->desc->name, chip); | 923 | IRQF_TRIGGER_FALLING | |
924 | IRQF_ONESHOT, | ||
925 | chip->battery->desc->name, | ||
926 | chip); | ||
924 | if (!ret) { | 927 | if (!ret) { |
925 | regmap_update_bits(chip->regmap, MAX17042_CONFIG, | 928 | regmap_update_bits(chip->regmap, MAX17042_CONFIG, |
926 | CONFIG_ALRT_BIT_ENBL, | 929 | CONFIG_ALRT_BIT_ENBL, |
@@ -944,16 +947,6 @@ static int max17042_probe(struct i2c_client *client, | |||
944 | return 0; | 947 | return 0; |
945 | } | 948 | } |
946 | 949 | ||
947 | static int max17042_remove(struct i2c_client *client) | ||
948 | { | ||
949 | struct max17042_chip *chip = i2c_get_clientdata(client); | ||
950 | |||
951 | if (client->irq) | ||
952 | free_irq(client->irq, chip); | ||
953 | power_supply_unregister(chip->battery); | ||
954 | return 0; | ||
955 | } | ||
956 | |||
957 | #ifdef CONFIG_PM_SLEEP | 950 | #ifdef CONFIG_PM_SLEEP |
958 | static int max17042_suspend(struct device *dev) | 951 | static int max17042_suspend(struct device *dev) |
959 | { | 952 | { |
@@ -1014,7 +1007,6 @@ static struct i2c_driver max17042_i2c_driver = { | |||
1014 | .pm = &max17042_pm_ops, | 1007 | .pm = &max17042_pm_ops, |
1015 | }, | 1008 | }, |
1016 | .probe = max17042_probe, | 1009 | .probe = max17042_probe, |
1017 | .remove = max17042_remove, | ||
1018 | .id_table = max17042_id, | 1010 | .id_table = max17042_id, |
1019 | }; | 1011 | }; |
1020 | module_i2c_driver(max17042_i2c_driver); | 1012 | module_i2c_driver(max17042_i2c_driver); |
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c index bf2b4b3a7cae..6d39d52040d4 100644 --- a/drivers/power/max8903_charger.c +++ b/drivers/power/max8903_charger.c | |||
@@ -201,8 +201,7 @@ static int max8903_probe(struct platform_device *pdev) | |||
201 | 201 | ||
202 | if (pdata->dc_valid == false && pdata->usb_valid == false) { | 202 | if (pdata->dc_valid == false && pdata->usb_valid == false) { |
203 | dev_err(dev, "No valid power sources.\n"); | 203 | dev_err(dev, "No valid power sources.\n"); |
204 | ret = -EINVAL; | 204 | return -EINVAL; |
205 | goto err; | ||
206 | } | 205 | } |
207 | 206 | ||
208 | if (pdata->dc_valid) { | 207 | if (pdata->dc_valid) { |
@@ -216,8 +215,7 @@ static int max8903_probe(struct platform_device *pdev) | |||
216 | } else { | 215 | } else { |
217 | dev_err(dev, "When DC is wired, DOK and DCM should" | 216 | dev_err(dev, "When DC is wired, DOK and DCM should" |
218 | " be wired as well.\n"); | 217 | " be wired as well.\n"); |
219 | ret = -EINVAL; | 218 | return -EINVAL; |
220 | goto err; | ||
221 | } | 219 | } |
222 | } else { | 220 | } else { |
223 | if (pdata->dcm) { | 221 | if (pdata->dcm) { |
@@ -225,8 +223,7 @@ static int max8903_probe(struct platform_device *pdev) | |||
225 | gpio_set_value(pdata->dcm, 0); | 223 | gpio_set_value(pdata->dcm, 0); |
226 | else { | 224 | else { |
227 | dev_err(dev, "Invalid pin: dcm.\n"); | 225 | dev_err(dev, "Invalid pin: dcm.\n"); |
228 | ret = -EINVAL; | 226 | return -EINVAL; |
229 | goto err; | ||
230 | } | 227 | } |
231 | } | 228 | } |
232 | } | 229 | } |
@@ -238,8 +235,7 @@ static int max8903_probe(struct platform_device *pdev) | |||
238 | } else { | 235 | } else { |
239 | dev_err(dev, "When USB is wired, UOK should be wired." | 236 | dev_err(dev, "When USB is wired, UOK should be wired." |
240 | "as well.\n"); | 237 | "as well.\n"); |
241 | ret = -EINVAL; | 238 | return -EINVAL; |
242 | goto err; | ||
243 | } | 239 | } |
244 | } | 240 | } |
245 | 241 | ||
@@ -248,32 +244,28 @@ static int max8903_probe(struct platform_device *pdev) | |||
248 | gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); | 244 | gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1); |
249 | } else { | 245 | } else { |
250 | dev_err(dev, "Invalid pin: cen.\n"); | 246 | dev_err(dev, "Invalid pin: cen.\n"); |
251 | ret = -EINVAL; | 247 | return -EINVAL; |
252 | goto err; | ||
253 | } | 248 | } |
254 | } | 249 | } |
255 | 250 | ||
256 | if (pdata->chg) { | 251 | if (pdata->chg) { |
257 | if (!gpio_is_valid(pdata->chg)) { | 252 | if (!gpio_is_valid(pdata->chg)) { |
258 | dev_err(dev, "Invalid pin: chg.\n"); | 253 | dev_err(dev, "Invalid pin: chg.\n"); |
259 | ret = -EINVAL; | 254 | return -EINVAL; |
260 | goto err; | ||
261 | } | 255 | } |
262 | } | 256 | } |
263 | 257 | ||
264 | if (pdata->flt) { | 258 | if (pdata->flt) { |
265 | if (!gpio_is_valid(pdata->flt)) { | 259 | if (!gpio_is_valid(pdata->flt)) { |
266 | dev_err(dev, "Invalid pin: flt.\n"); | 260 | dev_err(dev, "Invalid pin: flt.\n"); |
267 | ret = -EINVAL; | 261 | return -EINVAL; |
268 | goto err; | ||
269 | } | 262 | } |
270 | } | 263 | } |
271 | 264 | ||
272 | if (pdata->usus) { | 265 | if (pdata->usus) { |
273 | if (!gpio_is_valid(pdata->usus)) { | 266 | if (!gpio_is_valid(pdata->usus)) { |
274 | dev_err(dev, "Invalid pin: usus.\n"); | 267 | dev_err(dev, "Invalid pin: usus.\n"); |
275 | ret = -EINVAL; | 268 | return -EINVAL; |
276 | goto err; | ||
277 | } | 269 | } |
278 | } | 270 | } |
279 | 271 | ||
@@ -291,85 +283,56 @@ static int max8903_probe(struct platform_device *pdev) | |||
291 | 283 | ||
292 | psy_cfg.drv_data = data; | 284 | psy_cfg.drv_data = data; |
293 | 285 | ||
294 | data->psy = power_supply_register(dev, &data->psy_desc, &psy_cfg); | 286 | data->psy = devm_power_supply_register(dev, &data->psy_desc, &psy_cfg); |
295 | if (IS_ERR(data->psy)) { | 287 | if (IS_ERR(data->psy)) { |
296 | dev_err(dev, "failed: power supply register.\n"); | 288 | dev_err(dev, "failed: power supply register.\n"); |
297 | ret = PTR_ERR(data->psy); | 289 | return PTR_ERR(data->psy); |
298 | goto err; | ||
299 | } | 290 | } |
300 | 291 | ||
301 | if (pdata->dc_valid) { | 292 | if (pdata->dc_valid) { |
302 | ret = request_threaded_irq(gpio_to_irq(pdata->dok), | 293 | ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->dok), |
303 | NULL, max8903_dcin, | 294 | NULL, max8903_dcin, |
304 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 295 | IRQF_TRIGGER_FALLING | |
305 | "MAX8903 DC IN", data); | 296 | IRQF_TRIGGER_RISING, |
297 | "MAX8903 DC IN", data); | ||
306 | if (ret) { | 298 | if (ret) { |
307 | dev_err(dev, "Cannot request irq %d for DC (%d)\n", | 299 | dev_err(dev, "Cannot request irq %d for DC (%d)\n", |
308 | gpio_to_irq(pdata->dok), ret); | 300 | gpio_to_irq(pdata->dok), ret); |
309 | goto err_psy; | 301 | return ret; |
310 | } | 302 | } |
311 | } | 303 | } |
312 | 304 | ||
313 | if (pdata->usb_valid) { | 305 | if (pdata->usb_valid) { |
314 | ret = request_threaded_irq(gpio_to_irq(pdata->uok), | 306 | ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->uok), |
315 | NULL, max8903_usbin, | 307 | NULL, max8903_usbin, |
316 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 308 | IRQF_TRIGGER_FALLING | |
317 | "MAX8903 USB IN", data); | 309 | IRQF_TRIGGER_RISING, |
310 | "MAX8903 USB IN", data); | ||
318 | if (ret) { | 311 | if (ret) { |
319 | dev_err(dev, "Cannot request irq %d for USB (%d)\n", | 312 | dev_err(dev, "Cannot request irq %d for USB (%d)\n", |
320 | gpio_to_irq(pdata->uok), ret); | 313 | gpio_to_irq(pdata->uok), ret); |
321 | goto err_dc_irq; | 314 | return ret; |
322 | } | 315 | } |
323 | } | 316 | } |
324 | 317 | ||
325 | if (pdata->flt) { | 318 | if (pdata->flt) { |
326 | ret = request_threaded_irq(gpio_to_irq(pdata->flt), | 319 | ret = devm_request_threaded_irq(dev, gpio_to_irq(pdata->flt), |
327 | NULL, max8903_fault, | 320 | NULL, max8903_fault, |
328 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 321 | IRQF_TRIGGER_FALLING | |
329 | "MAX8903 Fault", data); | 322 | IRQF_TRIGGER_RISING, |
323 | "MAX8903 Fault", data); | ||
330 | if (ret) { | 324 | if (ret) { |
331 | dev_err(dev, "Cannot request irq %d for Fault (%d)\n", | 325 | dev_err(dev, "Cannot request irq %d for Fault (%d)\n", |
332 | gpio_to_irq(pdata->flt), ret); | 326 | gpio_to_irq(pdata->flt), ret); |
333 | goto err_usb_irq; | 327 | return ret; |
334 | } | 328 | } |
335 | } | 329 | } |
336 | 330 | ||
337 | return 0; | 331 | return 0; |
338 | |||
339 | err_usb_irq: | ||
340 | if (pdata->usb_valid) | ||
341 | free_irq(gpio_to_irq(pdata->uok), data); | ||
342 | err_dc_irq: | ||
343 | if (pdata->dc_valid) | ||
344 | free_irq(gpio_to_irq(pdata->dok), data); | ||
345 | err_psy: | ||
346 | power_supply_unregister(data->psy); | ||
347 | err: | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static int max8903_remove(struct platform_device *pdev) | ||
352 | { | ||
353 | struct max8903_data *data = platform_get_drvdata(pdev); | ||
354 | |||
355 | if (data) { | ||
356 | struct max8903_pdata *pdata = &data->pdata; | ||
357 | |||
358 | if (pdata->flt) | ||
359 | free_irq(gpio_to_irq(pdata->flt), data); | ||
360 | if (pdata->usb_valid) | ||
361 | free_irq(gpio_to_irq(pdata->uok), data); | ||
362 | if (pdata->dc_valid) | ||
363 | free_irq(gpio_to_irq(pdata->dok), data); | ||
364 | power_supply_unregister(data->psy); | ||
365 | } | ||
366 | |||
367 | return 0; | ||
368 | } | 332 | } |
369 | 333 | ||
370 | static struct platform_driver max8903_driver = { | 334 | static struct platform_driver max8903_driver = { |
371 | .probe = max8903_probe, | 335 | .probe = max8903_probe, |
372 | .remove = max8903_remove, | ||
373 | .driver = { | 336 | .driver = { |
374 | .name = "max8903-charger", | 337 | .name = "max8903-charger", |
375 | }, | 338 | }, |
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c index 47448d4bc6cd..b64cf0f14142 100644 --- a/drivers/power/max8998_charger.c +++ b/drivers/power/max8998_charger.c | |||
@@ -117,8 +117,7 @@ static int max8998_battery_probe(struct platform_device *pdev) | |||
117 | "EOC value not set: leave it unchanged.\n"); | 117 | "EOC value not set: leave it unchanged.\n"); |
118 | } else { | 118 | } else { |
119 | dev_err(max8998->dev, "Invalid EOC value\n"); | 119 | dev_err(max8998->dev, "Invalid EOC value\n"); |
120 | ret = -EINVAL; | 120 | return -EINVAL; |
121 | goto err; | ||
122 | } | 121 | } |
123 | 122 | ||
124 | /* Setup Charge Restart Level */ | 123 | /* Setup Charge Restart Level */ |
@@ -141,8 +140,7 @@ static int max8998_battery_probe(struct platform_device *pdev) | |||
141 | break; | 140 | break; |
142 | default: | 141 | default: |
143 | dev_err(max8998->dev, "Invalid Restart Level\n"); | 142 | dev_err(max8998->dev, "Invalid Restart Level\n"); |
144 | ret = -EINVAL; | 143 | return -EINVAL; |
145 | goto err; | ||
146 | } | 144 | } |
147 | 145 | ||
148 | /* Setup Charge Full Timeout */ | 146 | /* Setup Charge Full Timeout */ |
@@ -165,34 +163,22 @@ static int max8998_battery_probe(struct platform_device *pdev) | |||
165 | break; | 163 | break; |
166 | default: | 164 | default: |
167 | dev_err(max8998->dev, "Invalid Full Timeout value\n"); | 165 | dev_err(max8998->dev, "Invalid Full Timeout value\n"); |
168 | ret = -EINVAL; | 166 | return -EINVAL; |
169 | goto err; | ||
170 | } | 167 | } |
171 | 168 | ||
172 | psy_cfg.drv_data = max8998; | 169 | psy_cfg.drv_data = max8998; |
173 | 170 | ||
174 | max8998->battery = power_supply_register(max8998->dev, | 171 | max8998->battery = devm_power_supply_register(max8998->dev, |
175 | &max8998_battery_desc, | 172 | &max8998_battery_desc, |
176 | &psy_cfg); | 173 | &psy_cfg); |
177 | if (IS_ERR(max8998->battery)) { | 174 | if (IS_ERR(max8998->battery)) { |
178 | ret = PTR_ERR(max8998->battery); | 175 | ret = PTR_ERR(max8998->battery); |
179 | dev_err(max8998->dev, "failed: power supply register: %d\n", | 176 | dev_err(max8998->dev, "failed: power supply register: %d\n", |
180 | ret); | 177 | ret); |
181 | goto err; | 178 | return ret; |
182 | } | 179 | } |
183 | 180 | ||
184 | return 0; | 181 | return 0; |
185 | err: | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | static int max8998_battery_remove(struct platform_device *pdev) | ||
190 | { | ||
191 | struct max8998_battery_data *max8998 = platform_get_drvdata(pdev); | ||
192 | |||
193 | power_supply_unregister(max8998->battery); | ||
194 | |||
195 | return 0; | ||
196 | } | 182 | } |
197 | 183 | ||
198 | static const struct platform_device_id max8998_battery_id[] = { | 184 | static const struct platform_device_id max8998_battery_id[] = { |
@@ -205,7 +191,6 @@ static struct platform_driver max8998_battery_driver = { | |||
205 | .name = "max8998-battery", | 191 | .name = "max8998-battery", |
206 | }, | 192 | }, |
207 | .probe = max8998_battery_probe, | 193 | .probe = max8998_battery_probe, |
208 | .remove = max8998_battery_remove, | ||
209 | .id_table = max8998_battery_id, | 194 | .id_table = max8998_battery_id, |
210 | }; | 195 | }; |
211 | 196 | ||
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index 3a45cc0c4dce..8f9bd1d0eeb6 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c | |||
@@ -1264,5 +1264,4 @@ module_exit(pm2xxx_charger_exit); | |||
1264 | 1264 | ||
1265 | MODULE_LICENSE("GPL v2"); | 1265 | MODULE_LICENSE("GPL v2"); |
1266 | MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay"); | 1266 | MODULE_AUTHOR("Rajkumar kasirajan, Olivier Launay"); |
1267 | MODULE_ALIAS("i2c:pm2xxx-charger"); | ||
1268 | MODULE_DESCRIPTION("PM2xxx charger management driver"); | 1267 | MODULE_DESCRIPTION("PM2xxx charger management driver"); |
diff --git a/drivers/power/qcom_smbb.c b/drivers/power/qcom_smbb.c new file mode 100644 index 000000000000..5eb1e9e543e2 --- /dev/null +++ b/drivers/power/qcom_smbb.c | |||
@@ -0,0 +1,951 @@ | |||
1 | /* Copyright (c) 2014, Sony Mobile Communications Inc. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * This driver is for the multi-block Switch-Mode Battery Charger and Boost | ||
13 | * (SMBB) hardware, found in Qualcomm PM8941 PMICs. The charger is an | ||
14 | * integrated, single-cell lithium-ion battery charger. | ||
15 | * | ||
16 | * Sub-components: | ||
17 | * - Charger core | ||
18 | * - Buck | ||
19 | * - DC charge-path | ||
20 | * - USB charge-path | ||
21 | * - Battery interface | ||
22 | * - Boost (not implemented) | ||
23 | * - Misc | ||
24 | * - HF-Buck | ||
25 | */ | ||
26 | |||
27 | #include <linux/errno.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/mutex.h> | ||
32 | #include <linux/of.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/power_supply.h> | ||
35 | #include <linux/regmap.h> | ||
36 | #include <linux/slab.h> | ||
37 | |||
38 | #define SMBB_CHG_VMAX 0x040 | ||
39 | #define SMBB_CHG_VSAFE 0x041 | ||
40 | #define SMBB_CHG_CFG 0x043 | ||
41 | #define SMBB_CHG_IMAX 0x044 | ||
42 | #define SMBB_CHG_ISAFE 0x045 | ||
43 | #define SMBB_CHG_VIN_MIN 0x047 | ||
44 | #define SMBB_CHG_CTRL 0x049 | ||
45 | #define CTRL_EN BIT(7) | ||
46 | #define SMBB_CHG_VBAT_WEAK 0x052 | ||
47 | #define SMBB_CHG_IBAT_TERM_CHG 0x05b | ||
48 | #define IBAT_TERM_CHG_IEOC BIT(7) | ||
49 | #define IBAT_TERM_CHG_IEOC_BMS BIT(7) | ||
50 | #define IBAT_TERM_CHG_IEOC_CHG 0 | ||
51 | #define SMBB_CHG_VBAT_DET 0x05d | ||
52 | #define SMBB_CHG_TCHG_MAX_EN 0x060 | ||
53 | #define TCHG_MAX_EN BIT(7) | ||
54 | #define SMBB_CHG_WDOG_TIME 0x062 | ||
55 | #define SMBB_CHG_WDOG_EN 0x065 | ||
56 | #define WDOG_EN BIT(7) | ||
57 | |||
58 | #define SMBB_BUCK_REG_MODE 0x174 | ||
59 | #define BUCK_REG_MODE BIT(0) | ||
60 | #define BUCK_REG_MODE_VBAT BIT(0) | ||
61 | #define BUCK_REG_MODE_VSYS 0 | ||
62 | |||
63 | #define SMBB_BAT_PRES_STATUS 0x208 | ||
64 | #define PRES_STATUS_BAT_PRES BIT(7) | ||
65 | #define SMBB_BAT_TEMP_STATUS 0x209 | ||
66 | #define TEMP_STATUS_OK BIT(7) | ||
67 | #define TEMP_STATUS_HOT BIT(6) | ||
68 | #define SMBB_BAT_BTC_CTRL 0x249 | ||
69 | #define BTC_CTRL_COMP_EN BIT(7) | ||
70 | #define BTC_CTRL_COLD_EXT BIT(1) | ||
71 | #define BTC_CTRL_HOT_EXT_N BIT(0) | ||
72 | |||
73 | #define SMBB_USB_IMAX 0x344 | ||
74 | #define SMBB_USB_ENUM_TIMER_STOP 0x34e | ||
75 | #define ENUM_TIMER_STOP BIT(0) | ||
76 | #define SMBB_USB_SEC_ACCESS 0x3d0 | ||
77 | #define SEC_ACCESS_MAGIC 0xa5 | ||
78 | #define SMBB_USB_REV_BST 0x3ed | ||
79 | #define REV_BST_CHG_GONE BIT(7) | ||
80 | |||
81 | #define SMBB_DC_IMAX 0x444 | ||
82 | |||
83 | #define SMBB_MISC_REV2 0x601 | ||
84 | #define SMBB_MISC_BOOT_DONE 0x642 | ||
85 | #define BOOT_DONE BIT(7) | ||
86 | |||
87 | #define STATUS_USBIN_VALID BIT(0) /* USB connection is valid */ | ||
88 | #define STATUS_DCIN_VALID BIT(1) /* DC connection is valid */ | ||
89 | #define STATUS_BAT_HOT BIT(2) /* Battery temp 1=Hot, 0=Cold */ | ||
90 | #define STATUS_BAT_OK BIT(3) /* Battery temp OK */ | ||
91 | #define STATUS_BAT_PRESENT BIT(4) /* Battery is present */ | ||
92 | #define STATUS_CHG_DONE BIT(5) /* Charge cycle is complete */ | ||
93 | #define STATUS_CHG_TRKL BIT(6) /* Trickle charging */ | ||
94 | #define STATUS_CHG_FAST BIT(7) /* Fast charging */ | ||
95 | #define STATUS_CHG_GONE BIT(8) /* No charger is connected */ | ||
96 | |||
97 | enum smbb_attr { | ||
98 | ATTR_BAT_ISAFE, | ||
99 | ATTR_BAT_IMAX, | ||
100 | ATTR_USBIN_IMAX, | ||
101 | ATTR_DCIN_IMAX, | ||
102 | ATTR_BAT_VSAFE, | ||
103 | ATTR_BAT_VMAX, | ||
104 | ATTR_BAT_VMIN, | ||
105 | ATTR_CHG_VDET, | ||
106 | ATTR_VIN_MIN, | ||
107 | _ATTR_CNT, | ||
108 | }; | ||
109 | |||
110 | struct smbb_charger { | ||
111 | unsigned int revision; | ||
112 | unsigned int addr; | ||
113 | struct device *dev; | ||
114 | |||
115 | bool dc_disabled; | ||
116 | bool jeita_ext_temp; | ||
117 | unsigned long status; | ||
118 | struct mutex statlock; | ||
119 | |||
120 | unsigned int attr[_ATTR_CNT]; | ||
121 | |||
122 | struct power_supply *usb_psy; | ||
123 | struct power_supply *dc_psy; | ||
124 | struct power_supply *bat_psy; | ||
125 | struct regmap *regmap; | ||
126 | }; | ||
127 | |||
128 | static int smbb_vbat_weak_fn(unsigned int index) | ||
129 | { | ||
130 | return 2100000 + index * 100000; | ||
131 | } | ||
132 | |||
133 | static int smbb_vin_fn(unsigned int index) | ||
134 | { | ||
135 | if (index > 42) | ||
136 | return 5600000 + (index - 43) * 200000; | ||
137 | return 3400000 + index * 50000; | ||
138 | } | ||
139 | |||
140 | static int smbb_vmax_fn(unsigned int index) | ||
141 | { | ||
142 | return 3240000 + index * 10000; | ||
143 | } | ||
144 | |||
145 | static int smbb_vbat_det_fn(unsigned int index) | ||
146 | { | ||
147 | return 3240000 + index * 20000; | ||
148 | } | ||
149 | |||
150 | static int smbb_imax_fn(unsigned int index) | ||
151 | { | ||
152 | if (index < 2) | ||
153 | return 100000 + index * 50000; | ||
154 | return index * 100000; | ||
155 | } | ||
156 | |||
157 | static int smbb_bat_imax_fn(unsigned int index) | ||
158 | { | ||
159 | return index * 50000; | ||
160 | } | ||
161 | |||
162 | static unsigned int smbb_hw_lookup(unsigned int val, int (*fn)(unsigned int)) | ||
163 | { | ||
164 | unsigned int widx; | ||
165 | unsigned int sel; | ||
166 | |||
167 | for (widx = sel = 0; (*fn)(widx) <= val; ++widx) | ||
168 | sel = widx; | ||
169 | |||
170 | return sel; | ||
171 | } | ||
172 | |||
173 | static const struct smbb_charger_attr { | ||
174 | const char *name; | ||
175 | unsigned int reg; | ||
176 | unsigned int safe_reg; | ||
177 | unsigned int max; | ||
178 | unsigned int min; | ||
179 | unsigned int fail_ok; | ||
180 | int (*hw_fn)(unsigned int); | ||
181 | } smbb_charger_attrs[] = { | ||
182 | [ATTR_BAT_ISAFE] = { | ||
183 | .name = "qcom,fast-charge-safe-current", | ||
184 | .reg = SMBB_CHG_ISAFE, | ||
185 | .max = 3000000, | ||
186 | .min = 200000, | ||
187 | .hw_fn = smbb_bat_imax_fn, | ||
188 | .fail_ok = 1, | ||
189 | }, | ||
190 | [ATTR_BAT_IMAX] = { | ||
191 | .name = "qcom,fast-charge-current-limit", | ||
192 | .reg = SMBB_CHG_IMAX, | ||
193 | .safe_reg = SMBB_CHG_ISAFE, | ||
194 | .max = 3000000, | ||
195 | .min = 200000, | ||
196 | .hw_fn = smbb_bat_imax_fn, | ||
197 | }, | ||
198 | [ATTR_DCIN_IMAX] = { | ||
199 | .name = "qcom,dc-current-limit", | ||
200 | .reg = SMBB_DC_IMAX, | ||
201 | .max = 2500000, | ||
202 | .min = 100000, | ||
203 | .hw_fn = smbb_imax_fn, | ||
204 | }, | ||
205 | [ATTR_BAT_VSAFE] = { | ||
206 | .name = "qcom,fast-charge-safe-voltage", | ||
207 | .reg = SMBB_CHG_VSAFE, | ||
208 | .max = 5000000, | ||
209 | .min = 3240000, | ||
210 | .hw_fn = smbb_vmax_fn, | ||
211 | .fail_ok = 1, | ||
212 | }, | ||
213 | [ATTR_BAT_VMAX] = { | ||
214 | .name = "qcom,fast-charge-high-threshold-voltage", | ||
215 | .reg = SMBB_CHG_VMAX, | ||
216 | .safe_reg = SMBB_CHG_VSAFE, | ||
217 | .max = 5000000, | ||
218 | .min = 3240000, | ||
219 | .hw_fn = smbb_vmax_fn, | ||
220 | }, | ||
221 | [ATTR_BAT_VMIN] = { | ||
222 | .name = "qcom,fast-charge-low-threshold-voltage", | ||
223 | .reg = SMBB_CHG_VBAT_WEAK, | ||
224 | .max = 3600000, | ||
225 | .min = 2100000, | ||
226 | .hw_fn = smbb_vbat_weak_fn, | ||
227 | }, | ||
228 | [ATTR_CHG_VDET] = { | ||
229 | .name = "qcom,auto-recharge-threshold-voltage", | ||
230 | .reg = SMBB_CHG_VBAT_DET, | ||
231 | .max = 5000000, | ||
232 | .min = 3240000, | ||
233 | .hw_fn = smbb_vbat_det_fn, | ||
234 | }, | ||
235 | [ATTR_VIN_MIN] = { | ||
236 | .name = "qcom,minimum-input-voltage", | ||
237 | .reg = SMBB_CHG_VIN_MIN, | ||
238 | .max = 9600000, | ||
239 | .min = 4200000, | ||
240 | .hw_fn = smbb_vin_fn, | ||
241 | }, | ||
242 | [ATTR_USBIN_IMAX] = { | ||
243 | .name = "usb-charge-current-limit", | ||
244 | .reg = SMBB_USB_IMAX, | ||
245 | .max = 2500000, | ||
246 | .min = 100000, | ||
247 | .hw_fn = smbb_imax_fn, | ||
248 | }, | ||
249 | }; | ||
250 | |||
251 | static int smbb_charger_attr_write(struct smbb_charger *chg, | ||
252 | enum smbb_attr which, unsigned int val) | ||
253 | { | ||
254 | const struct smbb_charger_attr *prop; | ||
255 | unsigned int wval; | ||
256 | unsigned int out; | ||
257 | int rc; | ||
258 | |||
259 | prop = &smbb_charger_attrs[which]; | ||
260 | |||
261 | if (val > prop->max || val < prop->min) { | ||
262 | dev_err(chg->dev, "value out of range for %s [%u:%u]\n", | ||
263 | prop->name, prop->min, prop->max); | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | if (prop->safe_reg) { | ||
268 | rc = regmap_read(chg->regmap, | ||
269 | chg->addr + prop->safe_reg, &wval); | ||
270 | if (rc) { | ||
271 | dev_err(chg->dev, | ||
272 | "unable to read safe value for '%s'\n", | ||
273 | prop->name); | ||
274 | return rc; | ||
275 | } | ||
276 | |||
277 | wval = prop->hw_fn(wval); | ||
278 | |||
279 | if (val > wval) { | ||
280 | dev_warn(chg->dev, | ||
281 | "%s above safe value, clamping at %u\n", | ||
282 | prop->name, wval); | ||
283 | val = wval; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | wval = smbb_hw_lookup(val, prop->hw_fn); | ||
288 | |||
289 | rc = regmap_write(chg->regmap, chg->addr + prop->reg, wval); | ||
290 | if (rc) { | ||
291 | dev_err(chg->dev, "unable to update %s", prop->name); | ||
292 | return rc; | ||
293 | } | ||
294 | out = prop->hw_fn(wval); | ||
295 | if (out != val) { | ||
296 | dev_warn(chg->dev, | ||
297 | "%s inaccurate, rounded to %u\n", | ||
298 | prop->name, out); | ||
299 | } | ||
300 | |||
301 | dev_dbg(chg->dev, "%s <= %d\n", prop->name, out); | ||
302 | |||
303 | chg->attr[which] = out; | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int smbb_charger_attr_read(struct smbb_charger *chg, | ||
309 | enum smbb_attr which) | ||
310 | { | ||
311 | const struct smbb_charger_attr *prop; | ||
312 | unsigned int val; | ||
313 | int rc; | ||
314 | |||
315 | prop = &smbb_charger_attrs[which]; | ||
316 | |||
317 | rc = regmap_read(chg->regmap, chg->addr + prop->reg, &val); | ||
318 | if (rc) { | ||
319 | dev_err(chg->dev, "failed to read %s\n", prop->name); | ||
320 | return rc; | ||
321 | } | ||
322 | val = prop->hw_fn(val); | ||
323 | dev_dbg(chg->dev, "%s => %d\n", prop->name, val); | ||
324 | |||
325 | chg->attr[which] = val; | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static int smbb_charger_attr_parse(struct smbb_charger *chg, | ||
331 | enum smbb_attr which) | ||
332 | { | ||
333 | const struct smbb_charger_attr *prop; | ||
334 | unsigned int val; | ||
335 | int rc; | ||
336 | |||
337 | prop = &smbb_charger_attrs[which]; | ||
338 | |||
339 | rc = of_property_read_u32(chg->dev->of_node, prop->name, &val); | ||
340 | if (rc == 0) { | ||
341 | rc = smbb_charger_attr_write(chg, which, val); | ||
342 | if (!rc || !prop->fail_ok) | ||
343 | return rc; | ||
344 | } | ||
345 | return smbb_charger_attr_read(chg, which); | ||
346 | } | ||
347 | |||
348 | static void smbb_set_line_flag(struct smbb_charger *chg, int irq, int flag) | ||
349 | { | ||
350 | bool state; | ||
351 | int ret; | ||
352 | |||
353 | ret = irq_get_irqchip_state(irq, IRQCHIP_STATE_LINE_LEVEL, &state); | ||
354 | if (ret < 0) { | ||
355 | dev_err(chg->dev, "failed to read irq line\n"); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | mutex_lock(&chg->statlock); | ||
360 | if (state) | ||
361 | chg->status |= flag; | ||
362 | else | ||
363 | chg->status &= ~flag; | ||
364 | mutex_unlock(&chg->statlock); | ||
365 | |||
366 | dev_dbg(chg->dev, "status = %03lx\n", chg->status); | ||
367 | } | ||
368 | |||
369 | static irqreturn_t smbb_usb_valid_handler(int irq, void *_data) | ||
370 | { | ||
371 | struct smbb_charger *chg = _data; | ||
372 | |||
373 | smbb_set_line_flag(chg, irq, STATUS_USBIN_VALID); | ||
374 | power_supply_changed(chg->usb_psy); | ||
375 | |||
376 | return IRQ_HANDLED; | ||
377 | } | ||
378 | |||
379 | static irqreturn_t smbb_dc_valid_handler(int irq, void *_data) | ||
380 | { | ||
381 | struct smbb_charger *chg = _data; | ||
382 | |||
383 | smbb_set_line_flag(chg, irq, STATUS_DCIN_VALID); | ||
384 | if (!chg->dc_disabled) | ||
385 | power_supply_changed(chg->dc_psy); | ||
386 | |||
387 | return IRQ_HANDLED; | ||
388 | } | ||
389 | |||
390 | static irqreturn_t smbb_bat_temp_handler(int irq, void *_data) | ||
391 | { | ||
392 | struct smbb_charger *chg = _data; | ||
393 | unsigned int val; | ||
394 | int rc; | ||
395 | |||
396 | rc = regmap_read(chg->regmap, chg->addr + SMBB_BAT_TEMP_STATUS, &val); | ||
397 | if (rc) | ||
398 | return IRQ_HANDLED; | ||
399 | |||
400 | mutex_lock(&chg->statlock); | ||
401 | if (val & TEMP_STATUS_OK) { | ||
402 | chg->status |= STATUS_BAT_OK; | ||
403 | } else { | ||
404 | chg->status &= ~STATUS_BAT_OK; | ||
405 | if (val & TEMP_STATUS_HOT) | ||
406 | chg->status |= STATUS_BAT_HOT; | ||
407 | } | ||
408 | mutex_unlock(&chg->statlock); | ||
409 | |||
410 | power_supply_changed(chg->bat_psy); | ||
411 | return IRQ_HANDLED; | ||
412 | } | ||
413 | |||
414 | static irqreturn_t smbb_bat_present_handler(int irq, void *_data) | ||
415 | { | ||
416 | struct smbb_charger *chg = _data; | ||
417 | |||
418 | smbb_set_line_flag(chg, irq, STATUS_BAT_PRESENT); | ||
419 | power_supply_changed(chg->bat_psy); | ||
420 | |||
421 | return IRQ_HANDLED; | ||
422 | } | ||
423 | |||
424 | static irqreturn_t smbb_chg_done_handler(int irq, void *_data) | ||
425 | { | ||
426 | struct smbb_charger *chg = _data; | ||
427 | |||
428 | smbb_set_line_flag(chg, irq, STATUS_CHG_DONE); | ||
429 | power_supply_changed(chg->bat_psy); | ||
430 | |||
431 | return IRQ_HANDLED; | ||
432 | } | ||
433 | |||
434 | static irqreturn_t smbb_chg_gone_handler(int irq, void *_data) | ||
435 | { | ||
436 | struct smbb_charger *chg = _data; | ||
437 | |||
438 | smbb_set_line_flag(chg, irq, STATUS_CHG_GONE); | ||
439 | power_supply_changed(chg->bat_psy); | ||
440 | power_supply_changed(chg->usb_psy); | ||
441 | if (!chg->dc_disabled) | ||
442 | power_supply_changed(chg->dc_psy); | ||
443 | |||
444 | return IRQ_HANDLED; | ||
445 | } | ||
446 | |||
447 | static irqreturn_t smbb_chg_fast_handler(int irq, void *_data) | ||
448 | { | ||
449 | struct smbb_charger *chg = _data; | ||
450 | |||
451 | smbb_set_line_flag(chg, irq, STATUS_CHG_FAST); | ||
452 | power_supply_changed(chg->bat_psy); | ||
453 | |||
454 | return IRQ_HANDLED; | ||
455 | } | ||
456 | |||
457 | static irqreturn_t smbb_chg_trkl_handler(int irq, void *_data) | ||
458 | { | ||
459 | struct smbb_charger *chg = _data; | ||
460 | |||
461 | smbb_set_line_flag(chg, irq, STATUS_CHG_TRKL); | ||
462 | power_supply_changed(chg->bat_psy); | ||
463 | |||
464 | return IRQ_HANDLED; | ||
465 | } | ||
466 | |||
467 | static const struct smbb_irq { | ||
468 | const char *name; | ||
469 | irqreturn_t (*handler)(int, void *); | ||
470 | } smbb_charger_irqs[] = { | ||
471 | { "chg-done", smbb_chg_done_handler }, | ||
472 | { "chg-fast", smbb_chg_fast_handler }, | ||
473 | { "chg-trkl", smbb_chg_trkl_handler }, | ||
474 | { "bat-temp-ok", smbb_bat_temp_handler }, | ||
475 | { "bat-present", smbb_bat_present_handler }, | ||
476 | { "chg-gone", smbb_chg_gone_handler }, | ||
477 | { "usb-valid", smbb_usb_valid_handler }, | ||
478 | { "dc-valid", smbb_dc_valid_handler }, | ||
479 | }; | ||
480 | |||
481 | static int smbb_usbin_get_property(struct power_supply *psy, | ||
482 | enum power_supply_property psp, | ||
483 | union power_supply_propval *val) | ||
484 | { | ||
485 | struct smbb_charger *chg = power_supply_get_drvdata(psy); | ||
486 | int rc = 0; | ||
487 | |||
488 | switch (psp) { | ||
489 | case POWER_SUPPLY_PROP_ONLINE: | ||
490 | mutex_lock(&chg->statlock); | ||
491 | val->intval = !(chg->status & STATUS_CHG_GONE) && | ||
492 | (chg->status & STATUS_USBIN_VALID); | ||
493 | mutex_unlock(&chg->statlock); | ||
494 | break; | ||
495 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: | ||
496 | val->intval = chg->attr[ATTR_USBIN_IMAX]; | ||
497 | break; | ||
498 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: | ||
499 | val->intval = 2500000; | ||
500 | break; | ||
501 | default: | ||
502 | rc = -EINVAL; | ||
503 | break; | ||
504 | } | ||
505 | |||
506 | return rc; | ||
507 | } | ||
508 | |||
509 | static int smbb_usbin_set_property(struct power_supply *psy, | ||
510 | enum power_supply_property psp, | ||
511 | const union power_supply_propval *val) | ||
512 | { | ||
513 | struct smbb_charger *chg = power_supply_get_drvdata(psy); | ||
514 | int rc; | ||
515 | |||
516 | switch (psp) { | ||
517 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: | ||
518 | rc = smbb_charger_attr_write(chg, ATTR_USBIN_IMAX, | ||
519 | val->intval); | ||
520 | break; | ||
521 | default: | ||
522 | rc = -EINVAL; | ||
523 | break; | ||
524 | } | ||
525 | |||
526 | return rc; | ||
527 | } | ||
528 | |||
529 | static int smbb_dcin_get_property(struct power_supply *psy, | ||
530 | enum power_supply_property psp, | ||
531 | union power_supply_propval *val) | ||
532 | { | ||
533 | struct smbb_charger *chg = power_supply_get_drvdata(psy); | ||
534 | int rc = 0; | ||
535 | |||
536 | switch (psp) { | ||
537 | case POWER_SUPPLY_PROP_ONLINE: | ||
538 | mutex_lock(&chg->statlock); | ||
539 | val->intval = !(chg->status & STATUS_CHG_GONE) && | ||
540 | (chg->status & STATUS_DCIN_VALID); | ||
541 | mutex_unlock(&chg->statlock); | ||
542 | break; | ||
543 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: | ||
544 | val->intval = chg->attr[ATTR_DCIN_IMAX]; | ||
545 | break; | ||
546 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: | ||
547 | val->intval = 2500000; | ||
548 | break; | ||
549 | default: | ||
550 | rc = -EINVAL; | ||
551 | break; | ||
552 | } | ||
553 | |||
554 | return rc; | ||
555 | } | ||
556 | |||
557 | static int smbb_dcin_set_property(struct power_supply *psy, | ||
558 | enum power_supply_property psp, | ||
559 | const union power_supply_propval *val) | ||
560 | { | ||
561 | struct smbb_charger *chg = power_supply_get_drvdata(psy); | ||
562 | int rc; | ||
563 | |||
564 | switch (psp) { | ||
565 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: | ||
566 | rc = smbb_charger_attr_write(chg, ATTR_DCIN_IMAX, | ||
567 | val->intval); | ||
568 | break; | ||
569 | default: | ||
570 | rc = -EINVAL; | ||
571 | break; | ||
572 | } | ||
573 | |||
574 | return rc; | ||
575 | } | ||
576 | |||
577 | static int smbb_charger_writable_property(struct power_supply *psy, | ||
578 | enum power_supply_property psp) | ||
579 | { | ||
580 | return psp == POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT; | ||
581 | } | ||
582 | |||
583 | static int smbb_battery_get_property(struct power_supply *psy, | ||
584 | enum power_supply_property psp, | ||
585 | union power_supply_propval *val) | ||
586 | { | ||
587 | struct smbb_charger *chg = power_supply_get_drvdata(psy); | ||
588 | unsigned long status; | ||
589 | int rc = 0; | ||
590 | |||
591 | mutex_lock(&chg->statlock); | ||
592 | status = chg->status; | ||
593 | mutex_unlock(&chg->statlock); | ||
594 | |||
595 | switch (psp) { | ||
596 | case POWER_SUPPLY_PROP_STATUS: | ||
597 | if (status & STATUS_CHG_GONE) | ||
598 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
599 | else if (!(status & (STATUS_DCIN_VALID | STATUS_USBIN_VALID))) | ||
600 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
601 | else if (status & STATUS_CHG_DONE) | ||
602 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
603 | else if (!(status & STATUS_BAT_OK)) | ||
604 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
605 | else if (status & (STATUS_CHG_FAST | STATUS_CHG_TRKL)) | ||
606 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
607 | else /* everything is ok for charging, but we are not... */ | ||
608 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
609 | break; | ||
610 | case POWER_SUPPLY_PROP_HEALTH: | ||
611 | if (status & STATUS_BAT_OK) | ||
612 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
613 | else if (status & STATUS_BAT_HOT) | ||
614 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
615 | else | ||
616 | val->intval = POWER_SUPPLY_HEALTH_COLD; | ||
617 | break; | ||
618 | case POWER_SUPPLY_PROP_CHARGE_TYPE: | ||
619 | if (status & STATUS_CHG_FAST) | ||
620 | val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST; | ||
621 | else if (status & STATUS_CHG_TRKL) | ||
622 | val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE; | ||
623 | else | ||
624 | val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; | ||
625 | break; | ||
626 | case POWER_SUPPLY_PROP_PRESENT: | ||
627 | val->intval = !!(status & STATUS_BAT_PRESENT); | ||
628 | break; | ||
629 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
630 | val->intval = chg->attr[ATTR_BAT_IMAX]; | ||
631 | break; | ||
632 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | ||
633 | val->intval = chg->attr[ATTR_BAT_VMAX]; | ||
634 | break; | ||
635 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
636 | /* this charger is a single-cell lithium-ion battery charger | ||
637 | * only. If you hook up some other technology, there will be | ||
638 | * fireworks. | ||
639 | */ | ||
640 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
641 | break; | ||
642 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | ||
643 | val->intval = 3000000; /* single-cell li-ion low end */ | ||
644 | break; | ||
645 | default: | ||
646 | rc = -EINVAL; | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | return rc; | ||
651 | } | ||
652 | |||
653 | static int smbb_battery_set_property(struct power_supply *psy, | ||
654 | enum power_supply_property psp, | ||
655 | const union power_supply_propval *val) | ||
656 | { | ||
657 | struct smbb_charger *chg = power_supply_get_drvdata(psy); | ||
658 | int rc; | ||
659 | |||
660 | switch (psp) { | ||
661 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
662 | rc = smbb_charger_attr_write(chg, ATTR_BAT_IMAX, val->intval); | ||
663 | break; | ||
664 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | ||
665 | rc = smbb_charger_attr_write(chg, ATTR_BAT_VMAX, val->intval); | ||
666 | break; | ||
667 | default: | ||
668 | rc = -EINVAL; | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | return rc; | ||
673 | } | ||
674 | |||
675 | static int smbb_battery_writable_property(struct power_supply *psy, | ||
676 | enum power_supply_property psp) | ||
677 | { | ||
678 | switch (psp) { | ||
679 | case POWER_SUPPLY_PROP_CURRENT_MAX: | ||
680 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | ||
681 | return 1; | ||
682 | default: | ||
683 | return 0; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | static enum power_supply_property smbb_charger_properties[] = { | ||
688 | POWER_SUPPLY_PROP_ONLINE, | ||
689 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, | ||
690 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, | ||
691 | }; | ||
692 | |||
693 | static enum power_supply_property smbb_battery_properties[] = { | ||
694 | POWER_SUPPLY_PROP_STATUS, | ||
695 | POWER_SUPPLY_PROP_HEALTH, | ||
696 | POWER_SUPPLY_PROP_PRESENT, | ||
697 | POWER_SUPPLY_PROP_CHARGE_TYPE, | ||
698 | POWER_SUPPLY_PROP_CURRENT_MAX, | ||
699 | POWER_SUPPLY_PROP_VOLTAGE_MAX, | ||
700 | POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, | ||
701 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
702 | }; | ||
703 | |||
704 | static const struct reg_off_mask_default { | ||
705 | unsigned int offset; | ||
706 | unsigned int mask; | ||
707 | unsigned int value; | ||
708 | unsigned int rev_mask; | ||
709 | } smbb_charger_setup[] = { | ||
710 | /* The bootloader is supposed to set this... make sure anyway. */ | ||
711 | { SMBB_MISC_BOOT_DONE, BOOT_DONE, BOOT_DONE }, | ||
712 | |||
713 | /* Disable software timer */ | ||
714 | { SMBB_CHG_TCHG_MAX_EN, TCHG_MAX_EN, 0 }, | ||
715 | |||
716 | /* Clear and disable watchdog */ | ||
717 | { SMBB_CHG_WDOG_TIME, 0xff, 160 }, | ||
718 | { SMBB_CHG_WDOG_EN, WDOG_EN, 0 }, | ||
719 | |||
720 | /* Use charger based EoC detection */ | ||
721 | { SMBB_CHG_IBAT_TERM_CHG, IBAT_TERM_CHG_IEOC, IBAT_TERM_CHG_IEOC_CHG }, | ||
722 | |||
723 | /* Disable GSM PA load adjustment. | ||
724 | * The PA signal is incorrectly connected on v2. | ||
725 | */ | ||
726 | { SMBB_CHG_CFG, 0xff, 0x00, BIT(3) }, | ||
727 | |||
728 | /* Use VBAT (not VSYS) to compensate for IR drop during fast charging */ | ||
729 | { SMBB_BUCK_REG_MODE, BUCK_REG_MODE, BUCK_REG_MODE_VBAT }, | ||
730 | |||
731 | /* Enable battery temperature comparators */ | ||
732 | { SMBB_BAT_BTC_CTRL, BTC_CTRL_COMP_EN, BTC_CTRL_COMP_EN }, | ||
733 | |||
734 | /* Stop USB enumeration timer */ | ||
735 | { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP }, | ||
736 | |||
737 | #if 0 /* FIXME supposedly only to disable hardware ARB termination */ | ||
738 | { SMBB_USB_SEC_ACCESS, SEC_ACCESS_MAGIC }, | ||
739 | { SMBB_USB_REV_BST, 0xff, REV_BST_CHG_GONE }, | ||
740 | #endif | ||
741 | |||
742 | /* Stop USB enumeration timer, again */ | ||
743 | { SMBB_USB_ENUM_TIMER_STOP, ENUM_TIMER_STOP, ENUM_TIMER_STOP }, | ||
744 | |||
745 | /* Enable charging */ | ||
746 | { SMBB_CHG_CTRL, CTRL_EN, CTRL_EN }, | ||
747 | }; | ||
748 | |||
749 | static char *smbb_bif[] = { "smbb-bif" }; | ||
750 | |||
751 | static const struct power_supply_desc bat_psy_desc = { | ||
752 | .name = "smbb-bif", | ||
753 | .type = POWER_SUPPLY_TYPE_BATTERY, | ||
754 | .properties = smbb_battery_properties, | ||
755 | .num_properties = ARRAY_SIZE(smbb_battery_properties), | ||
756 | .get_property = smbb_battery_get_property, | ||
757 | .set_property = smbb_battery_set_property, | ||
758 | .property_is_writeable = smbb_battery_writable_property, | ||
759 | }; | ||
760 | |||
761 | static const struct power_supply_desc usb_psy_desc = { | ||
762 | .name = "smbb-usbin", | ||
763 | .type = POWER_SUPPLY_TYPE_USB, | ||
764 | .properties = smbb_charger_properties, | ||
765 | .num_properties = ARRAY_SIZE(smbb_charger_properties), | ||
766 | .get_property = smbb_usbin_get_property, | ||
767 | .set_property = smbb_usbin_set_property, | ||
768 | .property_is_writeable = smbb_charger_writable_property, | ||
769 | }; | ||
770 | |||
771 | static const struct power_supply_desc dc_psy_desc = { | ||
772 | .name = "smbb-dcin", | ||
773 | .type = POWER_SUPPLY_TYPE_MAINS, | ||
774 | .properties = smbb_charger_properties, | ||
775 | .num_properties = ARRAY_SIZE(smbb_charger_properties), | ||
776 | .get_property = smbb_dcin_get_property, | ||
777 | .set_property = smbb_dcin_set_property, | ||
778 | .property_is_writeable = smbb_charger_writable_property, | ||
779 | }; | ||
780 | |||
781 | static int smbb_charger_probe(struct platform_device *pdev) | ||
782 | { | ||
783 | struct power_supply_config bat_cfg = {}; | ||
784 | struct power_supply_config usb_cfg = {}; | ||
785 | struct power_supply_config dc_cfg = {}; | ||
786 | struct smbb_charger *chg; | ||
787 | int rc, i; | ||
788 | |||
789 | chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL); | ||
790 | if (!chg) | ||
791 | return -ENOMEM; | ||
792 | |||
793 | chg->dev = &pdev->dev; | ||
794 | mutex_init(&chg->statlock); | ||
795 | |||
796 | chg->regmap = dev_get_regmap(pdev->dev.parent, NULL); | ||
797 | if (!chg->regmap) { | ||
798 | dev_err(&pdev->dev, "failed to locate regmap\n"); | ||
799 | return -ENODEV; | ||
800 | } | ||
801 | |||
802 | rc = of_property_read_u32(pdev->dev.of_node, "reg", &chg->addr); | ||
803 | if (rc) { | ||
804 | dev_err(&pdev->dev, "missing or invalid 'reg' property\n"); | ||
805 | return rc; | ||
806 | } | ||
807 | |||
808 | rc = regmap_read(chg->regmap, chg->addr + SMBB_MISC_REV2, &chg->revision); | ||
809 | if (rc) { | ||
810 | dev_err(&pdev->dev, "unable to read revision\n"); | ||
811 | return rc; | ||
812 | } | ||
813 | |||
814 | chg->revision += 1; | ||
815 | if (chg->revision != 2 && chg->revision != 3) { | ||
816 | dev_err(&pdev->dev, "v1 hardware not supported\n"); | ||
817 | return -ENODEV; | ||
818 | } | ||
819 | dev_info(&pdev->dev, "Initializing SMBB rev %u", chg->revision); | ||
820 | |||
821 | chg->dc_disabled = of_property_read_bool(pdev->dev.of_node, "qcom,disable-dc"); | ||
822 | |||
823 | for (i = 0; i < _ATTR_CNT; ++i) { | ||
824 | rc = smbb_charger_attr_parse(chg, i); | ||
825 | if (rc) { | ||
826 | dev_err(&pdev->dev, "failed to parse/apply settings\n"); | ||
827 | return rc; | ||
828 | } | ||
829 | } | ||
830 | |||
831 | bat_cfg.drv_data = chg; | ||
832 | bat_cfg.of_node = pdev->dev.of_node; | ||
833 | chg->bat_psy = devm_power_supply_register(&pdev->dev, | ||
834 | &bat_psy_desc, | ||
835 | &bat_cfg); | ||
836 | if (IS_ERR(chg->bat_psy)) { | ||
837 | dev_err(&pdev->dev, "failed to register battery\n"); | ||
838 | return PTR_ERR(chg->bat_psy); | ||
839 | } | ||
840 | |||
841 | usb_cfg.drv_data = chg; | ||
842 | usb_cfg.supplied_to = smbb_bif; | ||
843 | usb_cfg.num_supplicants = ARRAY_SIZE(smbb_bif); | ||
844 | chg->usb_psy = devm_power_supply_register(&pdev->dev, | ||
845 | &usb_psy_desc, | ||
846 | &usb_cfg); | ||
847 | if (IS_ERR(chg->usb_psy)) { | ||
848 | dev_err(&pdev->dev, "failed to register USB power supply\n"); | ||
849 | return PTR_ERR(chg->usb_psy); | ||
850 | } | ||
851 | |||
852 | if (!chg->dc_disabled) { | ||
853 | dc_cfg.drv_data = chg; | ||
854 | dc_cfg.supplied_to = smbb_bif; | ||
855 | dc_cfg.num_supplicants = ARRAY_SIZE(smbb_bif); | ||
856 | chg->dc_psy = devm_power_supply_register(&pdev->dev, | ||
857 | &dc_psy_desc, | ||
858 | &dc_cfg); | ||
859 | if (IS_ERR(chg->dc_psy)) { | ||
860 | dev_err(&pdev->dev, "failed to register DC power supply\n"); | ||
861 | return PTR_ERR(chg->dc_psy); | ||
862 | } | ||
863 | } | ||
864 | |||
865 | for (i = 0; i < ARRAY_SIZE(smbb_charger_irqs); ++i) { | ||
866 | int irq; | ||
867 | |||
868 | irq = platform_get_irq_byname(pdev, smbb_charger_irqs[i].name); | ||
869 | if (irq < 0) { | ||
870 | dev_err(&pdev->dev, "failed to get irq '%s'\n", | ||
871 | smbb_charger_irqs[i].name); | ||
872 | return irq; | ||
873 | } | ||
874 | |||
875 | smbb_charger_irqs[i].handler(irq, chg); | ||
876 | |||
877 | rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, | ||
878 | smbb_charger_irqs[i].handler, IRQF_ONESHOT, | ||
879 | smbb_charger_irqs[i].name, chg); | ||
880 | if (rc) { | ||
881 | dev_err(&pdev->dev, "failed to request irq '%s'\n", | ||
882 | smbb_charger_irqs[i].name); | ||
883 | return rc; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | chg->jeita_ext_temp = of_property_read_bool(pdev->dev.of_node, | ||
888 | "qcom,jeita-extended-temp-range"); | ||
889 | |||
890 | /* Set temperature range to [35%:70%] or [25%:80%] accordingly */ | ||
891 | rc = regmap_update_bits(chg->regmap, chg->addr + SMBB_BAT_BTC_CTRL, | ||
892 | BTC_CTRL_COLD_EXT | BTC_CTRL_HOT_EXT_N, | ||
893 | chg->jeita_ext_temp ? | ||
894 | BTC_CTRL_COLD_EXT : | ||
895 | BTC_CTRL_HOT_EXT_N); | ||
896 | if (rc) { | ||
897 | dev_err(&pdev->dev, | ||
898 | "unable to set %s temperature range\n", | ||
899 | chg->jeita_ext_temp ? "JEITA extended" : "normal"); | ||
900 | return rc; | ||
901 | } | ||
902 | |||
903 | for (i = 0; i < ARRAY_SIZE(smbb_charger_setup); ++i) { | ||
904 | const struct reg_off_mask_default *r = &smbb_charger_setup[i]; | ||
905 | |||
906 | if (r->rev_mask & BIT(chg->revision)) | ||
907 | continue; | ||
908 | |||
909 | rc = regmap_update_bits(chg->regmap, chg->addr + r->offset, | ||
910 | r->mask, r->value); | ||
911 | if (rc) { | ||
912 | dev_err(&pdev->dev, | ||
913 | "unable to initializing charging, bailing\n"); | ||
914 | return rc; | ||
915 | } | ||
916 | } | ||
917 | |||
918 | platform_set_drvdata(pdev, chg); | ||
919 | |||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | static int smbb_charger_remove(struct platform_device *pdev) | ||
924 | { | ||
925 | struct smbb_charger *chg; | ||
926 | |||
927 | chg = platform_get_drvdata(pdev); | ||
928 | |||
929 | regmap_update_bits(chg->regmap, chg->addr + SMBB_CHG_CTRL, CTRL_EN, 0); | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static const struct of_device_id smbb_charger_id_table[] = { | ||
935 | { .compatible = "qcom,pm8941-charger" }, | ||
936 | { } | ||
937 | }; | ||
938 | MODULE_DEVICE_TABLE(of, smbb_charger_id_table); | ||
939 | |||
940 | static struct platform_driver smbb_charger_driver = { | ||
941 | .probe = smbb_charger_probe, | ||
942 | .remove = smbb_charger_remove, | ||
943 | .driver = { | ||
944 | .name = "qcom-smbb", | ||
945 | .of_match_table = smbb_charger_id_table, | ||
946 | }, | ||
947 | }; | ||
948 | module_platform_driver(smbb_charger_driver); | ||
949 | |||
950 | MODULE_DESCRIPTION("Qualcomm Switch-Mode Battery Charger and Boost driver"); | ||
951 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 5a0189bf19bb..1131cf75acc6 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig | |||
@@ -15,7 +15,7 @@ config POWER_RESET_AS3722 | |||
15 | This driver supports turning off board via a ams AS3722 power-off. | 15 | This driver supports turning off board via a ams AS3722 power-off. |
16 | 16 | ||
17 | config POWER_RESET_AT91_POWEROFF | 17 | config POWER_RESET_AT91_POWEROFF |
18 | bool "Atmel AT91 poweroff driver" | 18 | tristate "Atmel AT91 poweroff driver" |
19 | depends on ARCH_AT91 | 19 | depends on ARCH_AT91 |
20 | default SOC_AT91SAM9 || SOC_SAMA5 | 20 | default SOC_AT91SAM9 || SOC_SAMA5 |
21 | help | 21 | help |
@@ -23,7 +23,7 @@ config POWER_RESET_AT91_POWEROFF | |||
23 | SoCs | 23 | SoCs |
24 | 24 | ||
25 | config POWER_RESET_AT91_RESET | 25 | config POWER_RESET_AT91_RESET |
26 | bool "Atmel AT91 reset driver" | 26 | tristate "Atmel AT91 reset driver" |
27 | depends on ARCH_AT91 | 27 | depends on ARCH_AT91 |
28 | default SOC_AT91SAM9 || SOC_SAMA5 | 28 | default SOC_AT91SAM9 || SOC_SAMA5 |
29 | help | 29 | help |
diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c index 9847cfb7e23d..e9e24df35f26 100644 --- a/drivers/power/reset/at91-poweroff.c +++ b/drivers/power/reset/at91-poweroff.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * warranty of any kind, whether express or implied. | 10 | * warranty of any kind, whether express or implied. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/clk.h> | ||
13 | #include <linux/io.h> | 14 | #include <linux/io.h> |
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/of.h> | 16 | #include <linux/of.h> |
@@ -48,6 +49,7 @@ static const char *shdwc_wakeup_modes[] = { | |||
48 | }; | 49 | }; |
49 | 50 | ||
50 | static void __iomem *at91_shdwc_base; | 51 | static void __iomem *at91_shdwc_base; |
52 | static struct clk *sclk; | ||
51 | 53 | ||
52 | static void __init at91_wakeup_status(void) | 54 | static void __init at91_wakeup_status(void) |
53 | { | 55 | { |
@@ -119,9 +121,10 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev) | |||
119 | writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR); | 121 | writel(wakeup_mode | mode, at91_shdwc_base + AT91_SHDW_MR); |
120 | } | 122 | } |
121 | 123 | ||
122 | static int at91_poweroff_probe(struct platform_device *pdev) | 124 | static int __init at91_poweroff_probe(struct platform_device *pdev) |
123 | { | 125 | { |
124 | struct resource *res; | 126 | struct resource *res; |
127 | int ret; | ||
125 | 128 | ||
126 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 129 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
127 | at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res); | 130 | at91_shdwc_base = devm_ioremap_resource(&pdev->dev, res); |
@@ -130,6 +133,16 @@ static int at91_poweroff_probe(struct platform_device *pdev) | |||
130 | return PTR_ERR(at91_shdwc_base); | 133 | return PTR_ERR(at91_shdwc_base); |
131 | } | 134 | } |
132 | 135 | ||
136 | sclk = devm_clk_get(&pdev->dev, NULL); | ||
137 | if (IS_ERR(sclk)) | ||
138 | return PTR_ERR(sclk); | ||
139 | |||
140 | ret = clk_prepare_enable(sclk); | ||
141 | if (ret) { | ||
142 | dev_err(&pdev->dev, "Could not enable slow clock\n"); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
133 | at91_wakeup_status(); | 146 | at91_wakeup_status(); |
134 | 147 | ||
135 | if (pdev->dev.of_node) | 148 | if (pdev->dev.of_node) |
@@ -140,6 +153,16 @@ static int at91_poweroff_probe(struct platform_device *pdev) | |||
140 | return 0; | 153 | return 0; |
141 | } | 154 | } |
142 | 155 | ||
156 | static int __exit at91_poweroff_remove(struct platform_device *pdev) | ||
157 | { | ||
158 | if (pm_power_off == at91_poweroff) | ||
159 | pm_power_off = NULL; | ||
160 | |||
161 | clk_disable_unprepare(sclk); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
143 | static const struct of_device_id at91_poweroff_of_match[] = { | 166 | static const struct of_device_id at91_poweroff_of_match[] = { |
144 | { .compatible = "atmel,at91sam9260-shdwc", }, | 167 | { .compatible = "atmel,at91sam9260-shdwc", }, |
145 | { .compatible = "atmel,at91sam9rl-shdwc", }, | 168 | { .compatible = "atmel,at91sam9rl-shdwc", }, |
@@ -148,10 +171,14 @@ static const struct of_device_id at91_poweroff_of_match[] = { | |||
148 | }; | 171 | }; |
149 | 172 | ||
150 | static struct platform_driver at91_poweroff_driver = { | 173 | static struct platform_driver at91_poweroff_driver = { |
151 | .probe = at91_poweroff_probe, | 174 | .remove = __exit_p(at91_poweroff_remove), |
152 | .driver = { | 175 | .driver = { |
153 | .name = "at91-poweroff", | 176 | .name = "at91-poweroff", |
154 | .of_match_table = at91_poweroff_of_match, | 177 | .of_match_table = at91_poweroff_of_match, |
155 | }, | 178 | }, |
156 | }; | 179 | }; |
157 | module_platform_driver(at91_poweroff_driver); | 180 | module_platform_driver_probe(at91_poweroff_driver, at91_poweroff_probe); |
181 | |||
182 | MODULE_AUTHOR("Atmel Corporation"); | ||
183 | MODULE_DESCRIPTION("Shutdown driver for Atmel SoCs"); | ||
184 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index c378d4ec826f..3f6b5dd7c3d4 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Atmel AT91 SAM9 SoCs reset code | 2 | * Atmel AT91 SAM9 & SAMA5 SoCs reset code |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Atmel Corporation. | 4 | * Copyright (C) 2007 Atmel Corporation. |
5 | * Copyright (C) BitBox Ltd 2010 | 5 | * Copyright (C) BitBox Ltd 2010 |
@@ -11,6 +11,7 @@ | |||
11 | * warranty of any kind, whether express or implied. | 11 | * warranty of any kind, whether express or implied. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/clk.h> | ||
14 | #include <linux/io.h> | 15 | #include <linux/io.h> |
15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
16 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
@@ -46,6 +47,7 @@ enum reset_type { | |||
46 | }; | 47 | }; |
47 | 48 | ||
48 | static void __iomem *at91_ramc_base[2], *at91_rstc_base; | 49 | static void __iomem *at91_ramc_base[2], *at91_rstc_base; |
50 | static struct clk *sclk; | ||
49 | 51 | ||
50 | /* | 52 | /* |
51 | * unless the SDRAM is cleanly shutdown before we hit the | 53 | * unless the SDRAM is cleanly shutdown before we hit the |
@@ -178,11 +180,11 @@ static struct notifier_block at91_restart_nb = { | |||
178 | .priority = 192, | 180 | .priority = 192, |
179 | }; | 181 | }; |
180 | 182 | ||
181 | static int at91_reset_of_probe(struct platform_device *pdev) | 183 | static int __init at91_reset_probe(struct platform_device *pdev) |
182 | { | 184 | { |
183 | const struct of_device_id *match; | 185 | const struct of_device_id *match; |
184 | struct device_node *np; | 186 | struct device_node *np; |
185 | int idx = 0; | 187 | int ret, idx = 0; |
186 | 188 | ||
187 | at91_rstc_base = of_iomap(pdev->dev.of_node, 0); | 189 | at91_rstc_base = of_iomap(pdev->dev.of_node, 0); |
188 | if (!at91_rstc_base) { | 190 | if (!at91_rstc_base) { |
@@ -204,53 +206,32 @@ static int at91_reset_of_probe(struct platform_device *pdev) | |||
204 | 206 | ||
205 | match = of_match_node(at91_reset_of_match, pdev->dev.of_node); | 207 | match = of_match_node(at91_reset_of_match, pdev->dev.of_node); |
206 | at91_restart_nb.notifier_call = match->data; | 208 | at91_restart_nb.notifier_call = match->data; |
207 | return register_restart_handler(&at91_restart_nb); | ||
208 | } | ||
209 | 209 | ||
210 | static int at91_reset_platform_probe(struct platform_device *pdev) | 210 | sclk = devm_clk_get(&pdev->dev, NULL); |
211 | { | 211 | if (IS_ERR(sclk)) |
212 | const struct platform_device_id *match; | 212 | return PTR_ERR(sclk); |
213 | struct resource *res; | ||
214 | int idx = 0; | ||
215 | 213 | ||
216 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 214 | ret = clk_prepare_enable(sclk); |
217 | at91_rstc_base = devm_ioremap_resource(&pdev->dev, res); | 215 | if (ret) { |
218 | if (IS_ERR(at91_rstc_base)) { | 216 | dev_err(&pdev->dev, "Could not enable slow clock\n"); |
219 | dev_err(&pdev->dev, "Could not map reset controller address\n"); | 217 | return ret; |
220 | return PTR_ERR(at91_rstc_base); | ||
221 | } | 218 | } |
222 | 219 | ||
223 | for (idx = 0; idx < 2; idx++) { | 220 | ret = register_restart_handler(&at91_restart_nb); |
224 | res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 ); | 221 | if (ret) { |
225 | at91_ramc_base[idx] = devm_ioremap(&pdev->dev, res->start, | 222 | clk_disable_unprepare(sclk); |
226 | resource_size(res)); | 223 | return ret; |
227 | if (!at91_ramc_base[idx]) { | ||
228 | dev_err(&pdev->dev, "Could not map ram controller address\n"); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | } | 224 | } |
232 | 225 | ||
233 | match = platform_get_device_id(pdev); | 226 | at91_reset_status(pdev); |
234 | at91_restart_nb.notifier_call = | ||
235 | (int (*)(struct notifier_block *, | ||
236 | unsigned long, void *)) match->driver_data; | ||
237 | 227 | ||
238 | return register_restart_handler(&at91_restart_nb); | 228 | return 0; |
239 | } | 229 | } |
240 | 230 | ||
241 | static int at91_reset_probe(struct platform_device *pdev) | 231 | static int __exit at91_reset_remove(struct platform_device *pdev) |
242 | { | 232 | { |
243 | int ret; | 233 | unregister_restart_handler(&at91_restart_nb); |
244 | 234 | clk_disable_unprepare(sclk); | |
245 | if (pdev->dev.of_node) | ||
246 | ret = at91_reset_of_probe(pdev); | ||
247 | else | ||
248 | ret = at91_reset_platform_probe(pdev); | ||
249 | |||
250 | if (ret) | ||
251 | return ret; | ||
252 | |||
253 | at91_reset_status(pdev); | ||
254 | 235 | ||
255 | return 0; | 236 | return 0; |
256 | } | 237 | } |
@@ -262,11 +243,15 @@ static const struct platform_device_id at91_reset_plat_match[] = { | |||
262 | }; | 243 | }; |
263 | 244 | ||
264 | static struct platform_driver at91_reset_driver = { | 245 | static struct platform_driver at91_reset_driver = { |
265 | .probe = at91_reset_probe, | 246 | .remove = __exit_p(at91_reset_remove), |
266 | .driver = { | 247 | .driver = { |
267 | .name = "at91-reset", | 248 | .name = "at91-reset", |
268 | .of_match_table = at91_reset_of_match, | 249 | .of_match_table = at91_reset_of_match, |
269 | }, | 250 | }, |
270 | .id_table = at91_reset_plat_match, | 251 | .id_table = at91_reset_plat_match, |
271 | }; | 252 | }; |
272 | module_platform_driver(at91_reset_driver); | 253 | module_platform_driver_probe(at91_reset_driver, at91_reset_probe); |
254 | |||
255 | MODULE_AUTHOR("Atmel Corporation"); | ||
256 | MODULE_DESCRIPTION("Reset driver for Atmel SoCs"); | ||
257 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/rt9455_charger.c b/drivers/power/rt9455_charger.c index a49a9d44bdda..cfdbde9daf94 100644 --- a/drivers/power/rt9455_charger.c +++ b/drivers/power/rt9455_charger.c | |||
@@ -1760,5 +1760,4 @@ module_i2c_driver(rt9455_driver); | |||
1760 | 1760 | ||
1761 | MODULE_LICENSE("GPL"); | 1761 | MODULE_LICENSE("GPL"); |
1762 | MODULE_AUTHOR("Anda-Maria Nicolae <anda-maria.nicolae@intel.com>"); | 1762 | MODULE_AUTHOR("Anda-Maria Nicolae <anda-maria.nicolae@intel.com>"); |
1763 | MODULE_ALIAS("i2c:rt9455-charger"); | ||
1764 | MODULE_DESCRIPTION("Richtek RT9455 Charger Driver"); | 1763 | MODULE_DESCRIPTION("Richtek RT9455 Charger Driver"); |
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c index 0b60a0b5878b..072c5189bd6d 100644 --- a/drivers/power/smb347-charger.c +++ b/drivers/power/smb347-charger.c | |||
@@ -1332,4 +1332,3 @@ MODULE_AUTHOR("Bruce E. Robertson <bruce.e.robertson@intel.com>"); | |||
1332 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); | 1332 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); |
1333 | MODULE_DESCRIPTION("SMB347 battery charger driver"); | 1333 | MODULE_DESCRIPTION("SMB347 battery charger driver"); |
1334 | MODULE_LICENSE("GPL"); | 1334 | MODULE_LICENSE("GPL"); |
1335 | MODULE_ALIAS("i2c:smb347"); | ||
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index 7e8fbd29c30e..1b4b5e09538e 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c | |||
@@ -353,6 +353,7 @@ static const struct of_device_id of_tps65090_charger_match[] = { | |||
353 | { .compatible = "ti,tps65090-charger", }, | 353 | { .compatible = "ti,tps65090-charger", }, |
354 | { /* end */ } | 354 | { /* end */ } |
355 | }; | 355 | }; |
356 | MODULE_DEVICE_TABLE(of, of_tps65090_charger_match); | ||
356 | 357 | ||
357 | static struct platform_driver tps65090_charger_driver = { | 358 | static struct platform_driver tps65090_charger_driver = { |
358 | .driver = { | 359 | .driver = { |
diff --git a/drivers/power/tps65217_charger.c b/drivers/power/tps65217_charger.c new file mode 100644 index 000000000000..d9f56730c735 --- /dev/null +++ b/drivers/power/tps65217_charger.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * Battery charger driver for TI's tps65217 | ||
3 | * | ||
4 | * Copyright (c) 2015, Collabora Ltd. | ||
5 | |||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | |||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | |||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * Battery charger driver for TI's tps65217 | ||
21 | */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/kthread.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/err.h> | ||
31 | #include <linux/of.h> | ||
32 | #include <linux/of_device.h> | ||
33 | #include <linux/power_supply.h> | ||
34 | |||
35 | #include <linux/mfd/core.h> | ||
36 | #include <linux/mfd/tps65217.h> | ||
37 | |||
38 | #define POLL_INTERVAL (HZ * 2) | ||
39 | |||
40 | struct tps65217_charger { | ||
41 | struct tps65217 *tps; | ||
42 | struct device *dev; | ||
43 | struct power_supply *ac; | ||
44 | |||
45 | int ac_online; | ||
46 | int prev_ac_online; | ||
47 | |||
48 | struct task_struct *poll_task; | ||
49 | }; | ||
50 | |||
51 | static enum power_supply_property tps65217_ac_props[] = { | ||
52 | POWER_SUPPLY_PROP_ONLINE, | ||
53 | }; | ||
54 | |||
55 | static int tps65217_config_charger(struct tps65217_charger *charger) | ||
56 | { | ||
57 | int ret; | ||
58 | |||
59 | dev_dbg(charger->dev, "%s\n", __func__); | ||
60 | |||
61 | /* | ||
62 | * tps65217 rev. G, p. 31 (see p. 32 for NTC schematic) | ||
63 | * | ||
64 | * The device can be configured to support a 100k NTC (B = 3960) by | ||
65 | * setting the the NTC_TYPE bit in register CHGCONFIG1 to 1. However it | ||
66 | * is not recommended to do so. In sleep mode, the charger continues | ||
67 | * charging the battery, but all register values are reset to default | ||
68 | * values. Therefore, the charger would get the wrong temperature | ||
69 | * information. If 100k NTC setting is required, please contact the | ||
70 | * factory. | ||
71 | * | ||
72 | * ATTENTION, conflicting information, from p. 46 | ||
73 | * | ||
74 | * NTC TYPE (for battery temperature measurement) | ||
75 | * 0 – 100k (curve 1, B = 3960) | ||
76 | * 1 – 10k (curve 2, B = 3480) (default on reset) | ||
77 | * | ||
78 | */ | ||
79 | ret = tps65217_clear_bits(charger->tps, TPS65217_REG_CHGCONFIG1, | ||
80 | TPS65217_CHGCONFIG1_NTC_TYPE, | ||
81 | TPS65217_PROTECT_NONE); | ||
82 | if (ret) { | ||
83 | dev_err(charger->dev, | ||
84 | "failed to set 100k NTC setting: %d\n", ret); | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int tps65217_enable_charging(struct tps65217_charger *charger) | ||
92 | { | ||
93 | int ret; | ||
94 | |||
95 | /* charger already enabled */ | ||
96 | if (charger->ac_online) | ||
97 | return 0; | ||
98 | |||
99 | dev_dbg(charger->dev, "%s: enable charging\n", __func__); | ||
100 | ret = tps65217_set_bits(charger->tps, TPS65217_REG_CHGCONFIG1, | ||
101 | TPS65217_CHGCONFIG1_CHG_EN, | ||
102 | TPS65217_CHGCONFIG1_CHG_EN, | ||
103 | TPS65217_PROTECT_NONE); | ||
104 | if (ret) { | ||
105 | dev_err(charger->dev, | ||
106 | "%s: Error in writing CHG_EN in reg 0x%x: %d\n", | ||
107 | __func__, TPS65217_REG_CHGCONFIG1, ret); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | charger->ac_online = 1; | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int tps65217_ac_get_property(struct power_supply *psy, | ||
117 | enum power_supply_property psp, | ||
118 | union power_supply_propval *val) | ||
119 | { | ||
120 | struct tps65217_charger *charger = power_supply_get_drvdata(psy); | ||
121 | |||
122 | if (psp == POWER_SUPPLY_PROP_ONLINE) { | ||
123 | val->intval = charger->ac_online; | ||
124 | return 0; | ||
125 | } | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | static irqreturn_t tps65217_charger_irq(int irq, void *dev) | ||
130 | { | ||
131 | int ret, val; | ||
132 | struct tps65217_charger *charger = dev; | ||
133 | |||
134 | charger->prev_ac_online = charger->ac_online; | ||
135 | |||
136 | ret = tps65217_reg_read(charger->tps, TPS65217_REG_STATUS, &val); | ||
137 | if (ret < 0) { | ||
138 | dev_err(charger->dev, "%s: Error in reading reg 0x%x\n", | ||
139 | __func__, TPS65217_REG_STATUS); | ||
140 | return IRQ_HANDLED; | ||
141 | } | ||
142 | |||
143 | dev_dbg(charger->dev, "%s: 0x%x\n", __func__, val); | ||
144 | |||
145 | /* check for AC status bit */ | ||
146 | if (val & TPS65217_STATUS_ACPWR) { | ||
147 | ret = tps65217_enable_charging(charger); | ||
148 | if (ret) { | ||
149 | dev_err(charger->dev, | ||
150 | "failed to enable charger: %d\n", ret); | ||
151 | return IRQ_HANDLED; | ||
152 | } | ||
153 | } else { | ||
154 | charger->ac_online = 0; | ||
155 | } | ||
156 | |||
157 | if (charger->prev_ac_online != charger->ac_online) | ||
158 | power_supply_changed(charger->ac); | ||
159 | |||
160 | ret = tps65217_reg_read(charger->tps, TPS65217_REG_CHGCONFIG0, &val); | ||
161 | if (ret < 0) { | ||
162 | dev_err(charger->dev, "%s: Error in reading reg 0x%x\n", | ||
163 | __func__, TPS65217_REG_CHGCONFIG0); | ||
164 | return IRQ_HANDLED; | ||
165 | } | ||
166 | |||
167 | if (val & TPS65217_CHGCONFIG0_ACTIVE) | ||
168 | dev_dbg(charger->dev, "%s: charger is charging\n", __func__); | ||
169 | else | ||
170 | dev_dbg(charger->dev, | ||
171 | "%s: charger is NOT charging\n", __func__); | ||
172 | |||
173 | return IRQ_HANDLED; | ||
174 | } | ||
175 | |||
176 | static int tps65217_charger_poll_task(void *data) | ||
177 | { | ||
178 | set_freezable(); | ||
179 | |||
180 | while (!kthread_should_stop()) { | ||
181 | schedule_timeout_interruptible(POLL_INTERVAL); | ||
182 | try_to_freeze(); | ||
183 | tps65217_charger_irq(-1, data); | ||
184 | } | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static const struct power_supply_desc tps65217_charger_desc = { | ||
189 | .name = "tps65217-ac", | ||
190 | .type = POWER_SUPPLY_TYPE_MAINS, | ||
191 | .get_property = tps65217_ac_get_property, | ||
192 | .properties = tps65217_ac_props, | ||
193 | .num_properties = ARRAY_SIZE(tps65217_ac_props), | ||
194 | }; | ||
195 | |||
196 | static int tps65217_charger_probe(struct platform_device *pdev) | ||
197 | { | ||
198 | struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent); | ||
199 | struct tps65217_charger *charger; | ||
200 | int ret; | ||
201 | |||
202 | dev_dbg(&pdev->dev, "%s\n", __func__); | ||
203 | |||
204 | charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL); | ||
205 | if (!charger) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | charger->tps = tps; | ||
209 | charger->dev = &pdev->dev; | ||
210 | |||
211 | charger->ac = devm_power_supply_register(&pdev->dev, | ||
212 | &tps65217_charger_desc, | ||
213 | NULL); | ||
214 | if (IS_ERR(charger->ac)) { | ||
215 | dev_err(&pdev->dev, "failed: power supply register\n"); | ||
216 | return PTR_ERR(charger->ac); | ||
217 | } | ||
218 | |||
219 | ret = tps65217_config_charger(charger); | ||
220 | if (ret < 0) { | ||
221 | dev_err(charger->dev, "charger config failed, err %d\n", ret); | ||
222 | return ret; | ||
223 | } | ||
224 | |||
225 | charger->poll_task = kthread_run(tps65217_charger_poll_task, | ||
226 | charger, "ktps65217charger"); | ||
227 | if (IS_ERR(charger->poll_task)) { | ||
228 | ret = PTR_ERR(charger->poll_task); | ||
229 | dev_err(charger->dev, "Unable to run kthread err %d\n", ret); | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int tps65217_charger_remove(struct platform_device *pdev) | ||
237 | { | ||
238 | struct tps65217_charger *charger = platform_get_drvdata(pdev); | ||
239 | |||
240 | kthread_stop(charger->poll_task); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static const struct of_device_id tps65217_charger_match_table[] = { | ||
246 | { .compatible = "ti,tps65217-charger", }, | ||
247 | { /* sentinel */ } | ||
248 | }; | ||
249 | MODULE_DEVICE_TABLE(of, tps65217_charger_match_table); | ||
250 | |||
251 | static struct platform_driver tps65217_charger_driver = { | ||
252 | .probe = tps65217_charger_probe, | ||
253 | .remove = tps65217_charger_remove, | ||
254 | .driver = { | ||
255 | .name = "tps65217-charger", | ||
256 | .of_match_table = of_match_ptr(tps65217_charger_match_table), | ||
257 | }, | ||
258 | |||
259 | }; | ||
260 | module_platform_driver(tps65217_charger_driver); | ||
261 | |||
262 | MODULE_LICENSE("GPL v2"); | ||
263 | MODULE_AUTHOR("Enric Balletbo Serra <enric.balletbo@collabora.com>"); | ||
264 | MODULE_DESCRIPTION("TPS65217 battery charger driver"); | ||
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index 74f2d3ff1d7c..bcd4dc304f27 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include <linux/power_supply.h> | 22 | #include <linux/power_supply.h> |
23 | #include <linux/notifier.h> | 23 | #include <linux/notifier.h> |
24 | #include <linux/usb/otg.h> | 24 | #include <linux/usb/otg.h> |
25 | #include <linux/i2c/twl4030-madc.h> | 25 | #include <linux/iio/consumer.h> |
26 | 26 | ||
27 | #define TWL4030_BCIMDEN 0x00 | 27 | #define TWL4030_BCIMDEN 0x00 |
28 | #define TWL4030_BCIMDKEY 0x01 | 28 | #define TWL4030_BCIMDKEY 0x01 |
@@ -91,21 +91,23 @@ | |||
91 | #define TWL4030_MSTATEC_COMPLETE1 0x0b | 91 | #define TWL4030_MSTATEC_COMPLETE1 0x0b |
92 | #define TWL4030_MSTATEC_COMPLETE4 0x0e | 92 | #define TWL4030_MSTATEC_COMPLETE4 0x0e |
93 | 93 | ||
94 | #if IS_REACHABLE(CONFIG_TWL4030_MADC) | ||
95 | /* | 94 | /* |
96 | * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11) | 95 | * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11) |
97 | * then AC is available. | 96 | * then AC is available. |
98 | */ | 97 | */ |
99 | static inline int ac_available(void) | 98 | static inline int ac_available(struct iio_channel *channel_vac) |
100 | { | 99 | { |
101 | return twl4030_get_madc_conversion(11) > 4500; | 100 | int val, err; |
102 | } | 101 | |
103 | #else | 102 | if (!channel_vac) |
104 | static inline int ac_available(void) | 103 | return 0; |
105 | { | 104 | |
106 | return 0; | 105 | err = iio_read_channel_processed(channel_vac, &val); |
106 | if (err < 0) | ||
107 | return 0; | ||
108 | return val > 4500; | ||
107 | } | 109 | } |
108 | #endif | 110 | |
109 | static bool allow_usb; | 111 | static bool allow_usb; |
110 | module_param(allow_usb, bool, 0644); | 112 | module_param(allow_usb, bool, 0644); |
111 | MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current"); | 113 | MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current"); |
@@ -128,6 +130,7 @@ struct twl4030_bci { | |||
128 | */ | 130 | */ |
129 | unsigned int ichg_eoc, ichg_lo, ichg_hi; | 131 | unsigned int ichg_eoc, ichg_lo, ichg_hi; |
130 | unsigned int usb_cur, ac_cur; | 132 | unsigned int usb_cur, ac_cur; |
133 | struct iio_channel *channel_vac; | ||
131 | bool ac_is_active; | 134 | bool ac_is_active; |
132 | int usb_mode, ac_mode; /* charging mode requested */ | 135 | int usb_mode, ac_mode; /* charging mode requested */ |
133 | #define CHARGE_OFF 0 | 136 | #define CHARGE_OFF 0 |
@@ -278,7 +281,7 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci) | |||
278 | * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11) | 281 | * If AC (Accessory Charger) voltage exceeds 4.5V (MADC 11) |
279 | * and AC is enabled, set current for 'ac' | 282 | * and AC is enabled, set current for 'ac' |
280 | */ | 283 | */ |
281 | if (ac_available()) { | 284 | if (ac_available(bci->channel_vac)) { |
282 | cur = bci->ac_cur; | 285 | cur = bci->ac_cur; |
283 | bci->ac_is_active = true; | 286 | bci->ac_is_active = true; |
284 | } else { | 287 | } else { |
@@ -1048,6 +1051,12 @@ static int twl4030_bci_probe(struct platform_device *pdev) | |||
1048 | return ret; | 1051 | return ret; |
1049 | } | 1052 | } |
1050 | 1053 | ||
1054 | bci->channel_vac = iio_channel_get(&pdev->dev, "vac"); | ||
1055 | if (IS_ERR(bci->channel_vac)) { | ||
1056 | bci->channel_vac = NULL; | ||
1057 | dev_warn(&pdev->dev, "could not request vac iio channel"); | ||
1058 | } | ||
1059 | |||
1051 | INIT_WORK(&bci->work, twl4030_bci_usb_work); | 1060 | INIT_WORK(&bci->work, twl4030_bci_usb_work); |
1052 | INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker); | 1061 | INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker); |
1053 | 1062 | ||
@@ -1069,7 +1078,7 @@ static int twl4030_bci_probe(struct platform_device *pdev) | |||
1069 | TWL4030_INTERRUPTS_BCIIMR1A); | 1078 | TWL4030_INTERRUPTS_BCIIMR1A); |
1070 | if (ret < 0) { | 1079 | if (ret < 0) { |
1071 | dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret); | 1080 | dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret); |
1072 | return ret; | 1081 | goto fail; |
1073 | } | 1082 | } |
1074 | 1083 | ||
1075 | reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV); | 1084 | reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV); |
@@ -1102,6 +1111,10 @@ static int twl4030_bci_probe(struct platform_device *pdev) | |||
1102 | twl4030_charger_enable_backup(0, 0); | 1111 | twl4030_charger_enable_backup(0, 0); |
1103 | 1112 | ||
1104 | return 0; | 1113 | return 0; |
1114 | fail: | ||
1115 | iio_channel_release(bci->channel_vac); | ||
1116 | |||
1117 | return ret; | ||
1105 | } | 1118 | } |
1106 | 1119 | ||
1107 | static int __exit twl4030_bci_remove(struct platform_device *pdev) | 1120 | static int __exit twl4030_bci_remove(struct platform_device *pdev) |
@@ -1112,6 +1125,8 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) | |||
1112 | twl4030_charger_enable_usb(bci, false); | 1125 | twl4030_charger_enable_usb(bci, false); |
1113 | twl4030_charger_enable_backup(0, 0); | 1126 | twl4030_charger_enable_backup(0, 0); |
1114 | 1127 | ||
1128 | iio_channel_release(bci->channel_vac); | ||
1129 | |||
1115 | device_remove_file(&bci->usb->dev, &dev_attr_max_current); | 1130 | device_remove_file(&bci->usb->dev, &dev_attr_max_current); |
1116 | device_remove_file(&bci->usb->dev, &dev_attr_mode); | 1131 | device_remove_file(&bci->usb->dev, &dev_attr_mode); |
1117 | device_remove_file(&bci->ac->dev, &dev_attr_max_current); | 1132 | device_remove_file(&bci->ac->dev, &dev_attr_max_current); |
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index db11ae6599f3..7082301da945 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
@@ -499,7 +499,8 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
499 | struct wm831x_power *power; | 499 | struct wm831x_power *power; |
500 | int ret, irq, i; | 500 | int ret, irq, i; |
501 | 501 | ||
502 | power = kzalloc(sizeof(struct wm831x_power), GFP_KERNEL); | 502 | power = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_power), |
503 | GFP_KERNEL); | ||
503 | if (power == NULL) | 504 | if (power == NULL) |
504 | return -ENOMEM; | 505 | return -ENOMEM; |
505 | 506 | ||
@@ -536,7 +537,7 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
536 | NULL); | 537 | NULL); |
537 | if (IS_ERR(power->wall)) { | 538 | if (IS_ERR(power->wall)) { |
538 | ret = PTR_ERR(power->wall); | 539 | ret = PTR_ERR(power->wall); |
539 | goto err_kmalloc; | 540 | goto err; |
540 | } | 541 | } |
541 | 542 | ||
542 | power->usb_desc.name = power->usb_name, | 543 | power->usb_desc.name = power->usb_name, |
@@ -572,7 +573,7 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
572 | 573 | ||
573 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); | 574 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); |
574 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, | 575 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, |
575 | IRQF_TRIGGER_RISING, "System power low", | 576 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "System power low", |
576 | power); | 577 | power); |
577 | if (ret != 0) { | 578 | if (ret != 0) { |
578 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", | 579 | dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n", |
@@ -582,7 +583,7 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
582 | 583 | ||
583 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); | 584 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); |
584 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, | 585 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, |
585 | IRQF_TRIGGER_RISING, "Power source", | 586 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "Power source", |
586 | power); | 587 | power); |
587 | if (ret != 0) { | 588 | if (ret != 0) { |
588 | dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n", | 589 | dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n", |
@@ -595,7 +596,7 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
595 | platform_get_irq_byname(pdev, | 596 | platform_get_irq_byname(pdev, |
596 | wm831x_bat_irqs[i])); | 597 | wm831x_bat_irqs[i])); |
597 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, | 598 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, |
598 | IRQF_TRIGGER_RISING, | 599 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, |
599 | wm831x_bat_irqs[i], | 600 | wm831x_bat_irqs[i], |
600 | power); | 601 | power); |
601 | if (ret != 0) { | 602 | if (ret != 0) { |
@@ -626,8 +627,7 @@ err_usb: | |||
626 | power_supply_unregister(power->usb); | 627 | power_supply_unregister(power->usb); |
627 | err_wall: | 628 | err_wall: |
628 | power_supply_unregister(power->wall); | 629 | power_supply_unregister(power->wall); |
629 | err_kmalloc: | 630 | err: |
630 | kfree(power); | ||
631 | return ret; | 631 | return ret; |
632 | } | 632 | } |
633 | 633 | ||
@@ -654,7 +654,6 @@ static int wm831x_power_remove(struct platform_device *pdev) | |||
654 | power_supply_unregister(wm831x_power->battery); | 654 | power_supply_unregister(wm831x_power->battery); |
655 | power_supply_unregister(wm831x_power->wall); | 655 | power_supply_unregister(wm831x_power->wall); |
656 | power_supply_unregister(wm831x_power->usb); | 656 | power_supply_unregister(wm831x_power->usb); |
657 | kfree(wm831x_power); | ||
658 | return 0; | 657 | return 0; |
659 | } | 658 | } |
660 | 659 | ||