diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-23 19:10:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-23 19:10:27 -0400 |
commit | 36a1624d8844b6c165daf61649e6b68c02d0835f (patch) | |
tree | 70159ac0dfd7d298f2c7abc615a9f5c9f9188b71 /drivers/power | |
parent | 5262f25f0983ff6f2c21e3dadcfd0c809e5aa286 (diff) | |
parent | 43df61051ab9af985ec439ee9be9c299e7de34e8 (diff) |
Merge tag 'for-4.2' of git://git.infradead.org/battery-2.6
Pull power supply and reset updates from Sebastian Reichel:
- new charger drivers: BQ24257, BQ25890, AXP288, RT9455
- MAX17042 battery: add health & temperature support
- BQ2415x charger: add ACPI support
- misc fixes and cleanups
* tag 'for-4.2' of git://git.infradead.org/battery-2.6: (32 commits)
power_supply: Correct kerneldoc copy paste errors
wm831x_power: Fix off-by-one at free_irq()
power_supply: rt9455_charger: Fix error reported by static analysis tool
power_supply: bq24257: use flags argument of devm_gpiod_get
power_supply: bq25890: use flags argument of devm_gpiod_get
sbs-battery: add option to always register battery
power: Add devm_power_supply_get_by_phandle() helper function
power_supply: max17042: Add OF support for setting thresholds
power_supply: sysfs: Bring back write to writeable properties
power_supply: rt9455_charger: Check if CONFIG_USB_PHY is enabled
power: reset: gpio-restart: increase priority slightly
power_supply: bq25890: make chip_id int
power_supply: Add support for Richtek RT9455 battery charger
Documentation: devicetree: Add Richtek RT9455 bindings
of: Add vendor prefix for Richtek Technology Corporation
power_supply: 88pm860x_charger: Do not call free_irq() twice
power: bq24190_charger: Change first_time flag reset condition
power: axp288_charger: axp288 charger driver
power: max17042_battery: add HEALTH and TEMP_* properties support
power_supply: Add support for TI BQ25890 charger chip
...
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/88pm860x_charger.c | 1 | ||||
-rw-r--r-- | drivers/power/Kconfig | 28 | ||||
-rw-r--r-- | drivers/power/Makefile | 4 | ||||
-rw-r--r-- | drivers/power/axp288_charger.c | 941 | ||||
-rw-r--r-- | drivers/power/axp288_fuel_gauge.c | 2 | ||||
-rw-r--r-- | drivers/power/bq2415x_charger.c | 94 | ||||
-rw-r--r-- | drivers/power/bq24190_charger.c | 11 | ||||
-rw-r--r-- | drivers/power/bq24257_charger.c | 858 | ||||
-rw-r--r-- | drivers/power/bq25890_charger.c | 994 | ||||
-rw-r--r-- | drivers/power/charger-manager.c | 3 | ||||
-rw-r--r-- | drivers/power/max17042_battery.c | 199 | ||||
-rw-r--r-- | drivers/power/power_supply_core.c | 106 | ||||
-rw-r--r-- | drivers/power/power_supply_leds.c | 4 | ||||
-rw-r--r-- | drivers/power/power_supply_sysfs.c | 4 | ||||
-rw-r--r-- | drivers/power/reset/at91-reset.c | 2 | ||||
-rw-r--r-- | drivers/power/reset/gpio-poweroff.c | 25 | ||||
-rw-r--r-- | drivers/power/reset/gpio-restart.c | 2 | ||||
-rw-r--r-- | drivers/power/reset/ltc2952-poweroff.c | 7 | ||||
-rw-r--r-- | drivers/power/rt9455_charger.c | 1752 | ||||
-rw-r--r-- | drivers/power/sbs-battery.c | 21 | ||||
-rw-r--r-- | drivers/power/wm831x_power.c | 1 |
21 files changed, 4971 insertions, 88 deletions
diff --git a/drivers/power/88pm860x_charger.c b/drivers/power/88pm860x_charger.c index 0e448c68c02b..297e72dc70e6 100644 --- a/drivers/power/88pm860x_charger.c +++ b/drivers/power/88pm860x_charger.c | |||
@@ -742,7 +742,6 @@ static int pm860x_charger_remove(struct platform_device *pdev) | |||
742 | int i; | 742 | int i; |
743 | 743 | ||
744 | power_supply_unregister(info->usb); | 744 | power_supply_unregister(info->usb); |
745 | free_irq(info->irq[0], info); | ||
746 | for (i = 0; i < info->irq_nums; i++) | 745 | for (i = 0; i < info->irq_nums; i++) |
747 | free_irq(info->irq[i], info); | 746 | free_irq(info->irq[i], info); |
748 | return 0; | 747 | return 0; |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 4091fb092d06..08beeed5485d 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -204,6 +204,13 @@ config CHARGER_DA9150 | |||
204 | This driver can also be built as a module. If so, the module will be | 204 | This driver can also be built as a module. If so, the module will be |
205 | called da9150-charger. | 205 | called da9150-charger. |
206 | 206 | ||
207 | config AXP288_CHARGER | ||
208 | tristate "X-Powers AXP288 Charger" | ||
209 | depends on MFD_AXP20X && EXTCON_AXP288 | ||
210 | help | ||
211 | Say yes here to have support X-Power AXP288 power management IC (PMIC) | ||
212 | integrated charger. | ||
213 | |||
207 | config AXP288_FUEL_GAUGE | 214 | config AXP288_FUEL_GAUGE |
208 | tristate "X-Powers AXP288 Fuel Gauge" | 215 | tristate "X-Powers AXP288 Fuel Gauge" |
209 | depends on MFD_AXP20X && IIO | 216 | depends on MFD_AXP20X && IIO |
@@ -388,12 +395,26 @@ config CHARGER_BQ24190 | |||
388 | help | 395 | help |
389 | Say Y to enable support for the TI BQ24190 battery charger. | 396 | Say Y to enable support for the TI BQ24190 battery charger. |
390 | 397 | ||
398 | config CHARGER_BQ24257 | ||
399 | tristate "TI BQ24257 battery charger driver" | ||
400 | depends on I2C && GPIOLIB | ||
401 | depends on REGMAP_I2C | ||
402 | help | ||
403 | Say Y to enable support for the TI BQ24257 battery charger. | ||
404 | |||
391 | config CHARGER_BQ24735 | 405 | config CHARGER_BQ24735 |
392 | tristate "TI BQ24735 battery charger support" | 406 | tristate "TI BQ24735 battery charger support" |
393 | depends on I2C && GPIOLIB | 407 | depends on I2C && GPIOLIB |
394 | help | 408 | help |
395 | Say Y to enable support for the TI BQ24735 battery charger. | 409 | Say Y to enable support for the TI BQ24735 battery charger. |
396 | 410 | ||
411 | config CHARGER_BQ25890 | ||
412 | tristate "TI BQ25890 battery charger driver" | ||
413 | depends on I2C && GPIOLIB | ||
414 | select REGMAP_I2C | ||
415 | help | ||
416 | Say Y to enable support for the TI BQ25890 battery charger. | ||
417 | |||
397 | config CHARGER_SMB347 | 418 | config CHARGER_SMB347 |
398 | tristate "Summit Microelectronics SMB347 Battery Charger" | 419 | tristate "Summit Microelectronics SMB347 Battery Charger" |
399 | depends on I2C | 420 | depends on I2C |
@@ -439,6 +460,13 @@ config BATTERY_RT5033 | |||
439 | The fuelgauge calculates and determines the battery state of charge | 460 | The fuelgauge calculates and determines the battery state of charge |
440 | according to battery open circuit voltage. | 461 | according to battery open circuit voltage. |
441 | 462 | ||
463 | config CHARGER_RT9455 | ||
464 | tristate "Richtek RT9455 battery charger driver" | ||
465 | depends on I2C && GPIOLIB | ||
466 | select REGMAP_I2C | ||
467 | help | ||
468 | Say Y to enable support for Richtek RT9455 battery charger. | ||
469 | |||
442 | source "drivers/power/reset/Kconfig" | 470 | source "drivers/power/reset/Kconfig" |
443 | 471 | ||
444 | endif # POWER_SUPPLY | 472 | endif # POWER_SUPPLY |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index b7b0181c95e5..5752ce818f51 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -37,6 +37,7 @@ obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o | |||
37 | obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o | 37 | obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o |
38 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o | 38 | obj-$(CONFIG_BATTERY_Z2) += z2_battery.o |
39 | obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o | 39 | obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o |
40 | obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o | ||
40 | obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o | 41 | obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o |
41 | obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o | 42 | obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o |
42 | obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o | 43 | obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o |
@@ -58,9 +59,12 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | |||
58 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 59 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
59 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 60 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o |
60 | obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o | 61 | obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o |
62 | obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o | ||
61 | obj-$(CONFIG_CHARGER_BQ24735) += bq24735-charger.o | 63 | obj-$(CONFIG_CHARGER_BQ24735) += bq24735-charger.o |
64 | obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o | ||
62 | obj-$(CONFIG_POWER_AVS) += avs/ | 65 | obj-$(CONFIG_POWER_AVS) += avs/ |
63 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o | 66 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o |
64 | obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o | 67 | obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o |
65 | obj-$(CONFIG_POWER_RESET) += reset/ | 68 | obj-$(CONFIG_POWER_RESET) += reset/ |
66 | obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o | 69 | obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o |
70 | obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o | ||
diff --git a/drivers/power/axp288_charger.c b/drivers/power/axp288_charger.c new file mode 100644 index 000000000000..5680317f4823 --- /dev/null +++ b/drivers/power/axp288_charger.c | |||
@@ -0,0 +1,941 @@ | |||
1 | /* | ||
2 | * axp288_charger.c - X-power AXP288 PMIC Charger driver | ||
3 | * | ||
4 | * Copyright (C) 2014 Intel Corporation | ||
5 | * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * 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 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/usb/otg.h> | ||
24 | #include <linux/notifier.h> | ||
25 | #include <linux/power_supply.h> | ||
26 | #include <linux/notifier.h> | ||
27 | #include <linux/property.h> | ||
28 | #include <linux/mfd/axp20x.h> | ||
29 | #include <linux/extcon.h> | ||
30 | |||
31 | #define PS_STAT_VBUS_TRIGGER (1 << 0) | ||
32 | #define PS_STAT_BAT_CHRG_DIR (1 << 2) | ||
33 | #define PS_STAT_VBAT_ABOVE_VHOLD (1 << 3) | ||
34 | #define PS_STAT_VBUS_VALID (1 << 4) | ||
35 | #define PS_STAT_VBUS_PRESENT (1 << 5) | ||
36 | |||
37 | #define CHRG_STAT_BAT_SAFE_MODE (1 << 3) | ||
38 | #define CHRG_STAT_BAT_VALID (1 << 4) | ||
39 | #define CHRG_STAT_BAT_PRESENT (1 << 5) | ||
40 | #define CHRG_STAT_CHARGING (1 << 6) | ||
41 | #define CHRG_STAT_PMIC_OTP (1 << 7) | ||
42 | |||
43 | #define VBUS_ISPOUT_CUR_LIM_MASK 0x03 | ||
44 | #define VBUS_ISPOUT_CUR_LIM_BIT_POS 0 | ||
45 | #define VBUS_ISPOUT_CUR_LIM_900MA 0x0 /* 900mA */ | ||
46 | #define VBUS_ISPOUT_CUR_LIM_1500MA 0x1 /* 1500mA */ | ||
47 | #define VBUS_ISPOUT_CUR_LIM_2000MA 0x2 /* 2000mA */ | ||
48 | #define VBUS_ISPOUT_CUR_NO_LIM 0x3 /* 2500mA */ | ||
49 | #define VBUS_ISPOUT_VHOLD_SET_MASK 0x31 | ||
50 | #define VBUS_ISPOUT_VHOLD_SET_BIT_POS 0x3 | ||
51 | #define VBUS_ISPOUT_VHOLD_SET_OFFSET 4000 /* 4000mV */ | ||
52 | #define VBUS_ISPOUT_VHOLD_SET_LSB_RES 100 /* 100mV */ | ||
53 | #define VBUS_ISPOUT_VHOLD_SET_4300MV 0x3 /* 4300mV */ | ||
54 | #define VBUS_ISPOUT_VBUS_PATH_DIS (1 << 7) | ||
55 | |||
56 | #define CHRG_CCCV_CC_MASK 0xf /* 4 bits */ | ||
57 | #define CHRG_CCCV_CC_BIT_POS 0 | ||
58 | #define CHRG_CCCV_CC_OFFSET 200 /* 200mA */ | ||
59 | #define CHRG_CCCV_CC_LSB_RES 200 /* 200mA */ | ||
60 | #define CHRG_CCCV_ITERM_20P (1 << 4) /* 20% of CC */ | ||
61 | #define CHRG_CCCV_CV_MASK 0x60 /* 2 bits */ | ||
62 | #define CHRG_CCCV_CV_BIT_POS 5 | ||
63 | #define CHRG_CCCV_CV_4100MV 0x0 /* 4.10V */ | ||
64 | #define CHRG_CCCV_CV_4150MV 0x1 /* 4.15V */ | ||
65 | #define CHRG_CCCV_CV_4200MV 0x2 /* 4.20V */ | ||
66 | #define CHRG_CCCV_CV_4350MV 0x3 /* 4.35V */ | ||
67 | #define CHRG_CCCV_CHG_EN (1 << 7) | ||
68 | |||
69 | #define CNTL2_CC_TIMEOUT_MASK 0x3 /* 2 bits */ | ||
70 | #define CNTL2_CC_TIMEOUT_OFFSET 6 /* 6 Hrs */ | ||
71 | #define CNTL2_CC_TIMEOUT_LSB_RES 2 /* 2 Hrs */ | ||
72 | #define CNTL2_CC_TIMEOUT_12HRS 0x3 /* 12 Hrs */ | ||
73 | #define CNTL2_CHGLED_TYPEB (1 << 4) | ||
74 | #define CNTL2_CHG_OUT_TURNON (1 << 5) | ||
75 | #define CNTL2_PC_TIMEOUT_MASK 0xC0 | ||
76 | #define CNTL2_PC_TIMEOUT_OFFSET 40 /* 40 mins */ | ||
77 | #define CNTL2_PC_TIMEOUT_LSB_RES 10 /* 10 mins */ | ||
78 | #define CNTL2_PC_TIMEOUT_70MINS 0x3 | ||
79 | |||
80 | #define CHRG_ILIM_TEMP_LOOP_EN (1 << 3) | ||
81 | #define CHRG_VBUS_ILIM_MASK 0xf0 | ||
82 | #define CHRG_VBUS_ILIM_BIT_POS 4 | ||
83 | #define CHRG_VBUS_ILIM_100MA 0x0 /* 100mA */ | ||
84 | #define CHRG_VBUS_ILIM_500MA 0x1 /* 500mA */ | ||
85 | #define CHRG_VBUS_ILIM_900MA 0x2 /* 900mA */ | ||
86 | #define CHRG_VBUS_ILIM_1500MA 0x3 /* 1500mA */ | ||
87 | #define CHRG_VBUS_ILIM_2000MA 0x4 /* 2000mA */ | ||
88 | #define CHRG_VBUS_ILIM_2500MA 0x5 /* 2500mA */ | ||
89 | #define CHRG_VBUS_ILIM_3000MA 0x6 /* 3000mA */ | ||
90 | |||
91 | #define CHRG_VLTFC_0C 0xA5 /* 0 DegC */ | ||
92 | #define CHRG_VHTFC_45C 0x1F /* 45 DegC */ | ||
93 | |||
94 | #define BAT_IRQ_CFG_CHRG_DONE (1 << 2) | ||
95 | #define BAT_IRQ_CFG_CHRG_START (1 << 3) | ||
96 | #define BAT_IRQ_CFG_BAT_SAFE_EXIT (1 << 4) | ||
97 | #define BAT_IRQ_CFG_BAT_SAFE_ENTER (1 << 5) | ||
98 | #define BAT_IRQ_CFG_BAT_DISCON (1 << 6) | ||
99 | #define BAT_IRQ_CFG_BAT_CONN (1 << 7) | ||
100 | #define BAT_IRQ_CFG_BAT_MASK 0xFC | ||
101 | |||
102 | #define TEMP_IRQ_CFG_QCBTU (1 << 4) | ||
103 | #define TEMP_IRQ_CFG_CBTU (1 << 5) | ||
104 | #define TEMP_IRQ_CFG_QCBTO (1 << 6) | ||
105 | #define TEMP_IRQ_CFG_CBTO (1 << 7) | ||
106 | #define TEMP_IRQ_CFG_MASK 0xF0 | ||
107 | |||
108 | #define FG_CNTL_OCV_ADJ_EN (1 << 3) | ||
109 | |||
110 | #define CV_4100MV 4100 /* 4100mV */ | ||
111 | #define CV_4150MV 4150 /* 4150mV */ | ||
112 | #define CV_4200MV 4200 /* 4200mV */ | ||
113 | #define CV_4350MV 4350 /* 4350mV */ | ||
114 | |||
115 | #define CC_200MA 200 /* 200mA */ | ||
116 | #define CC_600MA 600 /* 600mA */ | ||
117 | #define CC_800MA 800 /* 800mA */ | ||
118 | #define CC_1000MA 1000 /* 1000mA */ | ||
119 | #define CC_1600MA 1600 /* 1600mA */ | ||
120 | #define CC_2000MA 2000 /* 2000mA */ | ||
121 | |||
122 | #define ILIM_100MA 100 /* 100mA */ | ||
123 | #define ILIM_500MA 500 /* 500mA */ | ||
124 | #define ILIM_900MA 900 /* 900mA */ | ||
125 | #define ILIM_1500MA 1500 /* 1500mA */ | ||
126 | #define ILIM_2000MA 2000 /* 2000mA */ | ||
127 | #define ILIM_2500MA 2500 /* 2500mA */ | ||
128 | #define ILIM_3000MA 3000 /* 3000mA */ | ||
129 | |||
130 | #define AXP288_EXTCON_DEV_NAME "axp288_extcon" | ||
131 | |||
132 | #define AXP288_EXTCON_SLOW_CHARGER "SLOW-CHARGER" | ||
133 | #define AXP288_EXTCON_DOWNSTREAM_CHARGER "CHARGE-DOWNSTREAM" | ||
134 | #define AXP288_EXTCON_FAST_CHARGER "FAST-CHARGER" | ||
135 | |||
136 | enum { | ||
137 | VBUS_OV_IRQ = 0, | ||
138 | CHARGE_DONE_IRQ, | ||
139 | CHARGE_CHARGING_IRQ, | ||
140 | BAT_SAFE_QUIT_IRQ, | ||
141 | BAT_SAFE_ENTER_IRQ, | ||
142 | QCBTU_IRQ, | ||
143 | CBTU_IRQ, | ||
144 | QCBTO_IRQ, | ||
145 | CBTO_IRQ, | ||
146 | CHRG_INTR_END, | ||
147 | }; | ||
148 | |||
149 | struct axp288_chrg_info { | ||
150 | struct platform_device *pdev; | ||
151 | struct axp20x_chrg_pdata *pdata; | ||
152 | struct regmap *regmap; | ||
153 | struct regmap_irq_chip_data *regmap_irqc; | ||
154 | int irq[CHRG_INTR_END]; | ||
155 | struct power_supply *psy_usb; | ||
156 | struct mutex lock; | ||
157 | |||
158 | /* OTG/Host mode */ | ||
159 | struct { | ||
160 | struct work_struct work; | ||
161 | struct extcon_specific_cable_nb cable; | ||
162 | struct notifier_block id_nb; | ||
163 | bool id_short; | ||
164 | } otg; | ||
165 | |||
166 | /* SDP/CDP/DCP USB charging cable notifications */ | ||
167 | struct { | ||
168 | struct extcon_dev *edev; | ||
169 | bool connected; | ||
170 | enum power_supply_type chg_type; | ||
171 | struct notifier_block nb; | ||
172 | struct work_struct work; | ||
173 | } cable; | ||
174 | |||
175 | int health; | ||
176 | int inlmt; | ||
177 | int cc; | ||
178 | int cv; | ||
179 | int max_cc; | ||
180 | int max_cv; | ||
181 | bool online; | ||
182 | bool present; | ||
183 | bool enable_charger; | ||
184 | bool is_charger_enabled; | ||
185 | }; | ||
186 | |||
187 | static inline int axp288_charger_set_cc(struct axp288_chrg_info *info, int cc) | ||
188 | { | ||
189 | u8 reg_val; | ||
190 | int ret; | ||
191 | |||
192 | if (cc < CHRG_CCCV_CC_OFFSET) | ||
193 | cc = CHRG_CCCV_CC_OFFSET; | ||
194 | else if (cc > info->max_cc) | ||
195 | cc = info->max_cc; | ||
196 | |||
197 | reg_val = (cc - CHRG_CCCV_CC_OFFSET) / CHRG_CCCV_CC_LSB_RES; | ||
198 | cc = (reg_val * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET; | ||
199 | reg_val = reg_val << CHRG_CCCV_CC_BIT_POS; | ||
200 | |||
201 | ret = regmap_update_bits(info->regmap, | ||
202 | AXP20X_CHRG_CTRL1, | ||
203 | CHRG_CCCV_CC_MASK, reg_val); | ||
204 | if (ret >= 0) | ||
205 | info->cc = cc; | ||
206 | |||
207 | return ret; | ||
208 | } | ||
209 | |||
210 | static inline int axp288_charger_set_cv(struct axp288_chrg_info *info, int cv) | ||
211 | { | ||
212 | u8 reg_val; | ||
213 | int ret; | ||
214 | |||
215 | if (cv <= CV_4100MV) { | ||
216 | reg_val = CHRG_CCCV_CV_4100MV; | ||
217 | cv = CV_4100MV; | ||
218 | } else if (cv <= CV_4150MV) { | ||
219 | reg_val = CHRG_CCCV_CV_4150MV; | ||
220 | cv = CV_4150MV; | ||
221 | } else if (cv <= CV_4200MV) { | ||
222 | reg_val = CHRG_CCCV_CV_4200MV; | ||
223 | cv = CV_4200MV; | ||
224 | } else { | ||
225 | reg_val = CHRG_CCCV_CV_4350MV; | ||
226 | cv = CV_4350MV; | ||
227 | } | ||
228 | |||
229 | reg_val = reg_val << CHRG_CCCV_CV_BIT_POS; | ||
230 | |||
231 | ret = regmap_update_bits(info->regmap, | ||
232 | AXP20X_CHRG_CTRL1, | ||
233 | CHRG_CCCV_CV_MASK, reg_val); | ||
234 | |||
235 | if (ret >= 0) | ||
236 | info->cv = cv; | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static inline int axp288_charger_set_vbus_inlmt(struct axp288_chrg_info *info, | ||
242 | int inlmt) | ||
243 | { | ||
244 | int ret; | ||
245 | unsigned int val; | ||
246 | u8 reg_val; | ||
247 | |||
248 | /* Read in limit register */ | ||
249 | ret = regmap_read(info->regmap, AXP20X_CHRG_BAK_CTRL, &val); | ||
250 | if (ret < 0) | ||
251 | goto set_inlmt_fail; | ||
252 | |||
253 | if (inlmt <= ILIM_100MA) { | ||
254 | reg_val = CHRG_VBUS_ILIM_100MA; | ||
255 | inlmt = ILIM_100MA; | ||
256 | } else if (inlmt <= ILIM_500MA) { | ||
257 | reg_val = CHRG_VBUS_ILIM_500MA; | ||
258 | inlmt = ILIM_500MA; | ||
259 | } else if (inlmt <= ILIM_900MA) { | ||
260 | reg_val = CHRG_VBUS_ILIM_900MA; | ||
261 | inlmt = ILIM_900MA; | ||
262 | } else if (inlmt <= ILIM_1500MA) { | ||
263 | reg_val = CHRG_VBUS_ILIM_1500MA; | ||
264 | inlmt = ILIM_1500MA; | ||
265 | } else if (inlmt <= ILIM_2000MA) { | ||
266 | reg_val = CHRG_VBUS_ILIM_2000MA; | ||
267 | inlmt = ILIM_2000MA; | ||
268 | } else if (inlmt <= ILIM_2500MA) { | ||
269 | reg_val = CHRG_VBUS_ILIM_2500MA; | ||
270 | inlmt = ILIM_2500MA; | ||
271 | } else { | ||
272 | reg_val = CHRG_VBUS_ILIM_3000MA; | ||
273 | inlmt = ILIM_3000MA; | ||
274 | } | ||
275 | |||
276 | reg_val = (val & ~CHRG_VBUS_ILIM_MASK) | ||
277 | | (reg_val << CHRG_VBUS_ILIM_BIT_POS); | ||
278 | ret = regmap_write(info->regmap, AXP20X_CHRG_BAK_CTRL, reg_val); | ||
279 | if (ret >= 0) | ||
280 | info->inlmt = inlmt; | ||
281 | else | ||
282 | dev_err(&info->pdev->dev, "charger BAK control %d\n", ret); | ||
283 | |||
284 | |||
285 | set_inlmt_fail: | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static int axp288_charger_vbus_path_select(struct axp288_chrg_info *info, | ||
290 | bool enable) | ||
291 | { | ||
292 | int ret; | ||
293 | |||
294 | if (enable) | ||
295 | ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT, | ||
296 | VBUS_ISPOUT_VBUS_PATH_DIS, 0); | ||
297 | else | ||
298 | ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT, | ||
299 | VBUS_ISPOUT_VBUS_PATH_DIS, VBUS_ISPOUT_VBUS_PATH_DIS); | ||
300 | |||
301 | if (ret < 0) | ||
302 | dev_err(&info->pdev->dev, "axp288 vbus path select %d\n", ret); | ||
303 | |||
304 | |||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | static int axp288_charger_enable_charger(struct axp288_chrg_info *info, | ||
309 | bool enable) | ||
310 | { | ||
311 | int ret; | ||
312 | |||
313 | if (enable) | ||
314 | ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1, | ||
315 | CHRG_CCCV_CHG_EN, CHRG_CCCV_CHG_EN); | ||
316 | else | ||
317 | ret = regmap_update_bits(info->regmap, AXP20X_CHRG_CTRL1, | ||
318 | CHRG_CCCV_CHG_EN, 0); | ||
319 | if (ret < 0) | ||
320 | dev_err(&info->pdev->dev, "axp288 enable charger %d\n", ret); | ||
321 | else | ||
322 | info->is_charger_enabled = enable; | ||
323 | |||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | static int axp288_charger_is_present(struct axp288_chrg_info *info) | ||
328 | { | ||
329 | int ret, present = 0; | ||
330 | unsigned int val; | ||
331 | |||
332 | ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val); | ||
333 | if (ret < 0) | ||
334 | return ret; | ||
335 | |||
336 | if (val & PS_STAT_VBUS_PRESENT) | ||
337 | present = 1; | ||
338 | return present; | ||
339 | } | ||
340 | |||
341 | static int axp288_charger_is_online(struct axp288_chrg_info *info) | ||
342 | { | ||
343 | int ret, online = 0; | ||
344 | unsigned int val; | ||
345 | |||
346 | ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | |||
350 | if (val & PS_STAT_VBUS_VALID) | ||
351 | online = 1; | ||
352 | return online; | ||
353 | } | ||
354 | |||
355 | static int axp288_get_charger_health(struct axp288_chrg_info *info) | ||
356 | { | ||
357 | int ret, pwr_stat, chrg_stat; | ||
358 | int health = POWER_SUPPLY_HEALTH_UNKNOWN; | ||
359 | unsigned int val; | ||
360 | |||
361 | ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val); | ||
362 | if ((ret < 0) || !(val & PS_STAT_VBUS_PRESENT)) | ||
363 | goto health_read_fail; | ||
364 | else | ||
365 | pwr_stat = val; | ||
366 | |||
367 | ret = regmap_read(info->regmap, AXP20X_PWR_OP_MODE, &val); | ||
368 | if (ret < 0) | ||
369 | goto health_read_fail; | ||
370 | else | ||
371 | chrg_stat = val; | ||
372 | |||
373 | if (!(pwr_stat & PS_STAT_VBUS_VALID)) | ||
374 | health = POWER_SUPPLY_HEALTH_DEAD; | ||
375 | else if (chrg_stat & CHRG_STAT_PMIC_OTP) | ||
376 | health = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
377 | else if (chrg_stat & CHRG_STAT_BAT_SAFE_MODE) | ||
378 | health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; | ||
379 | else | ||
380 | health = POWER_SUPPLY_HEALTH_GOOD; | ||
381 | |||
382 | health_read_fail: | ||
383 | return health; | ||
384 | } | ||
385 | |||
386 | static int axp288_charger_usb_set_property(struct power_supply *psy, | ||
387 | enum power_supply_property psp, | ||
388 | const union power_supply_propval *val) | ||
389 | { | ||
390 | struct axp288_chrg_info *info = power_supply_get_drvdata(psy); | ||
391 | int ret = 0; | ||
392 | int scaled_val; | ||
393 | |||
394 | mutex_lock(&info->lock); | ||
395 | |||
396 | switch (psp) { | ||
397 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
398 | scaled_val = min(val->intval, info->max_cc); | ||
399 | scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000); | ||
400 | ret = axp288_charger_set_cc(info, scaled_val); | ||
401 | if (ret < 0) | ||
402 | dev_warn(&info->pdev->dev, "set charge current failed\n"); | ||
403 | break; | ||
404 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
405 | scaled_val = min(val->intval, info->max_cv); | ||
406 | scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000); | ||
407 | ret = axp288_charger_set_cv(info, scaled_val); | ||
408 | if (ret < 0) | ||
409 | dev_warn(&info->pdev->dev, "set charge voltage failed\n"); | ||
410 | break; | ||
411 | default: | ||
412 | ret = -EINVAL; | ||
413 | } | ||
414 | |||
415 | mutex_unlock(&info->lock); | ||
416 | return ret; | ||
417 | } | ||
418 | |||
419 | static int axp288_charger_usb_get_property(struct power_supply *psy, | ||
420 | enum power_supply_property psp, | ||
421 | union power_supply_propval *val) | ||
422 | { | ||
423 | struct axp288_chrg_info *info = power_supply_get_drvdata(psy); | ||
424 | int ret = 0; | ||
425 | |||
426 | mutex_lock(&info->lock); | ||
427 | |||
428 | switch (psp) { | ||
429 | case POWER_SUPPLY_PROP_PRESENT: | ||
430 | /* Check for OTG case first */ | ||
431 | if (info->otg.id_short) { | ||
432 | val->intval = 0; | ||
433 | break; | ||
434 | } | ||
435 | ret = axp288_charger_is_present(info); | ||
436 | if (ret < 0) | ||
437 | goto psy_get_prop_fail; | ||
438 | info->present = ret; | ||
439 | val->intval = info->present; | ||
440 | break; | ||
441 | case POWER_SUPPLY_PROP_ONLINE: | ||
442 | /* Check for OTG case first */ | ||
443 | if (info->otg.id_short) { | ||
444 | val->intval = 0; | ||
445 | break; | ||
446 | } | ||
447 | ret = axp288_charger_is_online(info); | ||
448 | if (ret < 0) | ||
449 | goto psy_get_prop_fail; | ||
450 | info->online = ret; | ||
451 | val->intval = info->online; | ||
452 | break; | ||
453 | case POWER_SUPPLY_PROP_HEALTH: | ||
454 | val->intval = axp288_get_charger_health(info); | ||
455 | break; | ||
456 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
457 | val->intval = info->cc * 1000; | ||
458 | break; | ||
459 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: | ||
460 | val->intval = info->max_cc * 1000; | ||
461 | break; | ||
462 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
463 | val->intval = info->cv * 1000; | ||
464 | break; | ||
465 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: | ||
466 | val->intval = info->max_cv * 1000; | ||
467 | break; | ||
468 | case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: | ||
469 | val->intval = info->inlmt * 1000; | ||
470 | break; | ||
471 | default: | ||
472 | ret = -EINVAL; | ||
473 | goto psy_get_prop_fail; | ||
474 | } | ||
475 | |||
476 | psy_get_prop_fail: | ||
477 | mutex_unlock(&info->lock); | ||
478 | return ret; | ||
479 | } | ||
480 | |||
481 | static int axp288_charger_property_is_writeable(struct power_supply *psy, | ||
482 | enum power_supply_property psp) | ||
483 | { | ||
484 | int ret; | ||
485 | |||
486 | switch (psp) { | ||
487 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
488 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
489 | ret = 1; | ||
490 | break; | ||
491 | default: | ||
492 | ret = 0; | ||
493 | } | ||
494 | |||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | static enum power_supply_property axp288_usb_props[] = { | ||
499 | POWER_SUPPLY_PROP_PRESENT, | ||
500 | POWER_SUPPLY_PROP_ONLINE, | ||
501 | POWER_SUPPLY_PROP_TYPE, | ||
502 | POWER_SUPPLY_PROP_HEALTH, | ||
503 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
504 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, | ||
505 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | ||
506 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | ||
507 | POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, | ||
508 | }; | ||
509 | |||
510 | static const struct power_supply_desc axp288_charger_desc = { | ||
511 | .name = "axp288_charger", | ||
512 | .type = POWER_SUPPLY_TYPE_USB, | ||
513 | .properties = axp288_usb_props, | ||
514 | .num_properties = ARRAY_SIZE(axp288_usb_props), | ||
515 | .get_property = axp288_charger_usb_get_property, | ||
516 | .set_property = axp288_charger_usb_set_property, | ||
517 | .property_is_writeable = axp288_charger_property_is_writeable, | ||
518 | }; | ||
519 | |||
520 | static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev) | ||
521 | { | ||
522 | struct axp288_chrg_info *info = dev; | ||
523 | int i; | ||
524 | |||
525 | for (i = 0; i < CHRG_INTR_END; i++) { | ||
526 | if (info->irq[i] == irq) | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | if (i >= CHRG_INTR_END) { | ||
531 | dev_warn(&info->pdev->dev, "spurious interrupt!!\n"); | ||
532 | return IRQ_NONE; | ||
533 | } | ||
534 | |||
535 | switch (i) { | ||
536 | case VBUS_OV_IRQ: | ||
537 | dev_dbg(&info->pdev->dev, "VBUS Over Voltage INTR\n"); | ||
538 | break; | ||
539 | case CHARGE_DONE_IRQ: | ||
540 | dev_dbg(&info->pdev->dev, "Charging Done INTR\n"); | ||
541 | break; | ||
542 | case CHARGE_CHARGING_IRQ: | ||
543 | dev_dbg(&info->pdev->dev, "Start Charging IRQ\n"); | ||
544 | break; | ||
545 | case BAT_SAFE_QUIT_IRQ: | ||
546 | dev_dbg(&info->pdev->dev, | ||
547 | "Quit Safe Mode(restart timer) Charging IRQ\n"); | ||
548 | break; | ||
549 | case BAT_SAFE_ENTER_IRQ: | ||
550 | dev_dbg(&info->pdev->dev, | ||
551 | "Enter Safe Mode(timer expire) Charging IRQ\n"); | ||
552 | break; | ||
553 | case QCBTU_IRQ: | ||
554 | dev_dbg(&info->pdev->dev, | ||
555 | "Quit Battery Under Temperature(CHRG) INTR\n"); | ||
556 | break; | ||
557 | case CBTU_IRQ: | ||
558 | dev_dbg(&info->pdev->dev, | ||
559 | "Hit Battery Under Temperature(CHRG) INTR\n"); | ||
560 | break; | ||
561 | case QCBTO_IRQ: | ||
562 | dev_dbg(&info->pdev->dev, | ||
563 | "Quit Battery Over Temperature(CHRG) INTR\n"); | ||
564 | break; | ||
565 | case CBTO_IRQ: | ||
566 | dev_dbg(&info->pdev->dev, | ||
567 | "Hit Battery Over Temperature(CHRG) INTR\n"); | ||
568 | break; | ||
569 | default: | ||
570 | dev_warn(&info->pdev->dev, "Spurious Interrupt!!!\n"); | ||
571 | goto out; | ||
572 | } | ||
573 | |||
574 | power_supply_changed(info->psy_usb); | ||
575 | out: | ||
576 | return IRQ_HANDLED; | ||
577 | } | ||
578 | |||
579 | static void axp288_charger_extcon_evt_worker(struct work_struct *work) | ||
580 | { | ||
581 | struct axp288_chrg_info *info = | ||
582 | container_of(work, struct axp288_chrg_info, cable.work); | ||
583 | int ret, current_limit; | ||
584 | bool changed = false; | ||
585 | struct extcon_dev *edev = info->cable.edev; | ||
586 | bool old_connected = info->cable.connected; | ||
587 | |||
588 | /* Determine cable/charger type */ | ||
589 | if (extcon_get_cable_state(edev, AXP288_EXTCON_SLOW_CHARGER) > 0) { | ||
590 | dev_dbg(&info->pdev->dev, "USB SDP charger is connected"); | ||
591 | info->cable.connected = true; | ||
592 | info->cable.chg_type = POWER_SUPPLY_TYPE_USB; | ||
593 | } else if (extcon_get_cable_state(edev, | ||
594 | AXP288_EXTCON_DOWNSTREAM_CHARGER) > 0) { | ||
595 | dev_dbg(&info->pdev->dev, "USB CDP charger is connected"); | ||
596 | info->cable.connected = true; | ||
597 | info->cable.chg_type = POWER_SUPPLY_TYPE_USB_CDP; | ||
598 | } else if (extcon_get_cable_state(edev, | ||
599 | AXP288_EXTCON_FAST_CHARGER) > 0) { | ||
600 | dev_dbg(&info->pdev->dev, "USB DCP charger is connected"); | ||
601 | info->cable.connected = true; | ||
602 | info->cable.chg_type = POWER_SUPPLY_TYPE_USB_DCP; | ||
603 | } else { | ||
604 | if (old_connected) | ||
605 | dev_dbg(&info->pdev->dev, "USB charger disconnected"); | ||
606 | info->cable.connected = false; | ||
607 | info->cable.chg_type = POWER_SUPPLY_TYPE_USB; | ||
608 | } | ||
609 | |||
610 | /* Cable status changed */ | ||
611 | if (old_connected != info->cable.connected) | ||
612 | changed = true; | ||
613 | |||
614 | if (!changed) | ||
615 | return; | ||
616 | |||
617 | mutex_lock(&info->lock); | ||
618 | |||
619 | if (info->is_charger_enabled && !info->cable.connected) { | ||
620 | info->enable_charger = false; | ||
621 | ret = axp288_charger_enable_charger(info, info->enable_charger); | ||
622 | if (ret < 0) | ||
623 | dev_err(&info->pdev->dev, | ||
624 | "cannot disable charger (%d)", ret); | ||
625 | |||
626 | } else if (!info->is_charger_enabled && info->cable.connected) { | ||
627 | switch (info->cable.chg_type) { | ||
628 | case POWER_SUPPLY_TYPE_USB: | ||
629 | current_limit = ILIM_500MA; | ||
630 | break; | ||
631 | case POWER_SUPPLY_TYPE_USB_CDP: | ||
632 | current_limit = ILIM_1500MA; | ||
633 | break; | ||
634 | case POWER_SUPPLY_TYPE_USB_DCP: | ||
635 | current_limit = ILIM_2000MA; | ||
636 | break; | ||
637 | default: | ||
638 | /* Unknown */ | ||
639 | current_limit = 0; | ||
640 | break; | ||
641 | } | ||
642 | |||
643 | /* Set vbus current limit first, then enable charger */ | ||
644 | ret = axp288_charger_set_vbus_inlmt(info, current_limit); | ||
645 | if (ret < 0) { | ||
646 | dev_err(&info->pdev->dev, | ||
647 | "error setting current limit (%d)", ret); | ||
648 | } else { | ||
649 | info->enable_charger = (current_limit > 0); | ||
650 | ret = axp288_charger_enable_charger(info, | ||
651 | info->enable_charger); | ||
652 | if (ret < 0) | ||
653 | dev_err(&info->pdev->dev, | ||
654 | "cannot enable charger (%d)", ret); | ||
655 | } | ||
656 | } | ||
657 | |||
658 | if (changed) | ||
659 | info->health = axp288_get_charger_health(info); | ||
660 | |||
661 | mutex_unlock(&info->lock); | ||
662 | |||
663 | if (changed) | ||
664 | power_supply_changed(info->psy_usb); | ||
665 | } | ||
666 | |||
667 | static int axp288_charger_handle_cable_evt(struct notifier_block *nb, | ||
668 | unsigned long event, void *param) | ||
669 | { | ||
670 | struct axp288_chrg_info *info = | ||
671 | container_of(nb, struct axp288_chrg_info, cable.nb); | ||
672 | |||
673 | schedule_work(&info->cable.work); | ||
674 | |||
675 | return NOTIFY_OK; | ||
676 | } | ||
677 | |||
678 | static void axp288_charger_otg_evt_worker(struct work_struct *work) | ||
679 | { | ||
680 | struct axp288_chrg_info *info = | ||
681 | container_of(work, struct axp288_chrg_info, otg.work); | ||
682 | int ret; | ||
683 | |||
684 | /* Disable VBUS path before enabling the 5V boost */ | ||
685 | ret = axp288_charger_vbus_path_select(info, !info->otg.id_short); | ||
686 | if (ret < 0) | ||
687 | dev_warn(&info->pdev->dev, "vbus path disable failed\n"); | ||
688 | } | ||
689 | |||
690 | static int axp288_charger_handle_otg_evt(struct notifier_block *nb, | ||
691 | unsigned long event, void *param) | ||
692 | { | ||
693 | struct axp288_chrg_info *info = | ||
694 | container_of(nb, struct axp288_chrg_info, otg.id_nb); | ||
695 | struct extcon_dev *edev = param; | ||
696 | int usb_host = extcon_get_cable_state(edev, "USB-Host"); | ||
697 | |||
698 | dev_dbg(&info->pdev->dev, "external connector USB-Host is %s\n", | ||
699 | usb_host ? "attached" : "detached"); | ||
700 | |||
701 | /* | ||
702 | * Set usb_id_short flag to avoid running charger detection logic | ||
703 | * in case usb host. | ||
704 | */ | ||
705 | info->otg.id_short = usb_host; | ||
706 | schedule_work(&info->otg.work); | ||
707 | |||
708 | return NOTIFY_OK; | ||
709 | } | ||
710 | |||
711 | static void charger_init_hw_regs(struct axp288_chrg_info *info) | ||
712 | { | ||
713 | int ret, cc, cv; | ||
714 | unsigned int val; | ||
715 | |||
716 | /* Program temperature thresholds */ | ||
717 | ret = regmap_write(info->regmap, AXP20X_V_LTF_CHRG, CHRG_VLTFC_0C); | ||
718 | if (ret < 0) | ||
719 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
720 | AXP20X_V_LTF_CHRG, ret); | ||
721 | |||
722 | ret = regmap_write(info->regmap, AXP20X_V_HTF_CHRG, CHRG_VHTFC_45C); | ||
723 | if (ret < 0) | ||
724 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
725 | AXP20X_V_HTF_CHRG, ret); | ||
726 | |||
727 | /* Do not turn-off charger o/p after charge cycle ends */ | ||
728 | ret = regmap_update_bits(info->regmap, | ||
729 | AXP20X_CHRG_CTRL2, | ||
730 | CNTL2_CHG_OUT_TURNON, 1); | ||
731 | if (ret < 0) | ||
732 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
733 | AXP20X_CHRG_CTRL2, ret); | ||
734 | |||
735 | /* Enable interrupts */ | ||
736 | ret = regmap_update_bits(info->regmap, | ||
737 | AXP20X_IRQ2_EN, | ||
738 | BAT_IRQ_CFG_BAT_MASK, 1); | ||
739 | if (ret < 0) | ||
740 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
741 | AXP20X_IRQ2_EN, ret); | ||
742 | |||
743 | ret = regmap_update_bits(info->regmap, AXP20X_IRQ3_EN, | ||
744 | TEMP_IRQ_CFG_MASK, 1); | ||
745 | if (ret < 0) | ||
746 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
747 | AXP20X_IRQ3_EN, ret); | ||
748 | |||
749 | /* Setup ending condition for charging to be 10% of I(chrg) */ | ||
750 | ret = regmap_update_bits(info->regmap, | ||
751 | AXP20X_CHRG_CTRL1, | ||
752 | CHRG_CCCV_ITERM_20P, 0); | ||
753 | if (ret < 0) | ||
754 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
755 | AXP20X_CHRG_CTRL1, ret); | ||
756 | |||
757 | /* Disable OCV-SOC curve calibration */ | ||
758 | ret = regmap_update_bits(info->regmap, | ||
759 | AXP20X_CC_CTRL, | ||
760 | FG_CNTL_OCV_ADJ_EN, 0); | ||
761 | if (ret < 0) | ||
762 | dev_warn(&info->pdev->dev, "register(%x) write error(%d)\n", | ||
763 | AXP20X_CC_CTRL, ret); | ||
764 | |||
765 | /* Init charging current and voltage */ | ||
766 | info->max_cc = info->pdata->max_cc; | ||
767 | info->max_cv = info->pdata->max_cv; | ||
768 | |||
769 | /* Read current charge voltage and current limit */ | ||
770 | ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val); | ||
771 | if (ret < 0) { | ||
772 | /* Assume default if cannot read */ | ||
773 | info->cc = info->pdata->def_cc; | ||
774 | info->cv = info->pdata->def_cv; | ||
775 | } else { | ||
776 | /* Determine charge voltage */ | ||
777 | cv = (val & CHRG_CCCV_CV_MASK) >> CHRG_CCCV_CV_BIT_POS; | ||
778 | switch (cv) { | ||
779 | case CHRG_CCCV_CV_4100MV: | ||
780 | info->cv = CV_4100MV; | ||
781 | break; | ||
782 | case CHRG_CCCV_CV_4150MV: | ||
783 | info->cv = CV_4150MV; | ||
784 | break; | ||
785 | case CHRG_CCCV_CV_4200MV: | ||
786 | info->cv = CV_4200MV; | ||
787 | break; | ||
788 | case CHRG_CCCV_CV_4350MV: | ||
789 | info->cv = CV_4350MV; | ||
790 | break; | ||
791 | default: | ||
792 | info->cv = INT_MAX; | ||
793 | break; | ||
794 | } | ||
795 | |||
796 | /* Determine charge current limit */ | ||
797 | cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS; | ||
798 | cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET; | ||
799 | info->cc = cc; | ||
800 | |||
801 | /* Program default charging voltage and current */ | ||
802 | cc = min(info->pdata->def_cc, info->max_cc); | ||
803 | cv = min(info->pdata->def_cv, info->max_cv); | ||
804 | |||
805 | ret = axp288_charger_set_cc(info, cc); | ||
806 | if (ret < 0) | ||
807 | dev_warn(&info->pdev->dev, | ||
808 | "error(%d) in setting CC\n", ret); | ||
809 | |||
810 | ret = axp288_charger_set_cv(info, cv); | ||
811 | if (ret < 0) | ||
812 | dev_warn(&info->pdev->dev, | ||
813 | "error(%d) in setting CV\n", ret); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | static int axp288_charger_probe(struct platform_device *pdev) | ||
818 | { | ||
819 | int ret, i, pirq; | ||
820 | struct axp288_chrg_info *info; | ||
821 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); | ||
822 | struct power_supply_config charger_cfg = {}; | ||
823 | |||
824 | info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); | ||
825 | if (!info) | ||
826 | return -ENOMEM; | ||
827 | |||
828 | info->pdev = pdev; | ||
829 | info->regmap = axp20x->regmap; | ||
830 | info->regmap_irqc = axp20x->regmap_irqc; | ||
831 | info->pdata = pdev->dev.platform_data; | ||
832 | |||
833 | if (!info->pdata) { | ||
834 | /* Try ACPI provided pdata via device properties */ | ||
835 | if (!device_property_present(&pdev->dev, | ||
836 | "axp288_charger_data\n")) | ||
837 | dev_err(&pdev->dev, "failed to get platform data\n"); | ||
838 | return -ENODEV; | ||
839 | } | ||
840 | |||
841 | info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); | ||
842 | if (info->cable.edev == NULL) { | ||
843 | dev_dbg(&pdev->dev, "%s is not ready, probe deferred\n", | ||
844 | AXP288_EXTCON_DEV_NAME); | ||
845 | return -EPROBE_DEFER; | ||
846 | } | ||
847 | |||
848 | /* Register for extcon notification */ | ||
849 | INIT_WORK(&info->cable.work, axp288_charger_extcon_evt_worker); | ||
850 | info->cable.nb.notifier_call = axp288_charger_handle_cable_evt; | ||
851 | ret = extcon_register_notifier(info->cable.edev, &info->cable.nb); | ||
852 | if (ret) { | ||
853 | dev_err(&info->pdev->dev, | ||
854 | "failed to register extcon notifier %d\n", ret); | ||
855 | return ret; | ||
856 | } | ||
857 | |||
858 | platform_set_drvdata(pdev, info); | ||
859 | mutex_init(&info->lock); | ||
860 | |||
861 | /* Register with power supply class */ | ||
862 | charger_cfg.drv_data = info; | ||
863 | info->psy_usb = power_supply_register(&pdev->dev, &axp288_charger_desc, | ||
864 | &charger_cfg); | ||
865 | if (IS_ERR(info->psy_usb)) { | ||
866 | dev_err(&pdev->dev, "failed to register power supply charger\n"); | ||
867 | ret = PTR_ERR(info->psy_usb); | ||
868 | goto psy_reg_failed; | ||
869 | } | ||
870 | |||
871 | /* Register for OTG notification */ | ||
872 | INIT_WORK(&info->otg.work, axp288_charger_otg_evt_worker); | ||
873 | info->otg.id_nb.notifier_call = axp288_charger_handle_otg_evt; | ||
874 | ret = extcon_register_interest(&info->otg.cable, NULL, "USB-Host", | ||
875 | &info->otg.id_nb); | ||
876 | if (ret) | ||
877 | dev_warn(&pdev->dev, "failed to register otg notifier\n"); | ||
878 | |||
879 | if (info->otg.cable.edev) | ||
880 | info->otg.id_short = extcon_get_cable_state( | ||
881 | info->otg.cable.edev, "USB-Host"); | ||
882 | |||
883 | /* Register charger interrupts */ | ||
884 | for (i = 0; i < CHRG_INTR_END; i++) { | ||
885 | pirq = platform_get_irq(info->pdev, i); | ||
886 | info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq); | ||
887 | if (info->irq[i] < 0) { | ||
888 | dev_warn(&info->pdev->dev, | ||
889 | "failed to get virtual interrupt=%d\n", pirq); | ||
890 | ret = info->irq[i]; | ||
891 | goto intr_reg_failed; | ||
892 | } | ||
893 | ret = devm_request_threaded_irq(&info->pdev->dev, info->irq[i], | ||
894 | NULL, axp288_charger_irq_thread_handler, | ||
895 | IRQF_ONESHOT, info->pdev->name, info); | ||
896 | if (ret) { | ||
897 | dev_err(&pdev->dev, "failed to request interrupt=%d\n", | ||
898 | info->irq[i]); | ||
899 | goto intr_reg_failed; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | charger_init_hw_regs(info); | ||
904 | |||
905 | return 0; | ||
906 | |||
907 | intr_reg_failed: | ||
908 | if (info->otg.cable.edev) | ||
909 | extcon_unregister_interest(&info->otg.cable); | ||
910 | power_supply_unregister(info->psy_usb); | ||
911 | psy_reg_failed: | ||
912 | extcon_unregister_notifier(info->cable.edev, &info->cable.nb); | ||
913 | return ret; | ||
914 | } | ||
915 | |||
916 | static int axp288_charger_remove(struct platform_device *pdev) | ||
917 | { | ||
918 | struct axp288_chrg_info *info = dev_get_drvdata(&pdev->dev); | ||
919 | |||
920 | if (info->otg.cable.edev) | ||
921 | extcon_unregister_interest(&info->otg.cable); | ||
922 | |||
923 | extcon_unregister_notifier(info->cable.edev, &info->cable.nb); | ||
924 | power_supply_unregister(info->psy_usb); | ||
925 | |||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | static struct platform_driver axp288_charger_driver = { | ||
930 | .probe = axp288_charger_probe, | ||
931 | .remove = axp288_charger_remove, | ||
932 | .driver = { | ||
933 | .name = "axp288_charger", | ||
934 | }, | ||
935 | }; | ||
936 | |||
937 | module_platform_driver(axp288_charger_driver); | ||
938 | |||
939 | MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>"); | ||
940 | MODULE_DESCRIPTION("X-power AXP288 Charger Driver"); | ||
941 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/axp288_fuel_gauge.c b/drivers/power/axp288_fuel_gauge.c index bd1dbfee2515..50c0110d6b58 100644 --- a/drivers/power/axp288_fuel_gauge.c +++ b/drivers/power/axp288_fuel_gauge.c | |||
@@ -1117,7 +1117,7 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev) | |||
1117 | return ret; | 1117 | return ret; |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | static struct platform_device_id axp288_fg_id_table[] = { | 1120 | static const struct platform_device_id axp288_fg_id_table[] = { |
1121 | { .name = DEV_NAME }, | 1121 | { .name = DEV_NAME }, |
1122 | {}, | 1122 | {}, |
1123 | }; | 1123 | }; |
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c index 6c534dcbc19c..e98dcb661cc9 100644 --- a/drivers/power/bq2415x_charger.c +++ b/drivers/power/bq2415x_charger.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
36 | #include <linux/i2c.h> | 36 | #include <linux/i2c.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/acpi.h> | ||
38 | 39 | ||
39 | #include <linux/power/bq2415x_charger.h> | 40 | #include <linux/power/bq2415x_charger.h> |
40 | 41 | ||
@@ -631,7 +632,7 @@ static int bq2415x_set_charge_current(struct bq2415x_device *bq, int mA) | |||
631 | int val; | 632 | int val; |
632 | 633 | ||
633 | if (bq->init_data.resistor_sense <= 0) | 634 | if (bq->init_data.resistor_sense <= 0) |
634 | return -ENOSYS; | 635 | return -EINVAL; |
635 | 636 | ||
636 | val = (mA * bq->init_data.resistor_sense - 37400) / 6800; | 637 | val = (mA * bq->init_data.resistor_sense - 37400) / 6800; |
637 | if (val < 0) | 638 | if (val < 0) |
@@ -650,7 +651,7 @@ static int bq2415x_get_charge_current(struct bq2415x_device *bq) | |||
650 | int ret; | 651 | int ret; |
651 | 652 | ||
652 | if (bq->init_data.resistor_sense <= 0) | 653 | if (bq->init_data.resistor_sense <= 0) |
653 | return -ENOSYS; | 654 | return -EINVAL; |
654 | 655 | ||
655 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, | 656 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, |
656 | BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG); | 657 | BQ2415X_MASK_VI_CHRG, BQ2415X_SHIFT_VI_CHRG); |
@@ -665,7 +666,7 @@ static int bq2415x_set_termination_current(struct bq2415x_device *bq, int mA) | |||
665 | int val; | 666 | int val; |
666 | 667 | ||
667 | if (bq->init_data.resistor_sense <= 0) | 668 | if (bq->init_data.resistor_sense <= 0) |
668 | return -ENOSYS; | 669 | return -EINVAL; |
669 | 670 | ||
670 | val = (mA * bq->init_data.resistor_sense - 3400) / 3400; | 671 | val = (mA * bq->init_data.resistor_sense - 3400) / 3400; |
671 | if (val < 0) | 672 | if (val < 0) |
@@ -684,7 +685,7 @@ static int bq2415x_get_termination_current(struct bq2415x_device *bq) | |||
684 | int ret; | 685 | int ret; |
685 | 686 | ||
686 | if (bq->init_data.resistor_sense <= 0) | 687 | if (bq->init_data.resistor_sense <= 0) |
687 | return -ENOSYS; | 688 | return -EINVAL; |
688 | 689 | ||
689 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, | 690 | ret = bq2415x_i2c_read_mask(bq, BQ2415X_REG_CURRENT, |
690 | BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM); | 691 | BQ2415X_MASK_VI_TERM, BQ2415X_SHIFT_VI_TERM); |
@@ -1166,7 +1167,7 @@ static ssize_t bq2415x_sysfs_set_mode(struct device *dev, | |||
1166 | 1167 | ||
1167 | if (strncmp(buf, "auto", 4) == 0) { | 1168 | if (strncmp(buf, "auto", 4) == 0) { |
1168 | if (bq->automode < 0) | 1169 | if (bq->automode < 0) |
1169 | return -ENOSYS; | 1170 | return -EINVAL; |
1170 | bq->automode = 1; | 1171 | bq->automode = 1; |
1171 | mode = bq->reported_mode; | 1172 | mode = bq->reported_mode; |
1172 | } else if (strncmp(buf, "off", 3) == 0) { | 1173 | } else if (strncmp(buf, "off", 3) == 0) { |
@@ -1530,13 +1531,14 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1530 | { | 1531 | { |
1531 | int ret; | 1532 | int ret; |
1532 | int num; | 1533 | int num; |
1533 | char *name; | 1534 | char *name = NULL; |
1534 | struct bq2415x_device *bq; | 1535 | struct bq2415x_device *bq; |
1535 | struct device_node *np = client->dev.of_node; | 1536 | struct device_node *np = client->dev.of_node; |
1536 | struct bq2415x_platform_data *pdata = client->dev.platform_data; | 1537 | struct bq2415x_platform_data *pdata = client->dev.platform_data; |
1538 | const struct acpi_device_id *acpi_id = NULL; | ||
1537 | 1539 | ||
1538 | if (!np && !pdata) { | 1540 | if (!np && !pdata && !ACPI_HANDLE(&client->dev)) { |
1539 | dev_err(&client->dev, "platform data missing\n"); | 1541 | dev_err(&client->dev, "Neither devicetree, nor platform data, nor ACPI support\n"); |
1540 | return -ENODEV; | 1542 | return -ENODEV; |
1541 | } | 1543 | } |
1542 | 1544 | ||
@@ -1547,7 +1549,14 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1547 | if (num < 0) | 1549 | if (num < 0) |
1548 | return num; | 1550 | return num; |
1549 | 1551 | ||
1550 | name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num); | 1552 | if (id) { |
1553 | name = kasprintf(GFP_KERNEL, "%s-%d", id->name, num); | ||
1554 | } else if (ACPI_HANDLE(&client->dev)) { | ||
1555 | acpi_id = | ||
1556 | acpi_match_device(client->dev.driver->acpi_match_table, | ||
1557 | &client->dev); | ||
1558 | name = kasprintf(GFP_KERNEL, "%s-%d", acpi_id->id, num); | ||
1559 | } | ||
1551 | if (!name) { | 1560 | if (!name) { |
1552 | dev_err(&client->dev, "failed to allocate device name\n"); | 1561 | dev_err(&client->dev, "failed to allocate device name\n"); |
1553 | ret = -ENOMEM; | 1562 | ret = -ENOMEM; |
@@ -1556,63 +1565,72 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1556 | 1565 | ||
1557 | bq = devm_kzalloc(&client->dev, sizeof(*bq), GFP_KERNEL); | 1566 | bq = devm_kzalloc(&client->dev, sizeof(*bq), GFP_KERNEL); |
1558 | if (!bq) { | 1567 | if (!bq) { |
1559 | dev_err(&client->dev, "failed to allocate device data\n"); | ||
1560 | ret = -ENOMEM; | 1568 | ret = -ENOMEM; |
1561 | goto error_2; | 1569 | goto error_2; |
1562 | } | 1570 | } |
1563 | 1571 | ||
1564 | if (np) { | 1572 | if (np) { |
1565 | bq->notify_psy = power_supply_get_by_phandle(np, "ti,usb-charger-detection"); | 1573 | bq->notify_psy = power_supply_get_by_phandle(np, |
1574 | "ti,usb-charger-detection"); | ||
1566 | 1575 | ||
1567 | if (IS_ERR(bq->notify_psy)) { | 1576 | if (IS_ERR(bq->notify_psy)) { |
1568 | dev_info(&client->dev, | 1577 | dev_info(&client->dev, |
1569 | "no 'ti,usb-charger-detection' property (err=%ld)\n", | 1578 | "no 'ti,usb-charger-detection' property (err=%ld)\n", |
1570 | PTR_ERR(bq->notify_psy)); | 1579 | PTR_ERR(bq->notify_psy)); |
1571 | bq->notify_psy = NULL; | 1580 | bq->notify_psy = NULL; |
1572 | } else if (!bq->notify_psy) { | 1581 | } else if (!bq->notify_psy) { |
1573 | ret = -EPROBE_DEFER; | 1582 | ret = -EPROBE_DEFER; |
1574 | goto error_2; | 1583 | goto error_2; |
1575 | } | 1584 | } |
1576 | } | 1585 | } else if (pdata && pdata->notify_device) { |
1577 | else if (pdata->notify_device) | ||
1578 | bq->notify_psy = power_supply_get_by_name(pdata->notify_device); | 1586 | bq->notify_psy = power_supply_get_by_name(pdata->notify_device); |
1579 | else | 1587 | } else { |
1580 | bq->notify_psy = NULL; | 1588 | bq->notify_psy = NULL; |
1589 | } | ||
1581 | 1590 | ||
1582 | i2c_set_clientdata(client, bq); | 1591 | i2c_set_clientdata(client, bq); |
1583 | 1592 | ||
1584 | bq->id = num; | 1593 | bq->id = num; |
1585 | bq->dev = &client->dev; | 1594 | bq->dev = &client->dev; |
1586 | bq->chip = id->driver_data; | 1595 | if (id) |
1596 | bq->chip = id->driver_data; | ||
1597 | else if (ACPI_HANDLE(bq->dev)) | ||
1598 | bq->chip = acpi_id->driver_data; | ||
1587 | bq->name = name; | 1599 | bq->name = name; |
1588 | bq->mode = BQ2415X_MODE_OFF; | 1600 | bq->mode = BQ2415X_MODE_OFF; |
1589 | bq->reported_mode = BQ2415X_MODE_OFF; | 1601 | bq->reported_mode = BQ2415X_MODE_OFF; |
1590 | bq->autotimer = 0; | 1602 | bq->autotimer = 0; |
1591 | bq->automode = 0; | 1603 | bq->automode = 0; |
1592 | 1604 | ||
1593 | if (np) { | 1605 | if (np || ACPI_HANDLE(bq->dev)) { |
1594 | ret = of_property_read_u32(np, "ti,current-limit", | 1606 | ret = device_property_read_u32(bq->dev, |
1595 | &bq->init_data.current_limit); | 1607 | "ti,current-limit", |
1608 | &bq->init_data.current_limit); | ||
1596 | if (ret) | 1609 | if (ret) |
1597 | goto error_3; | 1610 | goto error_3; |
1598 | ret = of_property_read_u32(np, "ti,weak-battery-voltage", | 1611 | ret = device_property_read_u32(bq->dev, |
1599 | &bq->init_data.weak_battery_voltage); | 1612 | "ti,weak-battery-voltage", |
1613 | &bq->init_data.weak_battery_voltage); | ||
1600 | if (ret) | 1614 | if (ret) |
1601 | goto error_3; | 1615 | goto error_3; |
1602 | ret = of_property_read_u32(np, "ti,battery-regulation-voltage", | 1616 | ret = device_property_read_u32(bq->dev, |
1617 | "ti,battery-regulation-voltage", | ||
1603 | &bq->init_data.battery_regulation_voltage); | 1618 | &bq->init_data.battery_regulation_voltage); |
1604 | if (ret) | 1619 | if (ret) |
1605 | goto error_3; | 1620 | goto error_3; |
1606 | ret = of_property_read_u32(np, "ti,charge-current", | 1621 | ret = device_property_read_u32(bq->dev, |
1607 | &bq->init_data.charge_current); | 1622 | "ti,charge-current", |
1623 | &bq->init_data.charge_current); | ||
1608 | if (ret) | 1624 | if (ret) |
1609 | goto error_3; | 1625 | goto error_3; |
1610 | ret = of_property_read_u32(np, "ti,termination-current", | 1626 | ret = device_property_read_u32(bq->dev, |
1627 | "ti,termination-current", | ||
1611 | &bq->init_data.termination_current); | 1628 | &bq->init_data.termination_current); |
1612 | if (ret) | 1629 | if (ret) |
1613 | goto error_3; | 1630 | goto error_3; |
1614 | ret = of_property_read_u32(np, "ti,resistor-sense", | 1631 | ret = device_property_read_u32(bq->dev, |
1615 | &bq->init_data.resistor_sense); | 1632 | "ti,resistor-sense", |
1633 | &bq->init_data.resistor_sense); | ||
1616 | if (ret) | 1634 | if (ret) |
1617 | goto error_3; | 1635 | goto error_3; |
1618 | } else { | 1636 | } else { |
@@ -1648,7 +1666,8 @@ static int bq2415x_probe(struct i2c_client *client, | |||
1648 | } | 1666 | } |
1649 | 1667 | ||
1650 | /* Query for initial reported_mode and set it */ | 1668 | /* Query for initial reported_mode and set it */ |
1651 | bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED, bq->notify_psy); | 1669 | bq2415x_notifier_call(&bq->nb, PSY_EVENT_PROP_CHANGED, |
1670 | bq->notify_psy); | ||
1652 | bq2415x_set_mode(bq, bq->reported_mode); | 1671 | bq2415x_set_mode(bq, bq->reported_mode); |
1653 | 1672 | ||
1654 | bq->automode = 1; | 1673 | bq->automode = 1; |
@@ -1727,9 +1746,28 @@ static const struct i2c_device_id bq2415x_i2c_id_table[] = { | |||
1727 | }; | 1746 | }; |
1728 | MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table); | 1747 | MODULE_DEVICE_TABLE(i2c, bq2415x_i2c_id_table); |
1729 | 1748 | ||
1749 | static const struct acpi_device_id bq2415x_i2c_acpi_match[] = { | ||
1750 | { "BQ2415X", BQUNKNOWN }, | ||
1751 | { "BQ241500", BQ24150 }, | ||
1752 | { "BQA24150", BQ24150A }, | ||
1753 | { "BQ241510", BQ24151 }, | ||
1754 | { "BQA24151", BQ24151A }, | ||
1755 | { "BQ241520", BQ24152 }, | ||
1756 | { "BQ241530", BQ24153 }, | ||
1757 | { "BQA24153", BQ24153A }, | ||
1758 | { "BQ241550", BQ24155 }, | ||
1759 | { "BQ241560", BQ24156 }, | ||
1760 | { "BQA24156", BQ24156A }, | ||
1761 | { "BQS24157", BQ24157S }, | ||
1762 | { "BQ241580", BQ24158 }, | ||
1763 | {}, | ||
1764 | }; | ||
1765 | MODULE_DEVICE_TABLE(acpi, bq2415x_i2c_acpi_match); | ||
1766 | |||
1730 | static struct i2c_driver bq2415x_driver = { | 1767 | static struct i2c_driver bq2415x_driver = { |
1731 | .driver = { | 1768 | .driver = { |
1732 | .name = "bq2415x-charger", | 1769 | .name = "bq2415x-charger", |
1770 | .acpi_match_table = ACPI_PTR(bq2415x_i2c_acpi_match), | ||
1733 | }, | 1771 | }, |
1734 | .probe = bq2415x_probe, | 1772 | .probe = bq2415x_probe, |
1735 | .remove = bq2415x_remove, | 1773 | .remove = bq2415x_remove, |
diff --git a/drivers/power/bq24190_charger.c b/drivers/power/bq24190_charger.c index 407c4af83891..052db78c3736 100644 --- a/drivers/power/bq24190_charger.c +++ b/drivers/power/bq24190_charger.c | |||
@@ -1258,10 +1258,13 @@ static irqreturn_t bq24190_irq_handler_thread(int irq, void *data) | |||
1258 | * register reset so we should ignore that one (the very first | 1258 | * register reset so we should ignore that one (the very first |
1259 | * interrupt received). | 1259 | * interrupt received). |
1260 | */ | 1260 | */ |
1261 | if (alert_userspace && !bdi->first_time) { | 1261 | if (alert_userspace) { |
1262 | power_supply_changed(bdi->charger); | 1262 | if (!bdi->first_time) { |
1263 | power_supply_changed(bdi->battery); | 1263 | power_supply_changed(bdi->charger); |
1264 | bdi->first_time = false; | 1264 | power_supply_changed(bdi->battery); |
1265 | } else { | ||
1266 | bdi->first_time = false; | ||
1267 | } | ||
1265 | } | 1268 | } |
1266 | 1269 | ||
1267 | out: | 1270 | out: |
diff --git a/drivers/power/bq24257_charger.c b/drivers/power/bq24257_charger.c new file mode 100644 index 000000000000..5859bc7c1616 --- /dev/null +++ b/drivers/power/bq24257_charger.c | |||
@@ -0,0 +1,858 @@ | |||
1 | /* | ||
2 | * TI BQ24257 charger driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corporation | ||
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 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/power_supply.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/gpio/consumer.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #include <linux/acpi.h> | ||
28 | #include <linux/of.h> | ||
29 | |||
30 | #define BQ24257_REG_1 0x00 | ||
31 | #define BQ24257_REG_2 0x01 | ||
32 | #define BQ24257_REG_3 0x02 | ||
33 | #define BQ24257_REG_4 0x03 | ||
34 | #define BQ24257_REG_5 0x04 | ||
35 | #define BQ24257_REG_6 0x05 | ||
36 | #define BQ24257_REG_7 0x06 | ||
37 | |||
38 | #define BQ24257_MANUFACTURER "Texas Instruments" | ||
39 | #define BQ24257_STAT_IRQ "stat" | ||
40 | #define BQ24257_PG_GPIO "pg" | ||
41 | |||
42 | #define BQ24257_ILIM_SET_DELAY 1000 /* msec */ | ||
43 | |||
44 | enum bq24257_fields { | ||
45 | F_WD_FAULT, F_WD_EN, F_STAT, F_FAULT, /* REG 1 */ | ||
46 | F_RESET, F_IILIMIT, F_EN_STAT, F_EN_TERM, F_CE, F_HZ_MODE, /* REG 2 */ | ||
47 | F_VBAT, F_USB_DET, /* REG 3 */ | ||
48 | F_ICHG, F_ITERM, /* REG 4 */ | ||
49 | F_LOOP_STATUS, F_LOW_CHG, F_DPDM_EN, F_CE_STATUS, F_VINDPM, /* REG 5 */ | ||
50 | F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_STAT, /* REG 6 */ | ||
51 | F_VOVP, F_CLR_VDP, F_FORCE_BATDET, F_FORCE_PTM, /* REG 7 */ | ||
52 | |||
53 | F_MAX_FIELDS | ||
54 | }; | ||
55 | |||
56 | /* initial field values, converted from uV/uA */ | ||
57 | struct bq24257_init_data { | ||
58 | u8 ichg; /* charge current */ | ||
59 | u8 vbat; /* regulation voltage */ | ||
60 | u8 iterm; /* termination current */ | ||
61 | }; | ||
62 | |||
63 | struct bq24257_state { | ||
64 | u8 status; | ||
65 | u8 fault; | ||
66 | bool power_good; | ||
67 | }; | ||
68 | |||
69 | struct bq24257_device { | ||
70 | struct i2c_client *client; | ||
71 | struct device *dev; | ||
72 | struct power_supply *charger; | ||
73 | |||
74 | struct regmap *rmap; | ||
75 | struct regmap_field *rmap_fields[F_MAX_FIELDS]; | ||
76 | |||
77 | struct gpio_desc *pg; | ||
78 | |||
79 | struct delayed_work iilimit_setup_work; | ||
80 | |||
81 | struct bq24257_init_data init_data; | ||
82 | struct bq24257_state state; | ||
83 | |||
84 | struct mutex lock; /* protect state data */ | ||
85 | }; | ||
86 | |||
87 | static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg) | ||
88 | { | ||
89 | switch (reg) { | ||
90 | case BQ24257_REG_2: | ||
91 | case BQ24257_REG_4: | ||
92 | return false; | ||
93 | |||
94 | default: | ||
95 | return true; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static const struct regmap_config bq24257_regmap_config = { | ||
100 | .reg_bits = 8, | ||
101 | .val_bits = 8, | ||
102 | |||
103 | .max_register = BQ24257_REG_7, | ||
104 | .cache_type = REGCACHE_RBTREE, | ||
105 | |||
106 | .volatile_reg = bq24257_is_volatile_reg, | ||
107 | }; | ||
108 | |||
109 | static const struct reg_field bq24257_reg_fields[] = { | ||
110 | /* REG 1 */ | ||
111 | [F_WD_FAULT] = REG_FIELD(BQ24257_REG_1, 7, 7), | ||
112 | [F_WD_EN] = REG_FIELD(BQ24257_REG_1, 6, 6), | ||
113 | [F_STAT] = REG_FIELD(BQ24257_REG_1, 4, 5), | ||
114 | [F_FAULT] = REG_FIELD(BQ24257_REG_1, 0, 3), | ||
115 | /* REG 2 */ | ||
116 | [F_RESET] = REG_FIELD(BQ24257_REG_2, 7, 7), | ||
117 | [F_IILIMIT] = REG_FIELD(BQ24257_REG_2, 4, 6), | ||
118 | [F_EN_STAT] = REG_FIELD(BQ24257_REG_2, 3, 3), | ||
119 | [F_EN_TERM] = REG_FIELD(BQ24257_REG_2, 2, 2), | ||
120 | [F_CE] = REG_FIELD(BQ24257_REG_2, 1, 1), | ||
121 | [F_HZ_MODE] = REG_FIELD(BQ24257_REG_2, 0, 0), | ||
122 | /* REG 3 */ | ||
123 | [F_VBAT] = REG_FIELD(BQ24257_REG_3, 2, 7), | ||
124 | [F_USB_DET] = REG_FIELD(BQ24257_REG_3, 0, 1), | ||
125 | /* REG 4 */ | ||
126 | [F_ICHG] = REG_FIELD(BQ24257_REG_4, 3, 7), | ||
127 | [F_ITERM] = REG_FIELD(BQ24257_REG_4, 0, 2), | ||
128 | /* REG 5 */ | ||
129 | [F_LOOP_STATUS] = REG_FIELD(BQ24257_REG_5, 6, 7), | ||
130 | [F_LOW_CHG] = REG_FIELD(BQ24257_REG_5, 5, 5), | ||
131 | [F_DPDM_EN] = REG_FIELD(BQ24257_REG_5, 4, 4), | ||
132 | [F_CE_STATUS] = REG_FIELD(BQ24257_REG_5, 3, 3), | ||
133 | [F_VINDPM] = REG_FIELD(BQ24257_REG_5, 0, 2), | ||
134 | /* REG 6 */ | ||
135 | [F_X2_TMR_EN] = REG_FIELD(BQ24257_REG_6, 7, 7), | ||
136 | [F_TMR] = REG_FIELD(BQ24257_REG_6, 5, 6), | ||
137 | [F_SYSOFF] = REG_FIELD(BQ24257_REG_6, 4, 4), | ||
138 | [F_TS_STAT] = REG_FIELD(BQ24257_REG_6, 0, 2), | ||
139 | /* REG 7 */ | ||
140 | [F_VOVP] = REG_FIELD(BQ24257_REG_7, 5, 7), | ||
141 | [F_CLR_VDP] = REG_FIELD(BQ24257_REG_7, 4, 4), | ||
142 | [F_FORCE_BATDET] = REG_FIELD(BQ24257_REG_7, 3, 3), | ||
143 | [F_FORCE_PTM] = REG_FIELD(BQ24257_REG_7, 2, 2) | ||
144 | }; | ||
145 | |||
146 | static const u32 bq24257_vbat_map[] = { | ||
147 | 3500000, 3520000, 3540000, 3560000, 3580000, 3600000, 3620000, 3640000, | ||
148 | 3660000, 3680000, 3700000, 3720000, 3740000, 3760000, 3780000, 3800000, | ||
149 | 3820000, 3840000, 3860000, 3880000, 3900000, 3920000, 3940000, 3960000, | ||
150 | 3980000, 4000000, 4020000, 4040000, 4060000, 4080000, 4100000, 4120000, | ||
151 | 4140000, 4160000, 4180000, 4200000, 4220000, 4240000, 4260000, 4280000, | ||
152 | 4300000, 4320000, 4340000, 4360000, 4380000, 4400000, 4420000, 4440000 | ||
153 | }; | ||
154 | |||
155 | #define BQ24257_VBAT_MAP_SIZE ARRAY_SIZE(bq24257_vbat_map) | ||
156 | |||
157 | static const u32 bq24257_ichg_map[] = { | ||
158 | 500000, 550000, 600000, 650000, 700000, 750000, 800000, 850000, 900000, | ||
159 | 950000, 1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, | ||
160 | 1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000, | ||
161 | 1750000, 1800000, 1850000, 1900000, 1950000, 2000000 | ||
162 | }; | ||
163 | |||
164 | #define BQ24257_ICHG_MAP_SIZE ARRAY_SIZE(bq24257_ichg_map) | ||
165 | |||
166 | static const u32 bq24257_iterm_map[] = { | ||
167 | 50000, 75000, 100000, 125000, 150000, 175000, 200000, 225000 | ||
168 | }; | ||
169 | |||
170 | #define BQ24257_ITERM_MAP_SIZE ARRAY_SIZE(bq24257_iterm_map) | ||
171 | |||
172 | static int bq24257_field_read(struct bq24257_device *bq, | ||
173 | enum bq24257_fields field_id) | ||
174 | { | ||
175 | int ret; | ||
176 | int val; | ||
177 | |||
178 | ret = regmap_field_read(bq->rmap_fields[field_id], &val); | ||
179 | if (ret < 0) | ||
180 | return ret; | ||
181 | |||
182 | return val; | ||
183 | } | ||
184 | |||
185 | static int bq24257_field_write(struct bq24257_device *bq, | ||
186 | enum bq24257_fields field_id, u8 val) | ||
187 | { | ||
188 | return regmap_field_write(bq->rmap_fields[field_id], val); | ||
189 | } | ||
190 | |||
191 | static u8 bq24257_find_idx(u32 value, const u32 *map, u8 map_size) | ||
192 | { | ||
193 | u8 idx; | ||
194 | |||
195 | for (idx = 1; idx < map_size; idx++) | ||
196 | if (value < map[idx]) | ||
197 | break; | ||
198 | |||
199 | return idx - 1; | ||
200 | } | ||
201 | |||
202 | enum bq24257_status { | ||
203 | STATUS_READY, | ||
204 | STATUS_CHARGE_IN_PROGRESS, | ||
205 | STATUS_CHARGE_DONE, | ||
206 | STATUS_FAULT, | ||
207 | }; | ||
208 | |||
209 | enum bq24257_fault { | ||
210 | FAULT_NORMAL, | ||
211 | FAULT_INPUT_OVP, | ||
212 | FAULT_INPUT_UVLO, | ||
213 | FAULT_SLEEP, | ||
214 | FAULT_BAT_TS, | ||
215 | FAULT_BAT_OVP, | ||
216 | FAULT_TS, | ||
217 | FAULT_TIMER, | ||
218 | FAULT_NO_BAT, | ||
219 | FAULT_ISET, | ||
220 | FAULT_INPUT_LDO_LOW, | ||
221 | }; | ||
222 | |||
223 | static int bq24257_power_supply_get_property(struct power_supply *psy, | ||
224 | enum power_supply_property psp, | ||
225 | union power_supply_propval *val) | ||
226 | { | ||
227 | struct bq24257_device *bq = power_supply_get_drvdata(psy); | ||
228 | struct bq24257_state state; | ||
229 | |||
230 | mutex_lock(&bq->lock); | ||
231 | state = bq->state; | ||
232 | mutex_unlock(&bq->lock); | ||
233 | |||
234 | switch (psp) { | ||
235 | case POWER_SUPPLY_PROP_STATUS: | ||
236 | if (!state.power_good) | ||
237 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
238 | else if (state.status == STATUS_READY) | ||
239 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
240 | else if (state.status == STATUS_CHARGE_IN_PROGRESS) | ||
241 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
242 | else if (state.status == STATUS_CHARGE_DONE) | ||
243 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
244 | else | ||
245 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
246 | break; | ||
247 | |||
248 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
249 | val->strval = BQ24257_MANUFACTURER; | ||
250 | break; | ||
251 | |||
252 | case POWER_SUPPLY_PROP_ONLINE: | ||
253 | val->intval = state.power_good; | ||
254 | break; | ||
255 | |||
256 | case POWER_SUPPLY_PROP_HEALTH: | ||
257 | switch (state.fault) { | ||
258 | case FAULT_NORMAL: | ||
259 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
260 | break; | ||
261 | |||
262 | case FAULT_INPUT_OVP: | ||
263 | case FAULT_BAT_OVP: | ||
264 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
265 | break; | ||
266 | |||
267 | case FAULT_TS: | ||
268 | case FAULT_BAT_TS: | ||
269 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
270 | break; | ||
271 | |||
272 | case FAULT_TIMER: | ||
273 | val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; | ||
274 | break; | ||
275 | |||
276 | default: | ||
277 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | break; | ||
282 | |||
283 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
284 | val->intval = bq24257_ichg_map[bq->init_data.ichg]; | ||
285 | break; | ||
286 | |||
287 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: | ||
288 | val->intval = bq24257_ichg_map[BQ24257_ICHG_MAP_SIZE - 1]; | ||
289 | break; | ||
290 | |||
291 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
292 | val->intval = bq24257_vbat_map[bq->init_data.vbat]; | ||
293 | break; | ||
294 | |||
295 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: | ||
296 | val->intval = bq24257_vbat_map[BQ24257_VBAT_MAP_SIZE - 1]; | ||
297 | break; | ||
298 | |||
299 | case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: | ||
300 | val->intval = bq24257_iterm_map[bq->init_data.iterm]; | ||
301 | break; | ||
302 | |||
303 | default: | ||
304 | return -EINVAL; | ||
305 | } | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int bq24257_get_chip_state(struct bq24257_device *bq, | ||
311 | struct bq24257_state *state) | ||
312 | { | ||
313 | int ret; | ||
314 | |||
315 | ret = bq24257_field_read(bq, F_STAT); | ||
316 | if (ret < 0) | ||
317 | return ret; | ||
318 | |||
319 | state->status = ret; | ||
320 | |||
321 | ret = bq24257_field_read(bq, F_FAULT); | ||
322 | if (ret < 0) | ||
323 | return ret; | ||
324 | |||
325 | state->fault = ret; | ||
326 | |||
327 | state->power_good = !gpiod_get_value_cansleep(bq->pg); | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static bool bq24257_state_changed(struct bq24257_device *bq, | ||
333 | struct bq24257_state *new_state) | ||
334 | { | ||
335 | int ret; | ||
336 | |||
337 | mutex_lock(&bq->lock); | ||
338 | ret = (bq->state.status != new_state->status || | ||
339 | bq->state.fault != new_state->fault || | ||
340 | bq->state.power_good != new_state->power_good); | ||
341 | mutex_unlock(&bq->lock); | ||
342 | |||
343 | return ret; | ||
344 | } | ||
345 | |||
346 | enum bq24257_loop_status { | ||
347 | LOOP_STATUS_NONE, | ||
348 | LOOP_STATUS_IN_DPM, | ||
349 | LOOP_STATUS_IN_CURRENT_LIMIT, | ||
350 | LOOP_STATUS_THERMAL, | ||
351 | }; | ||
352 | |||
353 | enum bq24257_in_ilimit { | ||
354 | IILIMIT_100, | ||
355 | IILIMIT_150, | ||
356 | IILIMIT_500, | ||
357 | IILIMIT_900, | ||
358 | IILIMIT_1500, | ||
359 | IILIMIT_2000, | ||
360 | IILIMIT_EXT, | ||
361 | IILIMIT_NONE, | ||
362 | }; | ||
363 | |||
364 | enum bq24257_port_type { | ||
365 | PORT_TYPE_DCP, /* Dedicated Charging Port */ | ||
366 | PORT_TYPE_CDP, /* Charging Downstream Port */ | ||
367 | PORT_TYPE_SDP, /* Standard Downstream Port */ | ||
368 | PORT_TYPE_NON_STANDARD, | ||
369 | }; | ||
370 | |||
371 | enum bq24257_safety_timer { | ||
372 | SAFETY_TIMER_45, | ||
373 | SAFETY_TIMER_360, | ||
374 | SAFETY_TIMER_540, | ||
375 | SAFETY_TIMER_NONE, | ||
376 | }; | ||
377 | |||
378 | static int bq24257_iilimit_autoset(struct bq24257_device *bq) | ||
379 | { | ||
380 | int loop_status; | ||
381 | int iilimit; | ||
382 | int port_type; | ||
383 | int ret; | ||
384 | const u8 new_iilimit[] = { | ||
385 | [PORT_TYPE_DCP] = IILIMIT_2000, | ||
386 | [PORT_TYPE_CDP] = IILIMIT_2000, | ||
387 | [PORT_TYPE_SDP] = IILIMIT_500, | ||
388 | [PORT_TYPE_NON_STANDARD] = IILIMIT_500 | ||
389 | }; | ||
390 | |||
391 | ret = bq24257_field_read(bq, F_LOOP_STATUS); | ||
392 | if (ret < 0) | ||
393 | goto error; | ||
394 | |||
395 | loop_status = ret; | ||
396 | |||
397 | ret = bq24257_field_read(bq, F_IILIMIT); | ||
398 | if (ret < 0) | ||
399 | goto error; | ||
400 | |||
401 | iilimit = ret; | ||
402 | |||
403 | /* | ||
404 | * All USB ports should be able to handle 500mA. If not, DPM will lower | ||
405 | * the charging current to accommodate the power source. No need to set | ||
406 | * a lower IILIMIT value. | ||
407 | */ | ||
408 | if (loop_status == LOOP_STATUS_IN_DPM && iilimit == IILIMIT_500) | ||
409 | return 0; | ||
410 | |||
411 | ret = bq24257_field_read(bq, F_USB_DET); | ||
412 | if (ret < 0) | ||
413 | goto error; | ||
414 | |||
415 | port_type = ret; | ||
416 | |||
417 | ret = bq24257_field_write(bq, F_IILIMIT, new_iilimit[port_type]); | ||
418 | if (ret < 0) | ||
419 | goto error; | ||
420 | |||
421 | ret = bq24257_field_write(bq, F_TMR, SAFETY_TIMER_360); | ||
422 | if (ret < 0) | ||
423 | goto error; | ||
424 | |||
425 | ret = bq24257_field_write(bq, F_CLR_VDP, 1); | ||
426 | if (ret < 0) | ||
427 | goto error; | ||
428 | |||
429 | dev_dbg(bq->dev, "port/loop = %d/%d -> iilimit = %d\n", | ||
430 | port_type, loop_status, new_iilimit[port_type]); | ||
431 | |||
432 | return 0; | ||
433 | |||
434 | error: | ||
435 | dev_err(bq->dev, "%s: Error communicating with the chip.\n", __func__); | ||
436 | return ret; | ||
437 | } | ||
438 | |||
439 | static void bq24257_iilimit_setup_work(struct work_struct *work) | ||
440 | { | ||
441 | struct bq24257_device *bq = container_of(work, struct bq24257_device, | ||
442 | iilimit_setup_work.work); | ||
443 | |||
444 | bq24257_iilimit_autoset(bq); | ||
445 | } | ||
446 | |||
447 | static void bq24257_handle_state_change(struct bq24257_device *bq, | ||
448 | struct bq24257_state *new_state) | ||
449 | { | ||
450 | int ret; | ||
451 | struct bq24257_state old_state; | ||
452 | bool reset_iilimit = false; | ||
453 | bool config_iilimit = false; | ||
454 | |||
455 | mutex_lock(&bq->lock); | ||
456 | old_state = bq->state; | ||
457 | mutex_unlock(&bq->lock); | ||
458 | |||
459 | if (!new_state->power_good) { /* power removed */ | ||
460 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
461 | |||
462 | /* activate D+/D- port detection algorithm */ | ||
463 | ret = bq24257_field_write(bq, F_DPDM_EN, 1); | ||
464 | if (ret < 0) | ||
465 | goto error; | ||
466 | |||
467 | reset_iilimit = true; | ||
468 | } else if (!old_state.power_good) { /* power inserted */ | ||
469 | config_iilimit = true; | ||
470 | } else if (new_state->fault == FAULT_NO_BAT) { /* battery removed */ | ||
471 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
472 | |||
473 | reset_iilimit = true; | ||
474 | } else if (old_state.fault == FAULT_NO_BAT) { /* battery connected */ | ||
475 | config_iilimit = true; | ||
476 | } else if (new_state->fault == FAULT_TIMER) { /* safety timer expired */ | ||
477 | dev_err(bq->dev, "Safety timer expired! Battery dead?\n"); | ||
478 | } | ||
479 | |||
480 | if (reset_iilimit) { | ||
481 | ret = bq24257_field_write(bq, F_IILIMIT, IILIMIT_500); | ||
482 | if (ret < 0) | ||
483 | goto error; | ||
484 | } else if (config_iilimit) { | ||
485 | schedule_delayed_work(&bq->iilimit_setup_work, | ||
486 | msecs_to_jiffies(BQ24257_ILIM_SET_DELAY)); | ||
487 | } | ||
488 | |||
489 | return; | ||
490 | |||
491 | error: | ||
492 | dev_err(bq->dev, "%s: Error communicating with the chip.\n", __func__); | ||
493 | } | ||
494 | |||
495 | static irqreturn_t bq24257_irq_handler_thread(int irq, void *private) | ||
496 | { | ||
497 | int ret; | ||
498 | struct bq24257_device *bq = private; | ||
499 | struct bq24257_state state; | ||
500 | |||
501 | ret = bq24257_get_chip_state(bq, &state); | ||
502 | if (ret < 0) | ||
503 | return IRQ_HANDLED; | ||
504 | |||
505 | if (!bq24257_state_changed(bq, &state)) | ||
506 | return IRQ_HANDLED; | ||
507 | |||
508 | dev_dbg(bq->dev, "irq(state changed): status/fault/pg = %d/%d/%d\n", | ||
509 | state.status, state.fault, state.power_good); | ||
510 | |||
511 | bq24257_handle_state_change(bq, &state); | ||
512 | |||
513 | mutex_lock(&bq->lock); | ||
514 | bq->state = state; | ||
515 | mutex_unlock(&bq->lock); | ||
516 | |||
517 | power_supply_changed(bq->charger); | ||
518 | |||
519 | return IRQ_HANDLED; | ||
520 | } | ||
521 | |||
522 | static int bq24257_hw_init(struct bq24257_device *bq) | ||
523 | { | ||
524 | int ret; | ||
525 | int i; | ||
526 | struct bq24257_state state; | ||
527 | |||
528 | const struct { | ||
529 | int field; | ||
530 | u32 value; | ||
531 | } init_data[] = { | ||
532 | {F_ICHG, bq->init_data.ichg}, | ||
533 | {F_VBAT, bq->init_data.vbat}, | ||
534 | {F_ITERM, bq->init_data.iterm} | ||
535 | }; | ||
536 | |||
537 | /* | ||
538 | * Disable the watchdog timer to prevent the IC from going back to | ||
539 | * default settings after 50 seconds of I2C inactivity. | ||
540 | */ | ||
541 | ret = bq24257_field_write(bq, F_WD_EN, 0); | ||
542 | if (ret < 0) | ||
543 | return ret; | ||
544 | |||
545 | /* configure the charge currents and voltages */ | ||
546 | for (i = 0; i < ARRAY_SIZE(init_data); i++) { | ||
547 | ret = bq24257_field_write(bq, init_data[i].field, | ||
548 | init_data[i].value); | ||
549 | if (ret < 0) | ||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | ret = bq24257_get_chip_state(bq, &state); | ||
554 | if (ret < 0) | ||
555 | return ret; | ||
556 | |||
557 | mutex_lock(&bq->lock); | ||
558 | bq->state = state; | ||
559 | mutex_unlock(&bq->lock); | ||
560 | |||
561 | if (!state.power_good) | ||
562 | /* activate D+/D- detection algorithm */ | ||
563 | ret = bq24257_field_write(bq, F_DPDM_EN, 1); | ||
564 | else if (state.fault != FAULT_NO_BAT) | ||
565 | ret = bq24257_iilimit_autoset(bq); | ||
566 | |||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | static enum power_supply_property bq24257_power_supply_props[] = { | ||
571 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
572 | POWER_SUPPLY_PROP_STATUS, | ||
573 | POWER_SUPPLY_PROP_ONLINE, | ||
574 | POWER_SUPPLY_PROP_HEALTH, | ||
575 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
576 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, | ||
577 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | ||
578 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | ||
579 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, | ||
580 | }; | ||
581 | |||
582 | static char *bq24257_charger_supplied_to[] = { | ||
583 | "main-battery", | ||
584 | }; | ||
585 | |||
586 | static const struct power_supply_desc bq24257_power_supply_desc = { | ||
587 | .name = "bq24257-charger", | ||
588 | .type = POWER_SUPPLY_TYPE_USB, | ||
589 | .properties = bq24257_power_supply_props, | ||
590 | .num_properties = ARRAY_SIZE(bq24257_power_supply_props), | ||
591 | .get_property = bq24257_power_supply_get_property, | ||
592 | }; | ||
593 | |||
594 | static int bq24257_power_supply_init(struct bq24257_device *bq) | ||
595 | { | ||
596 | struct power_supply_config psy_cfg = { .drv_data = bq, }; | ||
597 | |||
598 | psy_cfg.supplied_to = bq24257_charger_supplied_to; | ||
599 | psy_cfg.num_supplicants = ARRAY_SIZE(bq24257_charger_supplied_to); | ||
600 | |||
601 | bq->charger = power_supply_register(bq->dev, &bq24257_power_supply_desc, | ||
602 | &psy_cfg); | ||
603 | if (IS_ERR(bq->charger)) | ||
604 | return PTR_ERR(bq->charger); | ||
605 | |||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static int bq24257_irq_probe(struct bq24257_device *bq) | ||
610 | { | ||
611 | struct gpio_desc *stat_irq; | ||
612 | |||
613 | stat_irq = devm_gpiod_get_index(bq->dev, BQ24257_STAT_IRQ, 0, GPIOD_IN); | ||
614 | if (IS_ERR(stat_irq)) { | ||
615 | dev_err(bq->dev, "could not probe stat_irq pin\n"); | ||
616 | return PTR_ERR(stat_irq); | ||
617 | } | ||
618 | |||
619 | return gpiod_to_irq(stat_irq); | ||
620 | } | ||
621 | |||
622 | static int bq24257_pg_gpio_probe(struct bq24257_device *bq) | ||
623 | { | ||
624 | bq->pg = devm_gpiod_get_index(bq->dev, BQ24257_PG_GPIO, 0, GPIOD_IN); | ||
625 | if (IS_ERR(bq->pg)) { | ||
626 | dev_err(bq->dev, "could not probe PG pin\n"); | ||
627 | return PTR_ERR(bq->pg); | ||
628 | } | ||
629 | |||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | static int bq24257_fw_probe(struct bq24257_device *bq) | ||
634 | { | ||
635 | int ret; | ||
636 | u32 property; | ||
637 | |||
638 | ret = device_property_read_u32(bq->dev, "ti,charge-current", &property); | ||
639 | if (ret < 0) | ||
640 | return ret; | ||
641 | |||
642 | bq->init_data.ichg = bq24257_find_idx(property, bq24257_ichg_map, | ||
643 | BQ24257_ICHG_MAP_SIZE); | ||
644 | |||
645 | ret = device_property_read_u32(bq->dev, "ti,battery-regulation-voltage", | ||
646 | &property); | ||
647 | if (ret < 0) | ||
648 | return ret; | ||
649 | |||
650 | bq->init_data.vbat = bq24257_find_idx(property, bq24257_vbat_map, | ||
651 | BQ24257_VBAT_MAP_SIZE); | ||
652 | |||
653 | ret = device_property_read_u32(bq->dev, "ti,termination-current", | ||
654 | &property); | ||
655 | if (ret < 0) | ||
656 | return ret; | ||
657 | |||
658 | bq->init_data.iterm = bq24257_find_idx(property, bq24257_iterm_map, | ||
659 | BQ24257_ITERM_MAP_SIZE); | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int bq24257_probe(struct i2c_client *client, | ||
665 | const struct i2c_device_id *id) | ||
666 | { | ||
667 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
668 | struct device *dev = &client->dev; | ||
669 | struct bq24257_device *bq; | ||
670 | int ret; | ||
671 | int i; | ||
672 | |||
673 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
674 | dev_err(dev, "No support for SMBUS_BYTE_DATA\n"); | ||
675 | return -ENODEV; | ||
676 | } | ||
677 | |||
678 | bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); | ||
679 | if (!bq) | ||
680 | return -ENOMEM; | ||
681 | |||
682 | bq->client = client; | ||
683 | bq->dev = dev; | ||
684 | |||
685 | mutex_init(&bq->lock); | ||
686 | |||
687 | bq->rmap = devm_regmap_init_i2c(client, &bq24257_regmap_config); | ||
688 | if (IS_ERR(bq->rmap)) { | ||
689 | dev_err(dev, "failed to allocate register map\n"); | ||
690 | return PTR_ERR(bq->rmap); | ||
691 | } | ||
692 | |||
693 | for (i = 0; i < ARRAY_SIZE(bq24257_reg_fields); i++) { | ||
694 | const struct reg_field *reg_fields = bq24257_reg_fields; | ||
695 | |||
696 | bq->rmap_fields[i] = devm_regmap_field_alloc(dev, bq->rmap, | ||
697 | reg_fields[i]); | ||
698 | if (IS_ERR(bq->rmap_fields[i])) { | ||
699 | dev_err(dev, "cannot allocate regmap field\n"); | ||
700 | return PTR_ERR(bq->rmap_fields[i]); | ||
701 | } | ||
702 | } | ||
703 | |||
704 | i2c_set_clientdata(client, bq); | ||
705 | |||
706 | INIT_DELAYED_WORK(&bq->iilimit_setup_work, bq24257_iilimit_setup_work); | ||
707 | |||
708 | if (!dev->platform_data) { | ||
709 | ret = bq24257_fw_probe(bq); | ||
710 | if (ret < 0) { | ||
711 | dev_err(dev, "Cannot read device properties.\n"); | ||
712 | return ret; | ||
713 | } | ||
714 | } else { | ||
715 | return -ENODEV; | ||
716 | } | ||
717 | |||
718 | /* we can only check Power Good status by probing the PG pin */ | ||
719 | ret = bq24257_pg_gpio_probe(bq); | ||
720 | if (ret < 0) | ||
721 | return ret; | ||
722 | |||
723 | /* reset all registers to defaults */ | ||
724 | ret = bq24257_field_write(bq, F_RESET, 1); | ||
725 | if (ret < 0) | ||
726 | return ret; | ||
727 | |||
728 | /* | ||
729 | * Put the RESET bit back to 0, in cache. For some reason the HW always | ||
730 | * returns 1 on this bit, so this is the only way to avoid resetting the | ||
731 | * chip every time we update another field in this register. | ||
732 | */ | ||
733 | ret = bq24257_field_write(bq, F_RESET, 0); | ||
734 | if (ret < 0) | ||
735 | return ret; | ||
736 | |||
737 | ret = bq24257_hw_init(bq); | ||
738 | if (ret < 0) { | ||
739 | dev_err(dev, "Cannot initialize the chip.\n"); | ||
740 | return ret; | ||
741 | } | ||
742 | |||
743 | if (client->irq <= 0) | ||
744 | client->irq = bq24257_irq_probe(bq); | ||
745 | |||
746 | if (client->irq < 0) { | ||
747 | dev_err(dev, "no irq resource found\n"); | ||
748 | return client->irq; | ||
749 | } | ||
750 | |||
751 | ret = devm_request_threaded_irq(dev, client->irq, NULL, | ||
752 | bq24257_irq_handler_thread, | ||
753 | IRQF_TRIGGER_FALLING | | ||
754 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
755 | BQ24257_STAT_IRQ, bq); | ||
756 | if (ret) | ||
757 | return ret; | ||
758 | |||
759 | ret = bq24257_power_supply_init(bq); | ||
760 | if (ret < 0) | ||
761 | dev_err(dev, "Failed to register power supply\n"); | ||
762 | |||
763 | return ret; | ||
764 | } | ||
765 | |||
766 | static int bq24257_remove(struct i2c_client *client) | ||
767 | { | ||
768 | struct bq24257_device *bq = i2c_get_clientdata(client); | ||
769 | |||
770 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
771 | |||
772 | power_supply_unregister(bq->charger); | ||
773 | |||
774 | bq24257_field_write(bq, F_RESET, 1); /* reset to defaults */ | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | #ifdef CONFIG_PM_SLEEP | ||
780 | static int bq24257_suspend(struct device *dev) | ||
781 | { | ||
782 | struct bq24257_device *bq = dev_get_drvdata(dev); | ||
783 | int ret = 0; | ||
784 | |||
785 | cancel_delayed_work_sync(&bq->iilimit_setup_work); | ||
786 | |||
787 | /* reset all registers to default (and activate standalone mode) */ | ||
788 | ret = bq24257_field_write(bq, F_RESET, 1); | ||
789 | if (ret < 0) | ||
790 | dev_err(bq->dev, "Cannot reset chip to standalone mode.\n"); | ||
791 | |||
792 | return ret; | ||
793 | } | ||
794 | |||
795 | static int bq24257_resume(struct device *dev) | ||
796 | { | ||
797 | int ret; | ||
798 | struct bq24257_device *bq = dev_get_drvdata(dev); | ||
799 | |||
800 | ret = regcache_drop_region(bq->rmap, BQ24257_REG_1, BQ24257_REG_7); | ||
801 | if (ret < 0) | ||
802 | return ret; | ||
803 | |||
804 | ret = bq24257_field_write(bq, F_RESET, 0); | ||
805 | if (ret < 0) | ||
806 | return ret; | ||
807 | |||
808 | ret = bq24257_hw_init(bq); | ||
809 | if (ret < 0) { | ||
810 | dev_err(bq->dev, "Cannot init chip after resume.\n"); | ||
811 | return ret; | ||
812 | } | ||
813 | |||
814 | /* signal userspace, maybe state changed while suspended */ | ||
815 | power_supply_changed(bq->charger); | ||
816 | |||
817 | return 0; | ||
818 | } | ||
819 | #endif | ||
820 | |||
821 | static const struct dev_pm_ops bq24257_pm = { | ||
822 | SET_SYSTEM_SLEEP_PM_OPS(bq24257_suspend, bq24257_resume) | ||
823 | }; | ||
824 | |||
825 | static const struct i2c_device_id bq24257_i2c_ids[] = { | ||
826 | { "bq24257", 0 }, | ||
827 | {}, | ||
828 | }; | ||
829 | MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids); | ||
830 | |||
831 | static const struct of_device_id bq24257_of_match[] = { | ||
832 | { .compatible = "ti,bq24257", }, | ||
833 | { }, | ||
834 | }; | ||
835 | MODULE_DEVICE_TABLE(of, bq24257_of_match); | ||
836 | |||
837 | static const struct acpi_device_id bq24257_acpi_match[] = { | ||
838 | {"BQ242570", 0}, | ||
839 | {}, | ||
840 | }; | ||
841 | MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match); | ||
842 | |||
843 | static struct i2c_driver bq24257_driver = { | ||
844 | .driver = { | ||
845 | .name = "bq24257-charger", | ||
846 | .of_match_table = of_match_ptr(bq24257_of_match), | ||
847 | .acpi_match_table = ACPI_PTR(bq24257_acpi_match), | ||
848 | .pm = &bq24257_pm, | ||
849 | }, | ||
850 | .probe = bq24257_probe, | ||
851 | .remove = bq24257_remove, | ||
852 | .id_table = bq24257_i2c_ids, | ||
853 | }; | ||
854 | module_i2c_driver(bq24257_driver); | ||
855 | |||
856 | MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>"); | ||
857 | MODULE_DESCRIPTION("bq24257 charger driver"); | ||
858 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/bq25890_charger.c b/drivers/power/bq25890_charger.c new file mode 100644 index 000000000000..f993a55cde20 --- /dev/null +++ b/drivers/power/bq25890_charger.c | |||
@@ -0,0 +1,994 @@ | |||
1 | /* | ||
2 | * TI BQ25890 charger driver | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corporation | ||
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 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/power_supply.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/gpio/consumer.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/usb/phy.h> | ||
27 | |||
28 | #include <linux/acpi.h> | ||
29 | #include <linux/of.h> | ||
30 | |||
31 | #define BQ25890_MANUFACTURER "Texas Instruments" | ||
32 | #define BQ25890_IRQ_PIN "bq25890_irq" | ||
33 | |||
34 | #define BQ25890_ID 3 | ||
35 | |||
36 | enum bq25890_fields { | ||
37 | F_EN_HIZ, F_EN_ILIM, F_IILIM, /* Reg00 */ | ||
38 | F_BHOT, F_BCOLD, F_VINDPM_OFS, /* Reg01 */ | ||
39 | F_CONV_START, F_CONV_RATE, F_BOOSTF, F_ICO_EN, | ||
40 | F_HVDCP_EN, F_MAXC_EN, F_FORCE_DPM, F_AUTO_DPDM_EN, /* Reg02 */ | ||
41 | F_BAT_LOAD_EN, F_WD_RST, F_OTG_CFG, F_CHG_CFG, F_SYSVMIN, /* Reg03 */ | ||
42 | F_PUMPX_EN, F_ICHG, /* Reg04 */ | ||
43 | F_IPRECHG, F_ITERM, /* Reg05 */ | ||
44 | F_VREG, F_BATLOWV, F_VRECHG, /* Reg06 */ | ||
45 | F_TERM_EN, F_STAT_DIS, F_WD, F_TMR_EN, F_CHG_TMR, | ||
46 | F_JEITA_ISET, /* Reg07 */ | ||
47 | F_BATCMP, F_VCLAMP, F_TREG, /* Reg08 */ | ||
48 | F_FORCE_ICO, F_TMR2X_EN, F_BATFET_DIS, F_JEITA_VSET, | ||
49 | F_BATFET_DLY, F_BATFET_RST_EN, F_PUMPX_UP, F_PUMPX_DN, /* Reg09 */ | ||
50 | F_BOOSTV, F_BOOSTI, /* Reg0A */ | ||
51 | F_VBUS_STAT, F_CHG_STAT, F_PG_STAT, F_SDP_STAT, F_VSYS_STAT, /* Reg0B */ | ||
52 | F_WD_FAULT, F_BOOST_FAULT, F_CHG_FAULT, F_BAT_FAULT, | ||
53 | F_NTC_FAULT, /* Reg0C */ | ||
54 | F_FORCE_VINDPM, F_VINDPM, /* Reg0D */ | ||
55 | F_THERM_STAT, F_BATV, /* Reg0E */ | ||
56 | F_SYSV, /* Reg0F */ | ||
57 | F_TSPCT, /* Reg10 */ | ||
58 | F_VBUS_GD, F_VBUSV, /* Reg11 */ | ||
59 | F_ICHGR, /* Reg12 */ | ||
60 | F_VDPM_STAT, F_IDPM_STAT, F_IDPM_LIM, /* Reg13 */ | ||
61 | F_REG_RST, F_ICO_OPTIMIZED, F_PN, F_TS_PROFILE, F_DEV_REV, /* Reg14 */ | ||
62 | |||
63 | F_MAX_FIELDS | ||
64 | }; | ||
65 | |||
66 | /* initial field values, converted to register values */ | ||
67 | struct bq25890_init_data { | ||
68 | u8 ichg; /* charge current */ | ||
69 | u8 vreg; /* regulation voltage */ | ||
70 | u8 iterm; /* termination current */ | ||
71 | u8 iprechg; /* precharge current */ | ||
72 | u8 sysvmin; /* minimum system voltage limit */ | ||
73 | u8 boostv; /* boost regulation voltage */ | ||
74 | u8 boosti; /* boost current limit */ | ||
75 | u8 boostf; /* boost frequency */ | ||
76 | u8 ilim_en; /* enable ILIM pin */ | ||
77 | u8 treg; /* thermal regulation threshold */ | ||
78 | }; | ||
79 | |||
80 | struct bq25890_state { | ||
81 | u8 online; | ||
82 | u8 chrg_status; | ||
83 | u8 chrg_fault; | ||
84 | u8 vsys_status; | ||
85 | u8 boost_fault; | ||
86 | u8 bat_fault; | ||
87 | }; | ||
88 | |||
89 | struct bq25890_device { | ||
90 | struct i2c_client *client; | ||
91 | struct device *dev; | ||
92 | struct power_supply *charger; | ||
93 | |||
94 | struct usb_phy *usb_phy; | ||
95 | struct notifier_block usb_nb; | ||
96 | struct work_struct usb_work; | ||
97 | unsigned long usb_event; | ||
98 | |||
99 | struct regmap *rmap; | ||
100 | struct regmap_field *rmap_fields[F_MAX_FIELDS]; | ||
101 | |||
102 | int chip_id; | ||
103 | struct bq25890_init_data init_data; | ||
104 | struct bq25890_state state; | ||
105 | |||
106 | struct mutex lock; /* protect state data */ | ||
107 | }; | ||
108 | |||
109 | static const struct regmap_range bq25890_readonly_reg_ranges[] = { | ||
110 | regmap_reg_range(0x0b, 0x0c), | ||
111 | regmap_reg_range(0x0e, 0x13), | ||
112 | }; | ||
113 | |||
114 | static const struct regmap_access_table bq25890_writeable_regs = { | ||
115 | .no_ranges = bq25890_readonly_reg_ranges, | ||
116 | .n_no_ranges = ARRAY_SIZE(bq25890_readonly_reg_ranges), | ||
117 | }; | ||
118 | |||
119 | static const struct regmap_range bq25890_volatile_reg_ranges[] = { | ||
120 | regmap_reg_range(0x00, 0x00), | ||
121 | regmap_reg_range(0x09, 0x09), | ||
122 | regmap_reg_range(0x0b, 0x0c), | ||
123 | regmap_reg_range(0x0e, 0x14), | ||
124 | }; | ||
125 | |||
126 | static const struct regmap_access_table bq25890_volatile_regs = { | ||
127 | .yes_ranges = bq25890_volatile_reg_ranges, | ||
128 | .n_yes_ranges = ARRAY_SIZE(bq25890_volatile_reg_ranges), | ||
129 | }; | ||
130 | |||
131 | static const struct regmap_config bq25890_regmap_config = { | ||
132 | .reg_bits = 8, | ||
133 | .val_bits = 8, | ||
134 | |||
135 | .max_register = 0x14, | ||
136 | .cache_type = REGCACHE_RBTREE, | ||
137 | |||
138 | .wr_table = &bq25890_writeable_regs, | ||
139 | .volatile_table = &bq25890_volatile_regs, | ||
140 | }; | ||
141 | |||
142 | static const struct reg_field bq25890_reg_fields[] = { | ||
143 | /* REG00 */ | ||
144 | [F_EN_HIZ] = REG_FIELD(0x00, 7, 7), | ||
145 | [F_EN_ILIM] = REG_FIELD(0x00, 6, 6), | ||
146 | [F_IILIM] = REG_FIELD(0x00, 0, 5), | ||
147 | /* REG01 */ | ||
148 | [F_BHOT] = REG_FIELD(0x01, 6, 7), | ||
149 | [F_BCOLD] = REG_FIELD(0x01, 5, 5), | ||
150 | [F_VINDPM_OFS] = REG_FIELD(0x01, 0, 4), | ||
151 | /* REG02 */ | ||
152 | [F_CONV_START] = REG_FIELD(0x02, 7, 7), | ||
153 | [F_CONV_RATE] = REG_FIELD(0x02, 6, 6), | ||
154 | [F_BOOSTF] = REG_FIELD(0x02, 5, 5), | ||
155 | [F_ICO_EN] = REG_FIELD(0x02, 4, 4), | ||
156 | [F_HVDCP_EN] = REG_FIELD(0x02, 3, 3), | ||
157 | [F_MAXC_EN] = REG_FIELD(0x02, 2, 2), | ||
158 | [F_FORCE_DPM] = REG_FIELD(0x02, 1, 1), | ||
159 | [F_AUTO_DPDM_EN] = REG_FIELD(0x02, 0, 0), | ||
160 | /* REG03 */ | ||
161 | [F_BAT_LOAD_EN] = REG_FIELD(0x03, 7, 7), | ||
162 | [F_WD_RST] = REG_FIELD(0x03, 6, 6), | ||
163 | [F_OTG_CFG] = REG_FIELD(0x03, 5, 5), | ||
164 | [F_CHG_CFG] = REG_FIELD(0x03, 4, 4), | ||
165 | [F_SYSVMIN] = REG_FIELD(0x03, 1, 3), | ||
166 | /* REG04 */ | ||
167 | [F_PUMPX_EN] = REG_FIELD(0x04, 7, 7), | ||
168 | [F_ICHG] = REG_FIELD(0x04, 0, 6), | ||
169 | /* REG05 */ | ||
170 | [F_IPRECHG] = REG_FIELD(0x05, 4, 7), | ||
171 | [F_ITERM] = REG_FIELD(0x05, 0, 3), | ||
172 | /* REG06 */ | ||
173 | [F_VREG] = REG_FIELD(0x06, 2, 7), | ||
174 | [F_BATLOWV] = REG_FIELD(0x06, 1, 1), | ||
175 | [F_VRECHG] = REG_FIELD(0x06, 0, 0), | ||
176 | /* REG07 */ | ||
177 | [F_TERM_EN] = REG_FIELD(0x07, 7, 7), | ||
178 | [F_STAT_DIS] = REG_FIELD(0x07, 6, 6), | ||
179 | [F_WD] = REG_FIELD(0x07, 4, 5), | ||
180 | [F_TMR_EN] = REG_FIELD(0x07, 3, 3), | ||
181 | [F_CHG_TMR] = REG_FIELD(0x07, 1, 2), | ||
182 | [F_JEITA_ISET] = REG_FIELD(0x07, 0, 0), | ||
183 | /* REG08 */ | ||
184 | [F_BATCMP] = REG_FIELD(0x08, 6, 7), | ||
185 | [F_VCLAMP] = REG_FIELD(0x08, 2, 4), | ||
186 | [F_TREG] = REG_FIELD(0x08, 0, 1), | ||
187 | /* REG09 */ | ||
188 | [F_FORCE_ICO] = REG_FIELD(0x09, 7, 7), | ||
189 | [F_TMR2X_EN] = REG_FIELD(0x09, 6, 6), | ||
190 | [F_BATFET_DIS] = REG_FIELD(0x09, 5, 5), | ||
191 | [F_JEITA_VSET] = REG_FIELD(0x09, 4, 4), | ||
192 | [F_BATFET_DLY] = REG_FIELD(0x09, 3, 3), | ||
193 | [F_BATFET_RST_EN] = REG_FIELD(0x09, 2, 2), | ||
194 | [F_PUMPX_UP] = REG_FIELD(0x09, 1, 1), | ||
195 | [F_PUMPX_DN] = REG_FIELD(0x09, 0, 0), | ||
196 | /* REG0A */ | ||
197 | [F_BOOSTV] = REG_FIELD(0x0A, 4, 7), | ||
198 | [F_BOOSTI] = REG_FIELD(0x0A, 0, 2), | ||
199 | /* REG0B */ | ||
200 | [F_VBUS_STAT] = REG_FIELD(0x0B, 5, 7), | ||
201 | [F_CHG_STAT] = REG_FIELD(0x0B, 3, 4), | ||
202 | [F_PG_STAT] = REG_FIELD(0x0B, 2, 2), | ||
203 | [F_SDP_STAT] = REG_FIELD(0x0B, 1, 1), | ||
204 | [F_VSYS_STAT] = REG_FIELD(0x0B, 0, 0), | ||
205 | /* REG0C */ | ||
206 | [F_WD_FAULT] = REG_FIELD(0x0C, 7, 7), | ||
207 | [F_BOOST_FAULT] = REG_FIELD(0x0C, 6, 6), | ||
208 | [F_CHG_FAULT] = REG_FIELD(0x0C, 4, 5), | ||
209 | [F_BAT_FAULT] = REG_FIELD(0x0C, 3, 3), | ||
210 | [F_NTC_FAULT] = REG_FIELD(0x0C, 0, 2), | ||
211 | /* REG0D */ | ||
212 | [F_FORCE_VINDPM] = REG_FIELD(0x0D, 7, 7), | ||
213 | [F_VINDPM] = REG_FIELD(0x0D, 0, 6), | ||
214 | /* REG0E */ | ||
215 | [F_THERM_STAT] = REG_FIELD(0x0E, 7, 7), | ||
216 | [F_BATV] = REG_FIELD(0x0E, 0, 6), | ||
217 | /* REG0F */ | ||
218 | [F_SYSV] = REG_FIELD(0x0F, 0, 6), | ||
219 | /* REG10 */ | ||
220 | [F_TSPCT] = REG_FIELD(0x10, 0, 6), | ||
221 | /* REG11 */ | ||
222 | [F_VBUS_GD] = REG_FIELD(0x11, 7, 7), | ||
223 | [F_VBUSV] = REG_FIELD(0x11, 0, 6), | ||
224 | /* REG12 */ | ||
225 | [F_ICHGR] = REG_FIELD(0x12, 0, 6), | ||
226 | /* REG13 */ | ||
227 | [F_VDPM_STAT] = REG_FIELD(0x13, 7, 7), | ||
228 | [F_IDPM_STAT] = REG_FIELD(0x13, 6, 6), | ||
229 | [F_IDPM_LIM] = REG_FIELD(0x13, 0, 5), | ||
230 | /* REG14 */ | ||
231 | [F_REG_RST] = REG_FIELD(0x14, 7, 7), | ||
232 | [F_ICO_OPTIMIZED] = REG_FIELD(0x14, 6, 6), | ||
233 | [F_PN] = REG_FIELD(0x14, 3, 5), | ||
234 | [F_TS_PROFILE] = REG_FIELD(0x14, 2, 2), | ||
235 | [F_DEV_REV] = REG_FIELD(0x14, 0, 1) | ||
236 | }; | ||
237 | |||
238 | /* | ||
239 | * Most of the val -> idx conversions can be computed, given the minimum, | ||
240 | * maximum and the step between values. For the rest of conversions, we use | ||
241 | * lookup tables. | ||
242 | */ | ||
243 | enum bq25890_table_ids { | ||
244 | /* range tables */ | ||
245 | TBL_ICHG, | ||
246 | TBL_ITERM, | ||
247 | TBL_IPRECHG, | ||
248 | TBL_VREG, | ||
249 | TBL_BATCMP, | ||
250 | TBL_VCLAMP, | ||
251 | TBL_BOOSTV, | ||
252 | TBL_SYSVMIN, | ||
253 | |||
254 | /* lookup tables */ | ||
255 | TBL_TREG, | ||
256 | TBL_BOOSTI, | ||
257 | }; | ||
258 | |||
259 | /* Thermal Regulation Threshold lookup table, in degrees Celsius */ | ||
260 | static const u32 bq25890_treg_tbl[] = { 60, 80, 100, 120 }; | ||
261 | |||
262 | #define BQ25890_TREG_TBL_SIZE ARRAY_SIZE(bq25890_treg_tbl) | ||
263 | |||
264 | /* Boost mode current limit lookup table, in uA */ | ||
265 | static const u32 bq25890_boosti_tbl[] = { | ||
266 | 500000, 700000, 1100000, 1300000, 1600000, 1800000, 2100000, 2400000 | ||
267 | }; | ||
268 | |||
269 | #define BQ25890_BOOSTI_TBL_SIZE ARRAY_SIZE(bq25890_boosti_tbl) | ||
270 | |||
271 | struct bq25890_range { | ||
272 | u32 min; | ||
273 | u32 max; | ||
274 | u32 step; | ||
275 | }; | ||
276 | |||
277 | struct bq25890_lookup { | ||
278 | const u32 *tbl; | ||
279 | u32 size; | ||
280 | }; | ||
281 | |||
282 | static const union { | ||
283 | struct bq25890_range rt; | ||
284 | struct bq25890_lookup lt; | ||
285 | } bq25890_tables[] = { | ||
286 | /* range tables */ | ||
287 | [TBL_ICHG] = { .rt = {0, 5056000, 64000} }, /* uA */ | ||
288 | [TBL_ITERM] = { .rt = {64000, 1024000, 64000} }, /* uA */ | ||
289 | [TBL_VREG] = { .rt = {3840000, 4608000, 16000} }, /* uV */ | ||
290 | [TBL_BATCMP] = { .rt = {0, 140, 20} }, /* mOhm */ | ||
291 | [TBL_VCLAMP] = { .rt = {0, 224000, 32000} }, /* uV */ | ||
292 | [TBL_BOOSTV] = { .rt = {4550000, 5510000, 64000} }, /* uV */ | ||
293 | [TBL_SYSVMIN] = { .rt = {3000000, 3700000, 100000} }, /* uV */ | ||
294 | |||
295 | /* lookup tables */ | ||
296 | [TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} }, | ||
297 | [TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} } | ||
298 | }; | ||
299 | |||
300 | static int bq25890_field_read(struct bq25890_device *bq, | ||
301 | enum bq25890_fields field_id) | ||
302 | { | ||
303 | int ret; | ||
304 | int val; | ||
305 | |||
306 | ret = regmap_field_read(bq->rmap_fields[field_id], &val); | ||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | |||
310 | return val; | ||
311 | } | ||
312 | |||
313 | static int bq25890_field_write(struct bq25890_device *bq, | ||
314 | enum bq25890_fields field_id, u8 val) | ||
315 | { | ||
316 | return regmap_field_write(bq->rmap_fields[field_id], val); | ||
317 | } | ||
318 | |||
319 | static u8 bq25890_find_idx(u32 value, enum bq25890_table_ids id) | ||
320 | { | ||
321 | u8 idx; | ||
322 | |||
323 | if (id >= TBL_TREG) { | ||
324 | const u32 *tbl = bq25890_tables[id].lt.tbl; | ||
325 | u32 tbl_size = bq25890_tables[id].lt.size; | ||
326 | |||
327 | for (idx = 1; idx < tbl_size && tbl[idx] <= value; idx++) | ||
328 | ; | ||
329 | } else { | ||
330 | const struct bq25890_range *rtbl = &bq25890_tables[id].rt; | ||
331 | u8 rtbl_size; | ||
332 | |||
333 | rtbl_size = (rtbl->max - rtbl->min) / rtbl->step + 1; | ||
334 | |||
335 | for (idx = 1; | ||
336 | idx < rtbl_size && (idx * rtbl->step + rtbl->min <= value); | ||
337 | idx++) | ||
338 | ; | ||
339 | } | ||
340 | |||
341 | return idx - 1; | ||
342 | } | ||
343 | |||
344 | static u32 bq25890_find_val(u8 idx, enum bq25890_table_ids id) | ||
345 | { | ||
346 | const struct bq25890_range *rtbl; | ||
347 | |||
348 | /* lookup table? */ | ||
349 | if (id >= TBL_TREG) | ||
350 | return bq25890_tables[id].lt.tbl[idx]; | ||
351 | |||
352 | /* range table */ | ||
353 | rtbl = &bq25890_tables[id].rt; | ||
354 | |||
355 | return (rtbl->min + idx * rtbl->step); | ||
356 | } | ||
357 | |||
358 | enum bq25890_status { | ||
359 | STATUS_NOT_CHARGING, | ||
360 | STATUS_PRE_CHARGING, | ||
361 | STATUS_FAST_CHARGING, | ||
362 | STATUS_TERMINATION_DONE, | ||
363 | }; | ||
364 | |||
365 | enum bq25890_chrg_fault { | ||
366 | CHRG_FAULT_NORMAL, | ||
367 | CHRG_FAULT_INPUT, | ||
368 | CHRG_FAULT_THERMAL_SHUTDOWN, | ||
369 | CHRG_FAULT_TIMER_EXPIRED, | ||
370 | }; | ||
371 | |||
372 | static int bq25890_power_supply_get_property(struct power_supply *psy, | ||
373 | enum power_supply_property psp, | ||
374 | union power_supply_propval *val) | ||
375 | { | ||
376 | int ret; | ||
377 | struct bq25890_device *bq = power_supply_get_drvdata(psy); | ||
378 | struct bq25890_state state; | ||
379 | |||
380 | mutex_lock(&bq->lock); | ||
381 | state = bq->state; | ||
382 | mutex_unlock(&bq->lock); | ||
383 | |||
384 | switch (psp) { | ||
385 | case POWER_SUPPLY_PROP_STATUS: | ||
386 | if (!state.online) | ||
387 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
388 | else if (state.chrg_status == STATUS_NOT_CHARGING) | ||
389 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
390 | else if (state.chrg_status == STATUS_PRE_CHARGING || | ||
391 | state.chrg_status == STATUS_FAST_CHARGING) | ||
392 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
393 | else if (state.chrg_status == STATUS_TERMINATION_DONE) | ||
394 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
395 | else | ||
396 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
397 | |||
398 | break; | ||
399 | |||
400 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
401 | val->strval = BQ25890_MANUFACTURER; | ||
402 | break; | ||
403 | |||
404 | case POWER_SUPPLY_PROP_ONLINE: | ||
405 | val->intval = state.online; | ||
406 | break; | ||
407 | |||
408 | case POWER_SUPPLY_PROP_HEALTH: | ||
409 | if (!state.chrg_fault && !state.bat_fault && !state.boost_fault) | ||
410 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
411 | else if (state.bat_fault) | ||
412 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
413 | else if (state.chrg_fault == CHRG_FAULT_TIMER_EXPIRED) | ||
414 | val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; | ||
415 | else if (state.chrg_fault == CHRG_FAULT_THERMAL_SHUTDOWN) | ||
416 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
417 | else | ||
418 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
419 | break; | ||
420 | |||
421 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
422 | ret = bq25890_field_read(bq, F_ICHGR); /* read measured value */ | ||
423 | if (ret < 0) | ||
424 | return ret; | ||
425 | |||
426 | /* converted_val = ADC_val * 50mA (table 10.3.19) */ | ||
427 | val->intval = ret * 50000; | ||
428 | break; | ||
429 | |||
430 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: | ||
431 | val->intval = bq25890_tables[TBL_ICHG].rt.max; | ||
432 | break; | ||
433 | |||
434 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
435 | if (!state.online) { | ||
436 | val->intval = 0; | ||
437 | break; | ||
438 | } | ||
439 | |||
440 | ret = bq25890_field_read(bq, F_BATV); /* read measured value */ | ||
441 | if (ret < 0) | ||
442 | return ret; | ||
443 | |||
444 | /* converted_val = 2.304V + ADC_val * 20mV (table 10.3.15) */ | ||
445 | val->intval = 2304000 + ret * 20000; | ||
446 | break; | ||
447 | |||
448 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: | ||
449 | val->intval = bq25890_tables[TBL_VREG].rt.max; | ||
450 | break; | ||
451 | |||
452 | case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: | ||
453 | val->intval = bq25890_find_val(bq->init_data.iterm, TBL_ITERM); | ||
454 | break; | ||
455 | |||
456 | default: | ||
457 | return -EINVAL; | ||
458 | } | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | static int bq25890_get_chip_state(struct bq25890_device *bq, | ||
464 | struct bq25890_state *state) | ||
465 | { | ||
466 | int i, ret; | ||
467 | |||
468 | struct { | ||
469 | enum bq25890_fields id; | ||
470 | u8 *data; | ||
471 | } state_fields[] = { | ||
472 | {F_CHG_STAT, &state->chrg_status}, | ||
473 | {F_PG_STAT, &state->online}, | ||
474 | {F_VSYS_STAT, &state->vsys_status}, | ||
475 | {F_BOOST_FAULT, &state->boost_fault}, | ||
476 | {F_BAT_FAULT, &state->bat_fault}, | ||
477 | {F_CHG_FAULT, &state->chrg_fault} | ||
478 | }; | ||
479 | |||
480 | for (i = 0; i < ARRAY_SIZE(state_fields); i++) { | ||
481 | ret = bq25890_field_read(bq, state_fields[i].id); | ||
482 | if (ret < 0) | ||
483 | return ret; | ||
484 | |||
485 | *state_fields[i].data = ret; | ||
486 | } | ||
487 | |||
488 | dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT=%d/%d/%d\n", | ||
489 | state->chrg_status, state->online, state->vsys_status, | ||
490 | state->chrg_fault, state->boost_fault, state->bat_fault); | ||
491 | |||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static bool bq25890_state_changed(struct bq25890_device *bq, | ||
496 | struct bq25890_state *new_state) | ||
497 | { | ||
498 | struct bq25890_state old_state; | ||
499 | |||
500 | mutex_lock(&bq->lock); | ||
501 | old_state = bq->state; | ||
502 | mutex_unlock(&bq->lock); | ||
503 | |||
504 | return (old_state.chrg_status != new_state->chrg_status || | ||
505 | old_state.chrg_fault != new_state->chrg_fault || | ||
506 | old_state.online != new_state->online || | ||
507 | old_state.bat_fault != new_state->bat_fault || | ||
508 | old_state.boost_fault != new_state->boost_fault || | ||
509 | old_state.vsys_status != new_state->vsys_status); | ||
510 | } | ||
511 | |||
512 | static void bq25890_handle_state_change(struct bq25890_device *bq, | ||
513 | struct bq25890_state *new_state) | ||
514 | { | ||
515 | int ret; | ||
516 | struct bq25890_state old_state; | ||
517 | |||
518 | mutex_lock(&bq->lock); | ||
519 | old_state = bq->state; | ||
520 | mutex_unlock(&bq->lock); | ||
521 | |||
522 | if (!new_state->online) { /* power removed */ | ||
523 | /* disable ADC */ | ||
524 | ret = bq25890_field_write(bq, F_CONV_START, 0); | ||
525 | if (ret < 0) | ||
526 | goto error; | ||
527 | } else if (!old_state.online) { /* power inserted */ | ||
528 | /* enable ADC, to have control of charge current/voltage */ | ||
529 | ret = bq25890_field_write(bq, F_CONV_START, 1); | ||
530 | if (ret < 0) | ||
531 | goto error; | ||
532 | } | ||
533 | |||
534 | return; | ||
535 | |||
536 | error: | ||
537 | dev_err(bq->dev, "Error communicating with the chip.\n"); | ||
538 | } | ||
539 | |||
540 | static irqreturn_t bq25890_irq_handler_thread(int irq, void *private) | ||
541 | { | ||
542 | struct bq25890_device *bq = private; | ||
543 | int ret; | ||
544 | struct bq25890_state state; | ||
545 | |||
546 | ret = bq25890_get_chip_state(bq, &state); | ||
547 | if (ret < 0) | ||
548 | goto handled; | ||
549 | |||
550 | if (!bq25890_state_changed(bq, &state)) | ||
551 | goto handled; | ||
552 | |||
553 | bq25890_handle_state_change(bq, &state); | ||
554 | |||
555 | mutex_lock(&bq->lock); | ||
556 | bq->state = state; | ||
557 | mutex_unlock(&bq->lock); | ||
558 | |||
559 | power_supply_changed(bq->charger); | ||
560 | |||
561 | handled: | ||
562 | return IRQ_HANDLED; | ||
563 | } | ||
564 | |||
565 | static int bq25890_chip_reset(struct bq25890_device *bq) | ||
566 | { | ||
567 | int ret; | ||
568 | int rst_check_counter = 10; | ||
569 | |||
570 | ret = bq25890_field_write(bq, F_REG_RST, 1); | ||
571 | if (ret < 0) | ||
572 | return ret; | ||
573 | |||
574 | do { | ||
575 | ret = bq25890_field_read(bq, F_REG_RST); | ||
576 | if (ret < 0) | ||
577 | return ret; | ||
578 | |||
579 | usleep_range(5, 10); | ||
580 | } while (ret == 1 && --rst_check_counter); | ||
581 | |||
582 | if (!rst_check_counter) | ||
583 | return -ETIMEDOUT; | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | |||
588 | static int bq25890_hw_init(struct bq25890_device *bq) | ||
589 | { | ||
590 | int ret; | ||
591 | int i; | ||
592 | struct bq25890_state state; | ||
593 | |||
594 | const struct { | ||
595 | enum bq25890_fields id; | ||
596 | u32 value; | ||
597 | } init_data[] = { | ||
598 | {F_ICHG, bq->init_data.ichg}, | ||
599 | {F_VREG, bq->init_data.vreg}, | ||
600 | {F_ITERM, bq->init_data.iterm}, | ||
601 | {F_IPRECHG, bq->init_data.iprechg}, | ||
602 | {F_SYSVMIN, bq->init_data.sysvmin}, | ||
603 | {F_BOOSTV, bq->init_data.boostv}, | ||
604 | {F_BOOSTI, bq->init_data.boosti}, | ||
605 | {F_BOOSTF, bq->init_data.boostf}, | ||
606 | {F_EN_ILIM, bq->init_data.ilim_en}, | ||
607 | {F_TREG, bq->init_data.treg} | ||
608 | }; | ||
609 | |||
610 | ret = bq25890_chip_reset(bq); | ||
611 | if (ret < 0) | ||
612 | return ret; | ||
613 | |||
614 | /* disable watchdog */ | ||
615 | ret = bq25890_field_write(bq, F_WD, 0); | ||
616 | if (ret < 0) | ||
617 | return ret; | ||
618 | |||
619 | /* initialize currents/voltages and other parameters */ | ||
620 | for (i = 0; i < ARRAY_SIZE(init_data); i++) { | ||
621 | ret = bq25890_field_write(bq, init_data[i].id, | ||
622 | init_data[i].value); | ||
623 | if (ret < 0) | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | /* Configure ADC for continuous conversions. This does not enable it. */ | ||
628 | ret = bq25890_field_write(bq, F_CONV_RATE, 1); | ||
629 | if (ret < 0) | ||
630 | return ret; | ||
631 | |||
632 | ret = bq25890_get_chip_state(bq, &state); | ||
633 | if (ret < 0) | ||
634 | return ret; | ||
635 | |||
636 | mutex_lock(&bq->lock); | ||
637 | bq->state = state; | ||
638 | mutex_unlock(&bq->lock); | ||
639 | |||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static enum power_supply_property bq25890_power_supply_props[] = { | ||
644 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
645 | POWER_SUPPLY_PROP_STATUS, | ||
646 | POWER_SUPPLY_PROP_ONLINE, | ||
647 | POWER_SUPPLY_PROP_HEALTH, | ||
648 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
649 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, | ||
650 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | ||
651 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | ||
652 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, | ||
653 | }; | ||
654 | |||
655 | static char *bq25890_charger_supplied_to[] = { | ||
656 | "main-battery", | ||
657 | }; | ||
658 | |||
659 | static const struct power_supply_desc bq25890_power_supply_desc = { | ||
660 | .name = "bq25890-charger", | ||
661 | .type = POWER_SUPPLY_TYPE_USB, | ||
662 | .properties = bq25890_power_supply_props, | ||
663 | .num_properties = ARRAY_SIZE(bq25890_power_supply_props), | ||
664 | .get_property = bq25890_power_supply_get_property, | ||
665 | }; | ||
666 | |||
667 | static int bq25890_power_supply_init(struct bq25890_device *bq) | ||
668 | { | ||
669 | struct power_supply_config psy_cfg = { .drv_data = bq, }; | ||
670 | |||
671 | psy_cfg.supplied_to = bq25890_charger_supplied_to; | ||
672 | psy_cfg.num_supplicants = ARRAY_SIZE(bq25890_charger_supplied_to); | ||
673 | |||
674 | bq->charger = power_supply_register(bq->dev, &bq25890_power_supply_desc, | ||
675 | &psy_cfg); | ||
676 | |||
677 | return PTR_ERR_OR_ZERO(bq->charger); | ||
678 | } | ||
679 | |||
680 | static void bq25890_usb_work(struct work_struct *data) | ||
681 | { | ||
682 | int ret; | ||
683 | struct bq25890_device *bq = | ||
684 | container_of(data, struct bq25890_device, usb_work); | ||
685 | |||
686 | switch (bq->usb_event) { | ||
687 | case USB_EVENT_ID: | ||
688 | /* Enable boost mode */ | ||
689 | ret = bq25890_field_write(bq, F_OTG_CFG, 1); | ||
690 | if (ret < 0) | ||
691 | goto error; | ||
692 | break; | ||
693 | |||
694 | case USB_EVENT_NONE: | ||
695 | /* Disable boost mode */ | ||
696 | ret = bq25890_field_write(bq, F_OTG_CFG, 0); | ||
697 | if (ret < 0) | ||
698 | goto error; | ||
699 | |||
700 | power_supply_changed(bq->charger); | ||
701 | break; | ||
702 | } | ||
703 | |||
704 | return; | ||
705 | |||
706 | error: | ||
707 | dev_err(bq->dev, "Error switching to boost/charger mode.\n"); | ||
708 | } | ||
709 | |||
710 | static int bq25890_usb_notifier(struct notifier_block *nb, unsigned long val, | ||
711 | void *priv) | ||
712 | { | ||
713 | struct bq25890_device *bq = | ||
714 | container_of(nb, struct bq25890_device, usb_nb); | ||
715 | |||
716 | bq->usb_event = val; | ||
717 | queue_work(system_power_efficient_wq, &bq->usb_work); | ||
718 | |||
719 | return NOTIFY_OK; | ||
720 | } | ||
721 | |||
722 | static int bq25890_irq_probe(struct bq25890_device *bq) | ||
723 | { | ||
724 | struct gpio_desc *irq; | ||
725 | |||
726 | irq = devm_gpiod_get_index(bq->dev, BQ25890_IRQ_PIN, 0, GPIOD_IN); | ||
727 | if (IS_ERR(irq)) { | ||
728 | dev_err(bq->dev, "Could not probe irq pin.\n"); | ||
729 | return PTR_ERR(irq); | ||
730 | } | ||
731 | |||
732 | return gpiod_to_irq(irq); | ||
733 | } | ||
734 | |||
735 | static int bq25890_fw_read_u32_props(struct bq25890_device *bq) | ||
736 | { | ||
737 | int ret; | ||
738 | u32 property; | ||
739 | int i; | ||
740 | struct bq25890_init_data *init = &bq->init_data; | ||
741 | struct { | ||
742 | char *name; | ||
743 | bool optional; | ||
744 | enum bq25890_table_ids tbl_id; | ||
745 | u8 *conv_data; /* holds converted value from given property */ | ||
746 | } props[] = { | ||
747 | /* required properties */ | ||
748 | {"ti,charge-current", false, TBL_ICHG, &init->ichg}, | ||
749 | {"ti,battery-regulation-voltage", false, TBL_VREG, &init->vreg}, | ||
750 | {"ti,termination-current", false, TBL_ITERM, &init->iterm}, | ||
751 | {"ti,precharge-current", false, TBL_ITERM, &init->iprechg}, | ||
752 | {"ti,minimum-sys-voltage", false, TBL_SYSVMIN, &init->sysvmin}, | ||
753 | {"ti,boost-voltage", false, TBL_BOOSTV, &init->boostv}, | ||
754 | {"ti,boost-max-current", false, TBL_BOOSTI, &init->boosti}, | ||
755 | |||
756 | /* optional properties */ | ||
757 | {"ti,thermal-regulation-threshold", true, TBL_TREG, &init->treg} | ||
758 | }; | ||
759 | |||
760 | /* initialize data for optional properties */ | ||
761 | init->treg = 3; /* 120 degrees Celsius */ | ||
762 | |||
763 | for (i = 0; i < ARRAY_SIZE(props); i++) { | ||
764 | ret = device_property_read_u32(bq->dev, props[i].name, | ||
765 | &property); | ||
766 | if (ret < 0) { | ||
767 | if (props[i].optional) | ||
768 | continue; | ||
769 | |||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | *props[i].conv_data = bq25890_find_idx(property, | ||
774 | props[i].tbl_id); | ||
775 | } | ||
776 | |||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | static int bq25890_fw_probe(struct bq25890_device *bq) | ||
781 | { | ||
782 | int ret; | ||
783 | struct bq25890_init_data *init = &bq->init_data; | ||
784 | |||
785 | ret = bq25890_fw_read_u32_props(bq); | ||
786 | if (ret < 0) | ||
787 | return ret; | ||
788 | |||
789 | init->ilim_en = device_property_read_bool(bq->dev, "ti,use-ilim-pin"); | ||
790 | init->boostf = device_property_read_bool(bq->dev, "ti,boost-low-freq"); | ||
791 | |||
792 | return 0; | ||
793 | } | ||
794 | |||
795 | static int bq25890_probe(struct i2c_client *client, | ||
796 | const struct i2c_device_id *id) | ||
797 | { | ||
798 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
799 | struct device *dev = &client->dev; | ||
800 | struct bq25890_device *bq; | ||
801 | int ret; | ||
802 | int i; | ||
803 | |||
804 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
805 | dev_err(dev, "No support for SMBUS_BYTE_DATA\n"); | ||
806 | return -ENODEV; | ||
807 | } | ||
808 | |||
809 | bq = devm_kzalloc(dev, sizeof(*bq), GFP_KERNEL); | ||
810 | if (!bq) | ||
811 | return -ENOMEM; | ||
812 | |||
813 | bq->client = client; | ||
814 | bq->dev = dev; | ||
815 | |||
816 | mutex_init(&bq->lock); | ||
817 | |||
818 | bq->rmap = devm_regmap_init_i2c(client, &bq25890_regmap_config); | ||
819 | if (IS_ERR(bq->rmap)) { | ||
820 | dev_err(dev, "failed to allocate register map\n"); | ||
821 | return PTR_ERR(bq->rmap); | ||
822 | } | ||
823 | |||
824 | for (i = 0; i < ARRAY_SIZE(bq25890_reg_fields); i++) { | ||
825 | const struct reg_field *reg_fields = bq25890_reg_fields; | ||
826 | |||
827 | bq->rmap_fields[i] = devm_regmap_field_alloc(dev, bq->rmap, | ||
828 | reg_fields[i]); | ||
829 | if (IS_ERR(bq->rmap_fields[i])) { | ||
830 | dev_err(dev, "cannot allocate regmap field\n"); | ||
831 | return PTR_ERR(bq->rmap_fields[i]); | ||
832 | } | ||
833 | } | ||
834 | |||
835 | i2c_set_clientdata(client, bq); | ||
836 | |||
837 | bq->chip_id = bq25890_field_read(bq, F_PN); | ||
838 | if (bq->chip_id < 0) { | ||
839 | dev_err(dev, "Cannot read chip ID.\n"); | ||
840 | return bq->chip_id; | ||
841 | } | ||
842 | |||
843 | if (bq->chip_id != BQ25890_ID) { | ||
844 | dev_err(dev, "Chip with ID=%d, not supported!\n", bq->chip_id); | ||
845 | return -ENODEV; | ||
846 | } | ||
847 | |||
848 | if (!dev->platform_data) { | ||
849 | ret = bq25890_fw_probe(bq); | ||
850 | if (ret < 0) { | ||
851 | dev_err(dev, "Cannot read device properties.\n"); | ||
852 | return ret; | ||
853 | } | ||
854 | } else { | ||
855 | return -ENODEV; | ||
856 | } | ||
857 | |||
858 | ret = bq25890_hw_init(bq); | ||
859 | if (ret < 0) { | ||
860 | dev_err(dev, "Cannot initialize the chip.\n"); | ||
861 | return ret; | ||
862 | } | ||
863 | |||
864 | if (client->irq <= 0) | ||
865 | client->irq = bq25890_irq_probe(bq); | ||
866 | |||
867 | if (client->irq < 0) { | ||
868 | dev_err(dev, "No irq resource found.\n"); | ||
869 | return client->irq; | ||
870 | } | ||
871 | |||
872 | /* OTG reporting */ | ||
873 | bq->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); | ||
874 | if (!IS_ERR_OR_NULL(bq->usb_phy)) { | ||
875 | INIT_WORK(&bq->usb_work, bq25890_usb_work); | ||
876 | bq->usb_nb.notifier_call = bq25890_usb_notifier; | ||
877 | usb_register_notifier(bq->usb_phy, &bq->usb_nb); | ||
878 | } | ||
879 | |||
880 | ret = devm_request_threaded_irq(dev, client->irq, NULL, | ||
881 | bq25890_irq_handler_thread, | ||
882 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
883 | BQ25890_IRQ_PIN, bq); | ||
884 | if (ret) | ||
885 | goto irq_fail; | ||
886 | |||
887 | ret = bq25890_power_supply_init(bq); | ||
888 | if (ret < 0) { | ||
889 | dev_err(dev, "Failed to register power supply\n"); | ||
890 | goto irq_fail; | ||
891 | } | ||
892 | |||
893 | return 0; | ||
894 | |||
895 | irq_fail: | ||
896 | if (!IS_ERR_OR_NULL(bq->usb_phy)) | ||
897 | usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); | ||
898 | |||
899 | return ret; | ||
900 | } | ||
901 | |||
902 | static int bq25890_remove(struct i2c_client *client) | ||
903 | { | ||
904 | struct bq25890_device *bq = i2c_get_clientdata(client); | ||
905 | |||
906 | power_supply_unregister(bq->charger); | ||
907 | |||
908 | if (!IS_ERR_OR_NULL(bq->usb_phy)) | ||
909 | usb_unregister_notifier(bq->usb_phy, &bq->usb_nb); | ||
910 | |||
911 | /* reset all registers to default values */ | ||
912 | bq25890_chip_reset(bq); | ||
913 | |||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | #ifdef CONFIG_PM_SLEEP | ||
918 | static int bq25890_suspend(struct device *dev) | ||
919 | { | ||
920 | struct bq25890_device *bq = dev_get_drvdata(dev); | ||
921 | |||
922 | /* | ||
923 | * If charger is removed, while in suspend, make sure ADC is diabled | ||
924 | * since it consumes slightly more power. | ||
925 | */ | ||
926 | return bq25890_field_write(bq, F_CONV_START, 0); | ||
927 | } | ||
928 | |||
929 | static int bq25890_resume(struct device *dev) | ||
930 | { | ||
931 | int ret; | ||
932 | struct bq25890_state state; | ||
933 | struct bq25890_device *bq = dev_get_drvdata(dev); | ||
934 | |||
935 | ret = bq25890_get_chip_state(bq, &state); | ||
936 | if (ret < 0) | ||
937 | return ret; | ||
938 | |||
939 | mutex_lock(&bq->lock); | ||
940 | bq->state = state; | ||
941 | mutex_unlock(&bq->lock); | ||
942 | |||
943 | /* Re-enable ADC only if charger is plugged in. */ | ||
944 | if (state.online) { | ||
945 | ret = bq25890_field_write(bq, F_CONV_START, 1); | ||
946 | if (ret < 0) | ||
947 | return ret; | ||
948 | } | ||
949 | |||
950 | /* signal userspace, maybe state changed while suspended */ | ||
951 | power_supply_changed(bq->charger); | ||
952 | |||
953 | return 0; | ||
954 | } | ||
955 | #endif | ||
956 | |||
957 | static const struct dev_pm_ops bq25890_pm = { | ||
958 | SET_SYSTEM_SLEEP_PM_OPS(bq25890_suspend, bq25890_resume) | ||
959 | }; | ||
960 | |||
961 | static const struct i2c_device_id bq25890_i2c_ids[] = { | ||
962 | { "bq25890", 0 }, | ||
963 | {}, | ||
964 | }; | ||
965 | MODULE_DEVICE_TABLE(i2c, bq25890_i2c_ids); | ||
966 | |||
967 | static const struct of_device_id bq25890_of_match[] = { | ||
968 | { .compatible = "ti,bq25890", }, | ||
969 | { }, | ||
970 | }; | ||
971 | MODULE_DEVICE_TABLE(of, bq25890_of_match); | ||
972 | |||
973 | static const struct acpi_device_id bq25890_acpi_match[] = { | ||
974 | {"BQ258900", 0}, | ||
975 | {}, | ||
976 | }; | ||
977 | MODULE_DEVICE_TABLE(acpi, bq25890_acpi_match); | ||
978 | |||
979 | static struct i2c_driver bq25890_driver = { | ||
980 | .driver = { | ||
981 | .name = "bq25890-charger", | ||
982 | .of_match_table = of_match_ptr(bq25890_of_match), | ||
983 | .acpi_match_table = ACPI_PTR(bq25890_acpi_match), | ||
984 | .pm = &bq25890_pm, | ||
985 | }, | ||
986 | .probe = bq25890_probe, | ||
987 | .remove = bq25890_remove, | ||
988 | .id_table = bq25890_i2c_ids, | ||
989 | }; | ||
990 | module_i2c_driver(bq25890_driver); | ||
991 | |||
992 | MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>"); | ||
993 | MODULE_DESCRIPTION("bq25890 charger driver"); | ||
994 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 0aed13f90891..1c202ccbd2a6 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c | |||
@@ -1768,7 +1768,8 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1768 | 1768 | ||
1769 | INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk); | 1769 | INIT_DELAYED_WORK(&cm->fullbatt_vchk_work, fullbatt_vchk); |
1770 | 1770 | ||
1771 | cm->charger_psy = power_supply_register(NULL, &cm->charger_psy_desc, | 1771 | cm->charger_psy = power_supply_register(&pdev->dev, |
1772 | &cm->charger_psy_desc, | ||
1772 | &psy_cfg); | 1773 | &psy_cfg); |
1773 | if (IS_ERR(cm->charger_psy)) { | 1774 | if (IS_ERR(cm->charger_psy)) { |
1774 | dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n", | 1775 | dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n", |
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index 6cc5e87ec031..e89255764745 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
@@ -63,6 +63,8 @@ | |||
63 | #define dP_ACC_100 0x1900 | 63 | #define dP_ACC_100 0x1900 |
64 | #define dP_ACC_200 0x3200 | 64 | #define dP_ACC_200 0x3200 |
65 | 65 | ||
66 | #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */ | ||
67 | |||
66 | struct max17042_chip { | 68 | struct max17042_chip { |
67 | struct i2c_client *client; | 69 | struct i2c_client *client; |
68 | struct regmap *regmap; | 70 | struct regmap *regmap; |
@@ -85,10 +87,94 @@ static enum power_supply_property max17042_battery_props[] = { | |||
85 | POWER_SUPPLY_PROP_CHARGE_FULL, | 87 | POWER_SUPPLY_PROP_CHARGE_FULL, |
86 | POWER_SUPPLY_PROP_CHARGE_COUNTER, | 88 | POWER_SUPPLY_PROP_CHARGE_COUNTER, |
87 | POWER_SUPPLY_PROP_TEMP, | 89 | POWER_SUPPLY_PROP_TEMP, |
90 | POWER_SUPPLY_PROP_TEMP_ALERT_MIN, | ||
91 | POWER_SUPPLY_PROP_TEMP_ALERT_MAX, | ||
92 | POWER_SUPPLY_PROP_TEMP_MIN, | ||
93 | POWER_SUPPLY_PROP_TEMP_MAX, | ||
94 | POWER_SUPPLY_PROP_HEALTH, | ||
88 | POWER_SUPPLY_PROP_CURRENT_NOW, | 95 | POWER_SUPPLY_PROP_CURRENT_NOW, |
89 | POWER_SUPPLY_PROP_CURRENT_AVG, | 96 | POWER_SUPPLY_PROP_CURRENT_AVG, |
90 | }; | 97 | }; |
91 | 98 | ||
99 | static int max17042_get_temperature(struct max17042_chip *chip, int *temp) | ||
100 | { | ||
101 | int ret; | ||
102 | u32 data; | ||
103 | struct regmap *map = chip->regmap; | ||
104 | |||
105 | ret = regmap_read(map, MAX17042_TEMP, &data); | ||
106 | if (ret < 0) | ||
107 | return ret; | ||
108 | |||
109 | *temp = data; | ||
110 | /* The value is signed. */ | ||
111 | if (*temp & 0x8000) { | ||
112 | *temp = (0x7fff & ~*temp) + 1; | ||
113 | *temp *= -1; | ||
114 | } | ||
115 | |||
116 | /* The value is converted into deci-centigrade scale */ | ||
117 | /* Units of LSB = 1 / 256 degree Celsius */ | ||
118 | *temp = *temp * 10 / 256; | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int max17042_get_battery_health(struct max17042_chip *chip, int *health) | ||
123 | { | ||
124 | int temp, vavg, vbatt, ret; | ||
125 | u32 val; | ||
126 | |||
127 | ret = regmap_read(chip->regmap, MAX17042_AvgVCELL, &val); | ||
128 | if (ret < 0) | ||
129 | goto health_error; | ||
130 | |||
131 | /* bits [0-3] unused */ | ||
132 | vavg = val * 625 / 8; | ||
133 | /* Convert to millivolts */ | ||
134 | vavg /= 1000; | ||
135 | |||
136 | ret = regmap_read(chip->regmap, MAX17042_VCELL, &val); | ||
137 | if (ret < 0) | ||
138 | goto health_error; | ||
139 | |||
140 | /* bits [0-3] unused */ | ||
141 | vbatt = val * 625 / 8; | ||
142 | /* Convert to millivolts */ | ||
143 | vbatt /= 1000; | ||
144 | |||
145 | if (vavg < chip->pdata->vmin) { | ||
146 | *health = POWER_SUPPLY_HEALTH_DEAD; | ||
147 | goto out; | ||
148 | } | ||
149 | |||
150 | if (vbatt > chip->pdata->vmax + MAX17042_VMAX_TOLERANCE) { | ||
151 | *health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
152 | goto out; | ||
153 | } | ||
154 | |||
155 | ret = max17042_get_temperature(chip, &temp); | ||
156 | if (ret < 0) | ||
157 | goto health_error; | ||
158 | |||
159 | if (temp <= chip->pdata->temp_min) { | ||
160 | *health = POWER_SUPPLY_HEALTH_COLD; | ||
161 | goto out; | ||
162 | } | ||
163 | |||
164 | if (temp >= chip->pdata->temp_max) { | ||
165 | *health = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
166 | goto out; | ||
167 | } | ||
168 | |||
169 | *health = POWER_SUPPLY_HEALTH_GOOD; | ||
170 | |||
171 | out: | ||
172 | return 0; | ||
173 | |||
174 | health_error: | ||
175 | return ret; | ||
176 | } | ||
177 | |||
92 | static int max17042_get_property(struct power_supply *psy, | 178 | static int max17042_get_property(struct power_supply *psy, |
93 | enum power_supply_property psp, | 179 | enum power_supply_property psp, |
94 | union power_supply_propval *val) | 180 | union power_supply_propval *val) |
@@ -181,19 +267,34 @@ static int max17042_get_property(struct power_supply *psy, | |||
181 | val->intval = data * 1000 / 2; | 267 | val->intval = data * 1000 / 2; |
182 | break; | 268 | break; |
183 | case POWER_SUPPLY_PROP_TEMP: | 269 | case POWER_SUPPLY_PROP_TEMP: |
184 | ret = regmap_read(map, MAX17042_TEMP, &data); | 270 | ret = max17042_get_temperature(chip, &val->intval); |
271 | if (ret < 0) | ||
272 | return ret; | ||
273 | break; | ||
274 | case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: | ||
275 | ret = regmap_read(map, MAX17042_TALRT_Th, &data); | ||
276 | if (ret < 0) | ||
277 | return ret; | ||
278 | /* LSB is Alert Minimum. In deci-centigrade */ | ||
279 | val->intval = (data & 0xff) * 10; | ||
280 | break; | ||
281 | case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: | ||
282 | ret = regmap_read(map, MAX17042_TALRT_Th, &data); | ||
283 | if (ret < 0) | ||
284 | return ret; | ||
285 | /* MSB is Alert Maximum. In deci-centigrade */ | ||
286 | val->intval = (data >> 8) * 10; | ||
287 | break; | ||
288 | case POWER_SUPPLY_PROP_TEMP_MIN: | ||
289 | val->intval = chip->pdata->temp_min; | ||
290 | break; | ||
291 | case POWER_SUPPLY_PROP_TEMP_MAX: | ||
292 | val->intval = chip->pdata->temp_max; | ||
293 | break; | ||
294 | case POWER_SUPPLY_PROP_HEALTH: | ||
295 | ret = max17042_get_battery_health(chip, &val->intval); | ||
185 | if (ret < 0) | 296 | if (ret < 0) |
186 | return ret; | 297 | return ret; |
187 | |||
188 | val->intval = data; | ||
189 | /* The value is signed. */ | ||
190 | if (val->intval & 0x8000) { | ||
191 | val->intval = (0x7fff & ~val->intval) + 1; | ||
192 | val->intval *= -1; | ||
193 | } | ||
194 | /* The value is converted into deci-centigrade scale */ | ||
195 | /* Units of LSB = 1 / 256 degree Celsius */ | ||
196 | val->intval = val->intval * 10 / 256; | ||
197 | break; | 298 | break; |
198 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 299 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
199 | if (chip->pdata->enable_current_sense) { | 300 | if (chip->pdata->enable_current_sense) { |
@@ -237,6 +338,69 @@ static int max17042_get_property(struct power_supply *psy, | |||
237 | return 0; | 338 | return 0; |
238 | } | 339 | } |
239 | 340 | ||
341 | static int max17042_set_property(struct power_supply *psy, | ||
342 | enum power_supply_property psp, | ||
343 | const union power_supply_propval *val) | ||
344 | { | ||
345 | struct max17042_chip *chip = power_supply_get_drvdata(psy); | ||
346 | struct regmap *map = chip->regmap; | ||
347 | int ret = 0; | ||
348 | u32 data; | ||
349 | int8_t temp; | ||
350 | |||
351 | switch (psp) { | ||
352 | case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: | ||
353 | ret = regmap_read(map, MAX17042_TALRT_Th, &data); | ||
354 | if (ret < 0) | ||
355 | return ret; | ||
356 | |||
357 | /* Input in deci-centigrade, convert to centigrade */ | ||
358 | temp = val->intval / 10; | ||
359 | /* force min < max */ | ||
360 | if (temp >= (int8_t)(data >> 8)) | ||
361 | temp = (int8_t)(data >> 8) - 1; | ||
362 | /* Write both MAX and MIN ALERT */ | ||
363 | data = (data & 0xff00) + temp; | ||
364 | ret = regmap_write(map, MAX17042_TALRT_Th, data); | ||
365 | break; | ||
366 | case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: | ||
367 | ret = regmap_read(map, MAX17042_TALRT_Th, &data); | ||
368 | if (ret < 0) | ||
369 | return ret; | ||
370 | |||
371 | /* Input in Deci-Centigrade, convert to centigrade */ | ||
372 | temp = val->intval / 10; | ||
373 | /* force max > min */ | ||
374 | if (temp <= (int8_t)(data & 0xff)) | ||
375 | temp = (int8_t)(data & 0xff) + 1; | ||
376 | /* Write both MAX and MIN ALERT */ | ||
377 | data = (data & 0xff) + (temp << 8); | ||
378 | ret = regmap_write(map, MAX17042_TALRT_Th, data); | ||
379 | break; | ||
380 | default: | ||
381 | ret = -EINVAL; | ||
382 | } | ||
383 | |||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | static int max17042_property_is_writeable(struct power_supply *psy, | ||
388 | enum power_supply_property psp) | ||
389 | { | ||
390 | int ret; | ||
391 | |||
392 | switch (psp) { | ||
393 | case POWER_SUPPLY_PROP_TEMP_ALERT_MIN: | ||
394 | case POWER_SUPPLY_PROP_TEMP_ALERT_MAX: | ||
395 | ret = 1; | ||
396 | break; | ||
397 | default: | ||
398 | ret = 0; | ||
399 | } | ||
400 | |||
401 | return ret; | ||
402 | } | ||
403 | |||
240 | static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value) | 404 | static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value) |
241 | { | 405 | { |
242 | int retries = 8; | 406 | int retries = 8; |
@@ -645,6 +809,15 @@ max17042_get_pdata(struct device *dev) | |||
645 | pdata->enable_current_sense = true; | 809 | pdata->enable_current_sense = true; |
646 | } | 810 | } |
647 | 811 | ||
812 | if (of_property_read_s32(np, "maxim,cold-temp", &pdata->temp_min)) | ||
813 | pdata->temp_min = INT_MIN; | ||
814 | if (of_property_read_s32(np, "maxim,over-heat-temp", &pdata->temp_max)) | ||
815 | pdata->temp_max = INT_MAX; | ||
816 | if (of_property_read_s32(np, "maxim,dead-volt", &pdata->vmin)) | ||
817 | pdata->vmin = INT_MIN; | ||
818 | if (of_property_read_s32(np, "maxim,over-volt", &pdata->vmax)) | ||
819 | pdata->vmax = INT_MAX; | ||
820 | |||
648 | return pdata; | 821 | return pdata; |
649 | } | 822 | } |
650 | #else | 823 | #else |
@@ -665,6 +838,8 @@ static const struct power_supply_desc max17042_psy_desc = { | |||
665 | .name = "max170xx_battery", | 838 | .name = "max170xx_battery", |
666 | .type = POWER_SUPPLY_TYPE_BATTERY, | 839 | .type = POWER_SUPPLY_TYPE_BATTERY, |
667 | .get_property = max17042_get_property, | 840 | .get_property = max17042_get_property, |
841 | .set_property = max17042_set_property, | ||
842 | .property_is_writeable = max17042_property_is_writeable, | ||
668 | .properties = max17042_battery_props, | 843 | .properties = max17042_battery_props, |
669 | .num_properties = ARRAY_SIZE(max17042_battery_props), | 844 | .num_properties = ARRAY_SIZE(max17042_battery_props), |
670 | }; | 845 | }; |
@@ -673,6 +848,8 @@ static const struct power_supply_desc max17042_no_current_sense_psy_desc = { | |||
673 | .name = "max170xx_battery", | 848 | .name = "max170xx_battery", |
674 | .type = POWER_SUPPLY_TYPE_BATTERY, | 849 | .type = POWER_SUPPLY_TYPE_BATTERY, |
675 | .get_property = max17042_get_property, | 850 | .get_property = max17042_get_property, |
851 | .set_property = max17042_set_property, | ||
852 | .property_is_writeable = max17042_property_is_writeable, | ||
676 | .properties = max17042_battery_props, | 853 | .properties = max17042_battery_props, |
677 | .num_properties = ARRAY_SIZE(max17042_battery_props) - 2, | 854 | .num_properties = ARRAY_SIZE(max17042_battery_props) - 2, |
678 | }; | 855 | }; |
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 2ed4a4a6b3c5..869284c2e1e8 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c | |||
@@ -30,6 +30,8 @@ EXPORT_SYMBOL_GPL(power_supply_notifier); | |||
30 | 30 | ||
31 | static struct device_type power_supply_dev_type; | 31 | static struct device_type power_supply_dev_type; |
32 | 32 | ||
33 | #define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10) | ||
34 | |||
33 | static bool __power_supply_is_supplied_by(struct power_supply *supplier, | 35 | static bool __power_supply_is_supplied_by(struct power_supply *supplier, |
34 | struct power_supply *supply) | 36 | struct power_supply *supply) |
35 | { | 37 | { |
@@ -121,6 +123,30 @@ void power_supply_changed(struct power_supply *psy) | |||
121 | } | 123 | } |
122 | EXPORT_SYMBOL_GPL(power_supply_changed); | 124 | EXPORT_SYMBOL_GPL(power_supply_changed); |
123 | 125 | ||
126 | /* | ||
127 | * Notify that power supply was registered after parent finished the probing. | ||
128 | * | ||
129 | * Often power supply is registered from driver's probe function. However | ||
130 | * calling power_supply_changed() directly from power_supply_register() | ||
131 | * would lead to execution of get_property() function provided by the driver | ||
132 | * too early - before the probe ends. | ||
133 | * | ||
134 | * Avoid that by waiting on parent's mutex. | ||
135 | */ | ||
136 | static void power_supply_deferred_register_work(struct work_struct *work) | ||
137 | { | ||
138 | struct power_supply *psy = container_of(work, struct power_supply, | ||
139 | deferred_register_work.work); | ||
140 | |||
141 | if (psy->dev.parent) | ||
142 | mutex_lock(&psy->dev.parent->mutex); | ||
143 | |||
144 | power_supply_changed(psy); | ||
145 | |||
146 | if (psy->dev.parent) | ||
147 | mutex_unlock(&psy->dev.parent->mutex); | ||
148 | } | ||
149 | |||
124 | #ifdef CONFIG_OF | 150 | #ifdef CONFIG_OF |
125 | #include <linux/of.h> | 151 | #include <linux/of.h> |
126 | 152 | ||
@@ -420,6 +446,45 @@ struct power_supply *power_supply_get_by_phandle(struct device_node *np, | |||
420 | return psy; | 446 | return psy; |
421 | } | 447 | } |
422 | EXPORT_SYMBOL_GPL(power_supply_get_by_phandle); | 448 | EXPORT_SYMBOL_GPL(power_supply_get_by_phandle); |
449 | |||
450 | static void devm_power_supply_put(struct device *dev, void *res) | ||
451 | { | ||
452 | struct power_supply **psy = res; | ||
453 | |||
454 | power_supply_put(*psy); | ||
455 | } | ||
456 | |||
457 | /** | ||
458 | * devm_power_supply_get_by_phandle() - Resource managed version of | ||
459 | * power_supply_get_by_phandle() | ||
460 | * @dev: Pointer to device holding phandle property | ||
461 | * @phandle_name: Name of property holding a power supply phandle | ||
462 | * | ||
463 | * Return: On success returns a reference to a power supply with | ||
464 | * matching name equals to value under @property, NULL or ERR_PTR otherwise. | ||
465 | */ | ||
466 | struct power_supply *devm_power_supply_get_by_phandle(struct device *dev, | ||
467 | const char *property) | ||
468 | { | ||
469 | struct power_supply **ptr, *psy; | ||
470 | |||
471 | if (!dev->of_node) | ||
472 | return ERR_PTR(-ENODEV); | ||
473 | |||
474 | ptr = devres_alloc(devm_power_supply_put, sizeof(*ptr), GFP_KERNEL); | ||
475 | if (!ptr) | ||
476 | return ERR_PTR(-ENOMEM); | ||
477 | |||
478 | psy = power_supply_get_by_phandle(dev->of_node, property); | ||
479 | if (IS_ERR_OR_NULL(psy)) { | ||
480 | devres_free(ptr); | ||
481 | } else { | ||
482 | *ptr = psy; | ||
483 | devres_add(dev, ptr); | ||
484 | } | ||
485 | return psy; | ||
486 | } | ||
487 | EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle); | ||
423 | #endif /* CONFIG_OF */ | 488 | #endif /* CONFIG_OF */ |
424 | 489 | ||
425 | int power_supply_get_property(struct power_supply *psy, | 490 | int power_supply_get_property(struct power_supply *psy, |
@@ -645,6 +710,10 @@ __power_supply_register(struct device *parent, | |||
645 | struct power_supply *psy; | 710 | struct power_supply *psy; |
646 | int rc; | 711 | int rc; |
647 | 712 | ||
713 | if (!parent) | ||
714 | pr_warn("%s: Expected proper parent device for '%s'\n", | ||
715 | __func__, desc->name); | ||
716 | |||
648 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); | 717 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); |
649 | if (!psy) | 718 | if (!psy) |
650 | return ERR_PTR(-ENOMEM); | 719 | return ERR_PTR(-ENOMEM); |
@@ -659,7 +728,6 @@ __power_supply_register(struct device *parent, | |||
659 | dev->release = power_supply_dev_release; | 728 | dev->release = power_supply_dev_release; |
660 | dev_set_drvdata(dev, psy); | 729 | dev_set_drvdata(dev, psy); |
661 | psy->desc = desc; | 730 | psy->desc = desc; |
662 | atomic_inc(&psy->use_cnt); | ||
663 | if (cfg) { | 731 | if (cfg) { |
664 | psy->drv_data = cfg->drv_data; | 732 | psy->drv_data = cfg->drv_data; |
665 | psy->of_node = cfg->of_node; | 733 | psy->of_node = cfg->of_node; |
@@ -672,6 +740,8 @@ __power_supply_register(struct device *parent, | |||
672 | goto dev_set_name_failed; | 740 | goto dev_set_name_failed; |
673 | 741 | ||
674 | INIT_WORK(&psy->changed_work, power_supply_changed_work); | 742 | INIT_WORK(&psy->changed_work, power_supply_changed_work); |
743 | INIT_DELAYED_WORK(&psy->deferred_register_work, | ||
744 | power_supply_deferred_register_work); | ||
675 | 745 | ||
676 | rc = power_supply_check_supplies(psy); | 746 | rc = power_supply_check_supplies(psy); |
677 | if (rc) { | 747 | if (rc) { |
@@ -700,7 +770,20 @@ __power_supply_register(struct device *parent, | |||
700 | if (rc) | 770 | if (rc) |
701 | goto create_triggers_failed; | 771 | goto create_triggers_failed; |
702 | 772 | ||
703 | power_supply_changed(psy); | 773 | /* |
774 | * Update use_cnt after any uevents (most notably from device_add()). | ||
775 | * We are here still during driver's probe but | ||
776 | * the power_supply_uevent() calls back driver's get_property | ||
777 | * method so: | ||
778 | * 1. Driver did not assigned the returned struct power_supply, | ||
779 | * 2. Driver could not finish initialization (anything in its probe | ||
780 | * after calling power_supply_register()). | ||
781 | */ | ||
782 | atomic_inc(&psy->use_cnt); | ||
783 | |||
784 | queue_delayed_work(system_power_efficient_wq, | ||
785 | &psy->deferred_register_work, | ||
786 | POWER_SUPPLY_DEFERRED_REGISTER_TIME); | ||
704 | 787 | ||
705 | return psy; | 788 | return psy; |
706 | 789 | ||
@@ -720,7 +803,8 @@ dev_set_name_failed: | |||
720 | 803 | ||
721 | /** | 804 | /** |
722 | * power_supply_register() - Register new power supply | 805 | * power_supply_register() - Register new power supply |
723 | * @parent: Device to be a parent of power supply's device | 806 | * @parent: Device to be a parent of power supply's device, usually |
807 | * the device which probe function calls this | ||
724 | * @desc: Description of power supply, must be valid through whole | 808 | * @desc: Description of power supply, must be valid through whole |
725 | * lifetime of this power supply | 809 | * lifetime of this power supply |
726 | * @cfg: Run-time specific configuration accessed during registering, | 810 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -740,8 +824,9 @@ struct power_supply *__must_check power_supply_register(struct device *parent, | |||
740 | EXPORT_SYMBOL_GPL(power_supply_register); | 824 | EXPORT_SYMBOL_GPL(power_supply_register); |
741 | 825 | ||
742 | /** | 826 | /** |
743 | * power_supply_register() - Register new non-waking-source power supply | 827 | * power_supply_register_no_ws() - Register new non-waking-source power supply |
744 | * @parent: Device to be a parent of power supply's device | 828 | * @parent: Device to be a parent of power supply's device, usually |
829 | * the device which probe function calls this | ||
745 | * @desc: Description of power supply, must be valid through whole | 830 | * @desc: Description of power supply, must be valid through whole |
746 | * lifetime of this power supply | 831 | * lifetime of this power supply |
747 | * @cfg: Run-time specific configuration accessed during registering, | 832 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -769,8 +854,9 @@ static void devm_power_supply_release(struct device *dev, void *res) | |||
769 | } | 854 | } |
770 | 855 | ||
771 | /** | 856 | /** |
772 | * power_supply_register() - Register managed power supply | 857 | * devm_power_supply_register() - Register managed power supply |
773 | * @parent: Device to be a parent of power supply's device | 858 | * @parent: Device to be a parent of power supply's device, usually |
859 | * the device which probe function calls this | ||
774 | * @desc: Description of power supply, must be valid through whole | 860 | * @desc: Description of power supply, must be valid through whole |
775 | * lifetime of this power supply | 861 | * lifetime of this power supply |
776 | * @cfg: Run-time specific configuration accessed during registering, | 862 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -804,8 +890,9 @@ devm_power_supply_register(struct device *parent, | |||
804 | EXPORT_SYMBOL_GPL(devm_power_supply_register); | 890 | EXPORT_SYMBOL_GPL(devm_power_supply_register); |
805 | 891 | ||
806 | /** | 892 | /** |
807 | * power_supply_register() - Register managed non-waking-source power supply | 893 | * devm_power_supply_register_no_ws() - Register managed non-waking-source power supply |
808 | * @parent: Device to be a parent of power supply's device | 894 | * @parent: Device to be a parent of power supply's device, usually |
895 | * the device which probe function calls this | ||
809 | * @desc: Description of power supply, must be valid through whole | 896 | * @desc: Description of power supply, must be valid through whole |
810 | * lifetime of this power supply | 897 | * lifetime of this power supply |
811 | * @cfg: Run-time specific configuration accessed during registering, | 898 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -849,6 +936,7 @@ void power_supply_unregister(struct power_supply *psy) | |||
849 | { | 936 | { |
850 | WARN_ON(atomic_dec_return(&psy->use_cnt)); | 937 | WARN_ON(atomic_dec_return(&psy->use_cnt)); |
851 | cancel_work_sync(&psy->changed_work); | 938 | cancel_work_sync(&psy->changed_work); |
939 | cancel_delayed_work_sync(&psy->deferred_register_work); | ||
852 | sysfs_remove_link(&psy->dev.kobj, "powers"); | 940 | sysfs_remove_link(&psy->dev.kobj, "powers"); |
853 | power_supply_remove_triggers(psy); | 941 | power_supply_remove_triggers(psy); |
854 | psy_unregister_cooler(psy); | 942 | psy_unregister_cooler(psy); |
diff --git a/drivers/power/power_supply_leds.c b/drivers/power/power_supply_leds.c index 2d41a43fc81a..2277ad9c2f68 100644 --- a/drivers/power/power_supply_leds.c +++ b/drivers/power/power_supply_leds.c | |||
@@ -25,7 +25,7 @@ static void power_supply_update_bat_leds(struct power_supply *psy) | |||
25 | unsigned long delay_on = 0; | 25 | unsigned long delay_on = 0; |
26 | unsigned long delay_off = 0; | 26 | unsigned long delay_off = 0; |
27 | 27 | ||
28 | if (psy->desc->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status)) | 28 | if (power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &status)) |
29 | return; | 29 | return; |
30 | 30 | ||
31 | dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval); | 31 | dev_dbg(&psy->dev, "%s %d\n", __func__, status.intval); |
@@ -115,7 +115,7 @@ static void power_supply_update_gen_leds(struct power_supply *psy) | |||
115 | { | 115 | { |
116 | union power_supply_propval online; | 116 | union power_supply_propval online; |
117 | 117 | ||
118 | if (psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online)) | 118 | if (power_supply_get_property(psy, POWER_SUPPLY_PROP_ONLINE, &online)) |
119 | return; | 119 | return; |
120 | 120 | ||
121 | dev_dbg(&psy->dev, "%s %d\n", __func__, online.intval); | 121 | dev_dbg(&psy->dev, "%s %d\n", __func__, online.intval); |
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 9134e3d2d95e..ed2d7fd0c734 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -125,7 +125,7 @@ static ssize_t power_supply_store_property(struct device *dev, | |||
125 | 125 | ||
126 | value.intval = long_val; | 126 | value.intval = long_val; |
127 | 127 | ||
128 | ret = psy->desc->set_property(psy, off, &value); | 128 | ret = power_supply_set_property(psy, off, &value); |
129 | if (ret < 0) | 129 | if (ret < 0) |
130 | return ret; | 130 | return ret; |
131 | 131 | ||
@@ -223,7 +223,7 @@ static umode_t power_supply_attr_is_visible(struct kobject *kobj, | |||
223 | 223 | ||
224 | if (property == attrno) { | 224 | if (property == attrno) { |
225 | if (psy->desc->property_is_writeable && | 225 | if (psy->desc->property_is_writeable && |
226 | power_supply_property_is_writeable(psy, property) > 0) | 226 | psy->desc->property_is_writeable(psy, property) > 0) |
227 | mode |= S_IWUSR; | 227 | mode |= S_IWUSR; |
228 | 228 | ||
229 | return mode; | 229 | return mode; |
diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index ca461ebc7ae8..36dc52fb2ec8 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c | |||
@@ -243,7 +243,7 @@ static int at91_reset_probe(struct platform_device *pdev) | |||
243 | return 0; | 243 | return 0; |
244 | } | 244 | } |
245 | 245 | ||
246 | static struct platform_device_id at91_reset_plat_match[] = { | 246 | static const struct platform_device_id at91_reset_plat_match[] = { |
247 | { "at91-sam9260-reset", (unsigned long)at91sam9260_restart }, | 247 | { "at91-sam9260-reset", (unsigned long)at91sam9260_restart }, |
248 | { "at91-sam9g45-reset", (unsigned long)at91sam9g45_restart }, | 248 | { "at91-sam9g45-reset", (unsigned long)at91sam9g45_restart }, |
249 | { /* sentinel */ } | 249 | { /* sentinel */ } |
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index e5332f1db8a7..be3d81ff51cc 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c | |||
@@ -48,6 +48,7 @@ static void gpio_poweroff_do_poweroff(void) | |||
48 | static int gpio_poweroff_probe(struct platform_device *pdev) | 48 | static int gpio_poweroff_probe(struct platform_device *pdev) |
49 | { | 49 | { |
50 | bool input = false; | 50 | bool input = false; |
51 | enum gpiod_flags flags; | ||
51 | 52 | ||
52 | /* If a pm_power_off function has already been added, leave it alone */ | 53 | /* If a pm_power_off function has already been added, leave it alone */ |
53 | if (pm_power_off != NULL) { | 54 | if (pm_power_off != NULL) { |
@@ -57,25 +58,15 @@ static int gpio_poweroff_probe(struct platform_device *pdev) | |||
57 | return -EBUSY; | 58 | return -EBUSY; |
58 | } | 59 | } |
59 | 60 | ||
60 | reset_gpio = devm_gpiod_get(&pdev->dev, NULL); | ||
61 | if (IS_ERR(reset_gpio)) | ||
62 | return PTR_ERR(reset_gpio); | ||
63 | |||
64 | input = of_property_read_bool(pdev->dev.of_node, "input"); | 61 | input = of_property_read_bool(pdev->dev.of_node, "input"); |
62 | if (input) | ||
63 | flags = GPIOD_IN; | ||
64 | else | ||
65 | flags = GPIOD_OUT_LOW; | ||
65 | 66 | ||
66 | if (input) { | 67 | reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags); |
67 | if (gpiod_direction_input(reset_gpio)) { | 68 | if (IS_ERR(reset_gpio)) |
68 | dev_err(&pdev->dev, | 69 | return PTR_ERR(reset_gpio); |
69 | "Could not set direction of reset GPIO to input\n"); | ||
70 | return -ENODEV; | ||
71 | } | ||
72 | } else { | ||
73 | if (gpiod_direction_output(reset_gpio, 0)) { | ||
74 | dev_err(&pdev->dev, | ||
75 | "Could not set direction of reset GPIO\n"); | ||
76 | return -ENODEV; | ||
77 | } | ||
78 | } | ||
79 | 70 | ||
80 | pm_power_off = &gpio_poweroff_do_poweroff; | 71 | pm_power_off = &gpio_poweroff_do_poweroff; |
81 | return 0; | 72 | return 0; |
diff --git a/drivers/power/reset/gpio-restart.c b/drivers/power/reset/gpio-restart.c index edb327efee8b..829b45f42021 100644 --- a/drivers/power/reset/gpio-restart.c +++ b/drivers/power/reset/gpio-restart.c | |||
@@ -78,7 +78,7 @@ static int gpio_restart_probe(struct platform_device *pdev) | |||
78 | } | 78 | } |
79 | 79 | ||
80 | gpio_restart->restart_handler.notifier_call = gpio_restart_notify; | 80 | gpio_restart->restart_handler.notifier_call = gpio_restart_notify; |
81 | gpio_restart->restart_handler.priority = 128; | 81 | gpio_restart->restart_handler.priority = 129; |
82 | gpio_restart->active_delay_ms = 100; | 82 | gpio_restart->active_delay_ms = 100; |
83 | gpio_restart->inactive_delay_ms = 100; | 83 | gpio_restart->inactive_delay_ms = 100; |
84 | gpio_restart->wait_delay_ms = 3000; | 84 | gpio_restart->wait_delay_ms = 3000; |
diff --git a/drivers/power/reset/ltc2952-poweroff.c b/drivers/power/reset/ltc2952-poweroff.c index 5f855f99bdfc..15fed9d8f871 100644 --- a/drivers/power/reset/ltc2952-poweroff.c +++ b/drivers/power/reset/ltc2952-poweroff.c | |||
@@ -201,16 +201,15 @@ static int ltc2952_poweroff_init(struct platform_device *pdev) | |||
201 | return ret; | 201 | return ret; |
202 | } | 202 | } |
203 | 203 | ||
204 | data->gpio_trigger = devm_gpiod_get(&pdev->dev, "trigger", GPIOD_IN); | 204 | data->gpio_trigger = devm_gpiod_get_optional(&pdev->dev, "trigger", |
205 | GPIOD_IN); | ||
205 | if (IS_ERR(data->gpio_trigger)) { | 206 | if (IS_ERR(data->gpio_trigger)) { |
206 | /* | 207 | /* |
207 | * It's not a problem if the trigger gpio isn't available, but | 208 | * It's not a problem if the trigger gpio isn't available, but |
208 | * it is worth a warning if its use was defined in the device | 209 | * it is worth a warning if its use was defined in the device |
209 | * tree. | 210 | * tree. |
210 | */ | 211 | */ |
211 | if (PTR_ERR(data->gpio_trigger) != -ENOENT) | 212 | dev_err(&pdev->dev, "unable to claim gpio \"trigger\"\n"); |
212 | dev_err(&pdev->dev, | ||
213 | "unable to claim gpio \"trigger\"\n"); | ||
214 | data->gpio_trigger = NULL; | 213 | data->gpio_trigger = NULL; |
215 | } | 214 | } |
216 | 215 | ||
diff --git a/drivers/power/rt9455_charger.c b/drivers/power/rt9455_charger.c new file mode 100644 index 000000000000..08baac6e3ada --- /dev/null +++ b/drivers/power/rt9455_charger.c | |||
@@ -0,0 +1,1752 @@ | |||
1 | /* | ||
2 | * Driver for Richtek RT9455WSC battery charger. | ||
3 | * | ||
4 | * Copyright (C) 2015 Intel Corporation | ||
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 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/of_irq.h> | ||
21 | #include <linux/of_device.h> | ||
22 | #include <linux/pm_runtime.h> | ||
23 | #include <linux/power_supply.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/acpi.h> | ||
26 | #include <linux/usb/phy.h> | ||
27 | #include <linux/regmap.h> | ||
28 | |||
29 | #define RT9455_MANUFACTURER "Richtek" | ||
30 | #define RT9455_MODEL_NAME "RT9455" | ||
31 | #define RT9455_DRIVER_NAME "rt9455-charger" | ||
32 | |||
33 | #define RT9455_IRQ_NAME "interrupt" | ||
34 | |||
35 | #define RT9455_PWR_RDY_DELAY 1 /* 1 second */ | ||
36 | #define RT9455_MAX_CHARGING_TIME 21600 /* 6 hrs */ | ||
37 | #define RT9455_BATT_PRESENCE_DELAY 60 /* 60 seconds */ | ||
38 | |||
39 | #define RT9455_CHARGE_MODE 0x00 | ||
40 | #define RT9455_BOOST_MODE 0x01 | ||
41 | |||
42 | #define RT9455_FAULT 0x03 | ||
43 | |||
44 | #define RT9455_IAICR_100MA 0x00 | ||
45 | #define RT9455_IAICR_500MA 0x01 | ||
46 | #define RT9455_IAICR_NO_LIMIT 0x03 | ||
47 | |||
48 | #define RT9455_CHARGE_DISABLE 0x00 | ||
49 | #define RT9455_CHARGE_ENABLE 0x01 | ||
50 | |||
51 | #define RT9455_PWR_FAULT 0x00 | ||
52 | #define RT9455_PWR_GOOD 0x01 | ||
53 | |||
54 | #define RT9455_REG_CTRL1 0x00 /* CTRL1 reg address */ | ||
55 | #define RT9455_REG_CTRL2 0x01 /* CTRL2 reg address */ | ||
56 | #define RT9455_REG_CTRL3 0x02 /* CTRL3 reg address */ | ||
57 | #define RT9455_REG_DEV_ID 0x03 /* DEV_ID reg address */ | ||
58 | #define RT9455_REG_CTRL4 0x04 /* CTRL4 reg address */ | ||
59 | #define RT9455_REG_CTRL5 0x05 /* CTRL5 reg address */ | ||
60 | #define RT9455_REG_CTRL6 0x06 /* CTRL6 reg address */ | ||
61 | #define RT9455_REG_CTRL7 0x07 /* CTRL7 reg address */ | ||
62 | #define RT9455_REG_IRQ1 0x08 /* IRQ1 reg address */ | ||
63 | #define RT9455_REG_IRQ2 0x09 /* IRQ2 reg address */ | ||
64 | #define RT9455_REG_IRQ3 0x0A /* IRQ3 reg address */ | ||
65 | #define RT9455_REG_MASK1 0x0B /* MASK1 reg address */ | ||
66 | #define RT9455_REG_MASK2 0x0C /* MASK2 reg address */ | ||
67 | #define RT9455_REG_MASK3 0x0D /* MASK3 reg address */ | ||
68 | |||
69 | enum rt9455_fields { | ||
70 | F_STAT, F_BOOST, F_PWR_RDY, F_OTG_PIN_POLARITY, /* CTRL1 reg fields */ | ||
71 | |||
72 | F_IAICR, F_TE_SHDN_EN, F_HIGHER_OCP, F_TE, F_IAICR_INT, F_HIZ, | ||
73 | F_OPA_MODE, /* CTRL2 reg fields */ | ||
74 | |||
75 | F_VOREG, F_OTG_PL, F_OTG_EN, /* CTRL3 reg fields */ | ||
76 | |||
77 | F_VENDOR_ID, F_CHIP_REV, /* DEV_ID reg fields */ | ||
78 | |||
79 | F_RST, /* CTRL4 reg fields */ | ||
80 | |||
81 | F_TMR_EN, F_MIVR, F_IPREC, F_IEOC_PERCENTAGE, /* CTRL5 reg fields*/ | ||
82 | |||
83 | F_IAICR_SEL, F_ICHRG, F_VPREC, /* CTRL6 reg fields */ | ||
84 | |||
85 | F_BATD_EN, F_CHG_EN, F_VMREG, /* CTRL7 reg fields */ | ||
86 | |||
87 | F_TSDI, F_VINOVPI, F_BATAB, /* IRQ1 reg fields */ | ||
88 | |||
89 | F_CHRVPI, F_CHBATOVI, F_CHTERMI, F_CHRCHGI, F_CH32MI, F_CHTREGI, | ||
90 | F_CHMIVRI, /* IRQ2 reg fields */ | ||
91 | |||
92 | F_BSTBUSOVI, F_BSTOLI, F_BSTLOWVI, F_BST32SI, /* IRQ3 reg fields */ | ||
93 | |||
94 | F_TSDM, F_VINOVPIM, F_BATABM, /* MASK1 reg fields */ | ||
95 | |||
96 | F_CHRVPIM, F_CHBATOVIM, F_CHTERMIM, F_CHRCHGIM, F_CH32MIM, F_CHTREGIM, | ||
97 | F_CHMIVRIM, /* MASK2 reg fields */ | ||
98 | |||
99 | F_BSTVINOVIM, F_BSTOLIM, F_BSTLOWVIM, F_BST32SIM, /* MASK3 reg fields */ | ||
100 | |||
101 | F_MAX_FIELDS | ||
102 | }; | ||
103 | |||
104 | static const struct reg_field rt9455_reg_fields[] = { | ||
105 | [F_STAT] = REG_FIELD(RT9455_REG_CTRL1, 4, 5), | ||
106 | [F_BOOST] = REG_FIELD(RT9455_REG_CTRL1, 3, 3), | ||
107 | [F_PWR_RDY] = REG_FIELD(RT9455_REG_CTRL1, 2, 2), | ||
108 | [F_OTG_PIN_POLARITY] = REG_FIELD(RT9455_REG_CTRL1, 1, 1), | ||
109 | |||
110 | [F_IAICR] = REG_FIELD(RT9455_REG_CTRL2, 6, 7), | ||
111 | [F_TE_SHDN_EN] = REG_FIELD(RT9455_REG_CTRL2, 5, 5), | ||
112 | [F_HIGHER_OCP] = REG_FIELD(RT9455_REG_CTRL2, 4, 4), | ||
113 | [F_TE] = REG_FIELD(RT9455_REG_CTRL2, 3, 3), | ||
114 | [F_IAICR_INT] = REG_FIELD(RT9455_REG_CTRL2, 2, 2), | ||
115 | [F_HIZ] = REG_FIELD(RT9455_REG_CTRL2, 1, 1), | ||
116 | [F_OPA_MODE] = REG_FIELD(RT9455_REG_CTRL2, 0, 0), | ||
117 | |||
118 | [F_VOREG] = REG_FIELD(RT9455_REG_CTRL3, 2, 7), | ||
119 | [F_OTG_PL] = REG_FIELD(RT9455_REG_CTRL3, 1, 1), | ||
120 | [F_OTG_EN] = REG_FIELD(RT9455_REG_CTRL3, 0, 0), | ||
121 | |||
122 | [F_VENDOR_ID] = REG_FIELD(RT9455_REG_DEV_ID, 4, 7), | ||
123 | [F_CHIP_REV] = REG_FIELD(RT9455_REG_DEV_ID, 0, 3), | ||
124 | |||
125 | [F_RST] = REG_FIELD(RT9455_REG_CTRL4, 7, 7), | ||
126 | |||
127 | [F_TMR_EN] = REG_FIELD(RT9455_REG_CTRL5, 7, 7), | ||
128 | [F_MIVR] = REG_FIELD(RT9455_REG_CTRL5, 4, 5), | ||
129 | [F_IPREC] = REG_FIELD(RT9455_REG_CTRL5, 2, 3), | ||
130 | [F_IEOC_PERCENTAGE] = REG_FIELD(RT9455_REG_CTRL5, 0, 1), | ||
131 | |||
132 | [F_IAICR_SEL] = REG_FIELD(RT9455_REG_CTRL6, 7, 7), | ||
133 | [F_ICHRG] = REG_FIELD(RT9455_REG_CTRL6, 4, 6), | ||
134 | [F_VPREC] = REG_FIELD(RT9455_REG_CTRL6, 0, 2), | ||
135 | |||
136 | [F_BATD_EN] = REG_FIELD(RT9455_REG_CTRL7, 6, 6), | ||
137 | [F_CHG_EN] = REG_FIELD(RT9455_REG_CTRL7, 4, 4), | ||
138 | [F_VMREG] = REG_FIELD(RT9455_REG_CTRL7, 0, 3), | ||
139 | |||
140 | [F_TSDI] = REG_FIELD(RT9455_REG_IRQ1, 7, 7), | ||
141 | [F_VINOVPI] = REG_FIELD(RT9455_REG_IRQ1, 6, 6), | ||
142 | [F_BATAB] = REG_FIELD(RT9455_REG_IRQ1, 0, 0), | ||
143 | |||
144 | [F_CHRVPI] = REG_FIELD(RT9455_REG_IRQ2, 7, 7), | ||
145 | [F_CHBATOVI] = REG_FIELD(RT9455_REG_IRQ2, 5, 5), | ||
146 | [F_CHTERMI] = REG_FIELD(RT9455_REG_IRQ2, 4, 4), | ||
147 | [F_CHRCHGI] = REG_FIELD(RT9455_REG_IRQ2, 3, 3), | ||
148 | [F_CH32MI] = REG_FIELD(RT9455_REG_IRQ2, 2, 2), | ||
149 | [F_CHTREGI] = REG_FIELD(RT9455_REG_IRQ2, 1, 1), | ||
150 | [F_CHMIVRI] = REG_FIELD(RT9455_REG_IRQ2, 0, 0), | ||
151 | |||
152 | [F_BSTBUSOVI] = REG_FIELD(RT9455_REG_IRQ3, 7, 7), | ||
153 | [F_BSTOLI] = REG_FIELD(RT9455_REG_IRQ3, 6, 6), | ||
154 | [F_BSTLOWVI] = REG_FIELD(RT9455_REG_IRQ3, 5, 5), | ||
155 | [F_BST32SI] = REG_FIELD(RT9455_REG_IRQ3, 3, 3), | ||
156 | |||
157 | [F_TSDM] = REG_FIELD(RT9455_REG_MASK1, 7, 7), | ||
158 | [F_VINOVPIM] = REG_FIELD(RT9455_REG_MASK1, 6, 6), | ||
159 | [F_BATABM] = REG_FIELD(RT9455_REG_MASK1, 0, 0), | ||
160 | |||
161 | [F_CHRVPIM] = REG_FIELD(RT9455_REG_MASK2, 7, 7), | ||
162 | [F_CHBATOVIM] = REG_FIELD(RT9455_REG_MASK2, 5, 5), | ||
163 | [F_CHTERMIM] = REG_FIELD(RT9455_REG_MASK2, 4, 4), | ||
164 | [F_CHRCHGIM] = REG_FIELD(RT9455_REG_MASK2, 3, 3), | ||
165 | [F_CH32MIM] = REG_FIELD(RT9455_REG_MASK2, 2, 2), | ||
166 | [F_CHTREGIM] = REG_FIELD(RT9455_REG_MASK2, 1, 1), | ||
167 | [F_CHMIVRIM] = REG_FIELD(RT9455_REG_MASK2, 0, 0), | ||
168 | |||
169 | [F_BSTVINOVIM] = REG_FIELD(RT9455_REG_MASK3, 7, 7), | ||
170 | [F_BSTOLIM] = REG_FIELD(RT9455_REG_MASK3, 6, 6), | ||
171 | [F_BSTLOWVIM] = REG_FIELD(RT9455_REG_MASK3, 5, 5), | ||
172 | [F_BST32SIM] = REG_FIELD(RT9455_REG_MASK3, 3, 3), | ||
173 | }; | ||
174 | |||
175 | #define GET_MASK(fid) (BIT(rt9455_reg_fields[fid].msb + 1) - \ | ||
176 | BIT(rt9455_reg_fields[fid].lsb)) | ||
177 | |||
178 | /* | ||
179 | * Each array initialised below shows the possible real-world values for a | ||
180 | * group of bits belonging to RT9455 registers. The arrays are sorted in | ||
181 | * ascending order. The index of each real-world value represents the value | ||
182 | * that is encoded in the group of bits belonging to RT9455 registers. | ||
183 | */ | ||
184 | /* REG06[6:4] (ICHRG) in uAh */ | ||
185 | static const int rt9455_ichrg_values[] = { | ||
186 | 500000, 650000, 800000, 950000, 1100000, 1250000, 1400000, 1550000 | ||
187 | }; | ||
188 | |||
189 | /* | ||
190 | * When the charger is in charge mode, REG02[7:2] represent battery regulation | ||
191 | * voltage. | ||
192 | */ | ||
193 | /* REG02[7:2] (VOREG) in uV */ | ||
194 | static const int rt9455_voreg_values[] = { | ||
195 | 3500000, 3520000, 3540000, 3560000, 3580000, 3600000, 3620000, 3640000, | ||
196 | 3660000, 3680000, 3700000, 3720000, 3740000, 3760000, 3780000, 3800000, | ||
197 | 3820000, 3840000, 3860000, 3880000, 3900000, 3920000, 3940000, 3960000, | ||
198 | 3980000, 4000000, 4020000, 4040000, 4060000, 4080000, 4100000, 4120000, | ||
199 | 4140000, 4160000, 4180000, 4200000, 4220000, 4240000, 4260000, 4280000, | ||
200 | 4300000, 4330000, 4350000, 4370000, 4390000, 4410000, 4430000, 4450000, | ||
201 | 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, | ||
202 | 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000 | ||
203 | }; | ||
204 | |||
205 | /* | ||
206 | * When the charger is in boost mode, REG02[7:2] represent boost output | ||
207 | * voltage. | ||
208 | */ | ||
209 | /* REG02[7:2] (Boost output voltage) in uV */ | ||
210 | static const int rt9455_boost_voltage_values[] = { | ||
211 | 4425000, 4450000, 4475000, 4500000, 4525000, 4550000, 4575000, 4600000, | ||
212 | 4625000, 4650000, 4675000, 4700000, 4725000, 4750000, 4775000, 4800000, | ||
213 | 4825000, 4850000, 4875000, 4900000, 4925000, 4950000, 4975000, 5000000, | ||
214 | 5025000, 5050000, 5075000, 5100000, 5125000, 5150000, 5175000, 5200000, | ||
215 | 5225000, 5250000, 5275000, 5300000, 5325000, 5350000, 5375000, 5400000, | ||
216 | 5425000, 5450000, 5475000, 5500000, 5525000, 5550000, 5575000, 5600000, | ||
217 | 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, | ||
218 | 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, | ||
219 | }; | ||
220 | |||
221 | /* REG07[3:0] (VMREG) in uV */ | ||
222 | static const int rt9455_vmreg_values[] = { | ||
223 | 4200000, 4220000, 4240000, 4260000, 4280000, 4300000, 4320000, 4340000, | ||
224 | 4360000, 4380000, 4400000, 4430000, 4450000, 4450000, 4450000, 4450000 | ||
225 | }; | ||
226 | |||
227 | /* REG05[5:4] (IEOC_PERCENTAGE) */ | ||
228 | static const int rt9455_ieoc_percentage_values[] = { | ||
229 | 10, 30, 20, 30 | ||
230 | }; | ||
231 | |||
232 | /* REG05[1:0] (MIVR) in uV */ | ||
233 | static const int rt9455_mivr_values[] = { | ||
234 | 4000000, 4250000, 4500000, 5000000 | ||
235 | }; | ||
236 | |||
237 | /* REG05[1:0] (IAICR) in uA */ | ||
238 | static const int rt9455_iaicr_values[] = { | ||
239 | 100000, 500000, 1000000, 2000000 | ||
240 | }; | ||
241 | |||
242 | struct rt9455_info { | ||
243 | struct i2c_client *client; | ||
244 | struct regmap *regmap; | ||
245 | struct regmap_field *regmap_fields[F_MAX_FIELDS]; | ||
246 | struct power_supply *charger; | ||
247 | #if IS_ENABLED(CONFIG_USB_PHY) | ||
248 | struct usb_phy *usb_phy; | ||
249 | struct notifier_block nb; | ||
250 | #endif | ||
251 | struct delayed_work pwr_rdy_work; | ||
252 | struct delayed_work max_charging_time_work; | ||
253 | struct delayed_work batt_presence_work; | ||
254 | u32 voreg; | ||
255 | u32 boost_voltage; | ||
256 | }; | ||
257 | |||
258 | /* | ||
259 | * Iterate through each element of the 'tbl' array until an element whose value | ||
260 | * is greater than v is found. Return the index of the respective element, | ||
261 | * or the index of the last element in the array, if no such element is found. | ||
262 | */ | ||
263 | static unsigned int rt9455_find_idx(const int tbl[], int tbl_size, int v) | ||
264 | { | ||
265 | int i; | ||
266 | |||
267 | /* | ||
268 | * No need to iterate until the last index in the table because | ||
269 | * if no element greater than v is found in the table, | ||
270 | * or if only the last element is greater than v, | ||
271 | * function returns the index of the last element. | ||
272 | */ | ||
273 | for (i = 0; i < tbl_size - 1; i++) | ||
274 | if (v <= tbl[i]) | ||
275 | return i; | ||
276 | |||
277 | return (tbl_size - 1); | ||
278 | } | ||
279 | |||
280 | static int rt9455_get_field_val(struct rt9455_info *info, | ||
281 | enum rt9455_fields field, | ||
282 | const int tbl[], int tbl_size, int *val) | ||
283 | { | ||
284 | unsigned int v; | ||
285 | int ret; | ||
286 | |||
287 | ret = regmap_field_read(info->regmap_fields[field], &v); | ||
288 | if (ret) | ||
289 | return ret; | ||
290 | |||
291 | v = (v >= tbl_size) ? (tbl_size - 1) : v; | ||
292 | *val = tbl[v]; | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int rt9455_set_field_val(struct rt9455_info *info, | ||
298 | enum rt9455_fields field, | ||
299 | const int tbl[], int tbl_size, int val) | ||
300 | { | ||
301 | unsigned int idx = rt9455_find_idx(tbl, tbl_size, val); | ||
302 | |||
303 | return regmap_field_write(info->regmap_fields[field], idx); | ||
304 | } | ||
305 | |||
306 | static int rt9455_register_reset(struct rt9455_info *info) | ||
307 | { | ||
308 | struct device *dev = &info->client->dev; | ||
309 | unsigned int v; | ||
310 | int ret, limit = 100; | ||
311 | |||
312 | ret = regmap_field_write(info->regmap_fields[F_RST], 0x01); | ||
313 | if (ret) { | ||
314 | dev_err(dev, "Failed to set RST bit\n"); | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * To make sure that reset operation has finished, loop until RST bit | ||
320 | * is set to 0. | ||
321 | */ | ||
322 | do { | ||
323 | ret = regmap_field_read(info->regmap_fields[F_RST], &v); | ||
324 | if (ret) { | ||
325 | dev_err(dev, "Failed to read RST bit\n"); | ||
326 | return ret; | ||
327 | } | ||
328 | |||
329 | if (!v) | ||
330 | break; | ||
331 | |||
332 | usleep_range(10, 100); | ||
333 | } while (--limit); | ||
334 | |||
335 | if (!limit) | ||
336 | return -EIO; | ||
337 | |||
338 | return 0; | ||
339 | } | ||
340 | |||
341 | /* Charger power supply property routines */ | ||
342 | static enum power_supply_property rt9455_charger_properties[] = { | ||
343 | POWER_SUPPLY_PROP_STATUS, | ||
344 | POWER_SUPPLY_PROP_HEALTH, | ||
345 | POWER_SUPPLY_PROP_PRESENT, | ||
346 | POWER_SUPPLY_PROP_ONLINE, | ||
347 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, | ||
348 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, | ||
349 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE, | ||
350 | POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, | ||
351 | POWER_SUPPLY_PROP_SCOPE, | ||
352 | POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, | ||
353 | POWER_SUPPLY_PROP_MODEL_NAME, | ||
354 | POWER_SUPPLY_PROP_MANUFACTURER, | ||
355 | }; | ||
356 | |||
357 | static char *rt9455_charger_supplied_to[] = { | ||
358 | "main-battery", | ||
359 | }; | ||
360 | |||
361 | static int rt9455_charger_get_status(struct rt9455_info *info, | ||
362 | union power_supply_propval *val) | ||
363 | { | ||
364 | unsigned int v, pwr_rdy; | ||
365 | int ret; | ||
366 | |||
367 | ret = regmap_field_read(info->regmap_fields[F_PWR_RDY], | ||
368 | &pwr_rdy); | ||
369 | if (ret) { | ||
370 | dev_err(&info->client->dev, "Failed to read PWR_RDY bit\n"); | ||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * If PWR_RDY bit is unset, the battery is discharging. Otherwise, | ||
376 | * STAT bits value must be checked. | ||
377 | */ | ||
378 | if (!pwr_rdy) { | ||
379 | val->intval = POWER_SUPPLY_STATUS_DISCHARGING; | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | ret = regmap_field_read(info->regmap_fields[F_STAT], &v); | ||
384 | if (ret) { | ||
385 | dev_err(&info->client->dev, "Failed to read STAT bits\n"); | ||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | switch (v) { | ||
390 | case 0: | ||
391 | /* | ||
392 | * If PWR_RDY bit is set, but STAT bits value is 0, the charger | ||
393 | * may be in one of the following cases: | ||
394 | * 1. CHG_EN bit is 0. | ||
395 | * 2. CHG_EN bit is 1 but the battery is not connected. | ||
396 | * In any of these cases, POWER_SUPPLY_STATUS_NOT_CHARGING is | ||
397 | * returned. | ||
398 | */ | ||
399 | val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; | ||
400 | return 0; | ||
401 | case 1: | ||
402 | val->intval = POWER_SUPPLY_STATUS_CHARGING; | ||
403 | return 0; | ||
404 | case 2: | ||
405 | val->intval = POWER_SUPPLY_STATUS_FULL; | ||
406 | return 0; | ||
407 | default: | ||
408 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | ||
409 | return 0; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | static int rt9455_charger_get_health(struct rt9455_info *info, | ||
414 | union power_supply_propval *val) | ||
415 | { | ||
416 | struct device *dev = &info->client->dev; | ||
417 | unsigned int v; | ||
418 | int ret; | ||
419 | |||
420 | val->intval = POWER_SUPPLY_HEALTH_GOOD; | ||
421 | |||
422 | ret = regmap_read(info->regmap, RT9455_REG_IRQ1, &v); | ||
423 | if (ret) { | ||
424 | dev_err(dev, "Failed to read IRQ1 register\n"); | ||
425 | return ret; | ||
426 | } | ||
427 | |||
428 | if (v & GET_MASK(F_TSDI)) { | ||
429 | val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; | ||
430 | return 0; | ||
431 | } | ||
432 | if (v & GET_MASK(F_VINOVPI)) { | ||
433 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
434 | return 0; | ||
435 | } | ||
436 | if (v & GET_MASK(F_BATAB)) { | ||
437 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | ret = regmap_read(info->regmap, RT9455_REG_IRQ2, &v); | ||
442 | if (ret) { | ||
443 | dev_err(dev, "Failed to read IRQ2 register\n"); | ||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | if (v & GET_MASK(F_CHBATOVI)) { | ||
448 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
449 | return 0; | ||
450 | } | ||
451 | if (v & GET_MASK(F_CH32MI)) { | ||
452 | val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | ret = regmap_read(info->regmap, RT9455_REG_IRQ3, &v); | ||
457 | if (ret) { | ||
458 | dev_err(dev, "Failed to read IRQ3 register\n"); | ||
459 | return ret; | ||
460 | } | ||
461 | |||
462 | if (v & GET_MASK(F_BSTBUSOVI)) { | ||
463 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
464 | return 0; | ||
465 | } | ||
466 | if (v & GET_MASK(F_BSTOLI)) { | ||
467 | val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; | ||
468 | return 0; | ||
469 | } | ||
470 | if (v & GET_MASK(F_BSTLOWVI)) { | ||
471 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
472 | return 0; | ||
473 | } | ||
474 | if (v & GET_MASK(F_BST32SI)) { | ||
475 | val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | ret = regmap_field_read(info->regmap_fields[F_STAT], &v); | ||
480 | if (ret) { | ||
481 | dev_err(dev, "Failed to read STAT bits\n"); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | if (v == RT9455_FAULT) { | ||
486 | val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | static int rt9455_charger_get_battery_presence(struct rt9455_info *info, | ||
494 | union power_supply_propval *val) | ||
495 | { | ||
496 | unsigned int v; | ||
497 | int ret; | ||
498 | |||
499 | ret = regmap_field_read(info->regmap_fields[F_BATAB], &v); | ||
500 | if (ret) { | ||
501 | dev_err(&info->client->dev, "Failed to read BATAB bit\n"); | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | /* | ||
506 | * Since BATAB is 1 when battery is NOT present and 0 otherwise, | ||
507 | * !BATAB is returned. | ||
508 | */ | ||
509 | val->intval = !v; | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int rt9455_charger_get_online(struct rt9455_info *info, | ||
515 | union power_supply_propval *val) | ||
516 | { | ||
517 | unsigned int v; | ||
518 | int ret; | ||
519 | |||
520 | ret = regmap_field_read(info->regmap_fields[F_PWR_RDY], &v); | ||
521 | if (ret) { | ||
522 | dev_err(&info->client->dev, "Failed to read PWR_RDY bit\n"); | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | val->intval = (int)v; | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | static int rt9455_charger_get_current(struct rt9455_info *info, | ||
532 | union power_supply_propval *val) | ||
533 | { | ||
534 | int curr; | ||
535 | int ret; | ||
536 | |||
537 | ret = rt9455_get_field_val(info, F_ICHRG, | ||
538 | rt9455_ichrg_values, | ||
539 | ARRAY_SIZE(rt9455_ichrg_values), | ||
540 | &curr); | ||
541 | if (ret) { | ||
542 | dev_err(&info->client->dev, "Failed to read ICHRG value\n"); | ||
543 | return ret; | ||
544 | } | ||
545 | |||
546 | val->intval = curr; | ||
547 | |||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static int rt9455_charger_get_current_max(struct rt9455_info *info, | ||
552 | union power_supply_propval *val) | ||
553 | { | ||
554 | int idx = ARRAY_SIZE(rt9455_ichrg_values) - 1; | ||
555 | |||
556 | val->intval = rt9455_ichrg_values[idx]; | ||
557 | |||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | static int rt9455_charger_get_voltage(struct rt9455_info *info, | ||
562 | union power_supply_propval *val) | ||
563 | { | ||
564 | int voltage; | ||
565 | int ret; | ||
566 | |||
567 | ret = rt9455_get_field_val(info, F_VOREG, | ||
568 | rt9455_voreg_values, | ||
569 | ARRAY_SIZE(rt9455_voreg_values), | ||
570 | &voltage); | ||
571 | if (ret) { | ||
572 | dev_err(&info->client->dev, "Failed to read VOREG value\n"); | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | val->intval = voltage; | ||
577 | |||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | static int rt9455_charger_get_voltage_max(struct rt9455_info *info, | ||
582 | union power_supply_propval *val) | ||
583 | { | ||
584 | int idx = ARRAY_SIZE(rt9455_vmreg_values) - 1; | ||
585 | |||
586 | val->intval = rt9455_vmreg_values[idx]; | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static int rt9455_charger_get_term_current(struct rt9455_info *info, | ||
592 | union power_supply_propval *val) | ||
593 | { | ||
594 | struct device *dev = &info->client->dev; | ||
595 | int ichrg, ieoc_percentage, ret; | ||
596 | |||
597 | ret = rt9455_get_field_val(info, F_ICHRG, | ||
598 | rt9455_ichrg_values, | ||
599 | ARRAY_SIZE(rt9455_ichrg_values), | ||
600 | &ichrg); | ||
601 | if (ret) { | ||
602 | dev_err(dev, "Failed to read ICHRG value\n"); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | ret = rt9455_get_field_val(info, F_IEOC_PERCENTAGE, | ||
607 | rt9455_ieoc_percentage_values, | ||
608 | ARRAY_SIZE(rt9455_ieoc_percentage_values), | ||
609 | &ieoc_percentage); | ||
610 | if (ret) { | ||
611 | dev_err(dev, "Failed to read IEOC value\n"); | ||
612 | return ret; | ||
613 | } | ||
614 | |||
615 | val->intval = ichrg * ieoc_percentage / 100; | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static int rt9455_charger_get_property(struct power_supply *psy, | ||
621 | enum power_supply_property psp, | ||
622 | union power_supply_propval *val) | ||
623 | { | ||
624 | struct rt9455_info *info = power_supply_get_drvdata(psy); | ||
625 | |||
626 | switch (psp) { | ||
627 | case POWER_SUPPLY_PROP_STATUS: | ||
628 | return rt9455_charger_get_status(info, val); | ||
629 | case POWER_SUPPLY_PROP_HEALTH: | ||
630 | return rt9455_charger_get_health(info, val); | ||
631 | case POWER_SUPPLY_PROP_PRESENT: | ||
632 | return rt9455_charger_get_battery_presence(info, val); | ||
633 | case POWER_SUPPLY_PROP_ONLINE: | ||
634 | return rt9455_charger_get_online(info, val); | ||
635 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: | ||
636 | return rt9455_charger_get_current(info, val); | ||
637 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: | ||
638 | return rt9455_charger_get_current_max(info, val); | ||
639 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE: | ||
640 | return rt9455_charger_get_voltage(info, val); | ||
641 | case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: | ||
642 | return rt9455_charger_get_voltage_max(info, val); | ||
643 | case POWER_SUPPLY_PROP_SCOPE: | ||
644 | val->intval = POWER_SUPPLY_SCOPE_SYSTEM; | ||
645 | return 0; | ||
646 | case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT: | ||
647 | return rt9455_charger_get_term_current(info, val); | ||
648 | case POWER_SUPPLY_PROP_MODEL_NAME: | ||
649 | val->strval = RT9455_MODEL_NAME; | ||
650 | return 0; | ||
651 | case POWER_SUPPLY_PROP_MANUFACTURER: | ||
652 | val->strval = RT9455_MANUFACTURER; | ||
653 | return 0; | ||
654 | default: | ||
655 | return -ENODATA; | ||
656 | } | ||
657 | } | ||
658 | |||
659 | static int rt9455_hw_init(struct rt9455_info *info, u32 ichrg, | ||
660 | u32 ieoc_percentage, | ||
661 | u32 mivr, u32 iaicr) | ||
662 | { | ||
663 | struct device *dev = &info->client->dev; | ||
664 | int idx, ret; | ||
665 | |||
666 | ret = rt9455_register_reset(info); | ||
667 | if (ret) { | ||
668 | dev_err(dev, "Power On Reset failed\n"); | ||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | /* Set TE bit in order to enable end of charge detection */ | ||
673 | ret = regmap_field_write(info->regmap_fields[F_TE], 1); | ||
674 | if (ret) { | ||
675 | dev_err(dev, "Failed to set TE bit\n"); | ||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | /* Set TE_SHDN_EN bit in order to enable end of charge detection */ | ||
680 | ret = regmap_field_write(info->regmap_fields[F_TE_SHDN_EN], 1); | ||
681 | if (ret) { | ||
682 | dev_err(dev, "Failed to set TE_SHDN_EN bit\n"); | ||
683 | return ret; | ||
684 | } | ||
685 | |||
686 | /* | ||
687 | * Set BATD_EN bit in order to enable battery detection | ||
688 | * when charging is done | ||
689 | */ | ||
690 | ret = regmap_field_write(info->regmap_fields[F_BATD_EN], 1); | ||
691 | if (ret) { | ||
692 | dev_err(dev, "Failed to set BATD_EN bit\n"); | ||
693 | return ret; | ||
694 | } | ||
695 | |||
696 | /* | ||
697 | * Disable Safety Timer. In charge mode, this timer terminates charging | ||
698 | * if no read or write via I2C is done within 32 minutes. This timer | ||
699 | * avoids overcharging the baterry when the OS is not loaded and the | ||
700 | * charger is connected to a power source. | ||
701 | * In boost mode, this timer triggers BST32SI interrupt if no read or | ||
702 | * write via I2C is done within 32 seconds. | ||
703 | * When the OS is loaded and the charger driver is inserted, it is used | ||
704 | * delayed_work, named max_charging_time_work, to avoid overcharging | ||
705 | * the battery. | ||
706 | */ | ||
707 | ret = regmap_field_write(info->regmap_fields[F_TMR_EN], 0x00); | ||
708 | if (ret) { | ||
709 | dev_err(dev, "Failed to disable Safety Timer\n"); | ||
710 | return ret; | ||
711 | } | ||
712 | |||
713 | /* Set ICHRG to value retrieved from device-specific data */ | ||
714 | ret = rt9455_set_field_val(info, F_ICHRG, | ||
715 | rt9455_ichrg_values, | ||
716 | ARRAY_SIZE(rt9455_ichrg_values), ichrg); | ||
717 | if (ret) { | ||
718 | dev_err(dev, "Failed to set ICHRG value\n"); | ||
719 | return ret; | ||
720 | } | ||
721 | |||
722 | /* Set IEOC Percentage to value retrieved from device-specific data */ | ||
723 | ret = rt9455_set_field_val(info, F_IEOC_PERCENTAGE, | ||
724 | rt9455_ieoc_percentage_values, | ||
725 | ARRAY_SIZE(rt9455_ieoc_percentage_values), | ||
726 | ieoc_percentage); | ||
727 | if (ret) { | ||
728 | dev_err(dev, "Failed to set IEOC Percentage value\n"); | ||
729 | return ret; | ||
730 | } | ||
731 | |||
732 | /* Set VOREG to value retrieved from device-specific data */ | ||
733 | ret = rt9455_set_field_val(info, F_VOREG, | ||
734 | rt9455_voreg_values, | ||
735 | ARRAY_SIZE(rt9455_voreg_values), | ||
736 | info->voreg); | ||
737 | if (ret) { | ||
738 | dev_err(dev, "Failed to set VOREG value\n"); | ||
739 | return ret; | ||
740 | } | ||
741 | |||
742 | /* Set VMREG value to maximum (4.45V). */ | ||
743 | idx = ARRAY_SIZE(rt9455_vmreg_values) - 1; | ||
744 | ret = rt9455_set_field_val(info, F_VMREG, | ||
745 | rt9455_vmreg_values, | ||
746 | ARRAY_SIZE(rt9455_vmreg_values), | ||
747 | rt9455_vmreg_values[idx]); | ||
748 | if (ret) { | ||
749 | dev_err(dev, "Failed to set VMREG value\n"); | ||
750 | return ret; | ||
751 | } | ||
752 | |||
753 | /* | ||
754 | * Set MIVR to value retrieved from device-specific data. | ||
755 | * If no value is specified, default value for MIVR is 4.5V. | ||
756 | */ | ||
757 | if (mivr == -1) | ||
758 | mivr = 4500000; | ||
759 | |||
760 | ret = rt9455_set_field_val(info, F_MIVR, | ||
761 | rt9455_mivr_values, | ||
762 | ARRAY_SIZE(rt9455_mivr_values), mivr); | ||
763 | if (ret) { | ||
764 | dev_err(dev, "Failed to set MIVR value\n"); | ||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | /* | ||
769 | * Set IAICR to value retrieved from device-specific data. | ||
770 | * If no value is specified, default value for IAICR is 500 mA. | ||
771 | */ | ||
772 | if (iaicr == -1) | ||
773 | iaicr = 500000; | ||
774 | |||
775 | ret = rt9455_set_field_val(info, F_IAICR, | ||
776 | rt9455_iaicr_values, | ||
777 | ARRAY_SIZE(rt9455_iaicr_values), iaicr); | ||
778 | if (ret) { | ||
779 | dev_err(dev, "Failed to set IAICR value\n"); | ||
780 | return ret; | ||
781 | } | ||
782 | |||
783 | /* | ||
784 | * Set IAICR_INT bit so that IAICR value is determined by IAICR bits | ||
785 | * and not by OTG pin. | ||
786 | */ | ||
787 | ret = regmap_field_write(info->regmap_fields[F_IAICR_INT], 0x01); | ||
788 | if (ret) { | ||
789 | dev_err(dev, "Failed to set IAICR_INT bit\n"); | ||
790 | return ret; | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | * Disable CHMIVRI interrupt. Because the driver sets MIVR value, | ||
795 | * CHMIVRI is triggered, but there is no action to be taken by the | ||
796 | * driver when CHMIVRI is triggered. | ||
797 | */ | ||
798 | ret = regmap_field_write(info->regmap_fields[F_CHMIVRIM], 0x01); | ||
799 | if (ret) { | ||
800 | dev_err(dev, "Failed to mask CHMIVRI interrupt\n"); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | #if IS_ENABLED(CONFIG_USB_PHY) | ||
808 | /* | ||
809 | * Before setting the charger into boost mode, boost output voltage is | ||
810 | * set. This is needed because boost output voltage may differ from battery | ||
811 | * regulation voltage. F_VOREG bits represent either battery regulation voltage | ||
812 | * or boost output voltage, depending on the mode the charger is. Both battery | ||
813 | * regulation voltage and boost output voltage are read from DT/ACPI during | ||
814 | * probe. | ||
815 | */ | ||
816 | static int rt9455_set_boost_voltage_before_boost_mode(struct rt9455_info *info) | ||
817 | { | ||
818 | struct device *dev = &info->client->dev; | ||
819 | int ret; | ||
820 | |||
821 | ret = rt9455_set_field_val(info, F_VOREG, | ||
822 | rt9455_boost_voltage_values, | ||
823 | ARRAY_SIZE(rt9455_boost_voltage_values), | ||
824 | info->boost_voltage); | ||
825 | if (ret) { | ||
826 | dev_err(dev, "Failed to set boost output voltage value\n"); | ||
827 | return ret; | ||
828 | } | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | #endif | ||
833 | |||
834 | /* | ||
835 | * Before setting the charger into charge mode, battery regulation voltage is | ||
836 | * set. This is needed because boost output voltage may differ from battery | ||
837 | * regulation voltage. F_VOREG bits represent either battery regulation voltage | ||
838 | * or boost output voltage, depending on the mode the charger is. Both battery | ||
839 | * regulation voltage and boost output voltage are read from DT/ACPI during | ||
840 | * probe. | ||
841 | */ | ||
842 | static int rt9455_set_voreg_before_charge_mode(struct rt9455_info *info) | ||
843 | { | ||
844 | struct device *dev = &info->client->dev; | ||
845 | int ret; | ||
846 | |||
847 | ret = rt9455_set_field_val(info, F_VOREG, | ||
848 | rt9455_voreg_values, | ||
849 | ARRAY_SIZE(rt9455_voreg_values), | ||
850 | info->voreg); | ||
851 | if (ret) { | ||
852 | dev_err(dev, "Failed to set VOREG value\n"); | ||
853 | return ret; | ||
854 | } | ||
855 | |||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | static int rt9455_irq_handler_check_irq1_register(struct rt9455_info *info, | ||
860 | bool *_is_battery_absent, | ||
861 | bool *_alert_userspace) | ||
862 | { | ||
863 | unsigned int irq1, mask1, mask2; | ||
864 | struct device *dev = &info->client->dev; | ||
865 | bool is_battery_absent = false; | ||
866 | bool alert_userspace = false; | ||
867 | int ret; | ||
868 | |||
869 | ret = regmap_read(info->regmap, RT9455_REG_IRQ1, &irq1); | ||
870 | if (ret) { | ||
871 | dev_err(dev, "Failed to read IRQ1 register\n"); | ||
872 | return ret; | ||
873 | } | ||
874 | |||
875 | ret = regmap_read(info->regmap, RT9455_REG_MASK1, &mask1); | ||
876 | if (ret) { | ||
877 | dev_err(dev, "Failed to read MASK1 register\n"); | ||
878 | return ret; | ||
879 | } | ||
880 | |||
881 | if (irq1 & GET_MASK(F_TSDI)) { | ||
882 | dev_err(dev, "Thermal shutdown fault occurred\n"); | ||
883 | alert_userspace = true; | ||
884 | } | ||
885 | |||
886 | if (irq1 & GET_MASK(F_VINOVPI)) { | ||
887 | dev_err(dev, "Overvoltage input occurred\n"); | ||
888 | alert_userspace = true; | ||
889 | } | ||
890 | |||
891 | if (irq1 & GET_MASK(F_BATAB)) { | ||
892 | dev_err(dev, "Battery absence occurred\n"); | ||
893 | is_battery_absent = true; | ||
894 | alert_userspace = true; | ||
895 | |||
896 | if ((mask1 & GET_MASK(F_BATABM)) == 0) { | ||
897 | ret = regmap_field_write(info->regmap_fields[F_BATABM], | ||
898 | 0x01); | ||
899 | if (ret) { | ||
900 | dev_err(dev, "Failed to mask BATAB interrupt\n"); | ||
901 | return ret; | ||
902 | } | ||
903 | } | ||
904 | |||
905 | ret = regmap_read(info->regmap, RT9455_REG_MASK2, &mask2); | ||
906 | if (ret) { | ||
907 | dev_err(dev, "Failed to read MASK2 register\n"); | ||
908 | return ret; | ||
909 | } | ||
910 | |||
911 | if (mask2 & GET_MASK(F_CHTERMIM)) { | ||
912 | ret = regmap_field_write( | ||
913 | info->regmap_fields[F_CHTERMIM], 0x00); | ||
914 | if (ret) { | ||
915 | dev_err(dev, "Failed to unmask CHTERMI interrupt\n"); | ||
916 | return ret; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | if (mask2 & GET_MASK(F_CHRCHGIM)) { | ||
921 | ret = regmap_field_write( | ||
922 | info->regmap_fields[F_CHRCHGIM], 0x00); | ||
923 | if (ret) { | ||
924 | dev_err(dev, "Failed to unmask CHRCHGI interrupt\n"); | ||
925 | return ret; | ||
926 | } | ||
927 | } | ||
928 | |||
929 | /* | ||
930 | * When the battery is absent, max_charging_time_work is | ||
931 | * cancelled, since no charging is done. | ||
932 | */ | ||
933 | cancel_delayed_work_sync(&info->max_charging_time_work); | ||
934 | /* | ||
935 | * Since no interrupt is triggered when the battery is | ||
936 | * reconnected, max_charging_time_work is not rescheduled. | ||
937 | * Therefore, batt_presence_work is scheduled to check whether | ||
938 | * the battery is still absent or not. | ||
939 | */ | ||
940 | queue_delayed_work(system_power_efficient_wq, | ||
941 | &info->batt_presence_work, | ||
942 | RT9455_BATT_PRESENCE_DELAY * HZ); | ||
943 | } | ||
944 | |||
945 | *_is_battery_absent = is_battery_absent; | ||
946 | |||
947 | if (alert_userspace) | ||
948 | *_alert_userspace = alert_userspace; | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | static int rt9455_irq_handler_check_irq2_register(struct rt9455_info *info, | ||
954 | bool is_battery_absent, | ||
955 | bool *_alert_userspace) | ||
956 | { | ||
957 | unsigned int irq2, mask2; | ||
958 | struct device *dev = &info->client->dev; | ||
959 | bool alert_userspace = false; | ||
960 | int ret; | ||
961 | |||
962 | ret = regmap_read(info->regmap, RT9455_REG_IRQ2, &irq2); | ||
963 | if (ret) { | ||
964 | dev_err(dev, "Failed to read IRQ2 register\n"); | ||
965 | return ret; | ||
966 | } | ||
967 | |||
968 | ret = regmap_read(info->regmap, RT9455_REG_MASK2, &mask2); | ||
969 | if (ret) { | ||
970 | dev_err(dev, "Failed to read MASK2 register\n"); | ||
971 | return ret; | ||
972 | } | ||
973 | |||
974 | if (irq2 & GET_MASK(F_CHRVPI)) { | ||
975 | dev_dbg(dev, "Charger fault occurred\n"); | ||
976 | alert_userspace = true; | ||
977 | /* | ||
978 | * CHRVPI bit is set in 2 cases: | ||
979 | * 1. when the power source is connected to the charger. | ||
980 | * 2. when the power source is disconnected from the charger. | ||
981 | * To identify the case, PWR_RDY bit is checked. Because | ||
982 | * PWR_RDY bit is set / cleared after CHRVPI interrupt is | ||
983 | * triggered, it is used delayed_work to later read PWR_RDY bit. | ||
984 | */ | ||
985 | queue_delayed_work(system_power_efficient_wq, | ||
986 | &info->pwr_rdy_work, | ||
987 | RT9455_PWR_RDY_DELAY * HZ); | ||
988 | } | ||
989 | if (irq2 & GET_MASK(F_CHBATOVI)) { | ||
990 | dev_err(dev, "Battery OVP occurred\n"); | ||
991 | alert_userspace = true; | ||
992 | } | ||
993 | if (irq2 & GET_MASK(F_CHTERMI)) { | ||
994 | dev_dbg(dev, "Charge terminated\n"); | ||
995 | if (!is_battery_absent) { | ||
996 | if ((mask2 & GET_MASK(F_CHTERMIM)) == 0) { | ||
997 | ret = regmap_field_write( | ||
998 | info->regmap_fields[F_CHTERMIM], 0x01); | ||
999 | if (ret) { | ||
1000 | dev_err(dev, "Failed to mask CHTERMI interrupt\n"); | ||
1001 | return ret; | ||
1002 | } | ||
1003 | /* | ||
1004 | * Update MASK2 value, since CHTERMIM bit is | ||
1005 | * set. | ||
1006 | */ | ||
1007 | mask2 = mask2 | GET_MASK(F_CHTERMIM); | ||
1008 | } | ||
1009 | cancel_delayed_work_sync(&info->max_charging_time_work); | ||
1010 | alert_userspace = true; | ||
1011 | } | ||
1012 | } | ||
1013 | if (irq2 & GET_MASK(F_CHRCHGI)) { | ||
1014 | dev_dbg(dev, "Recharge request\n"); | ||
1015 | ret = regmap_field_write(info->regmap_fields[F_CHG_EN], | ||
1016 | RT9455_CHARGE_ENABLE); | ||
1017 | if (ret) { | ||
1018 | dev_err(dev, "Failed to enable charging\n"); | ||
1019 | return ret; | ||
1020 | } | ||
1021 | if (mask2 & GET_MASK(F_CHTERMIM)) { | ||
1022 | ret = regmap_field_write( | ||
1023 | info->regmap_fields[F_CHTERMIM], 0x00); | ||
1024 | if (ret) { | ||
1025 | dev_err(dev, "Failed to unmask CHTERMI interrupt\n"); | ||
1026 | return ret; | ||
1027 | } | ||
1028 | /* Update MASK2 value, since CHTERMIM bit is cleared. */ | ||
1029 | mask2 = mask2 & ~GET_MASK(F_CHTERMIM); | ||
1030 | } | ||
1031 | if (!is_battery_absent) { | ||
1032 | /* | ||
1033 | * No need to check whether the charger is connected to | ||
1034 | * power source when CHRCHGI is received, since CHRCHGI | ||
1035 | * is not triggered if the charger is not connected to | ||
1036 | * the power source. | ||
1037 | */ | ||
1038 | queue_delayed_work(system_power_efficient_wq, | ||
1039 | &info->max_charging_time_work, | ||
1040 | RT9455_MAX_CHARGING_TIME * HZ); | ||
1041 | alert_userspace = true; | ||
1042 | } | ||
1043 | } | ||
1044 | if (irq2 & GET_MASK(F_CH32MI)) { | ||
1045 | dev_err(dev, "Charger fault. 32 mins timeout occurred\n"); | ||
1046 | alert_userspace = true; | ||
1047 | } | ||
1048 | if (irq2 & GET_MASK(F_CHTREGI)) { | ||
1049 | dev_warn(dev, | ||
1050 | "Charger warning. Thermal regulation loop active\n"); | ||
1051 | alert_userspace = true; | ||
1052 | } | ||
1053 | if (irq2 & GET_MASK(F_CHMIVRI)) { | ||
1054 | dev_dbg(dev, | ||
1055 | "Charger warning. Input voltage MIVR loop active\n"); | ||
1056 | } | ||
1057 | |||
1058 | if (alert_userspace) | ||
1059 | *_alert_userspace = alert_userspace; | ||
1060 | |||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1064 | static int rt9455_irq_handler_check_irq3_register(struct rt9455_info *info, | ||
1065 | bool *_alert_userspace) | ||
1066 | { | ||
1067 | unsigned int irq3, mask3; | ||
1068 | struct device *dev = &info->client->dev; | ||
1069 | bool alert_userspace = false; | ||
1070 | int ret; | ||
1071 | |||
1072 | ret = regmap_read(info->regmap, RT9455_REG_IRQ3, &irq3); | ||
1073 | if (ret) { | ||
1074 | dev_err(dev, "Failed to read IRQ3 register\n"); | ||
1075 | return ret; | ||
1076 | } | ||
1077 | |||
1078 | ret = regmap_read(info->regmap, RT9455_REG_MASK3, &mask3); | ||
1079 | if (ret) { | ||
1080 | dev_err(dev, "Failed to read MASK3 register\n"); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | if (irq3 & GET_MASK(F_BSTBUSOVI)) { | ||
1085 | dev_err(dev, "Boost fault. Overvoltage input occurred\n"); | ||
1086 | alert_userspace = true; | ||
1087 | } | ||
1088 | if (irq3 & GET_MASK(F_BSTOLI)) { | ||
1089 | dev_err(dev, "Boost fault. Overload\n"); | ||
1090 | alert_userspace = true; | ||
1091 | } | ||
1092 | if (irq3 & GET_MASK(F_BSTLOWVI)) { | ||
1093 | dev_err(dev, "Boost fault. Battery voltage too low\n"); | ||
1094 | alert_userspace = true; | ||
1095 | } | ||
1096 | if (irq3 & GET_MASK(F_BST32SI)) { | ||
1097 | dev_err(dev, "Boost fault. 32 seconds timeout occurred.\n"); | ||
1098 | alert_userspace = true; | ||
1099 | } | ||
1100 | |||
1101 | if (alert_userspace) { | ||
1102 | dev_info(dev, "Boost fault occurred, therefore the charger goes into charge mode\n"); | ||
1103 | ret = rt9455_set_voreg_before_charge_mode(info); | ||
1104 | if (ret) { | ||
1105 | dev_err(dev, "Failed to set VOREG before entering charge mode\n"); | ||
1106 | return ret; | ||
1107 | } | ||
1108 | ret = regmap_field_write(info->regmap_fields[F_OPA_MODE], | ||
1109 | RT9455_CHARGE_MODE); | ||
1110 | if (ret) { | ||
1111 | dev_err(dev, "Failed to set charger in charge mode\n"); | ||
1112 | return ret; | ||
1113 | } | ||
1114 | *_alert_userspace = alert_userspace; | ||
1115 | } | ||
1116 | |||
1117 | return 0; | ||
1118 | } | ||
1119 | |||
1120 | static irqreturn_t rt9455_irq_handler_thread(int irq, void *data) | ||
1121 | { | ||
1122 | struct rt9455_info *info = data; | ||
1123 | struct device *dev; | ||
1124 | bool alert_userspace = false; | ||
1125 | bool is_battery_absent = false; | ||
1126 | unsigned int status; | ||
1127 | int ret; | ||
1128 | |||
1129 | if (!info) | ||
1130 | return IRQ_NONE; | ||
1131 | |||
1132 | dev = &info->client->dev; | ||
1133 | |||
1134 | if (irq != info->client->irq) { | ||
1135 | dev_err(dev, "Interrupt is not for RT9455 charger\n"); | ||
1136 | return IRQ_NONE; | ||
1137 | } | ||
1138 | |||
1139 | ret = regmap_field_read(info->regmap_fields[F_STAT], &status); | ||
1140 | if (ret) { | ||
1141 | dev_err(dev, "Failed to read STAT bits\n"); | ||
1142 | return IRQ_HANDLED; | ||
1143 | } | ||
1144 | dev_dbg(dev, "Charger status is %d\n", status); | ||
1145 | |||
1146 | /* | ||
1147 | * Each function that processes an IRQ register receives as output | ||
1148 | * parameter alert_userspace pointer. alert_userspace is set to true | ||
1149 | * in such a function only if an interrupt has occurred in the | ||
1150 | * respective interrupt register. This way, it is avoided the following | ||
1151 | * case: interrupt occurs only in IRQ1 register, | ||
1152 | * rt9455_irq_handler_check_irq1_register() function sets to true | ||
1153 | * alert_userspace, but rt9455_irq_handler_check_irq2_register() | ||
1154 | * and rt9455_irq_handler_check_irq3_register() functions set to false | ||
1155 | * alert_userspace and power_supply_changed() is never called. | ||
1156 | */ | ||
1157 | ret = rt9455_irq_handler_check_irq1_register(info, &is_battery_absent, | ||
1158 | &alert_userspace); | ||
1159 | if (ret) { | ||
1160 | dev_err(dev, "Failed to handle IRQ1 register\n"); | ||
1161 | return IRQ_HANDLED; | ||
1162 | } | ||
1163 | |||
1164 | ret = rt9455_irq_handler_check_irq2_register(info, is_battery_absent, | ||
1165 | &alert_userspace); | ||
1166 | if (ret) { | ||
1167 | dev_err(dev, "Failed to handle IRQ2 register\n"); | ||
1168 | return IRQ_HANDLED; | ||
1169 | } | ||
1170 | |||
1171 | ret = rt9455_irq_handler_check_irq3_register(info, &alert_userspace); | ||
1172 | if (ret) { | ||
1173 | dev_err(dev, "Failed to handle IRQ3 register\n"); | ||
1174 | return IRQ_HANDLED; | ||
1175 | } | ||
1176 | |||
1177 | if (alert_userspace) { | ||
1178 | /* | ||
1179 | * Sometimes, an interrupt occurs while rt9455_probe() function | ||
1180 | * is executing and power_supply_register() is not yet called. | ||
1181 | * Do not call power_supply_charged() in this case. | ||
1182 | */ | ||
1183 | if (info->charger) | ||
1184 | power_supply_changed(info->charger); | ||
1185 | } | ||
1186 | |||
1187 | return IRQ_HANDLED; | ||
1188 | } | ||
1189 | |||
1190 | static int rt9455_discover_charger(struct rt9455_info *info, u32 *ichrg, | ||
1191 | u32 *ieoc_percentage, | ||
1192 | u32 *mivr, u32 *iaicr) | ||
1193 | { | ||
1194 | struct device *dev = &info->client->dev; | ||
1195 | int ret; | ||
1196 | |||
1197 | if (!dev->of_node && !ACPI_HANDLE(dev)) { | ||
1198 | dev_err(dev, "No support for either device tree or ACPI\n"); | ||
1199 | return -EINVAL; | ||
1200 | } | ||
1201 | /* | ||
1202 | * ICHRG, IEOC_PERCENTAGE, VOREG and boost output voltage are mandatory | ||
1203 | * parameters. | ||
1204 | */ | ||
1205 | ret = device_property_read_u32(dev, "richtek,output-charge-current", | ||
1206 | ichrg); | ||
1207 | if (ret) { | ||
1208 | dev_err(dev, "Error: missing \"output-charge-current\" property\n"); | ||
1209 | return ret; | ||
1210 | } | ||
1211 | |||
1212 | ret = device_property_read_u32(dev, "richtek,end-of-charge-percentage", | ||
1213 | ieoc_percentage); | ||
1214 | if (ret) { | ||
1215 | dev_err(dev, "Error: missing \"end-of-charge-percentage\" property\n"); | ||
1216 | return ret; | ||
1217 | } | ||
1218 | |||
1219 | ret = device_property_read_u32(dev, | ||
1220 | "richtek,battery-regulation-voltage", | ||
1221 | &info->voreg); | ||
1222 | if (ret) { | ||
1223 | dev_err(dev, "Error: missing \"battery-regulation-voltage\" property\n"); | ||
1224 | return ret; | ||
1225 | } | ||
1226 | |||
1227 | ret = device_property_read_u32(dev, "richtek,boost-output-voltage", | ||
1228 | &info->boost_voltage); | ||
1229 | if (ret) { | ||
1230 | dev_err(dev, "Error: missing \"boost-output-voltage\" property\n"); | ||
1231 | return ret; | ||
1232 | } | ||
1233 | |||
1234 | /* | ||
1235 | * MIVR and IAICR are optional parameters. Do not return error if one of | ||
1236 | * them is not present in ACPI table or device tree specification. | ||
1237 | */ | ||
1238 | device_property_read_u32(dev, "richtek,min-input-voltage-regulation", | ||
1239 | mivr); | ||
1240 | device_property_read_u32(dev, "richtek,avg-input-current-regulation", | ||
1241 | iaicr); | ||
1242 | |||
1243 | return 0; | ||
1244 | } | ||
1245 | |||
1246 | #if IS_ENABLED(CONFIG_USB_PHY) | ||
1247 | static int rt9455_usb_event_none(struct rt9455_info *info, | ||
1248 | u8 opa_mode, u8 iaicr) | ||
1249 | { | ||
1250 | struct device *dev = &info->client->dev; | ||
1251 | int ret; | ||
1252 | |||
1253 | if (opa_mode == RT9455_BOOST_MODE) { | ||
1254 | ret = rt9455_set_voreg_before_charge_mode(info); | ||
1255 | if (ret) { | ||
1256 | dev_err(dev, "Failed to set VOREG before entering charge mode\n"); | ||
1257 | return ret; | ||
1258 | } | ||
1259 | /* | ||
1260 | * If the charger is in boost mode, and it has received | ||
1261 | * USB_EVENT_NONE, this means the consumer device powered by the | ||
1262 | * charger is not connected anymore. | ||
1263 | * In this case, the charger goes into charge mode. | ||
1264 | */ | ||
1265 | dev_dbg(dev, "USB_EVENT_NONE received, therefore the charger goes into charge mode\n"); | ||
1266 | ret = regmap_field_write(info->regmap_fields[F_OPA_MODE], | ||
1267 | RT9455_CHARGE_MODE); | ||
1268 | if (ret) { | ||
1269 | dev_err(dev, "Failed to set charger in charge mode\n"); | ||
1270 | return NOTIFY_DONE; | ||
1271 | } | ||
1272 | } | ||
1273 | |||
1274 | dev_dbg(dev, "USB_EVENT_NONE received, therefore IAICR is set to its minimum value\n"); | ||
1275 | if (iaicr != RT9455_IAICR_100MA) { | ||
1276 | ret = regmap_field_write(info->regmap_fields[F_IAICR], | ||
1277 | RT9455_IAICR_100MA); | ||
1278 | if (ret) { | ||
1279 | dev_err(dev, "Failed to set IAICR value\n"); | ||
1280 | return NOTIFY_DONE; | ||
1281 | } | ||
1282 | } | ||
1283 | |||
1284 | return NOTIFY_OK; | ||
1285 | } | ||
1286 | |||
1287 | static int rt9455_usb_event_vbus(struct rt9455_info *info, | ||
1288 | u8 opa_mode, u8 iaicr) | ||
1289 | { | ||
1290 | struct device *dev = &info->client->dev; | ||
1291 | int ret; | ||
1292 | |||
1293 | if (opa_mode == RT9455_BOOST_MODE) { | ||
1294 | ret = rt9455_set_voreg_before_charge_mode(info); | ||
1295 | if (ret) { | ||
1296 | dev_err(dev, "Failed to set VOREG before entering charge mode\n"); | ||
1297 | return ret; | ||
1298 | } | ||
1299 | /* | ||
1300 | * If the charger is in boost mode, and it has received | ||
1301 | * USB_EVENT_VBUS, this means the consumer device powered by the | ||
1302 | * charger is not connected anymore. | ||
1303 | * In this case, the charger goes into charge mode. | ||
1304 | */ | ||
1305 | dev_dbg(dev, "USB_EVENT_VBUS received, therefore the charger goes into charge mode\n"); | ||
1306 | ret = regmap_field_write(info->regmap_fields[F_OPA_MODE], | ||
1307 | RT9455_CHARGE_MODE); | ||
1308 | if (ret) { | ||
1309 | dev_err(dev, "Failed to set charger in charge mode\n"); | ||
1310 | return NOTIFY_DONE; | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | dev_dbg(dev, "USB_EVENT_VBUS received, therefore IAICR is set to 500 mA\n"); | ||
1315 | if (iaicr != RT9455_IAICR_500MA) { | ||
1316 | ret = regmap_field_write(info->regmap_fields[F_IAICR], | ||
1317 | RT9455_IAICR_500MA); | ||
1318 | if (ret) { | ||
1319 | dev_err(dev, "Failed to set IAICR value\n"); | ||
1320 | return NOTIFY_DONE; | ||
1321 | } | ||
1322 | } | ||
1323 | |||
1324 | return NOTIFY_OK; | ||
1325 | } | ||
1326 | |||
1327 | static int rt9455_usb_event_id(struct rt9455_info *info, | ||
1328 | u8 opa_mode, u8 iaicr) | ||
1329 | { | ||
1330 | struct device *dev = &info->client->dev; | ||
1331 | int ret; | ||
1332 | |||
1333 | if (opa_mode == RT9455_CHARGE_MODE) { | ||
1334 | ret = rt9455_set_boost_voltage_before_boost_mode(info); | ||
1335 | if (ret) { | ||
1336 | dev_err(dev, "Failed to set boost output voltage before entering boost mode\n"); | ||
1337 | return ret; | ||
1338 | } | ||
1339 | /* | ||
1340 | * If the charger is in charge mode, and it has received | ||
1341 | * USB_EVENT_ID, this means a consumer device is connected and | ||
1342 | * it should be powered by the charger. | ||
1343 | * In this case, the charger goes into boost mode. | ||
1344 | */ | ||
1345 | dev_dbg(dev, "USB_EVENT_ID received, therefore the charger goes into boost mode\n"); | ||
1346 | ret = regmap_field_write(info->regmap_fields[F_OPA_MODE], | ||
1347 | RT9455_BOOST_MODE); | ||
1348 | if (ret) { | ||
1349 | dev_err(dev, "Failed to set charger in boost mode\n"); | ||
1350 | return NOTIFY_DONE; | ||
1351 | } | ||
1352 | } | ||
1353 | |||
1354 | dev_dbg(dev, "USB_EVENT_ID received, therefore IAICR is set to its minimum value\n"); | ||
1355 | if (iaicr != RT9455_IAICR_100MA) { | ||
1356 | ret = regmap_field_write(info->regmap_fields[F_IAICR], | ||
1357 | RT9455_IAICR_100MA); | ||
1358 | if (ret) { | ||
1359 | dev_err(dev, "Failed to set IAICR value\n"); | ||
1360 | return NOTIFY_DONE; | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1364 | return NOTIFY_OK; | ||
1365 | } | ||
1366 | |||
1367 | static int rt9455_usb_event_charger(struct rt9455_info *info, | ||
1368 | u8 opa_mode, u8 iaicr) | ||
1369 | { | ||
1370 | struct device *dev = &info->client->dev; | ||
1371 | int ret; | ||
1372 | |||
1373 | if (opa_mode == RT9455_BOOST_MODE) { | ||
1374 | ret = rt9455_set_voreg_before_charge_mode(info); | ||
1375 | if (ret) { | ||
1376 | dev_err(dev, "Failed to set VOREG before entering charge mode\n"); | ||
1377 | return ret; | ||
1378 | } | ||
1379 | /* | ||
1380 | * If the charger is in boost mode, and it has received | ||
1381 | * USB_EVENT_CHARGER, this means the consumer device powered by | ||
1382 | * the charger is not connected anymore. | ||
1383 | * In this case, the charger goes into charge mode. | ||
1384 | */ | ||
1385 | dev_dbg(dev, "USB_EVENT_CHARGER received, therefore the charger goes into charge mode\n"); | ||
1386 | ret = regmap_field_write(info->regmap_fields[F_OPA_MODE], | ||
1387 | RT9455_CHARGE_MODE); | ||
1388 | if (ret) { | ||
1389 | dev_err(dev, "Failed to set charger in charge mode\n"); | ||
1390 | return NOTIFY_DONE; | ||
1391 | } | ||
1392 | } | ||
1393 | |||
1394 | dev_dbg(dev, "USB_EVENT_CHARGER received, therefore IAICR is set to no current limit\n"); | ||
1395 | if (iaicr != RT9455_IAICR_NO_LIMIT) { | ||
1396 | ret = regmap_field_write(info->regmap_fields[F_IAICR], | ||
1397 | RT9455_IAICR_NO_LIMIT); | ||
1398 | if (ret) { | ||
1399 | dev_err(dev, "Failed to set IAICR value\n"); | ||
1400 | return NOTIFY_DONE; | ||
1401 | } | ||
1402 | } | ||
1403 | |||
1404 | return NOTIFY_OK; | ||
1405 | } | ||
1406 | |||
1407 | static int rt9455_usb_event(struct notifier_block *nb, | ||
1408 | unsigned long event, void *power) | ||
1409 | { | ||
1410 | struct rt9455_info *info = container_of(nb, struct rt9455_info, nb); | ||
1411 | struct device *dev = &info->client->dev; | ||
1412 | unsigned int opa_mode, iaicr; | ||
1413 | int ret; | ||
1414 | |||
1415 | /* | ||
1416 | * Determine whether the charger is in charge mode | ||
1417 | * or in boost mode. | ||
1418 | */ | ||
1419 | ret = regmap_field_read(info->regmap_fields[F_OPA_MODE], | ||
1420 | &opa_mode); | ||
1421 | if (ret) { | ||
1422 | dev_err(dev, "Failed to read OPA_MODE value\n"); | ||
1423 | return NOTIFY_DONE; | ||
1424 | } | ||
1425 | |||
1426 | ret = regmap_field_read(info->regmap_fields[F_IAICR], | ||
1427 | &iaicr); | ||
1428 | if (ret) { | ||
1429 | dev_err(dev, "Failed to read IAICR value\n"); | ||
1430 | return NOTIFY_DONE; | ||
1431 | } | ||
1432 | |||
1433 | dev_dbg(dev, "Received USB event %lu\n", event); | ||
1434 | switch (event) { | ||
1435 | case USB_EVENT_NONE: | ||
1436 | return rt9455_usb_event_none(info, opa_mode, iaicr); | ||
1437 | case USB_EVENT_VBUS: | ||
1438 | return rt9455_usb_event_vbus(info, opa_mode, iaicr); | ||
1439 | case USB_EVENT_ID: | ||
1440 | return rt9455_usb_event_id(info, opa_mode, iaicr); | ||
1441 | case USB_EVENT_CHARGER: | ||
1442 | return rt9455_usb_event_charger(info, opa_mode, iaicr); | ||
1443 | default: | ||
1444 | dev_err(dev, "Unknown USB event\n"); | ||
1445 | } | ||
1446 | return NOTIFY_DONE; | ||
1447 | } | ||
1448 | #endif | ||
1449 | |||
1450 | static void rt9455_pwr_rdy_work_callback(struct work_struct *work) | ||
1451 | { | ||
1452 | struct rt9455_info *info = container_of(work, struct rt9455_info, | ||
1453 | pwr_rdy_work.work); | ||
1454 | struct device *dev = &info->client->dev; | ||
1455 | unsigned int pwr_rdy; | ||
1456 | int ret; | ||
1457 | |||
1458 | ret = regmap_field_read(info->regmap_fields[F_PWR_RDY], &pwr_rdy); | ||
1459 | if (ret) { | ||
1460 | dev_err(dev, "Failed to read PWR_RDY bit\n"); | ||
1461 | return; | ||
1462 | } | ||
1463 | switch (pwr_rdy) { | ||
1464 | case RT9455_PWR_FAULT: | ||
1465 | dev_dbg(dev, "Charger disconnected from power source\n"); | ||
1466 | cancel_delayed_work_sync(&info->max_charging_time_work); | ||
1467 | break; | ||
1468 | case RT9455_PWR_GOOD: | ||
1469 | dev_dbg(dev, "Charger connected to power source\n"); | ||
1470 | ret = regmap_field_write(info->regmap_fields[F_CHG_EN], | ||
1471 | RT9455_CHARGE_ENABLE); | ||
1472 | if (ret) { | ||
1473 | dev_err(dev, "Failed to enable charging\n"); | ||
1474 | return; | ||
1475 | } | ||
1476 | queue_delayed_work(system_power_efficient_wq, | ||
1477 | &info->max_charging_time_work, | ||
1478 | RT9455_MAX_CHARGING_TIME * HZ); | ||
1479 | break; | ||
1480 | } | ||
1481 | } | ||
1482 | |||
1483 | static void rt9455_max_charging_time_work_callback(struct work_struct *work) | ||
1484 | { | ||
1485 | struct rt9455_info *info = container_of(work, struct rt9455_info, | ||
1486 | max_charging_time_work.work); | ||
1487 | struct device *dev = &info->client->dev; | ||
1488 | int ret; | ||
1489 | |||
1490 | dev_err(dev, "Battery has been charging for at least 6 hours and is not yet fully charged. Battery is dead, therefore charging is disabled.\n"); | ||
1491 | ret = regmap_field_write(info->regmap_fields[F_CHG_EN], | ||
1492 | RT9455_CHARGE_DISABLE); | ||
1493 | if (ret) | ||
1494 | dev_err(dev, "Failed to disable charging\n"); | ||
1495 | } | ||
1496 | |||
1497 | static void rt9455_batt_presence_work_callback(struct work_struct *work) | ||
1498 | { | ||
1499 | struct rt9455_info *info = container_of(work, struct rt9455_info, | ||
1500 | batt_presence_work.work); | ||
1501 | struct device *dev = &info->client->dev; | ||
1502 | unsigned int irq1, mask1; | ||
1503 | int ret; | ||
1504 | |||
1505 | ret = regmap_read(info->regmap, RT9455_REG_IRQ1, &irq1); | ||
1506 | if (ret) { | ||
1507 | dev_err(dev, "Failed to read IRQ1 register\n"); | ||
1508 | return; | ||
1509 | } | ||
1510 | |||
1511 | /* | ||
1512 | * If the battery is still absent, batt_presence_work is rescheduled. | ||
1513 | * Otherwise, max_charging_time is scheduled. | ||
1514 | */ | ||
1515 | if (irq1 & GET_MASK(F_BATAB)) { | ||
1516 | queue_delayed_work(system_power_efficient_wq, | ||
1517 | &info->batt_presence_work, | ||
1518 | RT9455_BATT_PRESENCE_DELAY * HZ); | ||
1519 | } else { | ||
1520 | queue_delayed_work(system_power_efficient_wq, | ||
1521 | &info->max_charging_time_work, | ||
1522 | RT9455_MAX_CHARGING_TIME * HZ); | ||
1523 | |||
1524 | ret = regmap_read(info->regmap, RT9455_REG_MASK1, &mask1); | ||
1525 | if (ret) { | ||
1526 | dev_err(dev, "Failed to read MASK1 register\n"); | ||
1527 | return; | ||
1528 | } | ||
1529 | |||
1530 | if (mask1 & GET_MASK(F_BATABM)) { | ||
1531 | ret = regmap_field_write(info->regmap_fields[F_BATABM], | ||
1532 | 0x00); | ||
1533 | if (ret) | ||
1534 | dev_err(dev, "Failed to unmask BATAB interrupt\n"); | ||
1535 | } | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | static const struct power_supply_desc rt9455_charger_desc = { | ||
1540 | .name = RT9455_DRIVER_NAME, | ||
1541 | .type = POWER_SUPPLY_TYPE_USB, | ||
1542 | .properties = rt9455_charger_properties, | ||
1543 | .num_properties = ARRAY_SIZE(rt9455_charger_properties), | ||
1544 | .get_property = rt9455_charger_get_property, | ||
1545 | }; | ||
1546 | |||
1547 | static bool rt9455_is_writeable_reg(struct device *dev, unsigned int reg) | ||
1548 | { | ||
1549 | switch (reg) { | ||
1550 | case RT9455_REG_DEV_ID: | ||
1551 | case RT9455_REG_IRQ1: | ||
1552 | case RT9455_REG_IRQ2: | ||
1553 | case RT9455_REG_IRQ3: | ||
1554 | return false; | ||
1555 | default: | ||
1556 | return true; | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1560 | static bool rt9455_is_volatile_reg(struct device *dev, unsigned int reg) | ||
1561 | { | ||
1562 | switch (reg) { | ||
1563 | case RT9455_REG_DEV_ID: | ||
1564 | case RT9455_REG_CTRL5: | ||
1565 | case RT9455_REG_CTRL6: | ||
1566 | return false; | ||
1567 | default: | ||
1568 | return true; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | static const struct regmap_config rt9455_regmap_config = { | ||
1573 | .reg_bits = 8, | ||
1574 | .val_bits = 8, | ||
1575 | .writeable_reg = rt9455_is_writeable_reg, | ||
1576 | .volatile_reg = rt9455_is_volatile_reg, | ||
1577 | .max_register = RT9455_REG_MASK3, | ||
1578 | .cache_type = REGCACHE_RBTREE, | ||
1579 | }; | ||
1580 | |||
1581 | static int rt9455_probe(struct i2c_client *client, | ||
1582 | const struct i2c_device_id *id) | ||
1583 | { | ||
1584 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
1585 | struct device *dev = &client->dev; | ||
1586 | struct rt9455_info *info; | ||
1587 | struct power_supply_config rt9455_charger_config = {}; | ||
1588 | /* | ||
1589 | * Mandatory device-specific data values. Also, VOREG and boost output | ||
1590 | * voltage are mandatory values, but they are stored in rt9455_info | ||
1591 | * structure. | ||
1592 | */ | ||
1593 | u32 ichrg, ieoc_percentage; | ||
1594 | /* Optional device-specific data values. */ | ||
1595 | u32 mivr = -1, iaicr = -1; | ||
1596 | int i, ret; | ||
1597 | |||
1598 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
1599 | dev_err(dev, "No support for SMBUS_BYTE_DATA\n"); | ||
1600 | return -ENODEV; | ||
1601 | } | ||
1602 | info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); | ||
1603 | if (!info) | ||
1604 | return -ENOMEM; | ||
1605 | |||
1606 | info->client = client; | ||
1607 | i2c_set_clientdata(client, info); | ||
1608 | |||
1609 | info->regmap = devm_regmap_init_i2c(client, | ||
1610 | &rt9455_regmap_config); | ||
1611 | if (IS_ERR(info->regmap)) { | ||
1612 | dev_err(dev, "Failed to initialize register map\n"); | ||
1613 | return -EINVAL; | ||
1614 | } | ||
1615 | |||
1616 | for (i = 0; i < F_MAX_FIELDS; i++) { | ||
1617 | info->regmap_fields[i] = | ||
1618 | devm_regmap_field_alloc(dev, info->regmap, | ||
1619 | rt9455_reg_fields[i]); | ||
1620 | if (IS_ERR(info->regmap_fields[i])) { | ||
1621 | dev_err(dev, | ||
1622 | "Failed to allocate regmap field = %d\n", i); | ||
1623 | return PTR_ERR(info->regmap_fields[i]); | ||
1624 | } | ||
1625 | } | ||
1626 | |||
1627 | ret = rt9455_discover_charger(info, &ichrg, &ieoc_percentage, | ||
1628 | &mivr, &iaicr); | ||
1629 | if (ret) { | ||
1630 | dev_err(dev, "Failed to discover charger\n"); | ||
1631 | return ret; | ||
1632 | } | ||
1633 | |||
1634 | #if IS_ENABLED(CONFIG_USB_PHY) | ||
1635 | info->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); | ||
1636 | if (IS_ERR(info->usb_phy)) { | ||
1637 | dev_err(dev, "Failed to get USB transceiver\n"); | ||
1638 | } else { | ||
1639 | info->nb.notifier_call = rt9455_usb_event; | ||
1640 | ret = usb_register_notifier(info->usb_phy, &info->nb); | ||
1641 | if (ret) { | ||
1642 | dev_err(dev, "Failed to register USB notifier\n"); | ||
1643 | /* | ||
1644 | * If usb_register_notifier() fails, set notifier_call | ||
1645 | * to NULL, to avoid calling usb_unregister_notifier(). | ||
1646 | */ | ||
1647 | info->nb.notifier_call = NULL; | ||
1648 | } | ||
1649 | } | ||
1650 | #endif | ||
1651 | |||
1652 | INIT_DEFERRABLE_WORK(&info->pwr_rdy_work, rt9455_pwr_rdy_work_callback); | ||
1653 | INIT_DEFERRABLE_WORK(&info->max_charging_time_work, | ||
1654 | rt9455_max_charging_time_work_callback); | ||
1655 | INIT_DEFERRABLE_WORK(&info->batt_presence_work, | ||
1656 | rt9455_batt_presence_work_callback); | ||
1657 | |||
1658 | rt9455_charger_config.of_node = dev->of_node; | ||
1659 | rt9455_charger_config.drv_data = info; | ||
1660 | rt9455_charger_config.supplied_to = rt9455_charger_supplied_to; | ||
1661 | rt9455_charger_config.num_supplicants = | ||
1662 | ARRAY_SIZE(rt9455_charger_supplied_to); | ||
1663 | ret = devm_request_threaded_irq(dev, client->irq, NULL, | ||
1664 | rt9455_irq_handler_thread, | ||
1665 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
1666 | RT9455_DRIVER_NAME, info); | ||
1667 | if (ret) { | ||
1668 | dev_err(dev, "Failed to register IRQ handler\n"); | ||
1669 | goto put_usb_notifier; | ||
1670 | } | ||
1671 | |||
1672 | ret = rt9455_hw_init(info, ichrg, ieoc_percentage, mivr, iaicr); | ||
1673 | if (ret) { | ||
1674 | dev_err(dev, "Failed to set charger to its default values\n"); | ||
1675 | goto put_usb_notifier; | ||
1676 | } | ||
1677 | |||
1678 | info->charger = devm_power_supply_register(dev, &rt9455_charger_desc, | ||
1679 | &rt9455_charger_config); | ||
1680 | if (IS_ERR(info->charger)) { | ||
1681 | dev_err(dev, "Failed to register charger\n"); | ||
1682 | ret = PTR_ERR(info->charger); | ||
1683 | goto put_usb_notifier; | ||
1684 | } | ||
1685 | |||
1686 | return 0; | ||
1687 | |||
1688 | put_usb_notifier: | ||
1689 | #if IS_ENABLED(CONFIG_USB_PHY) | ||
1690 | if (info->nb.notifier_call) { | ||
1691 | usb_unregister_notifier(info->usb_phy, &info->nb); | ||
1692 | info->nb.notifier_call = NULL; | ||
1693 | } | ||
1694 | #endif | ||
1695 | return ret; | ||
1696 | } | ||
1697 | |||
1698 | static int rt9455_remove(struct i2c_client *client) | ||
1699 | { | ||
1700 | int ret; | ||
1701 | struct rt9455_info *info = i2c_get_clientdata(client); | ||
1702 | |||
1703 | ret = rt9455_register_reset(info); | ||
1704 | if (ret) | ||
1705 | dev_err(&info->client->dev, "Failed to set charger to its default values\n"); | ||
1706 | |||
1707 | #if IS_ENABLED(CONFIG_USB_PHY) | ||
1708 | if (info->nb.notifier_call) | ||
1709 | usb_unregister_notifier(info->usb_phy, &info->nb); | ||
1710 | #endif | ||
1711 | |||
1712 | cancel_delayed_work_sync(&info->pwr_rdy_work); | ||
1713 | cancel_delayed_work_sync(&info->max_charging_time_work); | ||
1714 | cancel_delayed_work_sync(&info->batt_presence_work); | ||
1715 | |||
1716 | return ret; | ||
1717 | } | ||
1718 | |||
1719 | static const struct i2c_device_id rt9455_i2c_id_table[] = { | ||
1720 | { RT9455_DRIVER_NAME, 0 }, | ||
1721 | { }, | ||
1722 | }; | ||
1723 | MODULE_DEVICE_TABLE(i2c, rt9455_i2c_id_table); | ||
1724 | |||
1725 | static const struct of_device_id rt9455_of_match[] = { | ||
1726 | { .compatible = "richtek,rt9455", }, | ||
1727 | { }, | ||
1728 | }; | ||
1729 | MODULE_DEVICE_TABLE(of, rt9455_of_match); | ||
1730 | |||
1731 | static const struct acpi_device_id rt9455_i2c_acpi_match[] = { | ||
1732 | { "RT945500", 0 }, | ||
1733 | { } | ||
1734 | }; | ||
1735 | MODULE_DEVICE_TABLE(acpi, rt9455_i2c_acpi_match); | ||
1736 | |||
1737 | static struct i2c_driver rt9455_driver = { | ||
1738 | .probe = rt9455_probe, | ||
1739 | .remove = rt9455_remove, | ||
1740 | .id_table = rt9455_i2c_id_table, | ||
1741 | .driver = { | ||
1742 | .name = RT9455_DRIVER_NAME, | ||
1743 | .of_match_table = of_match_ptr(rt9455_of_match), | ||
1744 | .acpi_match_table = ACPI_PTR(rt9455_i2c_acpi_match), | ||
1745 | }, | ||
1746 | }; | ||
1747 | module_i2c_driver(rt9455_driver); | ||
1748 | |||
1749 | MODULE_LICENSE("GPL"); | ||
1750 | MODULE_AUTHOR("Anda-Maria Nicolae <anda-maria.nicolae@intel.com>"); | ||
1751 | MODULE_ALIAS("i2c:rt9455-charger"); | ||
1752 | MODULE_DESCRIPTION("Richtek RT9455 Charger Driver"); | ||
diff --git a/drivers/power/sbs-battery.c b/drivers/power/sbs-battery.c index de1178659d4b..d6226d68b574 100644 --- a/drivers/power/sbs-battery.c +++ b/drivers/power/sbs-battery.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
30 | #include <linux/of.h> | 30 | #include <linux/of.h> |
31 | #include <linux/stat.h> | ||
31 | 32 | ||
32 | #include <linux/power/sbs-battery.h> | 33 | #include <linux/power/sbs-battery.h> |
33 | 34 | ||
@@ -170,6 +171,7 @@ struct sbs_info { | |||
170 | 171 | ||
171 | static char model_name[I2C_SMBUS_BLOCK_MAX + 1]; | 172 | static char model_name[I2C_SMBUS_BLOCK_MAX + 1]; |
172 | static char manufacturer[I2C_SMBUS_BLOCK_MAX + 1]; | 173 | static char manufacturer[I2C_SMBUS_BLOCK_MAX + 1]; |
174 | static bool force_load; | ||
173 | 175 | ||
174 | static int sbs_read_word_data(struct i2c_client *client, u8 address) | 176 | static int sbs_read_word_data(struct i2c_client *client, u8 address) |
175 | { | 177 | { |
@@ -885,14 +887,17 @@ static int sbs_probe(struct i2c_client *client, | |||
885 | 887 | ||
886 | skip_gpio: | 888 | skip_gpio: |
887 | /* | 889 | /* |
888 | * Before we register, we need to make sure we can actually talk | 890 | * Before we register, we might need to make sure we can actually talk |
889 | * to the battery. | 891 | * to the battery. |
890 | */ | 892 | */ |
891 | rc = sbs_read_word_data(client, sbs_data[REG_STATUS].addr); | 893 | if (!force_load) { |
892 | if (rc < 0) { | 894 | rc = sbs_read_word_data(client, sbs_data[REG_STATUS].addr); |
893 | dev_err(&client->dev, "%s: Failed to get device status\n", | 895 | |
894 | __func__); | 896 | if (rc < 0) { |
895 | goto exit_psupply; | 897 | dev_err(&client->dev, "%s: Failed to get device status\n", |
898 | __func__); | ||
899 | goto exit_psupply; | ||
900 | } | ||
896 | } | 901 | } |
897 | 902 | ||
898 | chip->power_supply = power_supply_register(&client->dev, sbs_desc, | 903 | chip->power_supply = power_supply_register(&client->dev, sbs_desc, |
@@ -991,3 +996,7 @@ module_i2c_driver(sbs_battery_driver); | |||
991 | 996 | ||
992 | MODULE_DESCRIPTION("SBS battery monitor driver"); | 997 | MODULE_DESCRIPTION("SBS battery monitor driver"); |
993 | MODULE_LICENSE("GPL"); | 998 | MODULE_LICENSE("GPL"); |
999 | |||
1000 | module_param(force_load, bool, S_IRUSR | S_IRGRP | S_IROTH); | ||
1001 | MODULE_PARM_DESC(force_load, | ||
1002 | "Attempt to load the driver even if no battery is connected"); | ||
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 0161bdabd5a3..db11ae6599f3 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
@@ -609,6 +609,7 @@ static int wm831x_power_probe(struct platform_device *pdev) | |||
609 | return ret; | 609 | return ret; |
610 | 610 | ||
611 | err_bat_irq: | 611 | err_bat_irq: |
612 | --i; | ||
612 | for (; i >= 0; i--) { | 613 | for (; i >= 0; i--) { |
613 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 614 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
614 | free_irq(irq, power); | 615 | free_irq(irq, power); |