diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 22:26:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-13 22:26:04 -0500 |
commit | 7313264b899bbf3988841296265a6e0e8a7b6521 (patch) | |
tree | 59b5069980434945394152e94eeaef2b32cf4e72 | |
parent | d8c532c40721f7507896d202b8cae3b3642d2b0d (diff) | |
parent | 76d8a23b127020472207b281427d3e9f4f1227e4 (diff) |
Merge tag 'for-v3.8-merged' of git://git.infradead.org/battery-2.6
Pull battery subsystem updates from Anton Vorontsov:
"Highlights:
- Two new drivers from Pali Rohár and N900 hackers: rx51_battery and
bq2415x_charger. The drivers are a part of a solution to replace
the proprietary Nokia BME stack
- Power supply core now registers devices with a thermal cooling
subsystem, so we can now automatically throttle charging. Thanks
to Ramakrishna Pallala!
- Device tree support for ab8500 and max8925_power drivers
- Random fixups and enhancements for a bunch of drivers."
* tag 'for-v3.8-merged' of git://git.infradead.org/battery-2.6: (22 commits)
max8925_power: Add support for device-tree initialization
ab8500: Add devicetree support for chargalg
ab8500: Add devicetree support for charger
ab8500: Add devicetree support for btemp
ab8500: Add devicetree support for fuelgauge
twl4030_charger: Change TWL4030_MODULE_* ids to TWL_MODULE_*
jz4740-battery: Use devm_request_and_ioremap
jz4740-battery: Use devm_kzalloc
bq27x00_battery: Fixup nominal available capacity reporting
bq2415x_charger: Fix style issues
bq2415x_charger: Add Kconfig/Makefile entries
power_supply: Add bq2415x charger driver
power_supply: Add new Nokia RX-51 (N900) power supply battery driver
max17042_battery: Fix missing verify_model_lock() return value check
ds2782_battery: Fix signedness bug in ds278x_read_reg16()
lp8788-charger: Fix ADC channel names
lp8788-charger: Fix wrong ADC conversion
lp8788-charger: Use consumer device name on setting IIO channels
power_supply: Register power supply for thermal cooling device
power_supply: Add support for CHARGE_CONTROL_* attributes
...
31 files changed, 3123 insertions, 280 deletions
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt index ce83c8d3c00e..13b707b7355c 100644 --- a/Documentation/devicetree/bindings/mfd/ab8500.txt +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt | |||
@@ -24,7 +24,32 @@ ab8500-bm : : : Battery Manager | |||
24 | ab8500-btemp : : : Battery Temperature | 24 | ab8500-btemp : : : Battery Temperature |
25 | ab8500-charger : : : Battery Charger | 25 | ab8500-charger : : : Battery Charger |
26 | ab8500-codec : : : Audio Codec | 26 | ab8500-codec : : : Audio Codec |
27 | ab8500-fg : : : Fuel Gauge | 27 | ab8500-fg : : vddadc : Fuel Gauge |
28 | : NCONV_ACCU : : Accumulate N Sample Conversion | ||
29 | : BATT_OVV : : Battery Over Voltage | ||
30 | : LOW_BAT_F : : LOW threshold battery voltage | ||
31 | : CC_INT_CALIB : : Coulomb Counter Internal Calibration | ||
32 | : CCEOC : : Coulomb Counter End of Conversion | ||
33 | ab8500-btemp : : vtvout : Battery Temperature | ||
34 | : BAT_CTRL_INDB : : Battery Removal Indicator | ||
35 | : BTEMP_LOW : : Btemp < BtempLow, if battery temperature is lower than -10°C | ||
36 | : BTEMP_LOW_MEDIUM : : BtempLow < Btemp < BtempMedium,if battery temperature is between -10 and 0°C | ||
37 | : BTEMP_MEDIUM_HIGH : : BtempMedium < Btemp < BtempHigh,if battery temperature is between 0°C and“MaxTemp | ||
38 | : BTEMP_HIGH : : Btemp > BtempHigh, if battery temperature is higher than “MaxTemp | ||
39 | ab8500-charger : : vddadc : Charger interface | ||
40 | : MAIN_CH_UNPLUG_DET : : main charger unplug detection management (not in 8505) | ||
41 | : MAIN_CHARGE_PLUG_DET : : main charger plug detection management (not in 8505) | ||
42 | : MAIN_EXT_CH_NOT_OK : : main charger not OK | ||
43 | : MAIN_CH_TH_PROT_R : : Die temp is above main charger | ||
44 | : MAIN_CH_TH_PROT_F : : Die temp is below main charger | ||
45 | : VBUS_DET_F : : VBUS falling detected | ||
46 | : VBUS_DET_R : : VBUS rising detected | ||
47 | : USB_LINK_STATUS : : USB link status has changed | ||
48 | : USB_CH_TH_PROT_R : : Die temp is above usb charger | ||
49 | : USB_CH_TH_PROT_F : : Die temp is below usb charger | ||
50 | : USB_CHARGER_NOT_OKR : : allowed USB charger not ok detection | ||
51 | : VBUS_OVV : : Overvoltage on Vbus ball detected (USB charge is stopped) | ||
52 | : CH_WD_EXP : : Charger watchdog detected | ||
28 | ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter | 53 | ab8500-gpadc : HW_CONV_END : vddadc : Analogue to Digital Converter |
29 | SW_CONV_END : : | 54 | SW_CONV_END : : |
30 | ab8500-gpio : : : GPIO Controller | 55 | ab8500-gpio : : : GPIO Controller |
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt new file mode 100644 index 000000000000..0ba1bcc7f33a --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/btemp.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | === AB8500 Battery Temperature Monitor Driver === | ||
2 | |||
3 | The properties below describes the node for btemp driver. | ||
4 | |||
5 | Required Properties: | ||
6 | - compatible = Shall be: "stericsson,ab8500-btemp" | ||
7 | - battery = Shall be battery specific information | ||
8 | |||
9 | Example: | ||
10 | ab8500_btemp { | ||
11 | compatible = "stericsson,ab8500-btemp"; | ||
12 | battery = <&ab8500_battery>; | ||
13 | }; | ||
14 | |||
15 | For information on battery specific node, Ref: | ||
16 | Documentation/devicetree/bindings/power_supply/ab8500/fg.txt | ||
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt new file mode 100644 index 000000000000..ef5328371122 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/chargalg.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | === AB8500 Charging Algorithm Driver === | ||
2 | |||
3 | The properties below describes the node for chargalg driver. | ||
4 | |||
5 | Required Properties: | ||
6 | - compatible = Shall be: "stericsson,ab8500-chargalg" | ||
7 | - battery = Shall be battery specific information | ||
8 | |||
9 | Example: | ||
10 | ab8500_chargalg { | ||
11 | compatible = "stericsson,ab8500-chargalg"; | ||
12 | battery = <&ab8500_battery>; | ||
13 | }; | ||
14 | |||
15 | For information on battery specific node, Ref: | ||
16 | Documentation/devicetree/bindings/power_supply/ab8500/fg.txt | ||
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt new file mode 100644 index 000000000000..6bdbb08ea9e0 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/charger.txt | |||
@@ -0,0 +1,25 @@ | |||
1 | === AB8500 Charger Driver === | ||
2 | |||
3 | Required Properties: | ||
4 | - compatible = Shall be "stericsson,ab8500-charger" | ||
5 | - battery = Shall be battery specific information | ||
6 | Example: | ||
7 | ab8500_charger { | ||
8 | compatible = "stericsson,ab8500-charger"; | ||
9 | battery = <&ab8500_battery>; | ||
10 | }; | ||
11 | |||
12 | - vddadc-supply: Supply for USB and Main charger | ||
13 | Example: | ||
14 | ab8500-charger { | ||
15 | vddadc-supply = <&ab8500_ldo_tvout_reg>; | ||
16 | } | ||
17 | - autopower_cfg: | ||
18 | Boolean value depicting the presence of 'automatic poweron after powerloss' | ||
19 | Example: | ||
20 | ab8500-charger { | ||
21 | autopower_cfg; | ||
22 | }; | ||
23 | |||
24 | For information on battery specific node, Ref: | ||
25 | Documentation/devicetree/bindings/power_supply/ab8500/fg.txt | ||
diff --git a/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt new file mode 100644 index 000000000000..ccafcb9112fb --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ab8500/fg.txt | |||
@@ -0,0 +1,58 @@ | |||
1 | === AB8500 Fuel Gauge Driver === | ||
2 | |||
3 | AB8500 is a mixed signal multimedia and power management | ||
4 | device comprising: power and energy-management-module, | ||
5 | wall-charger, usb-charger, audio codec, general purpose adc, | ||
6 | tvout, clock management and sim card interface. | ||
7 | |||
8 | Fuelgauge support is part of energy-management-modules, other | ||
9 | components of this module are: | ||
10 | main-charger, usb-combo-charger and battery-temperature-monitoring. | ||
11 | |||
12 | The properties below describes the node for fuelgauge driver. | ||
13 | |||
14 | Required Properties: | ||
15 | - compatible = This shall be: "stericsson,ab8500-fg" | ||
16 | - battery = Shall be battery specific information | ||
17 | Example: | ||
18 | ab8500_fg { | ||
19 | compatible = "stericsson,ab8500-fg"; | ||
20 | battery = <&ab8500_battery>; | ||
21 | }; | ||
22 | |||
23 | dependent node: | ||
24 | ab8500_battery: ab8500_battery { | ||
25 | }; | ||
26 | This node will provide information on 'thermistor interface' and | ||
27 | 'battery technology type' used. | ||
28 | |||
29 | Properties of this node are: | ||
30 | thermistor-on-batctrl: | ||
31 | A boolean value indicating thermistor interface to battery | ||
32 | |||
33 | Note: | ||
34 | 'btemp' and 'batctrl' are the pins interfaced for battery temperature | ||
35 | measurement, 'btemp' signal is used when NTC(negative temperature | ||
36 | coefficient) resister is interfaced external to battery whereas | ||
37 | 'batctrl' pin is used when NTC resister is internal to battery. | ||
38 | |||
39 | Example: | ||
40 | ab8500_battery: ab8500_battery { | ||
41 | thermistor-on-batctrl; | ||
42 | }; | ||
43 | indicates: NTC resister is internal to battery, 'batctrl' is used | ||
44 | for thermal measurement. | ||
45 | |||
46 | The absence of property 'thermal-on-batctrl' indicates | ||
47 | NTC resister is external to battery and 'btemp' signal is used | ||
48 | for thermal measurement. | ||
49 | |||
50 | battery-type: | ||
51 | This shall be the battery manufacturing technology type, | ||
52 | allowed types are: | ||
53 | "UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn" | ||
54 | Example: | ||
55 | ab8500_battery: ab8500_battery { | ||
56 | stericsson,battery-type = "LIPO"; | ||
57 | } | ||
58 | |||
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt index 9c647bd7c5a9..3f10b39b0346 100644 --- a/Documentation/power/power_supply_class.txt +++ b/Documentation/power/power_supply_class.txt | |||
@@ -123,6 +123,9 @@ CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. | |||
123 | CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the | 123 | CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the |
124 | power supply object. | 124 | power supply object. |
125 | 125 | ||
126 | CHARGE_CONTROL_LIMIT - current charge control limit setting | ||
127 | CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting | ||
128 | |||
126 | ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. | 129 | ENERGY_FULL, ENERGY_EMPTY - same as above but for energy. |
127 | 130 | ||
128 | CAPACITY - capacity in percents. | 131 | CAPACITY - capacity in percents. |
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi index 0d69322f689f..2efd9c891bc9 100644 --- a/arch/arm/boot/dts/dbx5x0.dtsi +++ b/arch/arm/boot/dts/dbx5x0.dtsi | |||
@@ -340,7 +340,33 @@ | |||
340 | vddadc-supply = <&ab8500_ldo_tvout_reg>; | 340 | vddadc-supply = <&ab8500_ldo_tvout_reg>; |
341 | }; | 341 | }; |
342 | 342 | ||
343 | ab8500-usb { | 343 | ab8500_battery: ab8500_battery { |
344 | stericsson,battery-type = "LIPO"; | ||
345 | thermistor-on-batctrl; | ||
346 | }; | ||
347 | |||
348 | ab8500_fg { | ||
349 | compatible = "stericsson,ab8500-fg"; | ||
350 | battery = <&ab8500_battery>; | ||
351 | }; | ||
352 | |||
353 | ab8500_btemp { | ||
354 | compatible = "stericsson,ab8500-btemp"; | ||
355 | battery = <&ab8500_battery>; | ||
356 | }; | ||
357 | |||
358 | ab8500_charger { | ||
359 | compatible = "stericsson,ab8500-charger"; | ||
360 | battery = <&ab8500_battery>; | ||
361 | vddadc-supply = <&ab8500_ldo_tvout_reg>; | ||
362 | }; | ||
363 | |||
364 | ab8500_chargalg { | ||
365 | compatible = "stericsson,ab8500-chargalg"; | ||
366 | battery = <&ab8500_battery>; | ||
367 | }; | ||
368 | |||
369 | ab8500_usb { | ||
344 | compatible = "stericsson,ab8500-usb"; | 370 | compatible = "stericsson,ab8500-usb"; |
345 | interrupts = < 90 0x4 | 371 | interrupts = < 90 0x4 |
346 | 96 0x4 | 372 | 96 0x4 |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index 3e27c031aeaa..59da1650fb81 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -1036,23 +1036,43 @@ static struct mfd_cell abx500_common_devs[] = { | |||
1036 | static struct mfd_cell ab8500_bm_devs[] = { | 1036 | static struct mfd_cell ab8500_bm_devs[] = { |
1037 | { | 1037 | { |
1038 | .name = "ab8500-charger", | 1038 | .name = "ab8500-charger", |
1039 | .of_compatible = "stericsson,ab8500-charger", | ||
1039 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), | 1040 | .num_resources = ARRAY_SIZE(ab8500_charger_resources), |
1040 | .resources = ab8500_charger_resources, | 1041 | .resources = ab8500_charger_resources, |
1042 | #ifndef CONFIG_OF | ||
1043 | .platform_data = &ab8500_bm_data, | ||
1044 | .pdata_size = sizeof(ab8500_bm_data), | ||
1045 | #endif | ||
1041 | }, | 1046 | }, |
1042 | { | 1047 | { |
1043 | .name = "ab8500-btemp", | 1048 | .name = "ab8500-btemp", |
1049 | .of_compatible = "stericsson,ab8500-btemp", | ||
1044 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), | 1050 | .num_resources = ARRAY_SIZE(ab8500_btemp_resources), |
1045 | .resources = ab8500_btemp_resources, | 1051 | .resources = ab8500_btemp_resources, |
1052 | #ifndef CONFIG_OF | ||
1053 | .platform_data = &ab8500_bm_data, | ||
1054 | .pdata_size = sizeof(ab8500_bm_data), | ||
1055 | #endif | ||
1046 | }, | 1056 | }, |
1047 | { | 1057 | { |
1048 | .name = "ab8500-fg", | 1058 | .name = "ab8500-fg", |
1059 | .of_compatible = "stericsson,ab8500-fg", | ||
1049 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), | 1060 | .num_resources = ARRAY_SIZE(ab8500_fg_resources), |
1050 | .resources = ab8500_fg_resources, | 1061 | .resources = ab8500_fg_resources, |
1062 | #ifndef CONFIG_OF | ||
1063 | .platform_data = &ab8500_bm_data, | ||
1064 | .pdata_size = sizeof(ab8500_bm_data), | ||
1065 | #endif | ||
1051 | }, | 1066 | }, |
1052 | { | 1067 | { |
1053 | .name = "ab8500-chargalg", | 1068 | .name = "ab8500-chargalg", |
1069 | .of_compatible = "stericsson,ab8500-chargalg", | ||
1054 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), | 1070 | .num_resources = ARRAY_SIZE(ab8500_chargalg_resources), |
1055 | .resources = ab8500_chargalg_resources, | 1071 | .resources = ab8500_chargalg_resources, |
1072 | #ifndef CONFIG_OF | ||
1073 | .platform_data = &ab8500_bm_data, | ||
1074 | .pdata_size = sizeof(ab8500_bm_data), | ||
1075 | #endif | ||
1056 | }, | 1076 | }, |
1057 | }; | 1077 | }; |
1058 | 1078 | ||
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index b1d956d81f0c..9f45e2f77d53 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -245,6 +245,13 @@ config BATTERY_INTEL_MID | |||
245 | Say Y here to enable the battery driver on Intel MID | 245 | Say Y here to enable the battery driver on Intel MID |
246 | platforms. | 246 | platforms. |
247 | 247 | ||
248 | config BATTERY_RX51 | ||
249 | tristate "Nokia RX-51 (N900) battery driver" | ||
250 | depends on TWL4030_MADC | ||
251 | help | ||
252 | Say Y here to enable support for battery information on Nokia | ||
253 | RX-51, also known as N900 tablet. | ||
254 | |||
248 | config CHARGER_ISP1704 | 255 | config CHARGER_ISP1704 |
249 | tristate "ISP1704 USB Charger Detection" | 256 | tristate "ISP1704 USB Charger Detection" |
250 | depends on USB_OTG_UTILS | 257 | depends on USB_OTG_UTILS |
@@ -315,6 +322,16 @@ config CHARGER_MAX8998 | |||
315 | Say Y to enable support for the battery charger control sysfs and | 322 | Say Y to enable support for the battery charger control sysfs and |
316 | platform data of MAX8998/LP3974 PMICs. | 323 | platform data of MAX8998/LP3974 PMICs. |
317 | 324 | ||
325 | config CHARGER_BQ2415X | ||
326 | tristate "TI BQ2415x battery charger driver" | ||
327 | depends on I2C | ||
328 | help | ||
329 | Say Y to enable support for the TI BQ2415x battery charger | ||
330 | PMICs. | ||
331 | |||
332 | You'll need this driver to charge batteries on e.g. Nokia | ||
333 | RX-51/N900. | ||
334 | |||
318 | config CHARGER_SMB347 | 335 | config CHARGER_SMB347 |
319 | tristate "Summit Microelectronics SMB347 Battery Charger" | 336 | tristate "Summit Microelectronics SMB347 Battery Charger" |
320 | depends on I2C | 337 | depends on I2C |
@@ -329,13 +346,6 @@ config AB8500_BM | |||
329 | help | 346 | help |
330 | Say Y to include support for AB8500 battery management. | 347 | Say Y to include support for AB8500 battery management. |
331 | 348 | ||
332 | config AB8500_BATTERY_THERM_ON_BATCTRL | ||
333 | bool "Thermistor connected on BATCTRL ADC" | ||
334 | depends on AB8500_BM | ||
335 | help | ||
336 | Say Y to enable battery temperature measurements using | ||
337 | thermistor connected on BATCTRL ADC. | ||
338 | |||
339 | source "drivers/power/reset/Kconfig" | 349 | source "drivers/power/reset/Kconfig" |
340 | 350 | ||
341 | endif # POWER_SUPPLY | 351 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index f1d99f4a0bc3..22c8913382c0 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -37,7 +37,8 @@ obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o | |||
37 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o | 37 | obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o |
38 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o | 38 | obj-$(CONFIG_BATTERY_JZ4740) += jz4740-battery.o |
39 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o | 39 | obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o |
40 | obj-$(CONFIG_AB8500_BM) += ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o | 40 | obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o |
41 | obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_btemp.o ab8500_fg.o abx500_chargalg.o | ||
41 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o | 42 | obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o |
42 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o | 43 | obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o |
43 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o | 44 | obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o |
@@ -47,6 +48,7 @@ obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o | |||
47 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o | 48 | obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o |
48 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | 49 | obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o |
49 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 50 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
51 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | ||
50 | obj-$(CONFIG_POWER_AVS) += avs/ | 52 | obj-$(CONFIG_POWER_AVS) += avs/ |
51 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o | 53 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o |
52 | obj-$(CONFIG_POWER_RESET) += reset/ | 54 | obj-$(CONFIG_POWER_RESET) += reset/ |
diff --git a/drivers/power/ab8500_bmdata.c b/drivers/power/ab8500_bmdata.c new file mode 100644 index 000000000000..03cc528425cb --- /dev/null +++ b/drivers/power/ab8500_bmdata.c | |||
@@ -0,0 +1,521 @@ | |||
1 | #include <linux/export.h> | ||
2 | #include <linux/power_supply.h> | ||
3 | #include <linux/of.h> | ||
4 | #include <linux/mfd/abx500.h> | ||
5 | #include <linux/mfd/abx500/ab8500.h> | ||
6 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
7 | |||
8 | /* | ||
9 | * These are the defined batteries that uses a NTC and ID resistor placed | ||
10 | * inside of the battery pack. | ||
11 | * Note that the res_to_temp table must be strictly sorted by falling resistance | ||
12 | * values to work. | ||
13 | */ | ||
14 | static struct abx500_res_to_temp temp_tbl_A_thermistor[] = { | ||
15 | {-5, 53407}, | ||
16 | { 0, 48594}, | ||
17 | { 5, 43804}, | ||
18 | {10, 39188}, | ||
19 | {15, 34870}, | ||
20 | {20, 30933}, | ||
21 | {25, 27422}, | ||
22 | {30, 24347}, | ||
23 | {35, 21694}, | ||
24 | {40, 19431}, | ||
25 | {45, 17517}, | ||
26 | {50, 15908}, | ||
27 | {55, 14561}, | ||
28 | {60, 13437}, | ||
29 | {65, 12500}, | ||
30 | }; | ||
31 | |||
32 | static struct abx500_res_to_temp temp_tbl_B_thermistor[] = { | ||
33 | {-5, 200000}, | ||
34 | { 0, 159024}, | ||
35 | { 5, 151921}, | ||
36 | {10, 144300}, | ||
37 | {15, 136424}, | ||
38 | {20, 128565}, | ||
39 | {25, 120978}, | ||
40 | {30, 113875}, | ||
41 | {35, 107397}, | ||
42 | {40, 101629}, | ||
43 | {45, 96592}, | ||
44 | {50, 92253}, | ||
45 | {55, 88569}, | ||
46 | {60, 85461}, | ||
47 | {65, 82869}, | ||
48 | }; | ||
49 | |||
50 | static struct abx500_v_to_cap cap_tbl_A_thermistor[] = { | ||
51 | {4171, 100}, | ||
52 | {4114, 95}, | ||
53 | {4009, 83}, | ||
54 | {3947, 74}, | ||
55 | {3907, 67}, | ||
56 | {3863, 59}, | ||
57 | {3830, 56}, | ||
58 | {3813, 53}, | ||
59 | {3791, 46}, | ||
60 | {3771, 33}, | ||
61 | {3754, 25}, | ||
62 | {3735, 20}, | ||
63 | {3717, 17}, | ||
64 | {3681, 13}, | ||
65 | {3664, 8}, | ||
66 | {3651, 6}, | ||
67 | {3635, 5}, | ||
68 | {3560, 3}, | ||
69 | {3408, 1}, | ||
70 | {3247, 0}, | ||
71 | }; | ||
72 | |||
73 | static struct abx500_v_to_cap cap_tbl_B_thermistor[] = { | ||
74 | {4161, 100}, | ||
75 | {4124, 98}, | ||
76 | {4044, 90}, | ||
77 | {4003, 85}, | ||
78 | {3966, 80}, | ||
79 | {3933, 75}, | ||
80 | {3888, 67}, | ||
81 | {3849, 60}, | ||
82 | {3813, 55}, | ||
83 | {3787, 47}, | ||
84 | {3772, 30}, | ||
85 | {3751, 25}, | ||
86 | {3718, 20}, | ||
87 | {3681, 16}, | ||
88 | {3660, 14}, | ||
89 | {3589, 10}, | ||
90 | {3546, 7}, | ||
91 | {3495, 4}, | ||
92 | {3404, 2}, | ||
93 | {3250, 0}, | ||
94 | }; | ||
95 | |||
96 | static struct abx500_v_to_cap cap_tbl[] = { | ||
97 | {4186, 100}, | ||
98 | {4163, 99}, | ||
99 | {4114, 95}, | ||
100 | {4068, 90}, | ||
101 | {3990, 80}, | ||
102 | {3926, 70}, | ||
103 | {3898, 65}, | ||
104 | {3866, 60}, | ||
105 | {3833, 55}, | ||
106 | {3812, 50}, | ||
107 | {3787, 40}, | ||
108 | {3768, 30}, | ||
109 | {3747, 25}, | ||
110 | {3730, 20}, | ||
111 | {3705, 15}, | ||
112 | {3699, 14}, | ||
113 | {3684, 12}, | ||
114 | {3672, 9}, | ||
115 | {3657, 7}, | ||
116 | {3638, 6}, | ||
117 | {3556, 4}, | ||
118 | {3424, 2}, | ||
119 | {3317, 1}, | ||
120 | {3094, 0}, | ||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * Note that the res_to_temp table must be strictly sorted by falling | ||
125 | * resistance values to work. | ||
126 | */ | ||
127 | static struct abx500_res_to_temp temp_tbl[] = { | ||
128 | {-5, 214834}, | ||
129 | { 0, 162943}, | ||
130 | { 5, 124820}, | ||
131 | {10, 96520}, | ||
132 | {15, 75306}, | ||
133 | {20, 59254}, | ||
134 | {25, 47000}, | ||
135 | {30, 37566}, | ||
136 | {35, 30245}, | ||
137 | {40, 24520}, | ||
138 | {45, 20010}, | ||
139 | {50, 16432}, | ||
140 | {55, 13576}, | ||
141 | {60, 11280}, | ||
142 | {65, 9425}, | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * Note that the batres_vs_temp table must be strictly sorted by falling | ||
147 | * temperature values to work. | ||
148 | */ | ||
149 | static struct batres_vs_temp temp_to_batres_tbl_thermistor[] = { | ||
150 | { 40, 120}, | ||
151 | { 30, 135}, | ||
152 | { 20, 165}, | ||
153 | { 10, 230}, | ||
154 | { 00, 325}, | ||
155 | {-10, 445}, | ||
156 | {-20, 595}, | ||
157 | }; | ||
158 | |||
159 | /* | ||
160 | * Note that the batres_vs_temp table must be strictly sorted by falling | ||
161 | * temperature values to work. | ||
162 | */ | ||
163 | static struct batres_vs_temp temp_to_batres_tbl_ext_thermistor[] = { | ||
164 | { 60, 300}, | ||
165 | { 30, 300}, | ||
166 | { 20, 300}, | ||
167 | { 10, 300}, | ||
168 | { 00, 300}, | ||
169 | {-10, 300}, | ||
170 | {-20, 300}, | ||
171 | }; | ||
172 | |||
173 | /* battery resistance table for LI ION 9100 battery */ | ||
174 | static struct batres_vs_temp temp_to_batres_tbl_9100[] = { | ||
175 | { 60, 180}, | ||
176 | { 30, 180}, | ||
177 | { 20, 180}, | ||
178 | { 10, 180}, | ||
179 | { 00, 180}, | ||
180 | {-10, 180}, | ||
181 | {-20, 180}, | ||
182 | }; | ||
183 | |||
184 | static struct abx500_battery_type bat_type_thermistor[] = { | ||
185 | [BATTERY_UNKNOWN] = { | ||
186 | /* First element always represent the UNKNOWN battery */ | ||
187 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, | ||
188 | .resis_high = 0, | ||
189 | .resis_low = 0, | ||
190 | .battery_resistance = 300, | ||
191 | .charge_full_design = 612, | ||
192 | .nominal_voltage = 3700, | ||
193 | .termination_vol = 4050, | ||
194 | .termination_curr = 200, | ||
195 | .recharge_vol = 3990, | ||
196 | .normal_cur_lvl = 400, | ||
197 | .normal_vol_lvl = 4100, | ||
198 | .maint_a_cur_lvl = 400, | ||
199 | .maint_a_vol_lvl = 4050, | ||
200 | .maint_a_chg_timer_h = 60, | ||
201 | .maint_b_cur_lvl = 400, | ||
202 | .maint_b_vol_lvl = 4000, | ||
203 | .maint_b_chg_timer_h = 200, | ||
204 | .low_high_cur_lvl = 300, | ||
205 | .low_high_vol_lvl = 4000, | ||
206 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
207 | .r_to_t_tbl = temp_tbl, | ||
208 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
209 | .v_to_cap_tbl = cap_tbl, | ||
210 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
211 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
212 | }, | ||
213 | { | ||
214 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | ||
215 | .resis_high = 53407, | ||
216 | .resis_low = 12500, | ||
217 | .battery_resistance = 300, | ||
218 | .charge_full_design = 900, | ||
219 | .nominal_voltage = 3600, | ||
220 | .termination_vol = 4150, | ||
221 | .termination_curr = 80, | ||
222 | .recharge_vol = 4130, | ||
223 | .normal_cur_lvl = 700, | ||
224 | .normal_vol_lvl = 4200, | ||
225 | .maint_a_cur_lvl = 600, | ||
226 | .maint_a_vol_lvl = 4150, | ||
227 | .maint_a_chg_timer_h = 60, | ||
228 | .maint_b_cur_lvl = 600, | ||
229 | .maint_b_vol_lvl = 4100, | ||
230 | .maint_b_chg_timer_h = 200, | ||
231 | .low_high_cur_lvl = 300, | ||
232 | .low_high_vol_lvl = 4000, | ||
233 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A_thermistor), | ||
234 | .r_to_t_tbl = temp_tbl_A_thermistor, | ||
235 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A_thermistor), | ||
236 | .v_to_cap_tbl = cap_tbl_A_thermistor, | ||
237 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
238 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
239 | |||
240 | }, | ||
241 | { | ||
242 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | ||
243 | .resis_high = 200000, | ||
244 | .resis_low = 82869, | ||
245 | .battery_resistance = 300, | ||
246 | .charge_full_design = 900, | ||
247 | .nominal_voltage = 3600, | ||
248 | .termination_vol = 4150, | ||
249 | .termination_curr = 80, | ||
250 | .recharge_vol = 4130, | ||
251 | .normal_cur_lvl = 700, | ||
252 | .normal_vol_lvl = 4200, | ||
253 | .maint_a_cur_lvl = 600, | ||
254 | .maint_a_vol_lvl = 4150, | ||
255 | .maint_a_chg_timer_h = 60, | ||
256 | .maint_b_cur_lvl = 600, | ||
257 | .maint_b_vol_lvl = 4100, | ||
258 | .maint_b_chg_timer_h = 200, | ||
259 | .low_high_cur_lvl = 300, | ||
260 | .low_high_vol_lvl = 4000, | ||
261 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B_thermistor), | ||
262 | .r_to_t_tbl = temp_tbl_B_thermistor, | ||
263 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B_thermistor), | ||
264 | .v_to_cap_tbl = cap_tbl_B_thermistor, | ||
265 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
266 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
267 | }, | ||
268 | }; | ||
269 | |||
270 | static struct abx500_battery_type bat_type_ext_thermistor[] = { | ||
271 | [BATTERY_UNKNOWN] = { | ||
272 | /* First element always represent the UNKNOWN battery */ | ||
273 | .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN, | ||
274 | .resis_high = 0, | ||
275 | .resis_low = 0, | ||
276 | .battery_resistance = 300, | ||
277 | .charge_full_design = 612, | ||
278 | .nominal_voltage = 3700, | ||
279 | .termination_vol = 4050, | ||
280 | .termination_curr = 200, | ||
281 | .recharge_vol = 3990, | ||
282 | .normal_cur_lvl = 400, | ||
283 | .normal_vol_lvl = 4100, | ||
284 | .maint_a_cur_lvl = 400, | ||
285 | .maint_a_vol_lvl = 4050, | ||
286 | .maint_a_chg_timer_h = 60, | ||
287 | .maint_b_cur_lvl = 400, | ||
288 | .maint_b_vol_lvl = 4000, | ||
289 | .maint_b_chg_timer_h = 200, | ||
290 | .low_high_cur_lvl = 300, | ||
291 | .low_high_vol_lvl = 4000, | ||
292 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
293 | .r_to_t_tbl = temp_tbl, | ||
294 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
295 | .v_to_cap_tbl = cap_tbl, | ||
296 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
297 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
298 | }, | ||
299 | /* | ||
300 | * These are the batteries that doesn't have an internal NTC resistor to measure | ||
301 | * its temperature. The temperature in this case is measure with a NTC placed | ||
302 | * near the battery but on the PCB. | ||
303 | */ | ||
304 | { | ||
305 | .name = POWER_SUPPLY_TECHNOLOGY_LIPO, | ||
306 | .resis_high = 76000, | ||
307 | .resis_low = 53000, | ||
308 | .battery_resistance = 300, | ||
309 | .charge_full_design = 900, | ||
310 | .nominal_voltage = 3700, | ||
311 | .termination_vol = 4150, | ||
312 | .termination_curr = 100, | ||
313 | .recharge_vol = 4130, | ||
314 | .normal_cur_lvl = 700, | ||
315 | .normal_vol_lvl = 4200, | ||
316 | .maint_a_cur_lvl = 600, | ||
317 | .maint_a_vol_lvl = 4150, | ||
318 | .maint_a_chg_timer_h = 60, | ||
319 | .maint_b_cur_lvl = 600, | ||
320 | .maint_b_vol_lvl = 4100, | ||
321 | .maint_b_chg_timer_h = 200, | ||
322 | .low_high_cur_lvl = 300, | ||
323 | .low_high_vol_lvl = 4000, | ||
324 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
325 | .r_to_t_tbl = temp_tbl, | ||
326 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
327 | .v_to_cap_tbl = cap_tbl, | ||
328 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
329 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
330 | }, | ||
331 | { | ||
332 | .name = POWER_SUPPLY_TECHNOLOGY_LION, | ||
333 | .resis_high = 30000, | ||
334 | .resis_low = 10000, | ||
335 | .battery_resistance = 300, | ||
336 | .charge_full_design = 950, | ||
337 | .nominal_voltage = 3700, | ||
338 | .termination_vol = 4150, | ||
339 | .termination_curr = 100, | ||
340 | .recharge_vol = 4130, | ||
341 | .normal_cur_lvl = 700, | ||
342 | .normal_vol_lvl = 4200, | ||
343 | .maint_a_cur_lvl = 600, | ||
344 | .maint_a_vol_lvl = 4150, | ||
345 | .maint_a_chg_timer_h = 60, | ||
346 | .maint_b_cur_lvl = 600, | ||
347 | .maint_b_vol_lvl = 4100, | ||
348 | .maint_b_chg_timer_h = 200, | ||
349 | .low_high_cur_lvl = 300, | ||
350 | .low_high_vol_lvl = 4000, | ||
351 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
352 | .r_to_t_tbl = temp_tbl, | ||
353 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
354 | .v_to_cap_tbl = cap_tbl, | ||
355 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
356 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
357 | }, | ||
358 | { | ||
359 | .name = POWER_SUPPLY_TECHNOLOGY_LION, | ||
360 | .resis_high = 95000, | ||
361 | .resis_low = 76001, | ||
362 | .battery_resistance = 300, | ||
363 | .charge_full_design = 950, | ||
364 | .nominal_voltage = 3700, | ||
365 | .termination_vol = 4150, | ||
366 | .termination_curr = 100, | ||
367 | .recharge_vol = 4130, | ||
368 | .normal_cur_lvl = 700, | ||
369 | .normal_vol_lvl = 4200, | ||
370 | .maint_a_cur_lvl = 600, | ||
371 | .maint_a_vol_lvl = 4150, | ||
372 | .maint_a_chg_timer_h = 60, | ||
373 | .maint_b_cur_lvl = 600, | ||
374 | .maint_b_vol_lvl = 4100, | ||
375 | .maint_b_chg_timer_h = 200, | ||
376 | .low_high_cur_lvl = 300, | ||
377 | .low_high_vol_lvl = 4000, | ||
378 | .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl), | ||
379 | .r_to_t_tbl = temp_tbl, | ||
380 | .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl), | ||
381 | .v_to_cap_tbl = cap_tbl, | ||
382 | .n_batres_tbl_elements = ARRAY_SIZE(temp_to_batres_tbl_thermistor), | ||
383 | .batres_tbl = temp_to_batres_tbl_thermistor, | ||
384 | }, | ||
385 | }; | ||
386 | |||
387 | static const struct abx500_bm_capacity_levels cap_levels = { | ||
388 | .critical = 2, | ||
389 | .low = 10, | ||
390 | .normal = 70, | ||
391 | .high = 95, | ||
392 | .full = 100, | ||
393 | }; | ||
394 | |||
395 | static const struct abx500_fg_parameters fg = { | ||
396 | .recovery_sleep_timer = 10, | ||
397 | .recovery_total_time = 100, | ||
398 | .init_timer = 1, | ||
399 | .init_discard_time = 5, | ||
400 | .init_total_time = 40, | ||
401 | .high_curr_time = 60, | ||
402 | .accu_charging = 30, | ||
403 | .accu_high_curr = 30, | ||
404 | .high_curr_threshold = 50, | ||
405 | .lowbat_threshold = 3100, | ||
406 | .battok_falling_th_sel0 = 2860, | ||
407 | .battok_raising_th_sel1 = 2860, | ||
408 | .user_cap_limit = 15, | ||
409 | .maint_thres = 97, | ||
410 | }; | ||
411 | |||
412 | static const struct abx500_maxim_parameters maxi_params = { | ||
413 | .ena_maxi = true, | ||
414 | .chg_curr = 910, | ||
415 | .wait_cycles = 10, | ||
416 | .charger_curr_step = 100, | ||
417 | }; | ||
418 | |||
419 | static const struct abx500_bm_charger_parameters chg = { | ||
420 | .usb_volt_max = 5500, | ||
421 | .usb_curr_max = 1500, | ||
422 | .ac_volt_max = 7500, | ||
423 | .ac_curr_max = 1500, | ||
424 | }; | ||
425 | |||
426 | struct abx500_bm_data ab8500_bm_data = { | ||
427 | .temp_under = 3, | ||
428 | .temp_low = 8, | ||
429 | .temp_high = 43, | ||
430 | .temp_over = 48, | ||
431 | .main_safety_tmr_h = 4, | ||
432 | .temp_interval_chg = 20, | ||
433 | .temp_interval_nochg = 120, | ||
434 | .usb_safety_tmr_h = 4, | ||
435 | .bkup_bat_v = BUP_VCH_SEL_2P6V, | ||
436 | .bkup_bat_i = BUP_ICH_SEL_150UA, | ||
437 | .no_maintenance = false, | ||
438 | .adc_therm = ABx500_ADC_THERM_BATCTRL, | ||
439 | .chg_unknown_bat = false, | ||
440 | .enable_overshoot = false, | ||
441 | .fg_res = 100, | ||
442 | .cap_levels = &cap_levels, | ||
443 | .bat_type = bat_type_thermistor, | ||
444 | .n_btypes = 3, | ||
445 | .batt_id = 0, | ||
446 | .interval_charging = 5, | ||
447 | .interval_not_charging = 120, | ||
448 | .temp_hysteresis = 3, | ||
449 | .gnd_lift_resistance = 34, | ||
450 | .maxi = &maxi_params, | ||
451 | .chg_params = &chg, | ||
452 | .fg_params = &fg, | ||
453 | }; | ||
454 | |||
455 | int __devinit | ||
456 | bmdevs_of_probe(struct device *dev, | ||
457 | struct device_node *np, | ||
458 | struct abx500_bm_data **battery) | ||
459 | { | ||
460 | struct abx500_battery_type *btype; | ||
461 | struct device_node *np_bat_supply; | ||
462 | struct abx500_bm_data *bat; | ||
463 | const char *btech; | ||
464 | char bat_tech[8]; | ||
465 | int i, thermistor; | ||
466 | |||
467 | *battery = &ab8500_bm_data; | ||
468 | |||
469 | /* get phandle to 'battery-info' node */ | ||
470 | np_bat_supply = of_parse_phandle(np, "battery", 0); | ||
471 | if (!np_bat_supply) { | ||
472 | dev_err(dev, "missing property battery\n"); | ||
473 | return -EINVAL; | ||
474 | } | ||
475 | if (of_property_read_bool(np_bat_supply, | ||
476 | "thermistor-on-batctrl")) | ||
477 | thermistor = NTC_INTERNAL; | ||
478 | else | ||
479 | thermistor = NTC_EXTERNAL; | ||
480 | |||
481 | bat = *battery; | ||
482 | if (thermistor == NTC_EXTERNAL) { | ||
483 | bat->n_btypes = 4; | ||
484 | bat->bat_type = bat_type_ext_thermistor; | ||
485 | bat->adc_therm = ABx500_ADC_THERM_BATTEMP; | ||
486 | } | ||
487 | btech = of_get_property(np_bat_supply, | ||
488 | "stericsson,battery-type", NULL); | ||
489 | if (!btech) { | ||
490 | dev_warn(dev, "missing property battery-name/type\n"); | ||
491 | strcpy(bat_tech, "UNKNOWN"); | ||
492 | } else { | ||
493 | strcpy(bat_tech, btech); | ||
494 | } | ||
495 | |||
496 | if (strncmp(bat_tech, "LION", 4) == 0) { | ||
497 | bat->no_maintenance = true; | ||
498 | bat->chg_unknown_bat = true; | ||
499 | bat->bat_type[BATTERY_UNKNOWN].charge_full_design = 2600; | ||
500 | bat->bat_type[BATTERY_UNKNOWN].termination_vol = 4150; | ||
501 | bat->bat_type[BATTERY_UNKNOWN].recharge_vol = 4130; | ||
502 | bat->bat_type[BATTERY_UNKNOWN].normal_cur_lvl = 520; | ||
503 | bat->bat_type[BATTERY_UNKNOWN].normal_vol_lvl = 4200; | ||
504 | } | ||
505 | /* select the battery resolution table */ | ||
506 | for (i = 0; i < bat->n_btypes; ++i) { | ||
507 | btype = (bat->bat_type + i); | ||
508 | if (thermistor == NTC_EXTERNAL) { | ||
509 | btype->batres_tbl = | ||
510 | temp_to_batres_tbl_ext_thermistor; | ||
511 | } else if (strncmp(bat_tech, "LION", 4) == 0) { | ||
512 | btype->batres_tbl = | ||
513 | temp_to_batres_tbl_9100; | ||
514 | } else { | ||
515 | btype->batres_tbl = | ||
516 | temp_to_batres_tbl_thermistor; | ||
517 | } | ||
518 | } | ||
519 | of_node_put(np_bat_supply); | ||
520 | return 0; | ||
521 | } | ||
diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index 989b09950aff..20e2a7d3ef43 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c | |||
@@ -20,11 +20,13 @@ | |||
20 | #include <linux/power_supply.h> | 20 | #include <linux/power_supply.h> |
21 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/mfd/abx500/ab8500.h> | 23 | #include <linux/jiffies.h> |
24 | #include <linux/of.h> | ||
25 | #include <linux/mfd/core.h> | ||
24 | #include <linux/mfd/abx500.h> | 26 | #include <linux/mfd/abx500.h> |
27 | #include <linux/mfd/abx500/ab8500.h> | ||
25 | #include <linux/mfd/abx500/ab8500-bm.h> | 28 | #include <linux/mfd/abx500/ab8500-bm.h> |
26 | #include <linux/mfd/abx500/ab8500-gpadc.h> | 29 | #include <linux/mfd/abx500/ab8500-gpadc.h> |
27 | #include <linux/jiffies.h> | ||
28 | 30 | ||
29 | #define VTVOUT_V 1800 | 31 | #define VTVOUT_V 1800 |
30 | 32 | ||
@@ -76,7 +78,6 @@ struct ab8500_btemp_ranges { | |||
76 | * @parent: Pointer to the struct ab8500 | 78 | * @parent: Pointer to the struct ab8500 |
77 | * @gpadc: Pointer to the struct gpadc | 79 | * @gpadc: Pointer to the struct gpadc |
78 | * @fg: Pointer to the struct fg | 80 | * @fg: Pointer to the struct fg |
79 | * @pdata: Pointer to the abx500_btemp platform data | ||
80 | * @bat: Pointer to the abx500_bm platform data | 81 | * @bat: Pointer to the abx500_bm platform data |
81 | * @btemp_psy: Structure for BTEMP specific battery properties | 82 | * @btemp_psy: Structure for BTEMP specific battery properties |
82 | * @events: Structure for information about events triggered | 83 | * @events: Structure for information about events triggered |
@@ -93,7 +94,6 @@ struct ab8500_btemp { | |||
93 | struct ab8500 *parent; | 94 | struct ab8500 *parent; |
94 | struct ab8500_gpadc *gpadc; | 95 | struct ab8500_gpadc *gpadc; |
95 | struct ab8500_fg *fg; | 96 | struct ab8500_fg *fg; |
96 | struct abx500_btemp_platform_data *pdata; | ||
97 | struct abx500_bm_data *bat; | 97 | struct abx500_bm_data *bat; |
98 | struct power_supply btemp_psy; | 98 | struct power_supply btemp_psy; |
99 | struct ab8500_btemp_events events; | 99 | struct ab8500_btemp_events events; |
@@ -955,56 +955,57 @@ static int ab8500_btemp_remove(struct platform_device *pdev) | |||
955 | flush_scheduled_work(); | 955 | flush_scheduled_work(); |
956 | power_supply_unregister(&di->btemp_psy); | 956 | power_supply_unregister(&di->btemp_psy); |
957 | platform_set_drvdata(pdev, NULL); | 957 | platform_set_drvdata(pdev, NULL); |
958 | kfree(di); | ||
959 | 958 | ||
960 | return 0; | 959 | return 0; |
961 | } | 960 | } |
962 | 961 | ||
962 | static char *supply_interface[] = { | ||
963 | "ab8500_chargalg", | ||
964 | "ab8500_fg", | ||
965 | }; | ||
966 | |||
963 | static int ab8500_btemp_probe(struct platform_device *pdev) | 967 | static int ab8500_btemp_probe(struct platform_device *pdev) |
964 | { | 968 | { |
969 | struct device_node *np = pdev->dev.of_node; | ||
970 | struct ab8500_btemp *di; | ||
965 | int irq, i, ret = 0; | 971 | int irq, i, ret = 0; |
966 | u8 val; | 972 | u8 val; |
967 | struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; | ||
968 | struct ab8500_btemp *di; | ||
969 | |||
970 | if (!plat_data) { | ||
971 | dev_err(&pdev->dev, "No platform data\n"); | ||
972 | return -EINVAL; | ||
973 | } | ||
974 | 973 | ||
975 | di = kzalloc(sizeof(*di), GFP_KERNEL); | 974 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); |
976 | if (!di) | 975 | if (!di) { |
976 | dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__); | ||
977 | return -ENOMEM; | 977 | return -ENOMEM; |
978 | } | ||
979 | di->bat = pdev->mfd_cell->platform_data; | ||
980 | if (!di->bat) { | ||
981 | if (np) { | ||
982 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
983 | if (ret) { | ||
984 | dev_err(&pdev->dev, | ||
985 | "failed to get battery information\n"); | ||
986 | return ret; | ||
987 | } | ||
988 | } else { | ||
989 | dev_err(&pdev->dev, "missing dt node for ab8500_btemp\n"); | ||
990 | return -EINVAL; | ||
991 | } | ||
992 | } else { | ||
993 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
994 | } | ||
978 | 995 | ||
979 | /* get parent data */ | 996 | /* get parent data */ |
980 | di->dev = &pdev->dev; | 997 | di->dev = &pdev->dev; |
981 | di->parent = dev_get_drvdata(pdev->dev.parent); | 998 | di->parent = dev_get_drvdata(pdev->dev.parent); |
982 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 999 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
983 | 1000 | ||
984 | /* get btemp specific platform data */ | ||
985 | di->pdata = plat_data->btemp; | ||
986 | if (!di->pdata) { | ||
987 | dev_err(di->dev, "no btemp platform data supplied\n"); | ||
988 | ret = -EINVAL; | ||
989 | goto free_device_info; | ||
990 | } | ||
991 | |||
992 | /* get battery specific platform data */ | ||
993 | di->bat = plat_data->battery; | ||
994 | if (!di->bat) { | ||
995 | dev_err(di->dev, "no battery platform data supplied\n"); | ||
996 | ret = -EINVAL; | ||
997 | goto free_device_info; | ||
998 | } | ||
999 | |||
1000 | /* BTEMP supply */ | 1001 | /* BTEMP supply */ |
1001 | di->btemp_psy.name = "ab8500_btemp"; | 1002 | di->btemp_psy.name = "ab8500_btemp"; |
1002 | di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; | 1003 | di->btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY; |
1003 | di->btemp_psy.properties = ab8500_btemp_props; | 1004 | di->btemp_psy.properties = ab8500_btemp_props; |
1004 | di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props); | 1005 | di->btemp_psy.num_properties = ARRAY_SIZE(ab8500_btemp_props); |
1005 | di->btemp_psy.get_property = ab8500_btemp_get_property; | 1006 | di->btemp_psy.get_property = ab8500_btemp_get_property; |
1006 | di->btemp_psy.supplied_to = di->pdata->supplied_to; | 1007 | di->btemp_psy.supplied_to = supply_interface; |
1007 | di->btemp_psy.num_supplicants = di->pdata->num_supplicants; | 1008 | di->btemp_psy.num_supplicants = ARRAY_SIZE(supply_interface); |
1008 | di->btemp_psy.external_power_changed = | 1009 | di->btemp_psy.external_power_changed = |
1009 | ab8500_btemp_external_power_changed; | 1010 | ab8500_btemp_external_power_changed; |
1010 | 1011 | ||
@@ -1014,8 +1015,7 @@ static int ab8500_btemp_probe(struct platform_device *pdev) | |||
1014 | create_singlethread_workqueue("ab8500_btemp_wq"); | 1015 | create_singlethread_workqueue("ab8500_btemp_wq"); |
1015 | if (di->btemp_wq == NULL) { | 1016 | if (di->btemp_wq == NULL) { |
1016 | dev_err(di->dev, "failed to create work queue\n"); | 1017 | dev_err(di->dev, "failed to create work queue\n"); |
1017 | ret = -ENOMEM; | 1018 | return -ENOMEM; |
1018 | goto free_device_info; | ||
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | /* Init work for measuring temperature periodically */ | 1021 | /* Init work for measuring temperature periodically */ |
@@ -1093,12 +1093,14 @@ free_irq: | |||
1093 | } | 1093 | } |
1094 | free_btemp_wq: | 1094 | free_btemp_wq: |
1095 | destroy_workqueue(di->btemp_wq); | 1095 | destroy_workqueue(di->btemp_wq); |
1096 | free_device_info: | ||
1097 | kfree(di); | ||
1098 | |||
1099 | return ret; | 1096 | return ret; |
1100 | } | 1097 | } |
1101 | 1098 | ||
1099 | static const struct of_device_id ab8500_btemp_match[] = { | ||
1100 | { .compatible = "stericsson,ab8500-btemp", }, | ||
1101 | { }, | ||
1102 | }; | ||
1103 | |||
1102 | static struct platform_driver ab8500_btemp_driver = { | 1104 | static struct platform_driver ab8500_btemp_driver = { |
1103 | .probe = ab8500_btemp_probe, | 1105 | .probe = ab8500_btemp_probe, |
1104 | .remove = ab8500_btemp_remove, | 1106 | .remove = ab8500_btemp_remove, |
@@ -1107,6 +1109,7 @@ static struct platform_driver ab8500_btemp_driver = { | |||
1107 | .driver = { | 1109 | .driver = { |
1108 | .name = "ab8500-btemp", | 1110 | .name = "ab8500-btemp", |
1109 | .owner = THIS_MODULE, | 1111 | .owner = THIS_MODULE, |
1112 | .of_match_table = ab8500_btemp_match, | ||
1110 | }, | 1113 | }, |
1111 | }; | 1114 | }; |
1112 | 1115 | ||
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index 7ecb8abe20b5..3be9c0ee3fc5 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/err.h> | 23 | #include <linux/err.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/kobject.h> | 25 | #include <linux/kobject.h> |
26 | #include <linux/of.h> | ||
27 | #include <linux/mfd/core.h> | ||
26 | #include <linux/mfd/abx500/ab8500.h> | 28 | #include <linux/mfd/abx500/ab8500.h> |
27 | #include <linux/mfd/abx500.h> | 29 | #include <linux/mfd/abx500.h> |
28 | #include <linux/mfd/abx500/ab8500-bm.h> | 30 | #include <linux/mfd/abx500/ab8500-bm.h> |
@@ -181,9 +183,9 @@ struct ab8500_charger_usb_state { | |||
181 | * @vbat Battery voltage | 183 | * @vbat Battery voltage |
182 | * @old_vbat Previously measured battery voltage | 184 | * @old_vbat Previously measured battery voltage |
183 | * @autopower Indicate if we should have automatic pwron after pwrloss | 185 | * @autopower Indicate if we should have automatic pwron after pwrloss |
186 | * @autopower_cfg platform specific power config support for "pwron after pwrloss" | ||
184 | * @parent: Pointer to the struct ab8500 | 187 | * @parent: Pointer to the struct ab8500 |
185 | * @gpadc: Pointer to the struct gpadc | 188 | * @gpadc: Pointer to the struct gpadc |
186 | * @pdata: Pointer to the abx500_charger platform data | ||
187 | * @bat: Pointer to the abx500_bm platform data | 189 | * @bat: Pointer to the abx500_bm platform data |
188 | * @flags: Structure for information about events triggered | 190 | * @flags: Structure for information about events triggered |
189 | * @usb_state: Structure for usb stack information | 191 | * @usb_state: Structure for usb stack information |
@@ -218,9 +220,9 @@ struct ab8500_charger { | |||
218 | int vbat; | 220 | int vbat; |
219 | int old_vbat; | 221 | int old_vbat; |
220 | bool autopower; | 222 | bool autopower; |
223 | bool autopower_cfg; | ||
221 | struct ab8500 *parent; | 224 | struct ab8500 *parent; |
222 | struct ab8500_gpadc *gpadc; | 225 | struct ab8500_gpadc *gpadc; |
223 | struct abx500_charger_platform_data *pdata; | ||
224 | struct abx500_bm_data *bat; | 226 | struct abx500_bm_data *bat; |
225 | struct ab8500_charger_event_flags flags; | 227 | struct ab8500_charger_event_flags flags; |
226 | struct ab8500_charger_usb_state usb_state; | 228 | struct ab8500_charger_usb_state usb_state; |
@@ -322,7 +324,7 @@ static void ab8500_power_loss_handling(struct ab8500_charger *di) | |||
322 | static void ab8500_power_supply_changed(struct ab8500_charger *di, | 324 | static void ab8500_power_supply_changed(struct ab8500_charger *di, |
323 | struct power_supply *psy) | 325 | struct power_supply *psy) |
324 | { | 326 | { |
325 | if (di->pdata->autopower_cfg) { | 327 | if (di->autopower_cfg) { |
326 | if (!di->usb.charger_connected && | 328 | if (!di->usb.charger_connected && |
327 | !di->ac.charger_connected && | 329 | !di->ac.charger_connected && |
328 | di->autopower) { | 330 | di->autopower) { |
@@ -2526,25 +2528,45 @@ static int ab8500_charger_remove(struct platform_device *pdev) | |||
2526 | power_supply_unregister(&di->usb_chg.psy); | 2528 | power_supply_unregister(&di->usb_chg.psy); |
2527 | power_supply_unregister(&di->ac_chg.psy); | 2529 | power_supply_unregister(&di->ac_chg.psy); |
2528 | platform_set_drvdata(pdev, NULL); | 2530 | platform_set_drvdata(pdev, NULL); |
2529 | kfree(di); | ||
2530 | 2531 | ||
2531 | return 0; | 2532 | return 0; |
2532 | } | 2533 | } |
2533 | 2534 | ||
2535 | static char *supply_interface[] = { | ||
2536 | "ab8500_chargalg", | ||
2537 | "ab8500_fg", | ||
2538 | "ab8500_btemp", | ||
2539 | }; | ||
2540 | |||
2534 | static int ab8500_charger_probe(struct platform_device *pdev) | 2541 | static int ab8500_charger_probe(struct platform_device *pdev) |
2535 | { | 2542 | { |
2536 | int irq, i, charger_status, ret = 0; | 2543 | struct device_node *np = pdev->dev.of_node; |
2537 | struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; | ||
2538 | struct ab8500_charger *di; | 2544 | struct ab8500_charger *di; |
2545 | int irq, i, charger_status, ret = 0; | ||
2539 | 2546 | ||
2540 | if (!plat_data) { | 2547 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); |
2541 | dev_err(&pdev->dev, "No platform data\n"); | 2548 | if (!di) { |
2542 | return -EINVAL; | 2549 | dev_err(&pdev->dev, "%s no mem for ab8500_charger\n", __func__); |
2543 | } | ||
2544 | |||
2545 | di = kzalloc(sizeof(*di), GFP_KERNEL); | ||
2546 | if (!di) | ||
2547 | return -ENOMEM; | 2550 | return -ENOMEM; |
2551 | } | ||
2552 | di->bat = pdev->mfd_cell->platform_data; | ||
2553 | if (!di->bat) { | ||
2554 | if (np) { | ||
2555 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
2556 | if (ret) { | ||
2557 | dev_err(&pdev->dev, | ||
2558 | "failed to get battery information\n"); | ||
2559 | return ret; | ||
2560 | } | ||
2561 | di->autopower_cfg = of_property_read_bool(np, "autopower_cfg"); | ||
2562 | } else { | ||
2563 | dev_err(&pdev->dev, "missing dt node for ab8500_charger\n"); | ||
2564 | return -EINVAL; | ||
2565 | } | ||
2566 | } else { | ||
2567 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
2568 | di->autopower_cfg = false; | ||
2569 | } | ||
2548 | 2570 | ||
2549 | /* get parent data */ | 2571 | /* get parent data */ |
2550 | di->dev = &pdev->dev; | 2572 | di->dev = &pdev->dev; |
@@ -2554,22 +2576,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2554 | /* initialize lock */ | 2576 | /* initialize lock */ |
2555 | spin_lock_init(&di->usb_state.usb_lock); | 2577 | spin_lock_init(&di->usb_state.usb_lock); |
2556 | 2578 | ||
2557 | /* get charger specific platform data */ | ||
2558 | di->pdata = plat_data->charger; | ||
2559 | if (!di->pdata) { | ||
2560 | dev_err(di->dev, "no charger platform data supplied\n"); | ||
2561 | ret = -EINVAL; | ||
2562 | goto free_device_info; | ||
2563 | } | ||
2564 | |||
2565 | /* get battery specific platform data */ | ||
2566 | di->bat = plat_data->battery; | ||
2567 | if (!di->bat) { | ||
2568 | dev_err(di->dev, "no battery platform data supplied\n"); | ||
2569 | ret = -EINVAL; | ||
2570 | goto free_device_info; | ||
2571 | } | ||
2572 | |||
2573 | di->autopower = false; | 2579 | di->autopower = false; |
2574 | 2580 | ||
2575 | /* AC supply */ | 2581 | /* AC supply */ |
@@ -2579,8 +2585,8 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2579 | di->ac_chg.psy.properties = ab8500_charger_ac_props; | 2585 | di->ac_chg.psy.properties = ab8500_charger_ac_props; |
2580 | di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); | 2586 | di->ac_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_ac_props); |
2581 | di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; | 2587 | di->ac_chg.psy.get_property = ab8500_charger_ac_get_property; |
2582 | di->ac_chg.psy.supplied_to = di->pdata->supplied_to; | 2588 | di->ac_chg.psy.supplied_to = supply_interface; |
2583 | di->ac_chg.psy.num_supplicants = di->pdata->num_supplicants; | 2589 | di->ac_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), |
2584 | /* ux500_charger sub-class */ | 2590 | /* ux500_charger sub-class */ |
2585 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; | 2591 | di->ac_chg.ops.enable = &ab8500_charger_ac_en; |
2586 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | 2592 | di->ac_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; |
@@ -2597,8 +2603,8 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2597 | di->usb_chg.psy.properties = ab8500_charger_usb_props; | 2603 | di->usb_chg.psy.properties = ab8500_charger_usb_props; |
2598 | di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); | 2604 | di->usb_chg.psy.num_properties = ARRAY_SIZE(ab8500_charger_usb_props); |
2599 | di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; | 2605 | di->usb_chg.psy.get_property = ab8500_charger_usb_get_property; |
2600 | di->usb_chg.psy.supplied_to = di->pdata->supplied_to; | 2606 | di->usb_chg.psy.supplied_to = supply_interface; |
2601 | di->usb_chg.psy.num_supplicants = di->pdata->num_supplicants; | 2607 | di->usb_chg.psy.num_supplicants = ARRAY_SIZE(supply_interface), |
2602 | /* ux500_charger sub-class */ | 2608 | /* ux500_charger sub-class */ |
2603 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; | 2609 | di->usb_chg.ops.enable = &ab8500_charger_usb_en; |
2604 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; | 2610 | di->usb_chg.ops.kick_wd = &ab8500_charger_watchdog_kick; |
@@ -2614,8 +2620,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) | |||
2614 | create_singlethread_workqueue("ab8500_charger_wq"); | 2620 | create_singlethread_workqueue("ab8500_charger_wq"); |
2615 | if (di->charger_wq == NULL) { | 2621 | if (di->charger_wq == NULL) { |
2616 | dev_err(di->dev, "failed to create work queue\n"); | 2622 | dev_err(di->dev, "failed to create work queue\n"); |
2617 | ret = -ENOMEM; | 2623 | return -ENOMEM; |
2618 | goto free_device_info; | ||
2619 | } | 2624 | } |
2620 | 2625 | ||
2621 | /* Init work for HW failure check */ | 2626 | /* Init work for HW failure check */ |
@@ -2757,12 +2762,14 @@ free_regulator: | |||
2757 | regulator_put(di->regu); | 2762 | regulator_put(di->regu); |
2758 | free_charger_wq: | 2763 | free_charger_wq: |
2759 | destroy_workqueue(di->charger_wq); | 2764 | destroy_workqueue(di->charger_wq); |
2760 | free_device_info: | ||
2761 | kfree(di); | ||
2762 | |||
2763 | return ret; | 2765 | return ret; |
2764 | } | 2766 | } |
2765 | 2767 | ||
2768 | static const struct of_device_id ab8500_charger_match[] = { | ||
2769 | { .compatible = "stericsson,ab8500-charger", }, | ||
2770 | { }, | ||
2771 | }; | ||
2772 | |||
2766 | static struct platform_driver ab8500_charger_driver = { | 2773 | static struct platform_driver ab8500_charger_driver = { |
2767 | .probe = ab8500_charger_probe, | 2774 | .probe = ab8500_charger_probe, |
2768 | .remove = ab8500_charger_remove, | 2775 | .remove = ab8500_charger_remove, |
@@ -2771,6 +2778,7 @@ static struct platform_driver ab8500_charger_driver = { | |||
2771 | .driver = { | 2778 | .driver = { |
2772 | .name = "ab8500-charger", | 2779 | .name = "ab8500-charger", |
2773 | .owner = THIS_MODULE, | 2780 | .owner = THIS_MODULE, |
2781 | .of_match_table = ab8500_charger_match, | ||
2774 | }, | 2782 | }, |
2775 | }; | 2783 | }; |
2776 | 2784 | ||
diff --git a/drivers/power/ab8500_fg.c b/drivers/power/ab8500_fg.c index 331dc43ded4e..b3bf178c3462 100644 --- a/drivers/power/ab8500_fg.c +++ b/drivers/power/ab8500_fg.c | |||
@@ -22,15 +22,16 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/power_supply.h> | 23 | #include <linux/power_supply.h> |
24 | #include <linux/kobject.h> | 24 | #include <linux/kobject.h> |
25 | #include <linux/mfd/abx500/ab8500.h> | ||
26 | #include <linux/mfd/abx500.h> | ||
27 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
28 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
29 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
30 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
31 | #include <linux/mfd/abx500.h> | ||
32 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/of.h> | ||
33 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
30 | #include <linux/mfd/core.h> | ||
31 | #include <linux/mfd/abx500.h> | ||
32 | #include <linux/mfd/abx500/ab8500.h> | ||
33 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
34 | #include <linux/mfd/abx500/ab8500-gpadc.h> | ||
34 | 35 | ||
35 | #define MILLI_TO_MICRO 1000 | 36 | #define MILLI_TO_MICRO 1000 |
36 | #define FG_LSB_IN_MA 1627 | 37 | #define FG_LSB_IN_MA 1627 |
@@ -172,7 +173,6 @@ struct inst_curr_result_list { | |||
172 | * @avg_cap: Average capacity filter | 173 | * @avg_cap: Average capacity filter |
173 | * @parent: Pointer to the struct ab8500 | 174 | * @parent: Pointer to the struct ab8500 |
174 | * @gpadc: Pointer to the struct gpadc | 175 | * @gpadc: Pointer to the struct gpadc |
175 | * @pdata: Pointer to the abx500_fg platform data | ||
176 | * @bat: Pointer to the abx500_bm platform data | 176 | * @bat: Pointer to the abx500_bm platform data |
177 | * @fg_psy: Structure that holds the FG specific battery properties | 177 | * @fg_psy: Structure that holds the FG specific battery properties |
178 | * @fg_wq: Work queue for running the FG algorithm | 178 | * @fg_wq: Work queue for running the FG algorithm |
@@ -212,7 +212,6 @@ struct ab8500_fg { | |||
212 | struct ab8500_fg_avg_cap avg_cap; | 212 | struct ab8500_fg_avg_cap avg_cap; |
213 | struct ab8500 *parent; | 213 | struct ab8500 *parent; |
214 | struct ab8500_gpadc *gpadc; | 214 | struct ab8500_gpadc *gpadc; |
215 | struct abx500_fg_platform_data *pdata; | ||
216 | struct abx500_bm_data *bat; | 215 | struct abx500_bm_data *bat; |
217 | struct power_supply fg_psy; | 216 | struct power_supply fg_psy; |
218 | struct workqueue_struct *fg_wq; | 217 | struct workqueue_struct *fg_wq; |
@@ -2429,7 +2428,6 @@ static int ab8500_fg_remove(struct platform_device *pdev) | |||
2429 | flush_scheduled_work(); | 2428 | flush_scheduled_work(); |
2430 | power_supply_unregister(&di->fg_psy); | 2429 | power_supply_unregister(&di->fg_psy); |
2431 | platform_set_drvdata(pdev, NULL); | 2430 | platform_set_drvdata(pdev, NULL); |
2432 | kfree(di); | ||
2433 | return ret; | 2431 | return ret; |
2434 | } | 2432 | } |
2435 | 2433 | ||
@@ -2442,21 +2440,39 @@ static struct ab8500_fg_interrupts ab8500_fg_irq[] = { | |||
2442 | {"CCEOC", ab8500_fg_cc_data_end_handler}, | 2440 | {"CCEOC", ab8500_fg_cc_data_end_handler}, |
2443 | }; | 2441 | }; |
2444 | 2442 | ||
2443 | static char *supply_interface[] = { | ||
2444 | "ab8500_chargalg", | ||
2445 | "ab8500_usb", | ||
2446 | }; | ||
2447 | |||
2445 | static int ab8500_fg_probe(struct platform_device *pdev) | 2448 | static int ab8500_fg_probe(struct platform_device *pdev) |
2446 | { | 2449 | { |
2450 | struct device_node *np = pdev->dev.of_node; | ||
2451 | struct ab8500_fg *di; | ||
2447 | int i, irq; | 2452 | int i, irq; |
2448 | int ret = 0; | 2453 | int ret = 0; |
2449 | struct abx500_bm_plat_data *plat_data = pdev->dev.platform_data; | ||
2450 | struct ab8500_fg *di; | ||
2451 | |||
2452 | if (!plat_data) { | ||
2453 | dev_err(&pdev->dev, "No platform data\n"); | ||
2454 | return -EINVAL; | ||
2455 | } | ||
2456 | 2454 | ||
2457 | di = kzalloc(sizeof(*di), GFP_KERNEL); | 2455 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); |
2458 | if (!di) | 2456 | if (!di) { |
2457 | dev_err(&pdev->dev, "%s no mem for ab8500_fg\n", __func__); | ||
2459 | return -ENOMEM; | 2458 | return -ENOMEM; |
2459 | } | ||
2460 | di->bat = pdev->mfd_cell->platform_data; | ||
2461 | if (!di->bat) { | ||
2462 | if (np) { | ||
2463 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
2464 | if (ret) { | ||
2465 | dev_err(&pdev->dev, | ||
2466 | "failed to get battery information\n"); | ||
2467 | return ret; | ||
2468 | } | ||
2469 | } else { | ||
2470 | dev_err(&pdev->dev, "missing dt node for ab8500_fg\n"); | ||
2471 | return -EINVAL; | ||
2472 | } | ||
2473 | } else { | ||
2474 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
2475 | } | ||
2460 | 2476 | ||
2461 | mutex_init(&di->cc_lock); | 2477 | mutex_init(&di->cc_lock); |
2462 | 2478 | ||
@@ -2465,29 +2481,13 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2465 | di->parent = dev_get_drvdata(pdev->dev.parent); | 2481 | di->parent = dev_get_drvdata(pdev->dev.parent); |
2466 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); | 2482 | di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0"); |
2467 | 2483 | ||
2468 | /* get fg specific platform data */ | ||
2469 | di->pdata = plat_data->fg; | ||
2470 | if (!di->pdata) { | ||
2471 | dev_err(di->dev, "no fg platform data supplied\n"); | ||
2472 | ret = -EINVAL; | ||
2473 | goto free_device_info; | ||
2474 | } | ||
2475 | |||
2476 | /* get battery specific platform data */ | ||
2477 | di->bat = plat_data->battery; | ||
2478 | if (!di->bat) { | ||
2479 | dev_err(di->dev, "no battery platform data supplied\n"); | ||
2480 | ret = -EINVAL; | ||
2481 | goto free_device_info; | ||
2482 | } | ||
2483 | |||
2484 | di->fg_psy.name = "ab8500_fg"; | 2484 | di->fg_psy.name = "ab8500_fg"; |
2485 | di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; | 2485 | di->fg_psy.type = POWER_SUPPLY_TYPE_BATTERY; |
2486 | di->fg_psy.properties = ab8500_fg_props; | 2486 | di->fg_psy.properties = ab8500_fg_props; |
2487 | di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); | 2487 | di->fg_psy.num_properties = ARRAY_SIZE(ab8500_fg_props); |
2488 | di->fg_psy.get_property = ab8500_fg_get_property; | 2488 | di->fg_psy.get_property = ab8500_fg_get_property; |
2489 | di->fg_psy.supplied_to = di->pdata->supplied_to; | 2489 | di->fg_psy.supplied_to = supply_interface; |
2490 | di->fg_psy.num_supplicants = di->pdata->num_supplicants; | 2490 | di->fg_psy.num_supplicants = ARRAY_SIZE(supply_interface), |
2491 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; | 2491 | di->fg_psy.external_power_changed = ab8500_fg_external_power_changed; |
2492 | 2492 | ||
2493 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * | 2493 | di->bat_cap.max_mah_design = MILLI_TO_MICRO * |
@@ -2506,8 +2506,7 @@ static int ab8500_fg_probe(struct platform_device *pdev) | |||
2506 | di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); | 2506 | di->fg_wq = create_singlethread_workqueue("ab8500_fg_wq"); |
2507 | if (di->fg_wq == NULL) { | 2507 | if (di->fg_wq == NULL) { |
2508 | dev_err(di->dev, "failed to create work queue\n"); | 2508 | dev_err(di->dev, "failed to create work queue\n"); |
2509 | ret = -ENOMEM; | 2509 | return -ENOMEM; |
2510 | goto free_device_info; | ||
2511 | } | 2510 | } |
2512 | 2511 | ||
2513 | /* Init work for running the fg algorithm instantly */ | 2512 | /* Init work for running the fg algorithm instantly */ |
@@ -2606,12 +2605,14 @@ free_irq: | |||
2606 | } | 2605 | } |
2607 | free_inst_curr_wq: | 2606 | free_inst_curr_wq: |
2608 | destroy_workqueue(di->fg_wq); | 2607 | destroy_workqueue(di->fg_wq); |
2609 | free_device_info: | ||
2610 | kfree(di); | ||
2611 | |||
2612 | return ret; | 2608 | return ret; |
2613 | } | 2609 | } |
2614 | 2610 | ||
2611 | static const struct of_device_id ab8500_fg_match[] = { | ||
2612 | { .compatible = "stericsson,ab8500-fg", }, | ||
2613 | { }, | ||
2614 | }; | ||
2615 | |||
2615 | static struct platform_driver ab8500_fg_driver = { | 2616 | static struct platform_driver ab8500_fg_driver = { |
2616 | .probe = ab8500_fg_probe, | 2617 | .probe = ab8500_fg_probe, |
2617 | .remove = ab8500_fg_remove, | 2618 | .remove = ab8500_fg_remove, |
@@ -2620,6 +2621,7 @@ static struct platform_driver ab8500_fg_driver = { | |||
2620 | .driver = { | 2621 | .driver = { |
2621 | .name = "ab8500-fg", | 2622 | .name = "ab8500-fg", |
2622 | .owner = THIS_MODULE, | 2623 | .owner = THIS_MODULE, |
2624 | .of_match_table = ab8500_fg_match, | ||
2623 | }, | 2625 | }, |
2624 | }; | 2626 | }; |
2625 | 2627 | ||
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 19f254190790..297089146064 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
22 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
23 | #include <linux/kobject.h> | 23 | #include <linux/kobject.h> |
24 | #include <linux/of.h> | ||
25 | #include <linux/mfd/core.h> | ||
24 | #include <linux/mfd/abx500.h> | 26 | #include <linux/mfd/abx500.h> |
25 | #include <linux/mfd/abx500/ux500_chargalg.h> | 27 | #include <linux/mfd/abx500/ux500_chargalg.h> |
26 | #include <linux/mfd/abx500/ab8500-bm.h> | 28 | #include <linux/mfd/abx500/ab8500-bm.h> |
@@ -205,7 +207,6 @@ enum maxim_ret { | |||
205 | * @chg_info: information about connected charger types | 207 | * @chg_info: information about connected charger types |
206 | * @batt_data: data of the battery | 208 | * @batt_data: data of the battery |
207 | * @susp_status: current charger suspension status | 209 | * @susp_status: current charger suspension status |
208 | * @pdata: pointer to the abx500_chargalg platform data | ||
209 | * @bat: pointer to the abx500_bm platform data | 210 | * @bat: pointer to the abx500_bm platform data |
210 | * @chargalg_psy: structure that holds the battery properties exposed by | 211 | * @chargalg_psy: structure that holds the battery properties exposed by |
211 | * the charging algorithm | 212 | * the charging algorithm |
@@ -231,7 +232,6 @@ struct abx500_chargalg { | |||
231 | struct abx500_chargalg_charger_info chg_info; | 232 | struct abx500_chargalg_charger_info chg_info; |
232 | struct abx500_chargalg_battery_data batt_data; | 233 | struct abx500_chargalg_battery_data batt_data; |
233 | struct abx500_chargalg_suspension_status susp_status; | 234 | struct abx500_chargalg_suspension_status susp_status; |
234 | struct abx500_chargalg_platform_data *pdata; | ||
235 | struct abx500_bm_data *bat; | 235 | struct abx500_bm_data *bat; |
236 | struct power_supply chargalg_psy; | 236 | struct power_supply chargalg_psy; |
237 | struct ux500_charger *ac_chg; | 237 | struct ux500_charger *ac_chg; |
@@ -1795,36 +1795,53 @@ static int abx500_chargalg_remove(struct platform_device *pdev) | |||
1795 | flush_scheduled_work(); | 1795 | flush_scheduled_work(); |
1796 | power_supply_unregister(&di->chargalg_psy); | 1796 | power_supply_unregister(&di->chargalg_psy); |
1797 | platform_set_drvdata(pdev, NULL); | 1797 | platform_set_drvdata(pdev, NULL); |
1798 | kfree(di); | ||
1799 | 1798 | ||
1800 | return 0; | 1799 | return 0; |
1801 | } | 1800 | } |
1802 | 1801 | ||
1802 | static char *supply_interface[] = { | ||
1803 | "ab8500_fg", | ||
1804 | }; | ||
1805 | |||
1803 | static int abx500_chargalg_probe(struct platform_device *pdev) | 1806 | static int abx500_chargalg_probe(struct platform_device *pdev) |
1804 | { | 1807 | { |
1805 | struct abx500_bm_plat_data *plat_data; | 1808 | struct device_node *np = pdev->dev.of_node; |
1809 | struct abx500_chargalg *di; | ||
1806 | int ret = 0; | 1810 | int ret = 0; |
1807 | 1811 | ||
1808 | struct abx500_chargalg *di = | 1812 | di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL); |
1809 | kzalloc(sizeof(struct abx500_chargalg), GFP_KERNEL); | 1813 | if (!di) { |
1810 | if (!di) | 1814 | dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__); |
1811 | return -ENOMEM; | 1815 | return -ENOMEM; |
1816 | } | ||
1817 | di->bat = pdev->mfd_cell->platform_data; | ||
1818 | if (!di->bat) { | ||
1819 | if (np) { | ||
1820 | ret = bmdevs_of_probe(&pdev->dev, np, &di->bat); | ||
1821 | if (ret) { | ||
1822 | dev_err(&pdev->dev, | ||
1823 | "failed to get battery information\n"); | ||
1824 | return ret; | ||
1825 | } | ||
1826 | } else { | ||
1827 | dev_err(&pdev->dev, "missing dt node for ab8500_chargalg\n"); | ||
1828 | return -EINVAL; | ||
1829 | } | ||
1830 | } else { | ||
1831 | dev_info(&pdev->dev, "falling back to legacy platform data\n"); | ||
1832 | } | ||
1812 | 1833 | ||
1813 | /* get device struct */ | 1834 | /* get device struct */ |
1814 | di->dev = &pdev->dev; | 1835 | di->dev = &pdev->dev; |
1815 | 1836 | ||
1816 | plat_data = pdev->dev.platform_data; | ||
1817 | di->pdata = plat_data->chargalg; | ||
1818 | di->bat = plat_data->battery; | ||
1819 | |||
1820 | /* chargalg supply */ | 1837 | /* chargalg supply */ |
1821 | di->chargalg_psy.name = "abx500_chargalg"; | 1838 | di->chargalg_psy.name = "abx500_chargalg"; |
1822 | di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY; | 1839 | di->chargalg_psy.type = POWER_SUPPLY_TYPE_BATTERY; |
1823 | di->chargalg_psy.properties = abx500_chargalg_props; | 1840 | di->chargalg_psy.properties = abx500_chargalg_props; |
1824 | di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props); | 1841 | di->chargalg_psy.num_properties = ARRAY_SIZE(abx500_chargalg_props); |
1825 | di->chargalg_psy.get_property = abx500_chargalg_get_property; | 1842 | di->chargalg_psy.get_property = abx500_chargalg_get_property; |
1826 | di->chargalg_psy.supplied_to = di->pdata->supplied_to; | 1843 | di->chargalg_psy.supplied_to = supply_interface; |
1827 | di->chargalg_psy.num_supplicants = di->pdata->num_supplicants; | 1844 | di->chargalg_psy.num_supplicants = ARRAY_SIZE(supply_interface), |
1828 | di->chargalg_psy.external_power_changed = | 1845 | di->chargalg_psy.external_power_changed = |
1829 | abx500_chargalg_external_power_changed; | 1846 | abx500_chargalg_external_power_changed; |
1830 | 1847 | ||
@@ -1844,7 +1861,7 @@ static int abx500_chargalg_probe(struct platform_device *pdev) | |||
1844 | create_singlethread_workqueue("abx500_chargalg_wq"); | 1861 | create_singlethread_workqueue("abx500_chargalg_wq"); |
1845 | if (di->chargalg_wq == NULL) { | 1862 | if (di->chargalg_wq == NULL) { |
1846 | dev_err(di->dev, "failed to create work queue\n"); | 1863 | dev_err(di->dev, "failed to create work queue\n"); |
1847 | goto free_device_info; | 1864 | return -ENOMEM; |
1848 | } | 1865 | } |
1849 | 1866 | ||
1850 | /* Init work for chargalg */ | 1867 | /* Init work for chargalg */ |
@@ -1885,20 +1902,23 @@ free_psy: | |||
1885 | power_supply_unregister(&di->chargalg_psy); | 1902 | power_supply_unregister(&di->chargalg_psy); |
1886 | free_chargalg_wq: | 1903 | free_chargalg_wq: |
1887 | destroy_workqueue(di->chargalg_wq); | 1904 | destroy_workqueue(di->chargalg_wq); |
1888 | free_device_info: | ||
1889 | kfree(di); | ||
1890 | |||
1891 | return ret; | 1905 | return ret; |
1892 | } | 1906 | } |
1893 | 1907 | ||
1908 | static const struct of_device_id ab8500_chargalg_match[] = { | ||
1909 | { .compatible = "stericsson,ab8500-chargalg", }, | ||
1910 | { }, | ||
1911 | }; | ||
1912 | |||
1894 | static struct platform_driver abx500_chargalg_driver = { | 1913 | static struct platform_driver abx500_chargalg_driver = { |
1895 | .probe = abx500_chargalg_probe, | 1914 | .probe = abx500_chargalg_probe, |
1896 | .remove = abx500_chargalg_remove, | 1915 | .remove = abx500_chargalg_remove, |
1897 | .suspend = abx500_chargalg_suspend, | 1916 | .suspend = abx500_chargalg_suspend, |
1898 | .resume = abx500_chargalg_resume, | 1917 | .resume = abx500_chargalg_resume, |
1899 | .driver = { | 1918 | .driver = { |
1900 | .name = "abx500-chargalg", | 1919 | .name = "ab8500-chargalg", |
1901 | .owner = THIS_MODULE, | 1920 | .owner = THIS_MODULE, |
1921 | .of_match_table = ab8500_chargalg_match, | ||
1902 | }, | 1922 | }, |
1903 | }; | 1923 | }; |
1904 | 1924 | ||
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c new file mode 100644 index 000000000000..ee842b37f462 --- /dev/null +++ b/drivers/power/bq2415x_charger.c | |||
@@ -0,0 +1,1670 @@ | |||
1 | /* | ||
2 | * bq2415x charger driver | ||
3 | * | ||
4 | * Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * Datasheets: | ||
23 | * http://www.ti.com/product/bq24150 | ||
24 | * http://www.ti.com/product/bq24150a | ||
25 | * http://www.ti.com/product/bq24152 | ||
26 | * http://www.ti.com/product/bq24153 | ||
27 | * http://www.ti.com/product/bq24153a | ||
28 | * http://www.ti.com/product/bq24155 | ||
29 | */ | ||
30 | |||
31 | #include <linux/version.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/param.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/workqueue.h> | ||
37 | #include <linux/sysfs.h> | ||
38 | #include <linux/platform_device.h> | ||
39 | #include <linux/power_supply.h> | ||
40 | #include <linux/idr.h> | ||
41 | #include <linux/i2c.h> | ||
42 | #include <linux/slab.h> | ||
43 | |||
44 | #include <linux/power/bq2415x_charger.h> | ||
45 | |||
46 | /* timeout for resetting chip timer */ | ||
47 | #define BQ2415X_TIMER_TIMEOUT 10 | ||
48 | |||
49 | #define BQ2415X_REG_STATUS 0x00 | ||
50 | #define BQ2415X_REG_CONTROL 0x01 | ||
51 | #define BQ2415X_REG_VOLTAGE 0x02 | ||
52 | #define BQ2415X_REG_VENDER 0x03 | ||
53 | #define BQ2415X_REG_CURRENT 0x04 | ||
54 | |||
55 | /* reset state for all registers */ | ||
56 | #define BQ2415X_RESET_STATUS BIT(6) | ||
57 | #define BQ2415X_RESET_CONTROL (BIT(4)|BIT(5)) | ||
58 | #define BQ2415X_RESET_VOLTAGE (BIT(1)|BIT(3)) | ||
59 | #define BQ2415X_RESET_CURRENT (BIT(0)|BIT(3)|BIT(7)) | ||
60 | |||
61 | /* status register */ | ||
62 | #define BQ2415X_BIT_TMR_RST 7 | ||
63 | #define BQ2415X_BIT_OTG 7 | ||
64 | #define BQ2415X_BIT_EN_STAT 6 | ||
65 | #define BQ2415X_MASK_STAT (BIT(4)|BIT(5)) | ||
66 | #define BQ2415X_SHIFT_STAT 4 | ||
67 | #define BQ2415X_BIT_BOOST 3 | ||
68 | #define BQ2415X_MASK_FAULT (BIT(0)|BIT(1)|BIT(2)) | ||
69 | #define BQ2415X_SHIFT_FAULT 0 | ||
70 | |||
71 | /* control register */ | ||
72 | #define BQ2415X_MASK_LIMIT (BIT(6)|BIT(7)) | ||
73 | #define BQ2415X_SHIFT_LIMIT 6 | ||
74 | #define BQ2415X_MASK_VLOWV (BIT(4)|BIT(5)) | ||
75 | #define BQ2415X_SHIFT_VLOWV 4 | ||
76 | #define BQ2415X_BIT_TE 3 | ||
77 | #define BQ2415X_BIT_CE 2 | ||
78 | #define BQ2415X_BIT_HZ_MODE 1 | ||
79 | #define BQ2415X_BIT_OPA_MODE 0 | ||
80 | |||
81 | /* voltage register */ | ||
82 | #define BQ2415X_MASK_VO (BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(7)) | ||
83 | #define BQ2415X_SHIFT_VO 2 | ||
84 | #define BQ2415X_BIT_OTG_PL 1 | ||
85 | #define BQ2415X_BIT_OTG_EN 0 | ||
86 | |||
87 | /* vender register */ | ||
88 | #define BQ2415X_MASK_VENDER (BIT(5)|BIT(6)|BIT(7)) | ||
89 | #define BQ2415X_SHIFT_VENDER 5 | ||
90 | #define BQ2415X_MASK_PN (BIT(3)|BIT(4)) | ||
91 | #define BQ2415X_SHIFT_PN 3 | ||
92 | #define BQ2415X_MASK_REVISION (BIT(0)|BIT(1)|BIT(2)) | ||
93 | #define BQ2415X_SHIFT_REVISION 0 | ||
94 | |||
95 | /* current register */ | ||
96 | #define BQ2415X_MASK_RESET BIT(7) | ||
97 | #define BQ2415X_MASK_VI_CHRG (BIT(4)|BIT(5)|BIT(6)) | ||
98 | #define BQ2415X_SHIFT_VI_CHRG 4 | ||
99 | /* N/A BIT(3) */ | ||
100 | #define BQ2415X_MASK_VI_TERM (BIT(0)|BIT(1)|BIT(2)) | ||
101 | #define BQ2415X_SHIFT_VI_TERM 0 | ||
102 | |||
103 | |||
104 | enum bq2415x_command { | ||
105 | BQ2415X_TIMER_RESET, | ||
106 | BQ2415X_OTG_STATUS, | ||
107 | BQ2415X_STAT_PIN_STATUS, | ||
108 | BQ2415X_STAT_PIN_ENABLE, | ||
109 | BQ2415X_STAT_PIN_DISABLE, | ||
110 | BQ2415X_CHARGE_STATUS, | ||
111 | BQ2415X_BOOST_STATUS, | ||
112 | BQ2415X_FAULT_STATUS, | ||
113 | |||
114 | BQ2415X_CHARGE_TERMINATION_STATUS, | ||
115 | BQ2415X_CHARGE_TERMINATION_ENABLE, | ||
116 | BQ2415X_CHARGE_TERMINATION_DISABLE, | ||
117 | BQ2415X_CHARGER_STATUS, | ||
118 | BQ2415X_CHARGER_ENABLE, | ||
119 | BQ2415X_CHARGER_DISABLE, | ||
120 | BQ2415X_HIGH_IMPEDANCE_STATUS, | ||
121 | BQ2415X_HIGH_IMPEDANCE_ENABLE, | ||
122 | BQ2415X_HIGH_IMPEDANCE_DISABLE, | ||
123 | BQ2415X_BOOST_MODE_STATUS, | ||
124 | BQ2415X_BOOST_MODE_ENABLE, | ||
125 | BQ2415X_BOOST_MODE_DISABLE, | ||
126 | |||
127 | BQ2415X_OTG_LEVEL, | ||
128 | BQ2415X_OTG_ACTIVATE_HIGH, | ||
129 | BQ2415X_OTG_ACTIVATE_LOW, | ||
130 | BQ2415X_OTG_PIN_STATUS, | ||
131 | BQ2415X_OTG_PIN_ENABLE, | ||
132 | BQ2415X_OTG_PIN_DISABLE, | ||
133 | |||
134 | BQ2415X_VENDER_CODE, | ||
135 | BQ2415X_PART_NUMBER, | ||
136 | BQ2415X_REVISION, | ||
137 | }; | ||
138 | |||
139 | enum bq2415x_chip { | ||
140 | BQUNKNOWN, | ||
141 | BQ24150, | ||
142 | BQ24150A, | ||
143 | BQ24151, | ||
144 | BQ24151A, | ||
145 | BQ24152, | ||
146 | BQ24153, | ||
147 | BQ24153A, | ||
148 | BQ24155, | ||
149 | BQ24156, | ||
150 | BQ24156A, | ||
151 | BQ24158, | ||
152 | }; | ||
153 | |||
154 | static char *bq2415x_chip_name[] = { | ||
155 | "unknown", | ||
156 | "bq24150", | ||
157 | "bq24150a", | ||
158 | "bq24151", | ||
159 | "bq24151a", | ||
160 | "bq24152", | ||
161 | "bq24153", | ||
162 | "bq24153a", | ||
163 | "bq24155", | ||
164 | "bq24156", | ||
165 | "bq24156a", | ||
166 | "bq24158", | ||
167 | }; | ||
168 | |||
169 | struct bq2415x_device { | ||
170 | struct device *dev; | ||
171 | struct bq2415x_platform_data init_data; | ||
172 | struct power_supply charger; | ||
173 | struct delayed_work work; | ||
174 | enum bq2415x_mode reported_mode;/* mode reported by hook function */ | ||
175 | enum bq2415x_mode mode; /* current configured mode */ | ||
176 | enum bq2415x_chip chip; | ||
177 | const char *timer_error; | ||
178 | char *model; | ||
179 | char *name; | ||
180 | int autotimer; /* 1 - if driver automatically reset timer, 0 - not */ | ||
181 | int automode; /* 1 - enabled, 0 - disabled; -1 - not supported */ | ||
182 | int id; | ||
183 | }; | ||
184 | |||
185 | /* each registered chip must have unique id */ | ||
186 | static DEFINE_IDR(bq2415x_id); | ||
187 | |||
188 | static DEFINE_MUTEX(bq2415x_id_mutex); | ||
189 | static DEFINE_MUTEX(bq2415x_timer_mutex); | ||
190 | static DEFINE_MUTEX(bq2415x_i2c_mutex); | ||
191 | |||
192 | /**** i2c read functions ****/ | ||
193 | |||
194 | /* read value from register */ | ||
195 | static int bq2415x_i2c_read(struct bq2415x_device *bq, u8 reg) | ||
196 | { | ||
197 | struct i2c_client *client = to_i2c_client(bq->dev); | ||
198 | struct i2c_msg msg[2]; | ||
199 | u8 val; | ||
200 | int ret; | ||
201 | |||
202 | if (!client->adapter) | ||
203 | return -ENODEV; | ||
204 | |||
205 | msg[0].addr = client->addr; | ||
206 | msg[0].flags = 0; | ||
207 | msg[0].buf = ® | ||
208 | msg[0].len = sizeof(reg); | ||
209 | msg[1].addr = client->addr; | ||
210 | msg[1].flags = I2C_M_RD; | ||
211 | msg[1].buf = &val; | ||
212 | msg[1].len = sizeof(val); | ||
213 | |||
214 | mutex_lock(&bq2415x_i2c_mutex); | ||
215 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
216 | mutex_unlock(&bq2415x_i2c_mutex); | ||
217 | |||
218 | if (ret < 0) | ||
219 | return ret; | ||
220 | |||
221 | return val; | ||
222 | } | ||
223 | |||
224 | /* read value from register, apply mask and right shift it */ | ||
225 | static int bq2415x_i2c_read_mask(struct bq2415x_device *bq, u8 reg, | ||
226 | u8 mask, u8 shift) | ||
227 | { | ||
228 | int ret; | ||
229 | |||
230 | if (shift > 8) | ||
231 | return -EINVAL; | ||
232 | |||
233 | ret = bq2415x_i2c_read(bq, reg); | ||
234 | if (ret < 0) | ||
235 | return ret; | ||
236 | return (ret & mask) >> shift; | ||
237 | } | ||
238 | |||
239 | /* read value from register and return one specified bit */ | ||
240 | static int bq2415x_i2c_read_bit(struct bq2415x_device *bq, u8 reg, u8 bit) | ||
241 | { | ||
242 | if (bit > 8) | ||
243 | return -EINVAL; | ||
244 | return bq2415x_i2c_read_mask(bq, reg, BIT(bit), bit); | ||
245 | } | ||
246 | |||
247 | /**** i2c write functions ****/ | ||
248 | |||
249 | /* write value to register */ | ||
250 | static int bq2415x_i2c_write(struct bq2415x_device *bq, u8 reg, u8 val) | ||
251 | { | ||
252 | struct i2c_client *client = to_i2c_client(bq->dev); | ||
253 | struct i2c_msg msg[1]; | ||
254 | u8 data[2]; | ||
255 | int ret; | ||
256 | |||
257 | data[0] = reg; | ||
258 | data[1] = val; | ||
259 | |||
260 | msg[0].addr = client->addr; | ||
261 | msg[0].flags = 0; | ||
262 | msg[0].buf = data; | ||
263 | msg[0].len = ARRAY_SIZE(data); | ||
264 | |||
265 | mutex_lock(&bq2415x_i2c_mutex); | ||
266 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); | ||
267 | mutex_unlock(&bq2415x_i2c_mutex); | ||
268 | |||
269 | /* i2c_transfer returns number of messages transferred */ | ||
270 | if (ret < 0) | ||
271 | return ret; | ||
272 | else if (ret != 1) | ||
273 | return -EIO; | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* read value from register, change it with mask left shifted and write back */ | ||
279 | static int bq2415x_i2c_write_mask(struct bq2415x_device *bq, u8 reg, u8 val, | ||
280 | u8 mask, u8 shift) | ||
281 | { | ||
282 | int ret; | ||
283 | |||
284 | if (shift > 8) | ||
285 | return -EINVAL; | ||
286 | |||
287 | ret = bq2415x_i2c_read(bq, reg); | ||
288 | if (ret < 0) | ||
289 | return ret; | ||
290 | |||
291 | ret &= ~mask; | ||
292 | ret |= val << shift; | ||
293 | |||
294 | return bq2415x_i2c_write(bq, reg, ret); | ||
295 | } | ||
296 | |||
297 | /* change only one bit in register */ | ||
298 | static int bq2415x_i2c_write_bit(struct bq2415x_device *bq, u8 reg, | ||
299 | bool val, u8 bit) | ||
300 | { | ||
301 | if (bit > 8) | ||
302 | return -EINVAL; | ||
303 | return bq2415x_i2c_write_mask(bq, reg, val, BIT(bit), bit); | ||
304 | } | ||
305 | |||
306 | /**** global functions ****/ | ||
307 | |||
308 | /* exec command function */ | ||
309 | static int bq2415x_exec_command(struct bq2415x_device *bq, | ||
310 | enum bq2415x_command command) | ||
311 | { | ||
312 | int ret; | ||
313 | |||
314 | switch (command) { | ||
315 | case BQ2415X_TIMER_RESET: | ||
316 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, | ||
317 | 1, BQ2415X_BIT_TMR_RST); | ||
318 | case BQ2415X_OTG_STATUS: | ||
319 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS, | ||
320 | BQ2415X_BIT_OTG); | ||
321 | case BQ2415X_STAT_PIN_STATUS: | ||
322 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS, | ||
323 | BQ2415X_BIT_EN_STAT); | ||
324 | case BQ2415X_STAT_PIN_ENABLE: | ||
325 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 1, | ||
326 | BQ2415X_BIT_EN_STAT); | ||
327 | case BQ2415X_STAT_PIN_DISABLE: | ||
328 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_STATUS, 0, | ||
329 | BQ2415X_BIT_EN_STAT); | ||
330 | case BQ2415X_CHARGE_STATUS: | ||
331 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS, | ||
332 | BQ2415X_MASK_STAT, BQ2415X_SHIFT_STAT); | ||
333 | case BQ2415X_BOOST_STATUS: | ||
334 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_STATUS, | ||
335 | BQ2415X_BIT_BOOST); | ||
336 | case BQ2415X_FAULT_STATUS: | ||
337 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_STATUS, | ||
338 | BQ2415X_MASK_FAULT, BQ2415X_SHIFT_FAULT); | ||
339 | |||
340 | case BQ2415X_CHARGE_TERMINATION_STATUS: | ||
341 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
342 | BQ2415X_BIT_TE); | ||
343 | case BQ2415X_CHARGE_TERMINATION_ENABLE: | ||
344 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
345 | 1, BQ2415X_BIT_TE); | ||
346 | case BQ2415X_CHARGE_TERMINATION_DISABLE: | ||
347 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
348 | 0, BQ2415X_BIT_TE); | ||
349 | case BQ2415X_CHARGER_STATUS: | ||
350 | ret = bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
351 | BQ2415X_BIT_CE); | ||
352 | if (ret < 0) | ||
353 | return ret; | ||
354 | else | ||
355 | return ret > 0 ? 0 : 1; | ||
356 | case BQ2415X_CHARGER_ENABLE: | ||
357 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
358 | 0, BQ2415X_BIT_CE); | ||
359 | case BQ2415X_CHARGER_DISABLE: | ||
360 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
361 | 1, BQ2415X_BIT_CE); | ||
362 | case BQ2415X_HIGH_IMPEDANCE_STATUS: | ||
363 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
364 | BQ2415X_BIT_HZ_MODE); | ||
365 | case BQ2415X_HIGH_IMPEDANCE_ENABLE: | ||
366 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
367 | 1, BQ2415X_BIT_HZ_MODE); | ||
368 | case BQ2415X_HIGH_IMPEDANCE_DISABLE: | ||
369 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
370 | 0, BQ2415X_BIT_HZ_MODE); | ||
371 | case BQ2415X_BOOST_MODE_STATUS: | ||
372 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_CONTROL, | ||
373 | BQ2415X_BIT_OPA_MODE); | ||
374 | case BQ2415X_BOOST_MODE_ENABLE: | ||
375 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
376 | 1, BQ2415X_BIT_OPA_MODE); | ||
377 | case BQ2415X_BOOST_MODE_DISABLE: | ||
378 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_CONTROL, | ||
379 | 0, BQ2415X_BIT_OPA_MODE); | ||
380 | |||
381 | case BQ2415X_OTG_LEVEL: | ||
382 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE, | ||
383 | BQ2415X_BIT_OTG_PL); | ||
384 | case BQ2415X_OTG_ACTIVATE_HIGH: | ||
385 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
386 | 1, BQ2415X_BIT_OTG_PL); | ||
387 | case BQ2415X_OTG_ACTIVATE_LOW: | ||
388 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
389 | 0, BQ2415X_BIT_OTG_PL); | ||
390 | case BQ2415X_OTG_PIN_STATUS: | ||
391 | return bq2415x_i2c_read_bit(bq, BQ2415X_REG_VOLTAGE, | ||
392 | BQ2415X_BIT_OTG_EN); | ||
393 | case BQ2415X_OTG_PIN_ENABLE: | ||
394 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
395 | 1, BQ2415X_BIT_OTG_EN); | ||
396 | case BQ2415X_OTG_PIN_DISABLE: | ||
397 | return bq2415x_i2c_write_bit(bq, BQ2415X_REG_VOLTAGE, | ||
398 | 0, BQ2415X_BIT_OTG_EN); | ||
399 | |||
400 | case BQ2415X_VENDER_CODE: | ||
401 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER, | ||
402 | BQ2415X_MASK_VENDER, BQ2415X_SHIFT_VENDER); | ||
403 | case BQ2415X_PART_NUMBER: | ||
404 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER, | ||
405 | BQ2415X_MASK_PN, BQ2415X_SHIFT_PN); | ||
406 | case BQ2415X_REVISION: | ||
407 | return bq2415x_i2c_read_mask(bq, BQ2415X_REG_VENDER, | ||
408 | BQ2415X_MASK_REVISION, BQ2415X_SHIFT_REVISION); | ||
409 | } | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | /* detect chip type */ | ||
414 | static enum bq2415x_chip bq2415x_detect_chip(struct bq2415x_device *bq) | ||
415 | { | ||
416 | struct i2c_client *client = to_i2c_client(bq->dev); | ||
417 | int ret = bq2415x_exec_command(bq, BQ2415X_PART_NUMBER); | ||
418 | |||
419 | if (ret < 0) | ||
420 | return ret; | ||
421 | |||
422 | switch (client->addr) { | ||
423 | case 0x6b: | ||
424 | switch (ret) { | ||
425 | case 0: | ||
426 | if (bq->chip == BQ24151A) | ||
427 | return bq->chip; | ||
428 | else | ||
429 | return BQ24151; | ||
430 | case 1: | ||
431 | if (bq->chip == BQ24150A || | ||
432 | bq->chip == BQ24152 || | ||
433 | bq->chip == BQ24155) | ||
434 | return bq->chip; | ||
435 | else | ||
436 | return BQ24150; | ||
437 | case 2: | ||
438 | if (bq->chip == BQ24153A) | ||
439 | return bq->chip; | ||
440 | else | ||
441 | return BQ24153; | ||
442 | default: | ||
443 | return BQUNKNOWN; | ||
444 | } | ||
445 | break; | ||
446 | |||
447 | case 0x6a: | ||
448 | switch (ret) { | ||
449 | case 0: | ||
450 | if (bq->chip == BQ24156A) | ||
451 | return bq->chip; | ||
452 | else | ||
453 | return BQ24156; | ||
454 | case 2: | ||
455 | return BQ24158; | ||
456 | default: | ||
457 | return BQUNKNOWN; | ||
458 | } | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | return BQUNKNOWN; | ||
463 | } | ||
464 | |||
465 | /* detect chip revision */ | ||
466 | static int bq2415x_detect_revision(struct bq2415x_device *bq) | ||
467 | { | ||
468 | int ret = bq2415x_exec_command(bq, BQ2415X_REVISION); | ||
469 | int chip = bq2415x_detect_chip(bq); | ||
470 | |||
471 | if (ret < 0 || chip < 0) | ||
472 | return -1; | ||
473 | |||
474 | switch (chip) { | ||
475 | case BQ24150: | ||
476 | case BQ24150A: | ||
477 | case BQ24151: | ||
478 | case BQ24151A: | ||
479 | case BQ24152: | ||
480 | if (ret >= 0 && ret <= 3) | ||
481 | return ret; | ||
482 | else | ||
483 | return -1; | ||
484 | case BQ24153: | ||
485 | case BQ24153A: | ||
486 | case BQ24156: | ||
487 | case BQ24156A: | ||
488 | case BQ24158: | ||
489 | if (ret == 3) | ||
490 | return 0; | ||
491 | else if (ret == 1) | ||
492 | return 1; | ||
493 | else | ||
494 | return -1; | ||
495 | case BQ24155: | ||
496 | if (ret == 3) | ||
497 | return 3; | ||
498 | else | ||
499 | return -1; | ||
500 | case BQUNKNOWN: | ||
501 | return -1; | ||
502 | } | ||
503 | |||
504 | return -1; | ||
505 | } | ||
506 | |||
507 | /* return chip vender code */ | ||
508 | static int bq2415x_get_vender_code(struct bq2415x_device *bq) | ||
509 | { | ||
510 | int ret; | ||
511 | |||
512 | ret = bq2415x_exec_command(bq, BQ2415X_VENDER_CODE); | ||
513 | if (ret < 0) | ||
514 | return 0; | ||
515 | |||
516 | /* convert to binary */ | ||
517 | return (ret & 0x1) + | ||
518 | ((ret >> 1) & 0x1) * 10 + | ||
519 | ((ret >> 2) & 0x1) * 100; | ||
520 | } | ||
521 | |||
522 | /* reset all chip registers to default state */ | ||
523 | static void bq2415x_reset_chip(struct bq2415x_device *bq) | ||
524 | { | ||
525 | bq2415x_i2c_write(bq, BQ2415X_REG_CURRENT, BQ2415X_RESET_CURRENT); | ||
526 | bq2415x_i2c_write(bq, BQ2415X_REG_VOLTAGE, BQ2415X_RESET_VOLTAGE); | ||
527 | bq2415x_i2c_write(bq, BQ2415X_REG_CONTROL, BQ2415X_RESET_CONTROL); | ||
528 | bq2415x_i2c_write(bq, BQ2415X_REG_STATUS, BQ2415X_RESET_STATUS); | ||
529 | bq->timer_error = NULL; | ||
530 | } | ||
531 | |||
532 | /**** properties functions ****/ | ||
533 | |||
534 | /* set current limit in mA */ | ||
535 | static int bq2415x_set_current_limit(struct bq2415x_device *bq, int mA) | ||
536 | { | ||
537 | int val; | ||
538 | |||
539 | if (mA <= 100) | ||
540 | val = 0; | ||
541 | else if (mA <= 500) | ||
542 | val = 1; | ||
543 | else if (mA <= 800) | ||
544 | val = 2; | ||
545 | else | ||
546 | val = 3; | ||
547 | |||
548 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val, | ||
549 | BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT); | ||
550 | } | ||
551 | |||
552 | /* get current limit in mA */ | ||
553 | static int bq2415x_get_current_limit(struct bq2415x_device *bq) | ||
554 | { | ||
555 | int ret; | ||
556 | |||
557 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL, | ||
558 | BQ2415X_MASK_LIMIT, BQ2415X_SHIFT_LIMIT); | ||
559 | if (ret < 0) | ||
560 | return ret; | ||
561 | else if (ret == 0) | ||
562 | return 100; | ||
563 | else if (ret == 1) | ||
564 | return 500; | ||
565 | else if (ret == 2) | ||
566 | return 800; | ||
567 | else if (ret == 3) | ||
568 | return 1800; | ||
569 | return -EINVAL; | ||
570 | } | ||
571 | |||
572 | /* set weak battery voltage in mV */ | ||
573 | static int bq2415x_set_weak_battery_voltage(struct bq2415x_device *bq, int mV) | ||
574 | { | ||
575 | int val; | ||
576 | |||
577 | /* round to 100mV */ | ||
578 | if (mV <= 3400 + 50) | ||
579 | val = 0; | ||
580 | else if (mV <= 3500 + 50) | ||
581 | val = 1; | ||
582 | else if (mV <= 3600 + 50) | ||
583 | val = 2; | ||
584 | else | ||
585 | val = 3; | ||
586 | |||
587 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CONTROL, val, | ||
588 | BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV); | ||
589 | } | ||
590 | |||
591 | /* get weak battery voltage in mV */ | ||
592 | static int bq2415x_get_weak_battery_voltage(struct bq2415x_device *bq) | ||
593 | { | ||
594 | int ret; | ||
595 | |||
596 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CONTROL, | ||
597 | BQ2415X_MASK_VLOWV, BQ2415X_SHIFT_VLOWV); | ||
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | return 100 * (34 + ret); | ||
601 | } | ||
602 | |||
603 | /* set battery regulation voltage in mV */ | ||
604 | static int bq2415x_set_battery_regulation_voltage(struct bq2415x_device *bq, | ||
605 | int mV) | ||
606 | { | ||
607 | int val = (mV/10 - 350) / 2; | ||
608 | |||
609 | if (val < 0) | ||
610 | val = 0; | ||
611 | else if (val > 94) /* FIXME: Max is 94 or 122 ? Set max value ? */ | ||
612 | return -EINVAL; | ||
613 | |||
614 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val, | ||
615 | BQ2415X_MASK_VO, BQ2415X_SHIFT_VO); | ||
616 | } | ||
617 | |||
618 | /* get battery regulation voltage in mV */ | ||
619 | static int bq2415x_get_battery_regulation_voltage(struct bq2415x_device *bq) | ||
620 | { | ||
621 | int ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_VOLTAGE, | ||
622 | BQ2415X_MASK_VO, BQ2415X_SHIFT_VO); | ||
623 | |||
624 | if (ret < 0) | ||
625 | return ret; | ||
626 | return 10 * (350 + 2*ret); | ||
627 | } | ||
628 | |||
629 | /* set charge current in mA (platform data must provide resistor sense) */ | ||
630 | static int bq2415x_set_charge_current(struct bq2415x_device *bq, int mA) | ||
631 | { | ||
632 | int val; | ||
633 | |||
634 | if (bq->init_data.resistor_sense <= 0) | ||
635 | return -ENOSYS; | ||
636 | |||
637 | val = (mA * bq->init_data.resistor_sense - 37400) / 6800; | ||
638 | if (val < 0) | ||
639 | val = 0; | ||
640 | else if (val > 7) | ||
641 | val = 7; | ||
642 | |||
643 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val, | ||
644 | BQ2415X_MASK_VI_CHRG | BQ2415X_MASK_RESET, | ||
645 | BQ2415X_SHIFT_VI_CHRG); | ||
646 | } | ||
647 | |||
648 | /* get charge current in mA (platform data must provide resistor sense) */ | ||
649 | static int bq2415x_get_charge_current(struct bq2415x_device *bq) | ||
650 | { | ||
651 | int ret; | ||
652 | |||
653 | if (bq->init_data.resistor_sense <= 0) | ||
654 | return -ENOSYS; | ||
655 | |||
656 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, | ||
657 | BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG); | ||
658 | if (ret < 0) | ||
659 | return ret; | ||
660 | return (37400 + 6800*ret) / bq->init_data.resistor_sense; | ||
661 | } | ||
662 | |||
663 | /* set termination current in mA (platform data must provide resistor sense) */ | ||
664 | static int bq2415x_set_termination_current(struct bq2415x_device *bq, int mA) | ||
665 | { | ||
666 | int val; | ||
667 | |||
668 | if (bq->init_data.resistor_sense <= 0) | ||
669 | return -ENOSYS; | ||
670 | |||
671 | val = (mA * bq->init_data.resistor_sense - 3400) / 3400; | ||
672 | if (val < 0) | ||
673 | val = 0; | ||
674 | else if (val > 7) | ||
675 | val = 7; | ||
676 | |||
677 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_CURRENT, val, | ||
678 | BQ2415X_MASK_VI_TERM | BQ2415X_MASK_RESET, | ||
679 | BQ2415X_SHIFT_VI_TERM); | ||
680 | } | ||
681 | |||
682 | /* get termination current in mA (platform data must provide resistor sense) */ | ||
683 | static int bq2415x_get_termination_current(struct bq2415x_device *bq) | ||
684 | { | ||
685 | int ret; | ||
686 | |||
687 | if (bq->init_data.resistor_sense <= 0) | ||
688 | return -ENOSYS; | ||
689 | |||
690 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, | ||
691 | BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM); | ||
692 | if (ret < 0) | ||
693 | return ret; | ||
694 | return (3400 + 3400*ret) / bq->init_data.resistor_sense; | ||
695 | } | ||
696 | |||
697 | /* set default value of property */ | ||
698 | #define bq2415x_set_default_value(bq, prop) \ | ||
699 | do { \ | ||
700 | int ret = 0; \ | ||
701 | if (bq->init_data.prop != -1) \ | ||
702 | ret = bq2415x_set_##prop(bq, bq->init_data.prop); \ | ||
703 | if (ret < 0) \ | ||
704 | return ret; \ | ||
705 | } while (0) | ||
706 | |||
707 | /* set default values of all properties */ | ||
708 | static int bq2415x_set_defaults(struct bq2415x_device *bq) | ||
709 | { | ||
710 | bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE); | ||
711 | bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE); | ||
712 | bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_DISABLE); | ||
713 | |||
714 | bq2415x_set_default_value(bq, current_limit); | ||
715 | bq2415x_set_default_value(bq, weak_battery_voltage); | ||
716 | bq2415x_set_default_value(bq, battery_regulation_voltage); | ||
717 | |||
718 | if (bq->init_data.resistor_sense > 0) { | ||
719 | bq2415x_set_default_value(bq, charge_current); | ||
720 | bq2415x_set_default_value(bq, termination_current); | ||
721 | bq2415x_exec_command(bq, BQ2415X_CHARGE_TERMINATION_ENABLE); | ||
722 | } | ||
723 | |||
724 | bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE); | ||
725 | return 0; | ||
726 | } | ||
727 | |||
728 | /**** charger mode functions ****/ | ||
729 | |||
730 | /* set charger mode */ | ||
731 | static int bq2415x_set_mode(struct bq2415x_device *bq, enum bq2415x_mode mode) | ||
732 | { | ||
733 | int ret = 0; | ||
734 | int charger = 0; | ||
735 | int boost = 0; | ||
736 | |||
737 | if (mode == BQ2415X_MODE_HOST_CHARGER || | ||
738 | mode == BQ2415X_MODE_DEDICATED_CHARGER) | ||
739 | charger = 1; | ||
740 | |||
741 | if (mode == BQ2415X_MODE_BOOST) | ||
742 | boost = 1; | ||
743 | |||
744 | if (!charger) | ||
745 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_DISABLE); | ||
746 | |||
747 | if (!boost) | ||
748 | ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_DISABLE); | ||
749 | |||
750 | if (ret < 0) | ||
751 | return ret; | ||
752 | |||
753 | switch (mode) { | ||
754 | case BQ2415X_MODE_NONE: | ||
755 | dev_dbg(bq->dev, "changing mode to: N/A\n"); | ||
756 | ret = bq2415x_set_current_limit(bq, 100); | ||
757 | break; | ||
758 | case BQ2415X_MODE_HOST_CHARGER: | ||
759 | dev_dbg(bq->dev, "changing mode to: Host/HUB charger\n"); | ||
760 | ret = bq2415x_set_current_limit(bq, 500); | ||
761 | break; | ||
762 | case BQ2415X_MODE_DEDICATED_CHARGER: | ||
763 | dev_dbg(bq->dev, "changing mode to: Dedicated charger\n"); | ||
764 | ret = bq2415x_set_current_limit(bq, 1800); | ||
765 | break; | ||
766 | case BQ2415X_MODE_BOOST: /* Boost mode */ | ||
767 | dev_dbg(bq->dev, "changing mode to: Boost\n"); | ||
768 | ret = bq2415x_set_current_limit(bq, 100); | ||
769 | break; | ||
770 | } | ||
771 | |||
772 | if (ret < 0) | ||
773 | return ret; | ||
774 | |||
775 | if (charger) | ||
776 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGER_ENABLE); | ||
777 | else if (boost) | ||
778 | ret = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_ENABLE); | ||
779 | |||
780 | if (ret < 0) | ||
781 | return ret; | ||
782 | |||
783 | bq2415x_set_default_value(bq, weak_battery_voltage); | ||
784 | bq2415x_set_default_value(bq, battery_regulation_voltage); | ||
785 | |||
786 | bq->mode = mode; | ||
787 | sysfs_notify(&bq->charger.dev->kobj, NULL, "mode"); | ||
788 | |||
789 | return 0; | ||
790 | |||
791 | } | ||
792 | |||
793 | /* hook function called by other driver which set reported mode */ | ||
794 | static void bq2415x_hook_function(enum bq2415x_mode mode, void *data) | ||
795 | { | ||
796 | struct bq2415x_device *bq = data; | ||
797 | |||
798 | if (!bq) | ||
799 | return; | ||
800 | |||
801 | dev_dbg(bq->dev, "hook function was called\n"); | ||
802 | bq->reported_mode = mode; | ||
803 | |||
804 | /* if automode is not enabled do not tell about reported_mode */ | ||
805 | if (bq->automode < 1) | ||
806 | return; | ||
807 | |||
808 | sysfs_notify(&bq->charger.dev->kobj, NULL, "reported_mode"); | ||
809 | bq2415x_set_mode(bq, bq->reported_mode); | ||
810 | |||
811 | } | ||
812 | |||
813 | /**** timer functions ****/ | ||
814 | |||
815 | /* enable/disable auto resetting chip timer */ | ||
816 | static void bq2415x_set_autotimer(struct bq2415x_device *bq, int state) | ||
817 | { | ||
818 | mutex_lock(&bq2415x_timer_mutex); | ||
819 | |||
820 | if (bq->autotimer == state) { | ||
821 | mutex_unlock(&bq2415x_timer_mutex); | ||
822 | return; | ||
823 | } | ||
824 | |||
825 | bq->autotimer = state; | ||
826 | |||
827 | if (state) { | ||
828 | schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ); | ||
829 | bq2415x_exec_command(bq, BQ2415X_TIMER_RESET); | ||
830 | bq->timer_error = NULL; | ||
831 | } else { | ||
832 | cancel_delayed_work_sync(&bq->work); | ||
833 | } | ||
834 | |||
835 | mutex_unlock(&bq2415x_timer_mutex); | ||
836 | } | ||
837 | |||
838 | /* called by bq2415x_timer_work on timer error */ | ||
839 | static void bq2415x_timer_error(struct bq2415x_device *bq, const char *msg) | ||
840 | { | ||
841 | bq->timer_error = msg; | ||
842 | sysfs_notify(&bq->charger.dev->kobj, NULL, "timer"); | ||
843 | dev_err(bq->dev, "%s\n", msg); | ||
844 | if (bq->automode > 0) | ||
845 | bq->automode = 0; | ||
846 | bq2415x_set_mode(bq, BQ2415X_MODE_NONE); | ||
847 | bq2415x_set_autotimer(bq, 0); | ||
848 | } | ||
849 | |||
850 | /* delayed work function for auto resetting chip timer */ | ||
851 | static void bq2415x_timer_work(struct work_struct *work) | ||
852 | { | ||
853 | struct bq2415x_device *bq = container_of(work, struct bq2415x_device, | ||
854 | work.work); | ||
855 | int ret; | ||
856 | int error; | ||
857 | int boost; | ||
858 | |||
859 | if (!bq->autotimer) | ||
860 | return; | ||
861 | |||
862 | ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET); | ||
863 | if (ret < 0) { | ||
864 | bq2415x_timer_error(bq, "Resetting timer failed"); | ||
865 | return; | ||
866 | } | ||
867 | |||
868 | boost = bq2415x_exec_command(bq, BQ2415X_BOOST_MODE_STATUS); | ||
869 | if (boost < 0) { | ||
870 | bq2415x_timer_error(bq, "Unknown error"); | ||
871 | return; | ||
872 | } | ||
873 | |||
874 | error = bq2415x_exec_command(bq, BQ2415X_FAULT_STATUS); | ||
875 | if (error < 0) { | ||
876 | bq2415x_timer_error(bq, "Unknown error"); | ||
877 | return; | ||
878 | } | ||
879 | |||
880 | if (boost) { | ||
881 | switch (error) { | ||
882 | /* Non fatal errors, chip is OK */ | ||
883 | case 0: /* No error */ | ||
884 | break; | ||
885 | case 6: /* Timer expired */ | ||
886 | dev_err(bq->dev, "Timer expired\n"); | ||
887 | break; | ||
888 | case 3: /* Battery voltage too low */ | ||
889 | dev_err(bq->dev, "Battery voltage to low\n"); | ||
890 | break; | ||
891 | |||
892 | /* Fatal errors, disable and reset chip */ | ||
893 | case 1: /* Overvoltage protection (chip fried) */ | ||
894 | bq2415x_timer_error(bq, | ||
895 | "Overvoltage protection (chip fried)"); | ||
896 | return; | ||
897 | case 2: /* Overload */ | ||
898 | bq2415x_timer_error(bq, "Overload"); | ||
899 | return; | ||
900 | case 4: /* Battery overvoltage protection */ | ||
901 | bq2415x_timer_error(bq, | ||
902 | "Battery overvoltage protection"); | ||
903 | return; | ||
904 | case 5: /* Thermal shutdown (too hot) */ | ||
905 | bq2415x_timer_error(bq, | ||
906 | "Thermal shutdown (too hot)"); | ||
907 | return; | ||
908 | case 7: /* N/A */ | ||
909 | bq2415x_timer_error(bq, "Unknown error"); | ||
910 | return; | ||
911 | } | ||
912 | } else { | ||
913 | switch (error) { | ||
914 | /* Non fatal errors, chip is OK */ | ||
915 | case 0: /* No error */ | ||
916 | break; | ||
917 | case 2: /* Sleep mode */ | ||
918 | dev_err(bq->dev, "Sleep mode\n"); | ||
919 | break; | ||
920 | case 3: /* Poor input source */ | ||
921 | dev_err(bq->dev, "Poor input source\n"); | ||
922 | break; | ||
923 | case 6: /* Timer expired */ | ||
924 | dev_err(bq->dev, "Timer expired\n"); | ||
925 | break; | ||
926 | case 7: /* No battery */ | ||
927 | dev_err(bq->dev, "No battery\n"); | ||
928 | break; | ||
929 | |||
930 | /* Fatal errors, disable and reset chip */ | ||
931 | case 1: /* Overvoltage protection (chip fried) */ | ||
932 | bq2415x_timer_error(bq, | ||
933 | "Overvoltage protection (chip fried)"); | ||
934 | return; | ||
935 | case 4: /* Battery overvoltage protection */ | ||
936 | bq2415x_timer_error(bq, | ||
937 | "Battery overvoltage protection"); | ||
938 | return; | ||
939 | case 5: /* Thermal shutdown (too hot) */ | ||
940 | bq2415x_timer_error(bq, | ||
941 | "Thermal shutdown (too hot)"); | ||
942 | return; | ||
943 | } | ||
944 | } | ||
945 | |||
946 | schedule_delayed_work(&bq->work, BQ2415X_TIMER_TIMEOUT * HZ); | ||
947 | } | ||
948 | |||
949 | /**** power supply interface code ****/ | ||
950 | |||
951 | static enum power_supply_property bq2415x_power_supply_props[] = { | ||
952 | /* TODO: maybe add more power supply properties */ | ||
953 | POWER_SUPPLY_PROP_STATUS, | ||
954 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
955 | }; | ||
956 | |||
957 | static int bq2415x_power_supply_get_property(struct power_supply *psy, | ||
958 | enum power_supply_property psp, | ||
959 | union power_supply_propval *val) | ||
960 | { | ||
961 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
962 | charger); | ||
963 | int ret; | ||
964 | |||
965 | switch (psp) { | ||
966 | case POWER_SUPPLY_PROP_STATUS: | ||
967 | ret = bq2415x_exec_command(bq, BQ2415X_CHARGE_STATUS); | ||
968 | if (ret < 0) | ||
969 | return ret; | ||
970 | else if (ret == 0) /* Ready */ | ||
971 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
972 | else if (ret == 1) /* Charge in progress */ | ||
973 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
974 | else if (ret == 2) /* Charge done */ | ||
975 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
976 | else | ||
977 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
978 | break; | ||
979 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
980 | val->strval = bq->model; | ||
981 | break; | ||
982 | default: | ||
983 | return -EINVAL; | ||
984 | } | ||
985 | return 0; | ||
986 | } | ||
987 | |||
988 | static int bq2415x_power_supply_init(struct bq2415x_device *bq) | ||
989 | { | ||
990 | int ret; | ||
991 | int chip; | ||
992 | char revstr[8]; | ||
993 | |||
994 | bq->charger.name = bq->name; | ||
995 | bq->charger.type = POWER_SUPPLY_TYPE_USB; | ||
996 | bq->charger.properties = bq2415x_power_supply_props; | ||
997 | bq->charger.num_properties = ARRAY_SIZE(bq2415x_power_supply_props); | ||
998 | bq->charger.get_property = bq2415x_power_supply_get_property; | ||
999 | |||
1000 | ret = bq2415x_detect_chip(bq); | ||
1001 | if (ret < 0) | ||
1002 | chip = BQUNKNOWN; | ||
1003 | else | ||
1004 | chip = ret; | ||
1005 | |||
1006 | ret = bq2415x_detect_revision(bq); | ||
1007 | if (ret < 0) | ||
1008 | strcpy(revstr, "unknown"); | ||
1009 | else | ||
1010 | sprintf(revstr, "1.%d", ret); | ||
1011 | |||
1012 | bq->model = kasprintf(GFP_KERNEL, | ||
1013 | "chip %s, revision %s, vender code %.3d", | ||
1014 | bq2415x_chip_name[chip], revstr, | ||
1015 | bq2415x_get_vender_code(bq)); | ||
1016 | if (!bq->model) { | ||
1017 | dev_err(bq->dev, "failed to allocate model name\n"); | ||
1018 | return -ENOMEM; | ||
1019 | } | ||
1020 | |||
1021 | ret = power_supply_register(bq->dev, &bq->charger); | ||
1022 | if (ret) { | ||
1023 | kfree(bq->model); | ||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static void bq2415x_power_supply_exit(struct bq2415x_device *bq) | ||
1031 | { | ||
1032 | bq->autotimer = 0; | ||
1033 | if (bq->automode > 0) | ||
1034 | bq->automode = 0; | ||
1035 | cancel_delayed_work_sync(&bq->work); | ||
1036 | power_supply_unregister(&bq->charger); | ||
1037 | kfree(bq->model); | ||
1038 | } | ||
1039 | |||
1040 | /**** additional sysfs entries for power supply interface ****/ | ||
1041 | |||
1042 | /* show *_status entries */ | ||
1043 | static ssize_t bq2415x_sysfs_show_status(struct device *dev, | ||
1044 | struct device_attribute *attr, | ||
1045 | char *buf) | ||
1046 | { | ||
1047 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1048 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1049 | charger); | ||
1050 | enum bq2415x_command command; | ||
1051 | int ret; | ||
1052 | |||
1053 | if (strcmp(attr->attr.name, "otg_status") == 0) | ||
1054 | command = BQ2415X_OTG_STATUS; | ||
1055 | else if (strcmp(attr->attr.name, "charge_status") == 0) | ||
1056 | command = BQ2415X_CHARGE_STATUS; | ||
1057 | else if (strcmp(attr->attr.name, "boost_status") == 0) | ||
1058 | command = BQ2415X_BOOST_STATUS; | ||
1059 | else if (strcmp(attr->attr.name, "fault_status") == 0) | ||
1060 | command = BQ2415X_FAULT_STATUS; | ||
1061 | else | ||
1062 | return -EINVAL; | ||
1063 | |||
1064 | ret = bq2415x_exec_command(bq, command); | ||
1065 | if (ret < 0) | ||
1066 | return ret; | ||
1067 | return sprintf(buf, "%d\n", ret); | ||
1068 | } | ||
1069 | |||
1070 | /* | ||
1071 | * set timer entry: | ||
1072 | * auto - enable auto mode | ||
1073 | * off - disable auto mode | ||
1074 | * (other values) - reset chip timer | ||
1075 | */ | ||
1076 | static ssize_t bq2415x_sysfs_set_timer(struct device *dev, | ||
1077 | struct device_attribute *attr, | ||
1078 | const char *buf, | ||
1079 | size_t count) | ||
1080 | { | ||
1081 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1082 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1083 | charger); | ||
1084 | int ret = 0; | ||
1085 | |||
1086 | if (strncmp(buf, "auto", 4) == 0) | ||
1087 | bq2415x_set_autotimer(bq, 1); | ||
1088 | else if (strncmp(buf, "off", 3) == 0) | ||
1089 | bq2415x_set_autotimer(bq, 0); | ||
1090 | else | ||
1091 | ret = bq2415x_exec_command(bq, BQ2415X_TIMER_RESET); | ||
1092 | |||
1093 | if (ret < 0) | ||
1094 | return ret; | ||
1095 | return count; | ||
1096 | } | ||
1097 | |||
1098 | /* show timer entry (auto or off) */ | ||
1099 | static ssize_t bq2415x_sysfs_show_timer(struct device *dev, | ||
1100 | struct device_attribute *attr, | ||
1101 | char *buf) | ||
1102 | { | ||
1103 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1104 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1105 | charger); | ||
1106 | |||
1107 | if (bq->timer_error) | ||
1108 | return sprintf(buf, "%s\n", bq->timer_error); | ||
1109 | |||
1110 | if (bq->autotimer) | ||
1111 | return sprintf(buf, "auto\n"); | ||
1112 | return sprintf(buf, "off\n"); | ||
1113 | } | ||
1114 | |||
1115 | /* | ||
1116 | * set mode entry: | ||
1117 | * auto - if automode is supported, enable it and set mode to reported | ||
1118 | * none - disable charger and boost mode | ||
1119 | * host - charging mode for host/hub chargers (current limit 500mA) | ||
1120 | * dedicated - charging mode for dedicated chargers (unlimited current limit) | ||
1121 | * boost - disable charger and enable boost mode | ||
1122 | */ | ||
1123 | static ssize_t bq2415x_sysfs_set_mode(struct device *dev, | ||
1124 | struct device_attribute *attr, | ||
1125 | const char *buf, | ||
1126 | size_t count) | ||
1127 | { | ||
1128 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1129 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1130 | charger); | ||
1131 | enum bq2415x_mode mode; | ||
1132 | int ret = 0; | ||
1133 | |||
1134 | if (strncmp(buf, "auto", 4) == 0) { | ||
1135 | if (bq->automode < 0) | ||
1136 | return -ENOSYS; | ||
1137 | bq->automode = 1; | ||
1138 | mode = bq->reported_mode; | ||
1139 | } else if (strncmp(buf, "none", 4) == 0) { | ||
1140 | if (bq->automode > 0) | ||
1141 | bq->automode = 0; | ||
1142 | mode = BQ2415X_MODE_NONE; | ||
1143 | } else if (strncmp(buf, "host", 4) == 0) { | ||
1144 | if (bq->automode > 0) | ||
1145 | bq->automode = 0; | ||
1146 | mode = BQ2415X_MODE_HOST_CHARGER; | ||
1147 | } else if (strncmp(buf, "dedicated", 9) == 0) { | ||
1148 | if (bq->automode > 0) | ||
1149 | bq->automode = 0; | ||
1150 | mode = BQ2415X_MODE_DEDICATED_CHARGER; | ||
1151 | } else if (strncmp(buf, "boost", 5) == 0) { | ||
1152 | if (bq->automode > 0) | ||
1153 | bq->automode = 0; | ||
1154 | mode = BQ2415X_MODE_BOOST; | ||
1155 | } else if (strncmp(buf, "reset", 5) == 0) { | ||
1156 | bq2415x_reset_chip(bq); | ||
1157 | bq2415x_set_defaults(bq); | ||
1158 | if (bq->automode <= 0) | ||
1159 | return count; | ||
1160 | bq->automode = 1; | ||
1161 | mode = bq->reported_mode; | ||
1162 | } else { | ||
1163 | return -EINVAL; | ||
1164 | } | ||
1165 | |||
1166 | ret = bq2415x_set_mode(bq, mode); | ||
1167 | if (ret < 0) | ||
1168 | return ret; | ||
1169 | return count; | ||
1170 | } | ||
1171 | |||
1172 | /* show mode entry (auto, none, host, dedicated or boost) */ | ||
1173 | static ssize_t bq2415x_sysfs_show_mode(struct device *dev, | ||
1174 | struct device_attribute *attr, | ||
1175 | char *buf) | ||
1176 | { | ||
1177 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1178 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1179 | charger); | ||
1180 | ssize_t ret = 0; | ||
1181 | |||
1182 | if (bq->automode > 0) | ||
1183 | ret += sprintf(buf+ret, "auto ("); | ||
1184 | |||
1185 | switch (bq->mode) { | ||
1186 | case BQ2415X_MODE_NONE: | ||
1187 | ret += sprintf(buf+ret, "none"); | ||
1188 | break; | ||
1189 | case BQ2415X_MODE_HOST_CHARGER: | ||
1190 | ret += sprintf(buf+ret, "host"); | ||
1191 | break; | ||
1192 | case BQ2415X_MODE_DEDICATED_CHARGER: | ||
1193 | ret += sprintf(buf+ret, "dedicated"); | ||
1194 | break; | ||
1195 | case BQ2415X_MODE_BOOST: | ||
1196 | ret += sprintf(buf+ret, "boost"); | ||
1197 | break; | ||
1198 | } | ||
1199 | |||
1200 | if (bq->automode > 0) | ||
1201 | ret += sprintf(buf+ret, ")"); | ||
1202 | |||
1203 | ret += sprintf(buf+ret, "\n"); | ||
1204 | return ret; | ||
1205 | } | ||
1206 | |||
1207 | /* show reported_mode entry (none, host, dedicated or boost) */ | ||
1208 | static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev, | ||
1209 | struct device_attribute *attr, | ||
1210 | char *buf) | ||
1211 | { | ||
1212 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1213 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1214 | charger); | ||
1215 | |||
1216 | if (bq->automode < 0) | ||
1217 | return -EINVAL; | ||
1218 | |||
1219 | switch (bq->reported_mode) { | ||
1220 | case BQ2415X_MODE_NONE: | ||
1221 | return sprintf(buf, "none\n"); | ||
1222 | case BQ2415X_MODE_HOST_CHARGER: | ||
1223 | return sprintf(buf, "host\n"); | ||
1224 | case BQ2415X_MODE_DEDICATED_CHARGER: | ||
1225 | return sprintf(buf, "dedicated\n"); | ||
1226 | case BQ2415X_MODE_BOOST: | ||
1227 | return sprintf(buf, "boost\n"); | ||
1228 | } | ||
1229 | |||
1230 | return -EINVAL; | ||
1231 | } | ||
1232 | |||
1233 | /* directly set raw value to chip register, format: 'register value' */ | ||
1234 | static ssize_t bq2415x_sysfs_set_registers(struct device *dev, | ||
1235 | struct device_attribute *attr, | ||
1236 | const char *buf, | ||
1237 | size_t count) | ||
1238 | { | ||
1239 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1240 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1241 | charger); | ||
1242 | ssize_t ret = 0; | ||
1243 | unsigned int reg; | ||
1244 | unsigned int val; | ||
1245 | |||
1246 | if (sscanf(buf, "%x %x", ®, &val) != 2) | ||
1247 | return -EINVAL; | ||
1248 | |||
1249 | if (reg > 4 || val > 255) | ||
1250 | return -EINVAL; | ||
1251 | |||
1252 | ret = bq2415x_i2c_write(bq, reg, val); | ||
1253 | if (ret < 0) | ||
1254 | return ret; | ||
1255 | return count; | ||
1256 | } | ||
1257 | |||
1258 | /* print value of chip register, format: 'register=value' */ | ||
1259 | static ssize_t bq2415x_sysfs_print_reg(struct bq2415x_device *bq, | ||
1260 | u8 reg, | ||
1261 | char *buf) | ||
1262 | { | ||
1263 | int ret = bq2415x_i2c_read(bq, reg); | ||
1264 | |||
1265 | if (ret < 0) | ||
1266 | return sprintf(buf, "%#.2x=error %d\n", reg, ret); | ||
1267 | return sprintf(buf, "%#.2x=%#.2x\n", reg, ret); | ||
1268 | } | ||
1269 | |||
1270 | /* show all raw values of chip register, format per line: 'register=value' */ | ||
1271 | static ssize_t bq2415x_sysfs_show_registers(struct device *dev, | ||
1272 | struct device_attribute *attr, | ||
1273 | char *buf) | ||
1274 | { | ||
1275 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1276 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1277 | charger); | ||
1278 | ssize_t ret = 0; | ||
1279 | |||
1280 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_STATUS, buf+ret); | ||
1281 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CONTROL, buf+ret); | ||
1282 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VOLTAGE, buf+ret); | ||
1283 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_VENDER, buf+ret); | ||
1284 | ret += bq2415x_sysfs_print_reg(bq, BQ2415X_REG_CURRENT, buf+ret); | ||
1285 | return ret; | ||
1286 | } | ||
1287 | |||
1288 | /* set current and voltage limit entries (in mA or mV) */ | ||
1289 | static ssize_t bq2415x_sysfs_set_limit(struct device *dev, | ||
1290 | struct device_attribute *attr, | ||
1291 | const char *buf, | ||
1292 | size_t count) | ||
1293 | { | ||
1294 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1295 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1296 | charger); | ||
1297 | long val; | ||
1298 | int ret; | ||
1299 | |||
1300 | if (kstrtol(buf, 10, &val) < 0) | ||
1301 | return -EINVAL; | ||
1302 | |||
1303 | if (strcmp(attr->attr.name, "current_limit") == 0) | ||
1304 | ret = bq2415x_set_current_limit(bq, val); | ||
1305 | else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0) | ||
1306 | ret = bq2415x_set_weak_battery_voltage(bq, val); | ||
1307 | else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0) | ||
1308 | ret = bq2415x_set_battery_regulation_voltage(bq, val); | ||
1309 | else if (strcmp(attr->attr.name, "charge_current") == 0) | ||
1310 | ret = bq2415x_set_charge_current(bq, val); | ||
1311 | else if (strcmp(attr->attr.name, "termination_current") == 0) | ||
1312 | ret = bq2415x_set_termination_current(bq, val); | ||
1313 | else | ||
1314 | return -EINVAL; | ||
1315 | |||
1316 | if (ret < 0) | ||
1317 | return ret; | ||
1318 | return count; | ||
1319 | } | ||
1320 | |||
1321 | /* show current and voltage limit entries (in mA or mV) */ | ||
1322 | static ssize_t bq2415x_sysfs_show_limit(struct device *dev, | ||
1323 | struct device_attribute *attr, | ||
1324 | char *buf) | ||
1325 | { | ||
1326 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1327 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1328 | charger); | ||
1329 | int ret; | ||
1330 | |||
1331 | if (strcmp(attr->attr.name, "current_limit") == 0) | ||
1332 | ret = bq2415x_get_current_limit(bq); | ||
1333 | else if (strcmp(attr->attr.name, "weak_battery_voltage") == 0) | ||
1334 | ret = bq2415x_get_weak_battery_voltage(bq); | ||
1335 | else if (strcmp(attr->attr.name, "battery_regulation_voltage") == 0) | ||
1336 | ret = bq2415x_get_battery_regulation_voltage(bq); | ||
1337 | else if (strcmp(attr->attr.name, "charge_current") == 0) | ||
1338 | ret = bq2415x_get_charge_current(bq); | ||
1339 | else if (strcmp(attr->attr.name, "termination_current") == 0) | ||
1340 | ret = bq2415x_get_termination_current(bq); | ||
1341 | else | ||
1342 | return -EINVAL; | ||
1343 | |||
1344 | if (ret < 0) | ||
1345 | return ret; | ||
1346 | return sprintf(buf, "%d\n", ret); | ||
1347 | } | ||
1348 | |||
1349 | /* set *_enable entries */ | ||
1350 | static ssize_t bq2415x_sysfs_set_enable(struct device *dev, | ||
1351 | struct device_attribute *attr, | ||
1352 | const char *buf, | ||
1353 | size_t count) | ||
1354 | { | ||
1355 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1356 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1357 | charger); | ||
1358 | enum bq2415x_command command; | ||
1359 | long val; | ||
1360 | int ret; | ||
1361 | |||
1362 | if (kstrtol(buf, 10, &val) < 0) | ||
1363 | return -EINVAL; | ||
1364 | |||
1365 | if (strcmp(attr->attr.name, "charge_termination_enable") == 0) | ||
1366 | command = val ? BQ2415X_CHARGE_TERMINATION_ENABLE : | ||
1367 | BQ2415X_CHARGE_TERMINATION_DISABLE; | ||
1368 | else if (strcmp(attr->attr.name, "high_impedance_enable") == 0) | ||
1369 | command = val ? BQ2415X_HIGH_IMPEDANCE_ENABLE : | ||
1370 | BQ2415X_HIGH_IMPEDANCE_DISABLE; | ||
1371 | else if (strcmp(attr->attr.name, "otg_pin_enable") == 0) | ||
1372 | command = val ? BQ2415X_OTG_PIN_ENABLE : | ||
1373 | BQ2415X_OTG_PIN_DISABLE; | ||
1374 | else if (strcmp(attr->attr.name, "stat_pin_enable") == 0) | ||
1375 | command = val ? BQ2415X_STAT_PIN_ENABLE : | ||
1376 | BQ2415X_STAT_PIN_DISABLE; | ||
1377 | else | ||
1378 | return -EINVAL; | ||
1379 | |||
1380 | ret = bq2415x_exec_command(bq, command); | ||
1381 | if (ret < 0) | ||
1382 | return ret; | ||
1383 | return count; | ||
1384 | } | ||
1385 | |||
1386 | /* show *_enable entries */ | ||
1387 | static ssize_t bq2415x_sysfs_show_enable(struct device *dev, | ||
1388 | struct device_attribute *attr, | ||
1389 | char *buf) | ||
1390 | { | ||
1391 | struct power_supply *psy = dev_get_drvdata(dev); | ||
1392 | struct bq2415x_device *bq = container_of(psy, struct bq2415x_device, | ||
1393 | charger); | ||
1394 | enum bq2415x_command command; | ||
1395 | int ret; | ||
1396 | |||
1397 | if (strcmp(attr->attr.name, "charge_termination_enable") == 0) | ||
1398 | command = BQ2415X_CHARGE_TERMINATION_STATUS; | ||
1399 | else if (strcmp(attr->attr.name, "high_impedance_enable") == 0) | ||
1400 | command = BQ2415X_HIGH_IMPEDANCE_STATUS; | ||
1401 | else if (strcmp(attr->attr.name, "otg_pin_enable") == 0) | ||
1402 | command = BQ2415X_OTG_PIN_STATUS; | ||
1403 | else if (strcmp(attr->attr.name, "stat_pin_enable") == 0) | ||
1404 | command = BQ2415X_STAT_PIN_STATUS; | ||
1405 | else | ||
1406 | return -EINVAL; | ||
1407 | |||
1408 | ret = bq2415x_exec_command(bq, command); | ||
1409 | if (ret < 0) | ||
1410 | return ret; | ||
1411 | return sprintf(buf, "%d\n", ret); | ||
1412 | } | ||
1413 | |||
1414 | static DEVICE_ATTR(current_limit, S_IWUSR | S_IRUGO, | ||
1415 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1416 | static DEVICE_ATTR(weak_battery_voltage, S_IWUSR | S_IRUGO, | ||
1417 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1418 | static DEVICE_ATTR(battery_regulation_voltage, S_IWUSR | S_IRUGO, | ||
1419 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1420 | static DEVICE_ATTR(charge_current, S_IWUSR | S_IRUGO, | ||
1421 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1422 | static DEVICE_ATTR(termination_current, S_IWUSR | S_IRUGO, | ||
1423 | bq2415x_sysfs_show_limit, bq2415x_sysfs_set_limit); | ||
1424 | |||
1425 | static DEVICE_ATTR(charge_termination_enable, S_IWUSR | S_IRUGO, | ||
1426 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1427 | static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO, | ||
1428 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1429 | static DEVICE_ATTR(otg_pin_enable, S_IWUSR | S_IRUGO, | ||
1430 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1431 | static DEVICE_ATTR(stat_pin_enable, S_IWUSR | S_IRUGO, | ||
1432 | bq2415x_sysfs_show_enable, bq2415x_sysfs_set_enable); | ||
1433 | |||
1434 | static DEVICE_ATTR(reported_mode, S_IRUGO, | ||
1435 | bq2415x_sysfs_show_reported_mode, NULL); | ||
1436 | static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, | ||
1437 | bq2415x_sysfs_show_mode, bq2415x_sysfs_set_mode); | ||
1438 | static DEVICE_ATTR(timer, S_IWUSR | S_IRUGO, | ||
1439 | bq2415x_sysfs_show_timer, bq2415x_sysfs_set_timer); | ||
1440 | |||
1441 | static DEVICE_ATTR(registers, S_IWUSR | S_IRUGO, | ||
1442 | bq2415x_sysfs_show_registers, bq2415x_sysfs_set_registers); | ||
1443 | |||
1444 | static DEVICE_ATTR(otg_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1445 | static DEVICE_ATTR(charge_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1446 | static DEVICE_ATTR(boost_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1447 | static DEVICE_ATTR(fault_status, S_IRUGO, bq2415x_sysfs_show_status, NULL); | ||
1448 | |||
1449 | static struct attribute *bq2415x_sysfs_attributes[] = { | ||
1450 | /* | ||
1451 | * TODO: some (appropriate) of these attrs should be switched to | ||
1452 | * use power supply class props. | ||
1453 | */ | ||
1454 | &dev_attr_current_limit.attr, | ||
1455 | &dev_attr_weak_battery_voltage.attr, | ||
1456 | &dev_attr_battery_regulation_voltage.attr, | ||
1457 | &dev_attr_charge_current.attr, | ||
1458 | &dev_attr_termination_current.attr, | ||
1459 | |||
1460 | &dev_attr_charge_termination_enable.attr, | ||
1461 | &dev_attr_high_impedance_enable.attr, | ||
1462 | &dev_attr_otg_pin_enable.attr, | ||
1463 | &dev_attr_stat_pin_enable.attr, | ||
1464 | |||
1465 | &dev_attr_reported_mode.attr, | ||
1466 | &dev_attr_mode.attr, | ||
1467 | &dev_attr_timer.attr, | ||
1468 | |||
1469 | &dev_attr_registers.attr, | ||
1470 | |||
1471 | &dev_attr_otg_status.attr, | ||
1472 | &dev_attr_charge_status.attr, | ||
1473 | &dev_attr_boost_status.attr, | ||
1474 | &dev_attr_fault_status.attr, | ||
1475 | NULL, | ||
1476 | }; | ||
1477 | |||
1478 | static const struct attribute_group bq2415x_sysfs_attr_group = { | ||
1479 | .attrs = bq2415x_sysfs_attributes, | ||
1480 | }; | ||
1481 | |||
1482 | static int bq2415x_sysfs_init(struct bq2415x_device *bq) | ||
1483 | { | ||
1484 | return sysfs_create_group(&bq->charger.dev->kobj, | ||
1485 | &bq2415x_sysfs_attr_group); | ||
1486 | } | ||
1487 | |||
1488 | static void bq2415x_sysfs_exit(struct bq2415x_device *bq) | ||
1489 | { | ||
1490 | sysfs_remove_group(&bq->charger.dev->kobj, &bq2415x_sysfs_attr_group); | ||
1491 | } | ||
1492 | |||
1493 | /* main bq2415x probe function */ | ||
1494 | static int bq2415x_probe(struct i2c_client *client, | ||
1495 | const struct i2c_device_id *id) | ||
1496 | { | ||
1497 | int ret; | ||
1498 | int num; | ||
1499 | char *name; | ||
1500 | struct bq2415x_device *bq; | ||
1501 | |||
1502 | if (!client->dev.platform_data) { | ||
1503 | dev_err(&client->dev, "platform data not set\n"); | ||
1504 | return -ENODEV; | ||
1505 | } | ||
1506 | |||
1507 | /* Get new ID for the new device */ | ||
1508 | ret = idr_pre_get(&bq2415x_id, GFP_KERNEL); | ||
1509 | if (ret == 0) | ||
1510 | return -ENOMEM; | ||
1511 | |||
1512 | mutex_lock(&bq2415x_id_mutex); | ||
1513 | ret = idr_get_new(&bq2415x_id, client, &num); | ||
1514 | mutex_unlock(&bq2415x_id_mutex); | ||
1515 | |||
1516 | if (ret < 0) | ||
1517 | return ret; | ||
1518 | |||
1519 | name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num); | ||
1520 | if (!name) { | ||
1521 | dev_err(&client->dev, "failed to allocate device name\n"); | ||
1522 | ret = -ENOMEM; | ||
1523 | goto error_1; | ||
1524 | } | ||
1525 | |||
1526 | bq = kzalloc(sizeof(*bq), GFP_KERNEL); | ||
1527 | if (!bq) { | ||
1528 | dev_err(&client->dev, "failed to allocate device data\n"); | ||
1529 | ret = -ENOMEM; | ||
1530 | goto error_2; | ||
1531 | } | ||
1532 | |||
1533 | i2c_set_clientdata(client, bq); | ||
1534 | |||
1535 | bq->id = num; | ||
1536 | bq->dev = &client->dev; | ||
1537 | bq->chip = id->driver_data; | ||
1538 | bq->name = name; | ||
1539 | bq->mode = BQ2415X_MODE_NONE; | ||
1540 | bq->reported_mode = BQ2415X_MODE_NONE; | ||
1541 | bq->autotimer = 0; | ||
1542 | bq->automode = 0; | ||
1543 | |||
1544 | memcpy(&bq->init_data, client->dev.platform_data, | ||
1545 | sizeof(bq->init_data)); | ||
1546 | |||
1547 | bq2415x_reset_chip(bq); | ||
1548 | |||
1549 | ret = bq2415x_power_supply_init(bq); | ||
1550 | if (ret) { | ||
1551 | dev_err(bq->dev, "failed to register power supply: %d\n", ret); | ||
1552 | goto error_3; | ||
1553 | } | ||
1554 | |||
1555 | ret = bq2415x_sysfs_init(bq); | ||
1556 | if (ret) { | ||
1557 | dev_err(bq->dev, "failed to create sysfs entries: %d\n", ret); | ||
1558 | goto error_4; | ||
1559 | } | ||
1560 | |||
1561 | ret = bq2415x_set_defaults(bq); | ||
1562 | if (ret) { | ||
1563 | dev_err(bq->dev, "failed to set default values: %d\n", ret); | ||
1564 | goto error_5; | ||
1565 | } | ||
1566 | |||
1567 | if (bq->init_data.set_mode_hook) { | ||
1568 | if (bq->init_data.set_mode_hook( | ||
1569 | bq2415x_hook_function, bq)) { | ||
1570 | bq->automode = 1; | ||
1571 | bq2415x_set_mode(bq, bq->reported_mode); | ||
1572 | dev_info(bq->dev, "automode enabled\n"); | ||
1573 | } else { | ||
1574 | bq->automode = -1; | ||
1575 | dev_info(bq->dev, "automode failed\n"); | ||
1576 | } | ||
1577 | } else { | ||
1578 | bq->automode = -1; | ||
1579 | dev_info(bq->dev, "automode not supported\n"); | ||
1580 | } | ||
1581 | |||
1582 | INIT_DELAYED_WORK(&bq->work, bq2415x_timer_work); | ||
1583 | bq2415x_set_autotimer(bq, 1); | ||
1584 | |||
1585 | dev_info(bq->dev, "driver registered\n"); | ||
1586 | return 0; | ||
1587 | |||
1588 | error_5: | ||
1589 | bq2415x_sysfs_exit(bq); | ||
1590 | error_4: | ||
1591 | bq2415x_power_supply_exit(bq); | ||
1592 | error_3: | ||
1593 | kfree(bq); | ||
1594 | error_2: | ||
1595 | kfree(name); | ||
1596 | error_1: | ||
1597 | mutex_lock(&bq2415x_id_mutex); | ||
1598 | idr_remove(&bq2415x_id, num); | ||
1599 | mutex_unlock(&bq2415x_id_mutex); | ||
1600 | |||
1601 | return ret; | ||
1602 | } | ||
1603 | |||
1604 | /* main bq2415x remove function */ | ||
1605 | |||
1606 | static int bq2415x_remove(struct i2c_client *client) | ||
1607 | { | ||
1608 | struct bq2415x_device *bq = i2c_get_clientdata(client); | ||
1609 | |||
1610 | if (bq->init_data.set_mode_hook) | ||
1611 | bq->init_data.set_mode_hook(NULL, NULL); | ||
1612 | |||
1613 | bq2415x_sysfs_exit(bq); | ||
1614 | bq2415x_power_supply_exit(bq); | ||
1615 | |||
1616 | bq2415x_reset_chip(bq); | ||
1617 | |||
1618 | mutex_lock(&bq2415x_id_mutex); | ||
1619 | idr_remove(&bq2415x_id, bq->id); | ||
1620 | mutex_unlock(&bq2415x_id_mutex); | ||
1621 | |||
1622 | dev_info(bq->dev, "driver unregistered\n"); | ||
1623 | |||
1624 | kfree(bq->name); | ||
1625 | kfree(bq); | ||
1626 | |||
1627 | return 0; | ||
1628 | } | ||
1629 | |||
1630 | static const struct i2c_device_id bq2415x_i2c_id_table[] = { | ||
1631 | { "bq2415x", BQUNKNOWN }, | ||
1632 | { "bq24150", BQ24150 }, | ||
1633 | { "bq24150a", BQ24150A }, | ||
1634 | { "bq24151", BQ24151 }, | ||
1635 | { "bq24151a", BQ24151A }, | ||
1636 | { "bq24152", BQ24152 }, | ||
1637 | { "bq24153", BQ24153 }, | ||
1638 | { "bq24153a", BQ24153A }, | ||
1639 | { "bq24155", BQ24155 }, | ||
1640 | { "bq24156", BQ24156 }, | ||
1641 | { "bq24156a", BQ24156A }, | ||
1642 | { "bq24158", BQ24158 }, | ||
1643 | {}, | ||
1644 | }; | ||
1645 | MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table); | ||
1646 | |||
1647 | static struct i2c_driver bq2415x_driver = { | ||
1648 | .driver = { | ||
1649 | .name = "bq2415x-charger", | ||
1650 | }, | ||
1651 | .probe = bq2415x_probe, | ||
1652 | .remove = bq2415x_remove, | ||
1653 | .id_table = bq2415x_i2c_id_table, | ||
1654 | }; | ||
1655 | |||
1656 | static int __init bq2415x_init(void) | ||
1657 | { | ||
1658 | return i2c_add_driver(&bq2415x_driver); | ||
1659 | } | ||
1660 | module_init(bq2415x_init); | ||
1661 | |||
1662 | static void __exit bq2415x_exit(void) | ||
1663 | { | ||
1664 | i2c_del_driver(&bq2415x_driver); | ||
1665 | } | ||
1666 | module_exit(bq2415x_exit); | ||
1667 | |||
1668 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | ||
1669 | MODULE_DESCRIPTION("bq2415x charger driver"); | ||
1670 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c index e0edaf7de54b..36b34efdafc9 100644 --- a/drivers/power/bq27x00_battery.c +++ b/drivers/power/bq27x00_battery.c | |||
@@ -230,6 +230,14 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg) | |||
230 | */ | 230 | */ |
231 | static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di) | 231 | static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di) |
232 | { | 232 | { |
233 | int flags; | ||
234 | bool is_bq27500 = di->chip == BQ27500; | ||
235 | bool is_higher = bq27xxx_is_chip_version_higher(di); | ||
236 | |||
237 | flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); | ||
238 | if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI)) | ||
239 | return -ENODATA; | ||
240 | |||
233 | return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC); | 241 | return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC); |
234 | } | 242 | } |
235 | 243 | ||
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c index 6bb6e2f5ea81..2fa9b6bf1f3f 100644 --- a/drivers/power/ds2782_battery.c +++ b/drivers/power/ds2782_battery.c | |||
@@ -80,13 +80,13 @@ static inline int ds278x_read_reg16(struct ds278x_info *info, int reg_msb, | |||
80 | { | 80 | { |
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb)); | 83 | ret = i2c_smbus_read_word_data(info->client, reg_msb); |
84 | if (ret < 0) { | 84 | if (ret < 0) { |
85 | dev_err(&info->client->dev, "register read failed\n"); | 85 | dev_err(&info->client->dev, "register read failed\n"); |
86 | return ret; | 86 | return ret; |
87 | } | 87 | } |
88 | 88 | ||
89 | *val = ret; | 89 | *val = swab16(ret); |
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
diff --git a/drivers/power/generic-adc-battery.c b/drivers/power/generic-adc-battery.c index e902b088d52c..32ce17e235c0 100644 --- a/drivers/power/generic-adc-battery.c +++ b/drivers/power/generic-adc-battery.c | |||
@@ -279,7 +279,8 @@ static int gab_probe(struct platform_device *pdev) | |||
279 | } | 279 | } |
280 | 280 | ||
281 | memcpy(psy->properties, gab_props, sizeof(gab_props)); | 281 | memcpy(psy->properties, gab_props, sizeof(gab_props)); |
282 | properties = psy->properties + sizeof(gab_props); | 282 | properties = (enum power_supply_property *) |
283 | ((char *)psy->properties + sizeof(gab_props)); | ||
283 | 284 | ||
284 | /* | 285 | /* |
285 | * getting channel from iio and copying the battery properties | 286 | * getting channel from iio and copying the battery properties |
@@ -327,7 +328,7 @@ static int gab_probe(struct platform_device *pdev) | |||
327 | ret = request_any_context_irq(irq, gab_charged, | 328 | ret = request_any_context_irq(irq, gab_charged, |
328 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 329 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
329 | "battery charged", adc_bat); | 330 | "battery charged", adc_bat); |
330 | if (ret) | 331 | if (ret < 0) |
331 | goto err_gpio; | 332 | goto err_gpio; |
332 | } | 333 | } |
333 | 334 | ||
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c index 74ac69e0687f..bf914893c6fd 100644 --- a/drivers/power/jz4740-battery.c +++ b/drivers/power/jz4740-battery.c | |||
@@ -33,7 +33,6 @@ struct jz_battery { | |||
33 | struct jz_battery_platform_data *pdata; | 33 | struct jz_battery_platform_data *pdata; |
34 | struct platform_device *pdev; | 34 | struct platform_device *pdev; |
35 | 35 | ||
36 | struct resource *mem; | ||
37 | void __iomem *base; | 36 | void __iomem *base; |
38 | 37 | ||
39 | int irq; | 38 | int irq; |
@@ -244,13 +243,14 @@ static int jz_battery_probe(struct platform_device *pdev) | |||
244 | struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data; | 243 | struct jz_battery_platform_data *pdata = pdev->dev.parent->platform_data; |
245 | struct jz_battery *jz_battery; | 244 | struct jz_battery *jz_battery; |
246 | struct power_supply *battery; | 245 | struct power_supply *battery; |
246 | struct resource *mem; | ||
247 | 247 | ||
248 | if (!pdata) { | 248 | if (!pdata) { |
249 | dev_err(&pdev->dev, "No platform_data supplied\n"); | 249 | dev_err(&pdev->dev, "No platform_data supplied\n"); |
250 | return -ENXIO; | 250 | return -ENXIO; |
251 | } | 251 | } |
252 | 252 | ||
253 | jz_battery = kzalloc(sizeof(*jz_battery), GFP_KERNEL); | 253 | jz_battery = devm_kzalloc(&pdev->dev, sizeof(*jz_battery), GFP_KERNEL); |
254 | if (!jz_battery) { | 254 | if (!jz_battery) { |
255 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); | 255 | dev_err(&pdev->dev, "Failed to allocate driver structure\n"); |
256 | return -ENOMEM; | 256 | return -ENOMEM; |
@@ -260,33 +260,15 @@ static int jz_battery_probe(struct platform_device *pdev) | |||
260 | 260 | ||
261 | jz_battery->irq = platform_get_irq(pdev, 0); | 261 | jz_battery->irq = platform_get_irq(pdev, 0); |
262 | if (jz_battery->irq < 0) { | 262 | if (jz_battery->irq < 0) { |
263 | ret = jz_battery->irq; | ||
264 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); | 263 | dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); |
265 | goto err_free; | 264 | return jz_battery->irq; |
266 | } | 265 | } |
267 | 266 | ||
268 | jz_battery->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 267 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
269 | if (!jz_battery->mem) { | ||
270 | ret = -ENOENT; | ||
271 | dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); | ||
272 | goto err_free; | ||
273 | } | ||
274 | 268 | ||
275 | jz_battery->mem = request_mem_region(jz_battery->mem->start, | 269 | jz_battery->base = devm_request_and_ioremap(&pdev->dev, mem); |
276 | resource_size(jz_battery->mem), pdev->name); | 270 | if (!jz_battery->base) |
277 | if (!jz_battery->mem) { | 271 | return -EBUSY; |
278 | ret = -EBUSY; | ||
279 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
280 | goto err_free; | ||
281 | } | ||
282 | |||
283 | jz_battery->base = ioremap_nocache(jz_battery->mem->start, | ||
284 | resource_size(jz_battery->mem)); | ||
285 | if (!jz_battery->base) { | ||
286 | ret = -EBUSY; | ||
287 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | ||
288 | goto err_release_mem_region; | ||
289 | } | ||
290 | 272 | ||
291 | battery = &jz_battery->battery; | 273 | battery = &jz_battery->battery; |
292 | battery->name = pdata->info.name; | 274 | battery->name = pdata->info.name; |
@@ -309,7 +291,7 @@ static int jz_battery_probe(struct platform_device *pdev) | |||
309 | jz_battery); | 291 | jz_battery); |
310 | if (ret) { | 292 | if (ret) { |
311 | dev_err(&pdev->dev, "Failed to request irq %d\n", ret); | 293 | dev_err(&pdev->dev, "Failed to request irq %d\n", ret); |
312 | goto err_iounmap; | 294 | goto err; |
313 | } | 295 | } |
314 | disable_irq(jz_battery->irq); | 296 | disable_irq(jz_battery->irq); |
315 | 297 | ||
@@ -366,13 +348,8 @@ err_free_gpio: | |||
366 | gpio_free(jz_battery->pdata->gpio_charge); | 348 | gpio_free(jz_battery->pdata->gpio_charge); |
367 | err_free_irq: | 349 | err_free_irq: |
368 | free_irq(jz_battery->irq, jz_battery); | 350 | free_irq(jz_battery->irq, jz_battery); |
369 | err_iounmap: | 351 | err: |
370 | platform_set_drvdata(pdev, NULL); | 352 | platform_set_drvdata(pdev, NULL); |
371 | iounmap(jz_battery->base); | ||
372 | err_release_mem_region: | ||
373 | release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); | ||
374 | err_free: | ||
375 | kfree(jz_battery); | ||
376 | return ret; | 353 | return ret; |
377 | } | 354 | } |
378 | 355 | ||
@@ -392,10 +369,6 @@ static int jz_battery_remove(struct platform_device *pdev) | |||
392 | 369 | ||
393 | free_irq(jz_battery->irq, jz_battery); | 370 | free_irq(jz_battery->irq, jz_battery); |
394 | 371 | ||
395 | iounmap(jz_battery->base); | ||
396 | release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem)); | ||
397 | kfree(jz_battery); | ||
398 | |||
399 | return 0; | 372 | return 0; |
400 | } | 373 | } |
401 | 374 | ||
diff --git a/drivers/power/lp8788-charger.c b/drivers/power/lp8788-charger.c index a1c51ac117fd..22b6407c9ca9 100644 --- a/drivers/power/lp8788-charger.c +++ b/drivers/power/lp8788-charger.c | |||
@@ -235,25 +235,14 @@ static int lp8788_get_battery_present(struct lp8788_charger *pchg, | |||
235 | return 0; | 235 | return 0; |
236 | } | 236 | } |
237 | 237 | ||
238 | static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, | 238 | static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result) |
239 | unsigned int *result) | ||
240 | { | 239 | { |
241 | struct iio_channel *channel = pchg->chan[LP8788_VBATT]; | 240 | struct iio_channel *channel = pchg->chan[LP8788_VBATT]; |
242 | int scaleint; | ||
243 | int scalepart; | ||
244 | int ret; | ||
245 | 241 | ||
246 | if (!channel) | 242 | if (!channel) |
247 | return -EINVAL; | 243 | return -EINVAL; |
248 | 244 | ||
249 | ret = iio_read_channel_scale(channel, &scaleint, &scalepart); | 245 | return iio_read_channel_processed(channel, result); |
250 | if (ret != IIO_VAL_INT_PLUS_MICRO) | ||
251 | return -EINVAL; | ||
252 | |||
253 | /* unit: mV */ | ||
254 | *result = (scaleint + scalepart * 1000000) / 1000; | ||
255 | |||
256 | return 0; | ||
257 | } | 246 | } |
258 | 247 | ||
259 | static int lp8788_get_battery_voltage(struct lp8788_charger *pchg, | 248 | static int lp8788_get_battery_voltage(struct lp8788_charger *pchg, |
@@ -268,7 +257,7 @@ static int lp8788_get_battery_capacity(struct lp8788_charger *pchg, | |||
268 | struct lp8788 *lp = pchg->lp; | 257 | struct lp8788 *lp = pchg->lp; |
269 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | 258 | struct lp8788_charger_platform_data *pdata = pchg->pdata; |
270 | unsigned int max_vbatt; | 259 | unsigned int max_vbatt; |
271 | unsigned int vbatt; | 260 | int vbatt; |
272 | enum lp8788_charging_state state; | 261 | enum lp8788_charging_state state; |
273 | u8 data; | 262 | u8 data; |
274 | int ret; | 263 | int ret; |
@@ -304,19 +293,18 @@ static int lp8788_get_battery_temperature(struct lp8788_charger *pchg, | |||
304 | union power_supply_propval *val) | 293 | union power_supply_propval *val) |
305 | { | 294 | { |
306 | struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP]; | 295 | struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP]; |
307 | int scaleint; | 296 | int result; |
308 | int scalepart; | ||
309 | int ret; | 297 | int ret; |
310 | 298 | ||
311 | if (!channel) | 299 | if (!channel) |
312 | return -EINVAL; | 300 | return -EINVAL; |
313 | 301 | ||
314 | ret = iio_read_channel_scale(channel, &scaleint, &scalepart); | 302 | ret = iio_read_channel_processed(channel, &result); |
315 | if (ret != IIO_VAL_INT_PLUS_MICRO) | 303 | if (ret < 0) |
316 | return -EINVAL; | 304 | return -EINVAL; |
317 | 305 | ||
318 | /* unit: 0.1 'C */ | 306 | /* unit: 0.1 'C */ |
319 | val->intval = (scaleint + scalepart * 1000000) / 100; | 307 | val->intval = result * 10; |
320 | 308 | ||
321 | return 0; | 309 | return 0; |
322 | } | 310 | } |
@@ -592,53 +580,22 @@ static void lp8788_irq_unregister(struct platform_device *pdev, | |||
592 | } | 580 | } |
593 | } | 581 | } |
594 | 582 | ||
595 | static void lp8788_setup_adc_channel(struct lp8788_charger *pchg) | 583 | static void lp8788_setup_adc_channel(const char *consumer_name, |
584 | struct lp8788_charger *pchg) | ||
596 | { | 585 | { |
597 | struct lp8788_charger_platform_data *pdata = pchg->pdata; | 586 | struct lp8788_charger_platform_data *pdata = pchg->pdata; |
598 | struct device *dev = pchg->lp->dev; | ||
599 | struct iio_channel *chan; | 587 | struct iio_channel *chan; |
600 | enum lp8788_adc_id id; | ||
601 | const char *chan_name[LPADC_MAX] = { | ||
602 | [LPADC_VBATT_5P5] = "vbatt-5p5", | ||
603 | [LPADC_VBATT_6P0] = "vbatt-6p0", | ||
604 | [LPADC_VBATT_5P0] = "vbatt-5p0", | ||
605 | [LPADC_ADC1] = "adc1", | ||
606 | [LPADC_ADC2] = "adc2", | ||
607 | [LPADC_ADC3] = "adc3", | ||
608 | [LPADC_ADC4] = "adc4", | ||
609 | }; | ||
610 | 588 | ||
611 | if (!pdata) | 589 | if (!pdata) |
612 | return; | 590 | return; |
613 | 591 | ||
614 | id = pdata->vbatt_adc; | 592 | /* ADC channel for battery voltage */ |
615 | switch (id) { | 593 | chan = iio_channel_get(consumer_name, pdata->adc_vbatt); |
616 | case LPADC_VBATT_5P5: | 594 | pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; |
617 | case LPADC_VBATT_6P0: | ||
618 | case LPADC_VBATT_5P0: | ||
619 | chan = iio_channel_get(NULL, chan_name[id]); | ||
620 | pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; | ||
621 | break; | ||
622 | default: | ||
623 | dev_err(dev, "invalid ADC id for VBATT: %d\n", id); | ||
624 | pchg->chan[LP8788_VBATT] = NULL; | ||
625 | break; | ||
626 | } | ||
627 | 595 | ||
628 | id = pdata->batt_temp_adc; | 596 | /* ADC channel for battery temperature */ |
629 | switch (id) { | 597 | chan = iio_channel_get(consumer_name, pdata->adc_batt_temp); |
630 | case LPADC_ADC1: | 598 | pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; |
631 | case LPADC_ADC2: | ||
632 | case LPADC_ADC3: | ||
633 | case LPADC_ADC4: | ||
634 | chan = iio_channel_get(NULL, chan_name[id]); | ||
635 | pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; | ||
636 | break; | ||
637 | default: | ||
638 | dev_err(dev, "invalid ADC id for BATT_TEMP : %d\n", id); | ||
639 | pchg->chan[LP8788_BATT_TEMP] = NULL; | ||
640 | break; | ||
641 | } | ||
642 | } | 599 | } |
643 | 600 | ||
644 | static void lp8788_release_adc_channel(struct lp8788_charger *pchg) | 601 | static void lp8788_release_adc_channel(struct lp8788_charger *pchg) |
@@ -747,7 +704,7 @@ static int lp8788_charger_probe(struct platform_device *pdev) | |||
747 | if (ret) | 704 | if (ret) |
748 | return ret; | 705 | return ret; |
749 | 706 | ||
750 | lp8788_setup_adc_channel(pchg); | 707 | lp8788_setup_adc_channel(pdev->name, pchg); |
751 | 708 | ||
752 | ret = lp8788_psy_register(pdev, pchg); | 709 | ret = lp8788_psy_register(pdev, pchg); |
753 | if (ret) | 710 | if (ret) |
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index 5ffe46916f0b..d664ef58afa7 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
@@ -572,7 +572,8 @@ static int max17042_init_chip(struct max17042_chip *chip) | |||
572 | __func__); | 572 | __func__); |
573 | return -EIO; | 573 | return -EIO; |
574 | } | 574 | } |
575 | max17042_verify_model_lock(chip); | 575 | |
576 | ret = max17042_verify_model_lock(chip); | ||
576 | if (ret) { | 577 | if (ret) { |
577 | dev_err(&chip->client->dev, "%s lock verify failed\n", | 578 | dev_err(&chip->client->dev, "%s lock verify failed\n", |
578 | __func__); | 579 | __func__); |
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c index 1a075f1f1b67..665cdc76c265 100644 --- a/drivers/power/max8925_power.c +++ b/drivers/power/max8925_power.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/of.h> | ||
15 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
16 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
@@ -426,6 +427,54 @@ static int max8925_deinit_charger(struct max8925_power_info *info) | |||
426 | return 0; | 427 | return 0; |
427 | } | 428 | } |
428 | 429 | ||
430 | #ifdef CONFIG_OF | ||
431 | static struct max8925_power_pdata * | ||
432 | max8925_power_dt_init(struct platform_device *pdev) | ||
433 | { | ||
434 | struct device_node *nproot = pdev->dev.parent->of_node; | ||
435 | struct device_node *np; | ||
436 | int batt_detect; | ||
437 | int topoff_threshold; | ||
438 | int fast_charge; | ||
439 | int no_temp_support; | ||
440 | int no_insert_detect; | ||
441 | struct max8925_power_pdata *pdata; | ||
442 | |||
443 | if (!nproot) | ||
444 | return pdev->dev.platform_data; | ||
445 | |||
446 | np = of_find_node_by_name(nproot, "charger"); | ||
447 | if (!np) { | ||
448 | dev_err(&pdev->dev, "failed to find charger node\n"); | ||
449 | return NULL; | ||
450 | } | ||
451 | |||
452 | pdata = devm_kzalloc(&pdev->dev, | ||
453 | sizeof(struct max8925_power_pdata), | ||
454 | GFP_KERNEL); | ||
455 | |||
456 | of_property_read_u32(np, "topoff-threshold", &topoff_threshold); | ||
457 | of_property_read_u32(np, "batt-detect", &batt_detect); | ||
458 | of_property_read_u32(np, "fast-charge", &fast_charge); | ||
459 | of_property_read_u32(np, "no-insert-detect", &no_insert_detect); | ||
460 | of_property_read_u32(np, "no-temp-support", &no_temp_support); | ||
461 | |||
462 | pdata->batt_detect = batt_detect; | ||
463 | pdata->fast_charge = fast_charge; | ||
464 | pdata->topoff_threshold = topoff_threshold; | ||
465 | pdata->no_insert_detect = no_insert_detect; | ||
466 | pdata->no_temp_support = no_temp_support; | ||
467 | |||
468 | return pdata; | ||
469 | } | ||
470 | #else | ||
471 | static struct max8925_power_pdata * | ||
472 | max8925_power_dt_init(struct platform_device *pdev) | ||
473 | { | ||
474 | return pdev->dev.platform_data; | ||
475 | } | ||
476 | #endif | ||
477 | |||
429 | static int max8925_power_probe(struct platform_device *pdev) | 478 | static int max8925_power_probe(struct platform_device *pdev) |
430 | { | 479 | { |
431 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | 480 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); |
@@ -433,7 +482,7 @@ static int max8925_power_probe(struct platform_device *pdev) | |||
433 | struct max8925_power_info *info; | 482 | struct max8925_power_info *info; |
434 | int ret; | 483 | int ret; |
435 | 484 | ||
436 | pdata = pdev->dev.platform_data; | 485 | pdata = max8925_power_dt_init(pdev); |
437 | if (!pdata) { | 486 | if (!pdata) { |
438 | dev_err(&pdev->dev, "platform data isn't assigned to " | 487 | dev_err(&pdev->dev, "platform data isn't assigned to " |
439 | "power supply\n"); | 488 | "power supply\n"); |
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index f77a41272e5d..8a7cfb3cc166 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c | |||
@@ -216,6 +216,86 @@ static void psy_unregister_thermal(struct power_supply *psy) | |||
216 | return; | 216 | return; |
217 | thermal_zone_device_unregister(psy->tzd); | 217 | thermal_zone_device_unregister(psy->tzd); |
218 | } | 218 | } |
219 | |||
220 | /* thermal cooling device callbacks */ | ||
221 | static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd, | ||
222 | unsigned long *state) | ||
223 | { | ||
224 | struct power_supply *psy; | ||
225 | union power_supply_propval val; | ||
226 | int ret; | ||
227 | |||
228 | psy = tcd->devdata; | ||
229 | ret = psy->get_property(psy, | ||
230 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val); | ||
231 | if (!ret) | ||
232 | *state = val.intval; | ||
233 | |||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd, | ||
238 | unsigned long *state) | ||
239 | { | ||
240 | struct power_supply *psy; | ||
241 | union power_supply_propval val; | ||
242 | int ret; | ||
243 | |||
244 | psy = tcd->devdata; | ||
245 | ret = psy->get_property(psy, | ||
246 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val); | ||
247 | if (!ret) | ||
248 | *state = val.intval; | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd, | ||
254 | unsigned long state) | ||
255 | { | ||
256 | struct power_supply *psy; | ||
257 | union power_supply_propval val; | ||
258 | int ret; | ||
259 | |||
260 | psy = tcd->devdata; | ||
261 | val.intval = state; | ||
262 | ret = psy->set_property(psy, | ||
263 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val); | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
268 | static struct thermal_cooling_device_ops psy_tcd_ops = { | ||
269 | .get_max_state = ps_get_max_charge_cntl_limit, | ||
270 | .get_cur_state = ps_get_cur_chrage_cntl_limit, | ||
271 | .set_cur_state = ps_set_cur_charge_cntl_limit, | ||
272 | }; | ||
273 | |||
274 | static int psy_register_cooler(struct power_supply *psy) | ||
275 | { | ||
276 | int i; | ||
277 | |||
278 | /* Register for cooling device if psy can control charging */ | ||
279 | for (i = 0; i < psy->num_properties; i++) { | ||
280 | if (psy->properties[i] == | ||
281 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) { | ||
282 | psy->tcd = thermal_cooling_device_register( | ||
283 | (char *)psy->name, | ||
284 | psy, &psy_tcd_ops); | ||
285 | if (IS_ERR(psy->tcd)) | ||
286 | return PTR_ERR(psy->tcd); | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void psy_unregister_cooler(struct power_supply *psy) | ||
294 | { | ||
295 | if (IS_ERR_OR_NULL(psy->tcd)) | ||
296 | return; | ||
297 | thermal_cooling_device_unregister(psy->tcd); | ||
298 | } | ||
219 | #else | 299 | #else |
220 | static int psy_register_thermal(struct power_supply *psy) | 300 | static int psy_register_thermal(struct power_supply *psy) |
221 | { | 301 | { |
@@ -225,6 +305,15 @@ static int psy_register_thermal(struct power_supply *psy) | |||
225 | static void psy_unregister_thermal(struct power_supply *psy) | 305 | static void psy_unregister_thermal(struct power_supply *psy) |
226 | { | 306 | { |
227 | } | 307 | } |
308 | |||
309 | static int psy_register_cooler(struct power_supply *psy) | ||
310 | { | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static void psy_unregister_cooler(struct power_supply *psy) | ||
315 | { | ||
316 | } | ||
228 | #endif | 317 | #endif |
229 | 318 | ||
230 | int power_supply_register(struct device *parent, struct power_supply *psy) | 319 | int power_supply_register(struct device *parent, struct power_supply *psy) |
@@ -259,6 +348,10 @@ int power_supply_register(struct device *parent, struct power_supply *psy) | |||
259 | if (rc) | 348 | if (rc) |
260 | goto register_thermal_failed; | 349 | goto register_thermal_failed; |
261 | 350 | ||
351 | rc = psy_register_cooler(psy); | ||
352 | if (rc) | ||
353 | goto register_cooler_failed; | ||
354 | |||
262 | rc = power_supply_create_triggers(psy); | 355 | rc = power_supply_create_triggers(psy); |
263 | if (rc) | 356 | if (rc) |
264 | goto create_triggers_failed; | 357 | goto create_triggers_failed; |
@@ -268,6 +361,8 @@ int power_supply_register(struct device *parent, struct power_supply *psy) | |||
268 | goto success; | 361 | goto success; |
269 | 362 | ||
270 | create_triggers_failed: | 363 | create_triggers_failed: |
364 | psy_unregister_cooler(psy); | ||
365 | register_cooler_failed: | ||
271 | psy_unregister_thermal(psy); | 366 | psy_unregister_thermal(psy); |
272 | register_thermal_failed: | 367 | register_thermal_failed: |
273 | device_del(dev); | 368 | device_del(dev); |
@@ -284,6 +379,7 @@ void power_supply_unregister(struct power_supply *psy) | |||
284 | cancel_work_sync(&psy->changed_work); | 379 | cancel_work_sync(&psy->changed_work); |
285 | sysfs_remove_link(&psy->dev->kobj, "powers"); | 380 | sysfs_remove_link(&psy->dev->kobj, "powers"); |
286 | power_supply_remove_triggers(psy); | 381 | power_supply_remove_triggers(psy); |
382 | psy_unregister_cooler(psy); | ||
287 | psy_unregister_thermal(psy); | 383 | psy_unregister_thermal(psy); |
288 | device_unregister(psy->dev); | 384 | device_unregister(psy->dev); |
289 | } | 385 | } |
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 395c2cfa16c0..40fa3b7cae54 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -164,6 +164,8 @@ static struct device_attribute power_supply_attrs[] = { | |||
164 | POWER_SUPPLY_ATTR(constant_charge_current_max), | 164 | POWER_SUPPLY_ATTR(constant_charge_current_max), |
165 | POWER_SUPPLY_ATTR(constant_charge_voltage), | 165 | POWER_SUPPLY_ATTR(constant_charge_voltage), |
166 | POWER_SUPPLY_ATTR(constant_charge_voltage_max), | 166 | POWER_SUPPLY_ATTR(constant_charge_voltage_max), |
167 | POWER_SUPPLY_ATTR(charge_control_limit), | ||
168 | POWER_SUPPLY_ATTR(charge_control_limit_max), | ||
167 | POWER_SUPPLY_ATTR(energy_full_design), | 169 | POWER_SUPPLY_ATTR(energy_full_design), |
168 | POWER_SUPPLY_ATTR(energy_empty_design), | 170 | POWER_SUPPLY_ATTR(energy_empty_design), |
169 | POWER_SUPPLY_ATTR(energy_full), | 171 | POWER_SUPPLY_ATTR(energy_full), |
diff --git a/drivers/power/rx51_battery.c b/drivers/power/rx51_battery.c new file mode 100644 index 000000000000..ca49d6c0ee9d --- /dev/null +++ b/drivers/power/rx51_battery.c | |||
@@ -0,0 +1,251 @@ | |||
1 | /* | ||
2 | * Nokia RX-51 battery driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/param.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/power_supply.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/i2c/twl4030-madc.h> | ||
27 | |||
28 | struct rx51_device_info { | ||
29 | struct device *dev; | ||
30 | struct power_supply bat; | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * Read ADCIN channel value, code copied from maemo kernel | ||
35 | */ | ||
36 | static int rx51_battery_read_adc(int channel) | ||
37 | { | ||
38 | struct twl4030_madc_request req; | ||
39 | |||
40 | req.channels = 1 << channel; | ||
41 | req.do_avg = 1; | ||
42 | req.method = TWL4030_MADC_SW1; | ||
43 | req.func_cb = NULL; | ||
44 | req.type = TWL4030_MADC_WAIT; | ||
45 | |||
46 | if (twl4030_madc_conversion(&req) <= 0) | ||
47 | return -ENODATA; | ||
48 | |||
49 | return req.rbuf[channel]; | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Read ADCIN channel 12 (voltage) and convert RAW value to micro voltage | ||
54 | * This conversion formula was extracted from maemo program bsi-read | ||
55 | */ | ||
56 | static int rx51_battery_read_voltage(struct rx51_device_info *di) | ||
57 | { | ||
58 | int voltage = rx51_battery_read_adc(12); | ||
59 | |||
60 | if (voltage < 0) | ||
61 | return voltage; | ||
62 | |||
63 | return 1000 * (10000 * voltage / 1705); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Temperature look-up tables | ||
68 | * TEMP = (1/(t1 + 1/298) - 273.15) | ||
69 | * Where t1 = (1/B) * ln((RAW_ADC_U * 2.5)/(R * I * 255)) | ||
70 | * Formula is based on experimental data, RX-51 CAL data, maemo program bme | ||
71 | * and formula from da9052 driver with values R = 100, B = 3380, I = 0.00671 | ||
72 | */ | ||
73 | |||
74 | /* | ||
75 | * Table1 (temperature for first 25 RAW values) | ||
76 | * Usage: TEMP = rx51_temp_table1[RAW] | ||
77 | * RAW is between 1 and 24 | ||
78 | * TEMP is between 201 C and 55 C | ||
79 | */ | ||
80 | static u8 rx51_temp_table1[] = { | ||
81 | 255, 201, 159, 138, 124, 114, 106, 99, 94, 89, 85, 82, 78, 75, | ||
82 | 73, 70, 68, 66, 64, 62, 61, 59, 57, 56, 55 | ||
83 | }; | ||
84 | |||
85 | /* | ||
86 | * Table2 (lowest RAW value for temperature) | ||
87 | * Usage: RAW = rx51_temp_table2[TEMP-rx51_temp_table2_first] | ||
88 | * TEMP is between 53 C and -32 C | ||
89 | * RAW is between 25 and 993 | ||
90 | */ | ||
91 | #define rx51_temp_table2_first 53 | ||
92 | static u16 rx51_temp_table2[] = { | ||
93 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, | ||
94 | 40, 41, 43, 44, 46, 48, 49, 51, 53, 55, 57, 59, 61, 64, | ||
95 | 66, 69, 71, 74, 77, 80, 83, 86, 90, 94, 97, 101, 106, 110, | ||
96 | 115, 119, 125, 130, 136, 141, 148, 154, 161, 168, 176, 184, 202, 211, | ||
97 | 221, 231, 242, 254, 266, 279, 293, 308, 323, 340, 357, 375, 395, 415, | ||
98 | 437, 460, 485, 511, 539, 568, 600, 633, 669, 706, 747, 790, 836, 885, | ||
99 | 937, 993, 1024 | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * Read ADCIN channel 0 (battery temp) and convert value to tenths of Celsius | ||
104 | * Use Temperature look-up tables for conversation | ||
105 | */ | ||
106 | static int rx51_battery_read_temperature(struct rx51_device_info *di) | ||
107 | { | ||
108 | int min = 0; | ||
109 | int max = ARRAY_SIZE(rx51_temp_table2) - 1; | ||
110 | int raw = rx51_battery_read_adc(0); | ||
111 | |||
112 | /* Zero and negative values are undefined */ | ||
113 | if (raw <= 0) | ||
114 | return INT_MAX; | ||
115 | |||
116 | /* ADC channels are 10 bit, higher value are undefined */ | ||
117 | if (raw >= (1 << 10)) | ||
118 | return INT_MIN; | ||
119 | |||
120 | /* First check for temperature in first direct table */ | ||
121 | if (raw < ARRAY_SIZE(rx51_temp_table1)) | ||
122 | return rx51_temp_table1[raw] * 100; | ||
123 | |||
124 | /* Binary search RAW value in second inverse table */ | ||
125 | while (max - min > 1) { | ||
126 | int mid = (max + min) / 2; | ||
127 | if (rx51_temp_table2[mid] <= raw) | ||
128 | min = mid; | ||
129 | else if (rx51_temp_table2[mid] > raw) | ||
130 | max = mid; | ||
131 | if (rx51_temp_table2[mid] == raw) | ||
132 | break; | ||
133 | } | ||
134 | |||
135 | return (rx51_temp_table2_first - min) * 100; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Read ADCIN channel 4 (BSI) and convert RAW value to micro Ah | ||
140 | * This conversion formula was extracted from maemo program bsi-read | ||
141 | */ | ||
142 | static int rx51_battery_read_capacity(struct rx51_device_info *di) | ||
143 | { | ||
144 | int capacity = rx51_battery_read_adc(4); | ||
145 | |||
146 | if (capacity < 0) | ||
147 | return capacity; | ||
148 | |||
149 | return 1280 * (1200 * capacity)/(1024 - capacity); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * Return power_supply property | ||
154 | */ | ||
155 | static int rx51_battery_get_property(struct power_supply *psy, | ||
156 | enum power_supply_property psp, | ||
157 | union power_supply_propval *val) | ||
158 | { | ||
159 | struct rx51_device_info *di = container_of((psy), | ||
160 | struct rx51_device_info, bat); | ||
161 | |||
162 | switch (psp) { | ||
163 | case POWER_SUPPLY_PROP_TECHNOLOGY: | ||
164 | val->intval = POWER_SUPPLY_TECHNOLOGY_LION; | ||
165 | break; | ||
166 | case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: | ||
167 | val->intval = 4200000; | ||
168 | break; | ||
169 | case POWER_SUPPLY_PROP_PRESENT: | ||
170 | val->intval = rx51_battery_read_voltage(di) ? 1 : 0; | ||
171 | break; | ||
172 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | ||
173 | val->intval = rx51_battery_read_voltage(di); | ||
174 | break; | ||
175 | case POWER_SUPPLY_PROP_TEMP: | ||
176 | val->intval = rx51_battery_read_temperature(di); | ||
177 | break; | ||
178 | case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: | ||
179 | val->intval = rx51_battery_read_capacity(di); | ||
180 | break; | ||
181 | default: | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | if (val->intval == INT_MAX || val->intval == INT_MIN) | ||
186 | return -EINVAL; | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static enum power_supply_property rx51_battery_props[] = { | ||
192 | POWER_SUPPLY_PROP_TECHNOLOGY, | ||
193 | POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, | ||
194 | POWER_SUPPLY_PROP_PRESENT, | ||
195 | POWER_SUPPLY_PROP_VOLTAGE_NOW, | ||
196 | POWER_SUPPLY_PROP_TEMP, | ||
197 | POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, | ||
198 | }; | ||
199 | |||
200 | static int __devinit rx51_battery_probe(struct platform_device *pdev) | ||
201 | { | ||
202 | struct rx51_device_info *di; | ||
203 | int ret; | ||
204 | |||
205 | di = kzalloc(sizeof(*di), GFP_KERNEL); | ||
206 | if (!di) | ||
207 | return -ENOMEM; | ||
208 | |||
209 | platform_set_drvdata(pdev, di); | ||
210 | |||
211 | di->bat.name = dev_name(&pdev->dev); | ||
212 | di->bat.type = POWER_SUPPLY_TYPE_BATTERY; | ||
213 | di->bat.properties = rx51_battery_props; | ||
214 | di->bat.num_properties = ARRAY_SIZE(rx51_battery_props); | ||
215 | di->bat.get_property = rx51_battery_get_property; | ||
216 | |||
217 | ret = power_supply_register(di->dev, &di->bat); | ||
218 | if (ret) { | ||
219 | platform_set_drvdata(pdev, NULL); | ||
220 | kfree(di); | ||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int __devexit rx51_battery_remove(struct platform_device *pdev) | ||
228 | { | ||
229 | struct rx51_device_info *di = platform_get_drvdata(pdev); | ||
230 | |||
231 | power_supply_unregister(&di->bat); | ||
232 | platform_set_drvdata(pdev, NULL); | ||
233 | kfree(di); | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static struct platform_driver rx51_battery_driver = { | ||
239 | .probe = rx51_battery_probe, | ||
240 | .remove = __devexit_p(rx51_battery_remove), | ||
241 | .driver = { | ||
242 | .name = "rx51-battery", | ||
243 | .owner = THIS_MODULE, | ||
244 | }, | ||
245 | }; | ||
246 | module_platform_driver(rx51_battery_driver); | ||
247 | |||
248 | MODULE_ALIAS("platform:rx51-battery"); | ||
249 | MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); | ||
250 | MODULE_DESCRIPTION("Nokia RX-51 battery driver"); | ||
251 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index f9e70cf08199..a69d0d11b540 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c | |||
@@ -114,12 +114,12 @@ static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg) | |||
114 | 114 | ||
115 | static int twl4030_bci_read(u8 reg, u8 *val) | 115 | static int twl4030_bci_read(u8 reg, u8 *val) |
116 | { | 116 | { |
117 | return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg); | 117 | return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg); |
118 | } | 118 | } |
119 | 119 | ||
120 | static int twl4030_clear_set_boot_bci(u8 clear, u8 set) | 120 | static int twl4030_clear_set_boot_bci(u8 clear, u8 set) |
121 | { | 121 | { |
122 | return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, clear, | 122 | return twl4030_clear_set(TWL_MODULE_PM_MASTER, clear, |
123 | TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, | 123 | TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set, |
124 | TWL4030_PM_MASTER_BOOT_BCI); | 124 | TWL4030_PM_MASTER_BOOT_BCI); |
125 | } | 125 | } |
@@ -152,7 +152,7 @@ static int twl4030_bci_have_vbus(struct twl4030_bci *bci) | |||
152 | int ret; | 152 | int ret; |
153 | u8 hwsts; | 153 | u8 hwsts; |
154 | 154 | ||
155 | ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts, | 155 | ret = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &hwsts, |
156 | TWL4030_PM_MASTER_STS_HW_CONDITIONS); | 156 | TWL4030_PM_MASTER_STS_HW_CONDITIONS); |
157 | if (ret < 0) | 157 | if (ret < 0) |
158 | return 0; | 158 | return 0; |
@@ -199,7 +199,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable) | |||
199 | return ret; | 199 | return ret; |
200 | 200 | ||
201 | /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */ | 201 | /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */ |
202 | ret = twl4030_clear_set(TWL4030_MODULE_MAIN_CHARGE, 0, | 202 | ret = twl4030_clear_set(TWL_MODULE_MAIN_CHARGE, 0, |
203 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); | 203 | TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4); |
204 | } else { | 204 | } else { |
205 | ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); | 205 | ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0); |
@@ -238,7 +238,7 @@ static int twl4030_charger_enable_backup(int uvolt, int uamp) | |||
238 | if (uvolt < 2500000 || | 238 | if (uvolt < 2500000 || |
239 | uamp < 25) { | 239 | uamp < 25) { |
240 | /* disable charging of backup battery */ | 240 | /* disable charging of backup battery */ |
241 | ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, | 241 | ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER, |
242 | TWL4030_BBCHEN, 0, TWL4030_BB_CFG); | 242 | TWL4030_BBCHEN, 0, TWL4030_BB_CFG); |
243 | return ret; | 243 | return ret; |
244 | } | 244 | } |
@@ -262,7 +262,7 @@ static int twl4030_charger_enable_backup(int uvolt, int uamp) | |||
262 | else | 262 | else |
263 | flags |= TWL4030_BBISEL_25uA; | 263 | flags |= TWL4030_BBISEL_25uA; |
264 | 264 | ||
265 | ret = twl4030_clear_set(TWL4030_MODULE_PM_RECEIVER, | 265 | ret = twl4030_clear_set(TWL_MODULE_PM_RECEIVER, |
266 | TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK, | 266 | TWL4030_BBSEL_MASK | TWL4030_BBISEL_MASK, |
267 | flags, | 267 | flags, |
268 | TWL4030_BB_CFG); | 268 | TWL4030_BB_CFG); |
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h index 5d5298d56026..2138bd33021a 100644 --- a/include/linux/mfd/abx500.h +++ b/include/linux/mfd/abx500.h | |||
@@ -267,39 +267,21 @@ struct abx500_bm_data { | |||
267 | int gnd_lift_resistance; | 267 | int gnd_lift_resistance; |
268 | const struct abx500_maxim_parameters *maxi; | 268 | const struct abx500_maxim_parameters *maxi; |
269 | const struct abx500_bm_capacity_levels *cap_levels; | 269 | const struct abx500_bm_capacity_levels *cap_levels; |
270 | const struct abx500_battery_type *bat_type; | 270 | struct abx500_battery_type *bat_type; |
271 | const struct abx500_bm_charger_parameters *chg_params; | 271 | const struct abx500_bm_charger_parameters *chg_params; |
272 | const struct abx500_fg_parameters *fg_params; | 272 | const struct abx500_fg_parameters *fg_params; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | struct abx500_chargalg_platform_data { | 275 | extern struct abx500_bm_data ab8500_bm_data; |
276 | char **supplied_to; | ||
277 | size_t num_supplicants; | ||
278 | }; | ||
279 | |||
280 | struct abx500_charger_platform_data { | ||
281 | char **supplied_to; | ||
282 | size_t num_supplicants; | ||
283 | bool autopower_cfg; | ||
284 | }; | ||
285 | 276 | ||
286 | struct abx500_btemp_platform_data { | 277 | enum { |
287 | char **supplied_to; | 278 | NTC_EXTERNAL = 0, |
288 | size_t num_supplicants; | 279 | NTC_INTERNAL, |
289 | }; | 280 | }; |
290 | 281 | ||
291 | struct abx500_fg_platform_data { | 282 | int bmdevs_of_probe(struct device *dev, |
292 | char **supplied_to; | 283 | struct device_node *np, |
293 | size_t num_supplicants; | 284 | struct abx500_bm_data **battery); |
294 | }; | ||
295 | |||
296 | struct abx500_bm_plat_data { | ||
297 | struct abx500_bm_data *battery; | ||
298 | struct abx500_charger_platform_data *charger; | ||
299 | struct abx500_btemp_platform_data *btemp; | ||
300 | struct abx500_fg_platform_data *fg; | ||
301 | struct abx500_chargalg_platform_data *chargalg; | ||
302 | }; | ||
303 | 285 | ||
304 | int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | 286 | int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, |
305 | u8 value); | 287 | u8 value); |
diff --git a/include/linux/mfd/lp8788.h b/include/linux/mfd/lp8788.h index cec364bdccfa..2a32b16f79cb 100644 --- a/include/linux/mfd/lp8788.h +++ b/include/linux/mfd/lp8788.h | |||
@@ -211,16 +211,16 @@ struct lp8788_chg_param { | |||
211 | 211 | ||
212 | /* | 212 | /* |
213 | * struct lp8788_charger_platform_data | 213 | * struct lp8788_charger_platform_data |
214 | * @vbatt_adc : adc selection id for battery voltage | 214 | * @adc_vbatt : adc channel name for battery voltage |
215 | * @batt_temp_adc : adc selection id for battery temperature | 215 | * @adc_batt_temp : adc channel name for battery temperature |
216 | * @max_vbatt_mv : used for calculating battery capacity | 216 | * @max_vbatt_mv : used for calculating battery capacity |
217 | * @chg_params : initial charging parameters | 217 | * @chg_params : initial charging parameters |
218 | * @num_chg_params : numbers of charging parameters | 218 | * @num_chg_params : numbers of charging parameters |
219 | * @charger_event : the charger event can be reported to the platform side | 219 | * @charger_event : the charger event can be reported to the platform side |
220 | */ | 220 | */ |
221 | struct lp8788_charger_platform_data { | 221 | struct lp8788_charger_platform_data { |
222 | enum lp8788_adc_id vbatt_adc; | 222 | const char *adc_vbatt; |
223 | enum lp8788_adc_id batt_temp_adc; | 223 | const char *adc_batt_temp; |
224 | unsigned int max_vbatt_mv; | 224 | unsigned int max_vbatt_mv; |
225 | struct lp8788_chg_param *chg_params; | 225 | struct lp8788_chg_param *chg_params; |
226 | int num_chg_params; | 226 | int num_chg_params; |
diff --git a/include/linux/power/bq2415x_charger.h b/include/linux/power/bq2415x_charger.h new file mode 100644 index 000000000000..97a1665eaeaf --- /dev/null +++ b/include/linux/power/bq2415x_charger.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * bq2415x charger driver | ||
3 | * | ||
4 | * Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef BQ2415X_CHARGER_H | ||
22 | #define BQ2415X_CHARGER_H | ||
23 | |||
24 | /* | ||
25 | * This is platform data for bq2415x chip. It contains default board | ||
26 | * voltages and currents which can be also later configured via sysfs. If | ||
27 | * value is -1 then default chip value (specified in datasheet) will be | ||
28 | * used. | ||
29 | * | ||
30 | * Value resistor_sense is needed for for configuring charge and | ||
31 | * termination current. It it is less or equal to zero, configuring charge | ||
32 | * and termination current will not be possible. | ||
33 | * | ||
34 | * Function set_mode_hook is needed for automode (setting correct current | ||
35 | * limit when charger is connected/disconnected or setting boost mode). | ||
36 | * When is NULL, automode function is disabled. When is not NULL, it must | ||
37 | * have this prototype: | ||
38 | * | ||
39 | * int (*set_mode_hook)( | ||
40 | * void (*hook)(enum bq2415x_mode mode, void *data), | ||
41 | * void *data) | ||
42 | * | ||
43 | * hook is hook function (see below) and data is pointer to driver private | ||
44 | * data | ||
45 | * | ||
46 | * bq2415x driver will call it as: | ||
47 | * | ||
48 | * platform_data->set_mode_hook(bq2415x_hook_function, bq2415x_device); | ||
49 | * | ||
50 | * Board/platform function set_mode_hook return non zero value when hook | ||
51 | * function was successful registered. Platform code should call that hook | ||
52 | * function (which get from pointer, with data) every time when charger | ||
53 | * was connected/disconnected or require to enable boost mode. bq2415x | ||
54 | * driver then will set correct current limit, enable/disable charger or | ||
55 | * boost mode. | ||
56 | * | ||
57 | * Hook function has this prototype: | ||
58 | * | ||
59 | * void hook(enum bq2415x_mode mode, void *data); | ||
60 | * | ||
61 | * mode is bq2415x mode (charger or boost) | ||
62 | * data is pointer to driver private data (which get from | ||
63 | * set_charger_type_hook) | ||
64 | * | ||
65 | * When bq driver is being unloaded, it call function: | ||
66 | * | ||
67 | * platform_data->set_mode_hook(NULL, NULL); | ||
68 | * | ||
69 | * (hook function and driver private data are NULL) | ||
70 | * | ||
71 | * After that board/platform code must not call driver hook function! It | ||
72 | * is possible that pointer to hook function will not be valid and calling | ||
73 | * will cause undefined result. | ||
74 | */ | ||
75 | |||
76 | /* Supported modes with maximal current limit */ | ||
77 | enum bq2415x_mode { | ||
78 | BQ2415X_MODE_NONE, /* unknown or no charger (100mA) */ | ||
79 | BQ2415X_MODE_HOST_CHARGER, /* usb host/hub charger (500mA) */ | ||
80 | BQ2415X_MODE_DEDICATED_CHARGER, /* dedicated charger (unlimited) */ | ||
81 | BQ2415X_MODE_BOOST, /* boost mode (charging disabled) */ | ||
82 | }; | ||
83 | |||
84 | struct bq2415x_platform_data { | ||
85 | int current_limit; /* mA */ | ||
86 | int weak_battery_voltage; /* mV */ | ||
87 | int battery_regulation_voltage; /* mV */ | ||
88 | int charge_current; /* mA */ | ||
89 | int termination_current; /* mA */ | ||
90 | int resistor_sense; /* m ohm */ | ||
91 | int (*set_mode_hook)(void (*hook)(enum bq2415x_mode mode, void *data), | ||
92 | void *data); | ||
93 | }; | ||
94 | |||
95 | #endif | ||
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index e5ef45834c3c..1f0ab90aff00 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h | |||
@@ -114,6 +114,8 @@ enum power_supply_property { | |||
114 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, | 114 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, |
115 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | 115 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, |
116 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | 116 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, |
117 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, | ||
118 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, | ||
117 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, | 119 | POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, |
118 | POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, | 120 | POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, |
119 | POWER_SUPPLY_PROP_ENERGY_FULL, | 121 | POWER_SUPPLY_PROP_ENERGY_FULL, |
@@ -186,6 +188,7 @@ struct power_supply { | |||
186 | struct work_struct changed_work; | 188 | struct work_struct changed_work; |
187 | #ifdef CONFIG_THERMAL | 189 | #ifdef CONFIG_THERMAL |
188 | struct thermal_zone_device *tzd; | 190 | struct thermal_zone_device *tzd; |
191 | struct thermal_cooling_device *tcd; | ||
189 | #endif | 192 | #endif |
190 | 193 | ||
191 | #ifdef CONFIG_LEDS_TRIGGERS | 194 | #ifdef CONFIG_LEDS_TRIGGERS |