diff options
-rw-r--r-- | Documentation/devicetree/bindings/power/twl-charger.txt | 20 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/power_supply/ti,bq24735.txt | 32 | ||||
-rw-r--r-- | Documentation/power/power_supply_class.txt | 8 | ||||
-rw-r--r-- | arch/arm/boot/dts/twl4030.dtsi | 6 | ||||
-rw-r--r-- | drivers/power/Kconfig | 6 | ||||
-rw-r--r-- | drivers/power/Makefile | 1 | ||||
-rw-r--r-- | drivers/power/ab8500_charger.c | 17 | ||||
-rw-r--r-- | drivers/power/bq2415x_charger.c | 6 | ||||
-rw-r--r-- | drivers/power/bq24735-charger.c | 419 | ||||
-rw-r--r-- | drivers/power/charger-manager.c | 85 | ||||
-rw-r--r-- | drivers/power/isp1704_charger.c | 91 | ||||
-rw-r--r-- | drivers/power/max17042_battery.c | 373 | ||||
-rw-r--r-- | drivers/power/pm2301_charger.c | 27 | ||||
-rw-r--r-- | drivers/power/tps65090-charger.c | 30 | ||||
-rw-r--r-- | drivers/power/twl4030_charger.c | 47 | ||||
-rw-r--r-- | include/linux/power/bq24735-charger.h | 39 |
16 files changed, 852 insertions, 355 deletions
diff --git a/Documentation/devicetree/bindings/power/twl-charger.txt b/Documentation/devicetree/bindings/power/twl-charger.txt new file mode 100644 index 000000000000..d5c706216df5 --- /dev/null +++ b/Documentation/devicetree/bindings/power/twl-charger.txt | |||
@@ -0,0 +1,20 @@ | |||
1 | TWL BCI (Battery Charger Interface) | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: | ||
5 | - "ti,twl4030-bci" | ||
6 | - interrupts: two interrupt lines from the TWL SIH (secondary | ||
7 | interrupt handler) - interrupts 9 and 2. | ||
8 | |||
9 | Optional properties: | ||
10 | - ti,bb-uvolt: microvolts for charging the backup battery. | ||
11 | - ti,bb-uamp: microamps for charging the backup battery. | ||
12 | |||
13 | Examples: | ||
14 | |||
15 | bci { | ||
16 | compatible = "ti,twl4030-bci"; | ||
17 | interrupts = <9>, <2>; | ||
18 | ti,bb-uvolt = <3200000>; | ||
19 | ti,bb-uamp = <150>; | ||
20 | }; | ||
diff --git a/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt b/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt new file mode 100644 index 000000000000..4f6a550184d0 --- /dev/null +++ b/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt | |||
@@ -0,0 +1,32 @@ | |||
1 | TI BQ24735 Charge Controller | ||
2 | ~~~~~~~~~~ | ||
3 | |||
4 | Required properties : | ||
5 | - compatible : "ti,bq24735" | ||
6 | |||
7 | Optional properties : | ||
8 | - interrupts : Specify the interrupt to be used to trigger when the AC | ||
9 | adapter is either plugged in or removed. | ||
10 | - ti,ac-detect-gpios : This GPIO is optionally used to read the AC adapter | ||
11 | presence. This is a Host GPIO that is configured as an input and | ||
12 | connected to the bq24735. | ||
13 | - ti,charge-current : Used to control and set the charging current. This value | ||
14 | must be between 128mA and 8.128A with a 64mA step resolution. The POR value | ||
15 | is 0x0000h. This number is in mA (e.g. 8192), see spec for more information | ||
16 | about the ChargeCurrent (0x14h) register. | ||
17 | - ti,charge-voltage : Used to control and set the charging voltage. This value | ||
18 | must be between 1.024V and 19.2V with a 16mV step resolution. The POR value | ||
19 | is 0x0000h. This number is in mV (e.g. 19200), see spec for more information | ||
20 | about the ChargeVoltage (0x15h) register. | ||
21 | - ti,input-current : Used to control and set the charger input current. This | ||
22 | value must be between 128mA and 8.064A with a 128mA step resolution. The | ||
23 | POR value is 0x1000h. This number is in mA (e.g. 8064), see the spec for | ||
24 | more information about the InputCurrent (0x3fh) register. | ||
25 | |||
26 | Example: | ||
27 | |||
28 | bq24735@9 { | ||
29 | compatible = "ti,bq24735"; | ||
30 | reg = <0x9>; | ||
31 | ti,ac-detect-gpios = <&gpio 72 0x1>; | ||
32 | } | ||
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt index 3f10b39b0346..89a8816990ff 100644 --- a/Documentation/power/power_supply_class.txt +++ b/Documentation/power/power_supply_class.txt | |||
@@ -135,11 +135,11 @@ CAPACITY_LEVEL - capacity level. This corresponds to | |||
135 | POWER_SUPPLY_CAPACITY_LEVEL_*. | 135 | POWER_SUPPLY_CAPACITY_LEVEL_*. |
136 | 136 | ||
137 | TEMP - temperature of the power supply. | 137 | TEMP - temperature of the power supply. |
138 | TEMP_ALERT_MIN - minimum battery temperature alert value in milli centigrade. | 138 | TEMP_ALERT_MIN - minimum battery temperature alert. |
139 | TEMP_ALERT_MAX - maximum battery temperature alert value in milli centigrade. | 139 | TEMP_ALERT_MAX - maximum battery temperature alert. |
140 | TEMP_AMBIENT - ambient temperature. | 140 | TEMP_AMBIENT - ambient temperature. |
141 | TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert value in milli centigrade. | 141 | TEMP_AMBIENT_ALERT_MIN - minimum ambient temperature alert. |
142 | TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert value in milli centigrade. | 142 | TEMP_AMBIENT_ALERT_MAX - maximum ambient temperature alert. |
143 | 143 | ||
144 | TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e. | 144 | TIME_TO_EMPTY - seconds left for battery to be considered empty (i.e. |
145 | while battery powers a load) | 145 | while battery powers a load) |
diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi index fb1b2ec8eaa9..4217096ee677 100644 --- a/arch/arm/boot/dts/twl4030.dtsi +++ b/arch/arm/boot/dts/twl4030.dtsi | |||
@@ -19,6 +19,12 @@ | |||
19 | interrupts = <11>; | 19 | interrupts = <11>; |
20 | }; | 20 | }; |
21 | 21 | ||
22 | charger: bci { | ||
23 | compatible = "ti,twl4030-bci"; | ||
24 | interrupts = <9>, <2>; | ||
25 | bci3v1-supply = <&vusb3v1>; | ||
26 | }; | ||
27 | |||
22 | watchdog { | 28 | watchdog { |
23 | compatible = "ti,twl4030-wdt"; | 29 | compatible = "ti,twl4030-wdt"; |
24 | }; | 30 | }; |
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index e6f92b450913..5e2054afe840 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig | |||
@@ -346,6 +346,12 @@ config CHARGER_BQ24190 | |||
346 | help | 346 | help |
347 | Say Y to enable support for the TI BQ24190 battery charger. | 347 | Say Y to enable support for the TI BQ24190 battery charger. |
348 | 348 | ||
349 | config CHARGER_BQ24735 | ||
350 | tristate "TI BQ24735 battery charger support" | ||
351 | depends on I2C && GPIOLIB | ||
352 | help | ||
353 | Say Y to enable support for the TI BQ24735 battery charger. | ||
354 | |||
349 | config CHARGER_SMB347 | 355 | config CHARGER_SMB347 |
350 | tristate "Summit Microelectronics SMB347 Battery Charger" | 356 | tristate "Summit Microelectronics SMB347 Battery Charger" |
351 | depends on I2C | 357 | depends on I2C |
diff --git a/drivers/power/Makefile b/drivers/power/Makefile index a4b74177706f..372b4e8ab598 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile | |||
@@ -52,6 +52,7 @@ obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o | |||
52 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o | 52 | obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o |
53 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o | 53 | obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o |
54 | obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o | 54 | obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o |
55 | obj-$(CONFIG_CHARGER_BQ24735) += bq24735-charger.o | ||
55 | obj-$(CONFIG_POWER_AVS) += avs/ | 56 | obj-$(CONFIG_POWER_AVS) += avs/ |
56 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o | 57 | obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o |
57 | obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o | 58 | obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o |
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c index a4c4a10b3a41..19110aa613a1 100644 --- a/drivers/power/ab8500_charger.c +++ b/drivers/power/ab8500_charger.c | |||
@@ -766,7 +766,6 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, | |||
766 | ret = -ENXIO; | 766 | ret = -ENXIO; |
767 | break; | 767 | break; |
768 | } | 768 | } |
769 | break; | ||
770 | case USB_STAT_CARKIT_1: | 769 | case USB_STAT_CARKIT_1: |
771 | case USB_STAT_CARKIT_2: | 770 | case USB_STAT_CARKIT_2: |
772 | case USB_STAT_ACA_DOCK_CHARGER: | 771 | case USB_STAT_ACA_DOCK_CHARGER: |
@@ -1387,8 +1386,12 @@ static int ab8500_charger_ac_en(struct ux500_charger *charger, | |||
1387 | * the GPADC module independant of the AB8500 chargers | 1386 | * the GPADC module independant of the AB8500 chargers |
1388 | */ | 1387 | */ |
1389 | if (!di->vddadc_en_ac) { | 1388 | if (!di->vddadc_en_ac) { |
1390 | regulator_enable(di->regu); | 1389 | ret = regulator_enable(di->regu); |
1391 | di->vddadc_en_ac = true; | 1390 | if (ret) |
1391 | dev_warn(di->dev, | ||
1392 | "Failed to enable regulator\n"); | ||
1393 | else | ||
1394 | di->vddadc_en_ac = true; | ||
1392 | } | 1395 | } |
1393 | 1396 | ||
1394 | /* Check if the requested voltage or current is valid */ | 1397 | /* Check if the requested voltage or current is valid */ |
@@ -1556,8 +1559,12 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, | |||
1556 | * the GPADC module independant of the AB8500 chargers | 1559 | * the GPADC module independant of the AB8500 chargers |
1557 | */ | 1560 | */ |
1558 | if (!di->vddadc_en_usb) { | 1561 | if (!di->vddadc_en_usb) { |
1559 | regulator_enable(di->regu); | 1562 | ret = regulator_enable(di->regu); |
1560 | di->vddadc_en_usb = true; | 1563 | if (ret) |
1564 | dev_warn(di->dev, | ||
1565 | "Failed to enable regulator\n"); | ||
1566 | else | ||
1567 | di->vddadc_en_usb = true; | ||
1561 | } | 1568 | } |
1562 | 1569 | ||
1563 | /* Enable USB charging */ | 1570 | /* Enable USB charging */ |
diff --git a/drivers/power/bq2415x_charger.c b/drivers/power/bq2415x_charger.c index 0727f9256138..df893dd1447d 100644 --- a/drivers/power/bq2415x_charger.c +++ b/drivers/power/bq2415x_charger.c | |||
@@ -605,9 +605,13 @@ static int bq2415x_set_battery_regulation_voltage(struct bq2415x_device *bq, | |||
605 | { | 605 | { |
606 | int val = (mV/10 - 350) / 2; | 606 | int val = (mV/10 - 350) / 2; |
607 | 607 | ||
608 | /* | ||
609 | * According to datasheet, maximum battery regulation voltage is | ||
610 | * 4440mV which is b101111 = 47. | ||
611 | */ | ||
608 | if (val < 0) | 612 | if (val < 0) |
609 | val = 0; | 613 | val = 0; |
610 | else if (val > 94) /* FIXME: Max is 94 or 122 ? Set max value ? */ | 614 | else if (val > 47) |
611 | return -EINVAL; | 615 | return -EINVAL; |
612 | 616 | ||
613 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val, | 617 | return bq2415x_i2c_write_mask(bq, BQ2415X_REG_VOLTAGE, val, |
diff --git a/drivers/power/bq24735-charger.c b/drivers/power/bq24735-charger.c new file mode 100644 index 000000000000..d022b823305b --- /dev/null +++ b/drivers/power/bq24735-charger.c | |||
@@ -0,0 +1,419 @@ | |||
1 | /* | ||
2 | * Battery charger driver for TI BQ24735 | ||
3 | * | ||
4 | * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. | ||
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; | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | #include <linux/err.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/of.h> | ||
28 | #include <linux/of_gpio.h> | ||
29 | #include <linux/power_supply.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | #include <linux/power/bq24735-charger.h> | ||
33 | |||
34 | #define BQ24735_CHG_OPT 0x12 | ||
35 | #define BQ24735_CHG_OPT_CHARGE_DISABLE (1 << 0) | ||
36 | #define BQ24735_CHG_OPT_AC_PRESENT (1 << 4) | ||
37 | #define BQ24735_CHARGE_CURRENT 0x14 | ||
38 | #define BQ24735_CHARGE_CURRENT_MASK 0x1fc0 | ||
39 | #define BQ24735_CHARGE_VOLTAGE 0x15 | ||
40 | #define BQ24735_CHARGE_VOLTAGE_MASK 0x7ff0 | ||
41 | #define BQ24735_INPUT_CURRENT 0x3f | ||
42 | #define BQ24735_INPUT_CURRENT_MASK 0x1f80 | ||
43 | #define BQ24735_MANUFACTURER_ID 0xfe | ||
44 | #define BQ24735_DEVICE_ID 0xff | ||
45 | |||
46 | struct bq24735 { | ||
47 | struct power_supply charger; | ||
48 | struct i2c_client *client; | ||
49 | struct bq24735_platform *pdata; | ||
50 | }; | ||
51 | |||
52 | static inline struct bq24735 *to_bq24735(struct power_supply *psy) | ||
53 | { | ||
54 | return container_of(psy, struct bq24735, charger); | ||
55 | } | ||
56 | |||
57 | static enum power_supply_property bq24735_charger_properties[] = { | ||
58 | POWER_SUPPLY_PROP_ONLINE, | ||
59 | }; | ||
60 | |||
61 | static inline int bq24735_write_word(struct i2c_client *client, u8 reg, | ||
62 | u16 value) | ||
63 | { | ||
64 | return i2c_smbus_write_word_data(client, reg, le16_to_cpu(value)); | ||
65 | } | ||
66 | |||
67 | static inline int bq24735_read_word(struct i2c_client *client, u8 reg) | ||
68 | { | ||
69 | s32 ret = i2c_smbus_read_word_data(client, reg); | ||
70 | |||
71 | return ret < 0 ? ret : le16_to_cpu(ret); | ||
72 | } | ||
73 | |||
74 | static int bq24735_update_word(struct i2c_client *client, u8 reg, | ||
75 | u16 mask, u16 value) | ||
76 | { | ||
77 | unsigned int tmp; | ||
78 | int ret; | ||
79 | |||
80 | ret = bq24735_read_word(client, reg); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | tmp = ret & ~mask; | ||
85 | tmp |= value & mask; | ||
86 | |||
87 | return bq24735_write_word(client, reg, tmp); | ||
88 | } | ||
89 | |||
90 | static inline int bq24735_enable_charging(struct bq24735 *charger) | ||
91 | { | ||
92 | return bq24735_update_word(charger->client, BQ24735_CHG_OPT, | ||
93 | BQ24735_CHG_OPT_CHARGE_DISABLE, | ||
94 | ~BQ24735_CHG_OPT_CHARGE_DISABLE); | ||
95 | } | ||
96 | |||
97 | static inline int bq24735_disable_charging(struct bq24735 *charger) | ||
98 | { | ||
99 | return bq24735_update_word(charger->client, BQ24735_CHG_OPT, | ||
100 | BQ24735_CHG_OPT_CHARGE_DISABLE, | ||
101 | BQ24735_CHG_OPT_CHARGE_DISABLE); | ||
102 | } | ||
103 | |||
104 | static int bq24735_config_charger(struct bq24735 *charger) | ||
105 | { | ||
106 | struct bq24735_platform *pdata = charger->pdata; | ||
107 | int ret; | ||
108 | u16 value; | ||
109 | |||
110 | if (pdata->charge_current) { | ||
111 | value = pdata->charge_current & BQ24735_CHARGE_CURRENT_MASK; | ||
112 | |||
113 | ret = bq24735_write_word(charger->client, | ||
114 | BQ24735_CHARGE_CURRENT, value); | ||
115 | if (ret < 0) { | ||
116 | dev_err(&charger->client->dev, | ||
117 | "Failed to write charger current : %d\n", | ||
118 | ret); | ||
119 | return ret; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | if (pdata->charge_voltage) { | ||
124 | value = pdata->charge_voltage & BQ24735_CHARGE_VOLTAGE_MASK; | ||
125 | |||
126 | ret = bq24735_write_word(charger->client, | ||
127 | BQ24735_CHARGE_VOLTAGE, value); | ||
128 | if (ret < 0) { | ||
129 | dev_err(&charger->client->dev, | ||
130 | "Failed to write charger voltage : %d\n", | ||
131 | ret); | ||
132 | return ret; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | if (pdata->input_current) { | ||
137 | value = pdata->input_current & BQ24735_INPUT_CURRENT_MASK; | ||
138 | |||
139 | ret = bq24735_write_word(charger->client, | ||
140 | BQ24735_INPUT_CURRENT, value); | ||
141 | if (ret < 0) { | ||
142 | dev_err(&charger->client->dev, | ||
143 | "Failed to write input current : %d\n", | ||
144 | ret); | ||
145 | return ret; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static bool bq24735_charger_is_present(struct bq24735 *charger) | ||
153 | { | ||
154 | struct bq24735_platform *pdata = charger->pdata; | ||
155 | int ret; | ||
156 | |||
157 | if (pdata->status_gpio_valid) { | ||
158 | ret = gpio_get_value_cansleep(pdata->status_gpio); | ||
159 | return ret ^= pdata->status_gpio_active_low == 0; | ||
160 | } else { | ||
161 | int ac = 0; | ||
162 | |||
163 | ac = bq24735_read_word(charger->client, BQ24735_CHG_OPT); | ||
164 | if (ac < 0) { | ||
165 | dev_err(&charger->client->dev, | ||
166 | "Failed to read charger options : %d\n", | ||
167 | ac); | ||
168 | return false; | ||
169 | } | ||
170 | return (ac & BQ24735_CHG_OPT_AC_PRESENT) ? true : false; | ||
171 | } | ||
172 | |||
173 | return false; | ||
174 | } | ||
175 | |||
176 | static irqreturn_t bq24735_charger_isr(int irq, void *devid) | ||
177 | { | ||
178 | struct power_supply *psy = devid; | ||
179 | struct bq24735 *charger = to_bq24735(psy); | ||
180 | |||
181 | if (bq24735_charger_is_present(charger)) | ||
182 | bq24735_enable_charging(charger); | ||
183 | else | ||
184 | bq24735_disable_charging(charger); | ||
185 | |||
186 | power_supply_changed(psy); | ||
187 | |||
188 | return IRQ_HANDLED; | ||
189 | } | ||
190 | |||
191 | static int bq24735_charger_get_property(struct power_supply *psy, | ||
192 | enum power_supply_property psp, | ||
193 | union power_supply_propval *val) | ||
194 | { | ||
195 | struct bq24735 *charger; | ||
196 | |||
197 | charger = container_of(psy, struct bq24735, charger); | ||
198 | |||
199 | switch (psp) { | ||
200 | case POWER_SUPPLY_PROP_ONLINE: | ||
201 | val->intval = bq24735_charger_is_present(charger) ? 1 : 0; | ||
202 | break; | ||
203 | default: | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client) | ||
211 | { | ||
212 | struct bq24735_platform *pdata; | ||
213 | struct device_node *np = client->dev.of_node; | ||
214 | u32 val; | ||
215 | int ret; | ||
216 | enum of_gpio_flags flags; | ||
217 | |||
218 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
219 | if (!pdata) { | ||
220 | dev_err(&client->dev, | ||
221 | "Memory alloc for bq24735 pdata failed\n"); | ||
222 | return NULL; | ||
223 | } | ||
224 | |||
225 | pdata->status_gpio = of_get_named_gpio_flags(np, "ti,ac-detect-gpios", | ||
226 | 0, &flags); | ||
227 | |||
228 | if (flags & OF_GPIO_ACTIVE_LOW) | ||
229 | pdata->status_gpio_active_low = 1; | ||
230 | |||
231 | ret = of_property_read_u32(np, "ti,charge-current", &val); | ||
232 | if (!ret) | ||
233 | pdata->charge_current = val; | ||
234 | |||
235 | ret = of_property_read_u32(np, "ti,charge-voltage", &val); | ||
236 | if (!ret) | ||
237 | pdata->charge_voltage = val; | ||
238 | |||
239 | ret = of_property_read_u32(np, "ti,input-current", &val); | ||
240 | if (!ret) | ||
241 | pdata->input_current = val; | ||
242 | |||
243 | return pdata; | ||
244 | } | ||
245 | |||
246 | static int bq24735_charger_probe(struct i2c_client *client, | ||
247 | const struct i2c_device_id *id) | ||
248 | { | ||
249 | int ret; | ||
250 | struct bq24735 *charger; | ||
251 | struct power_supply *supply; | ||
252 | char *name; | ||
253 | |||
254 | charger = devm_kzalloc(&client->dev, sizeof(*charger), GFP_KERNEL); | ||
255 | if (!charger) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | charger->pdata = client->dev.platform_data; | ||
259 | |||
260 | if (IS_ENABLED(CONFIG_OF) && !charger->pdata && client->dev.of_node) | ||
261 | charger->pdata = bq24735_parse_dt_data(client); | ||
262 | |||
263 | if (!charger->pdata) { | ||
264 | dev_err(&client->dev, "no platform data provided\n"); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | name = (char *)charger->pdata->name; | ||
269 | if (!name) { | ||
270 | name = kasprintf(GFP_KERNEL, "bq24735@%s", | ||
271 | dev_name(&client->dev)); | ||
272 | if (!name) { | ||
273 | dev_err(&client->dev, "Failed to alloc device name\n"); | ||
274 | return -ENOMEM; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | charger->client = client; | ||
279 | |||
280 | supply = &charger->charger; | ||
281 | |||
282 | supply->name = name; | ||
283 | supply->type = POWER_SUPPLY_TYPE_MAINS; | ||
284 | supply->properties = bq24735_charger_properties; | ||
285 | supply->num_properties = ARRAY_SIZE(bq24735_charger_properties); | ||
286 | supply->get_property = bq24735_charger_get_property; | ||
287 | supply->supplied_to = charger->pdata->supplied_to; | ||
288 | supply->num_supplicants = charger->pdata->num_supplicants; | ||
289 | supply->of_node = client->dev.of_node; | ||
290 | |||
291 | i2c_set_clientdata(client, charger); | ||
292 | |||
293 | ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID); | ||
294 | if (ret < 0) { | ||
295 | dev_err(&client->dev, "Failed to read manufacturer id : %d\n", | ||
296 | ret); | ||
297 | goto err_free_name; | ||
298 | } else if (ret != 0x0040) { | ||
299 | dev_err(&client->dev, | ||
300 | "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret); | ||
301 | ret = -ENODEV; | ||
302 | goto err_free_name; | ||
303 | } | ||
304 | |||
305 | ret = bq24735_read_word(client, BQ24735_DEVICE_ID); | ||
306 | if (ret < 0) { | ||
307 | dev_err(&client->dev, "Failed to read device id : %d\n", ret); | ||
308 | goto err_free_name; | ||
309 | } else if (ret != 0x000B) { | ||
310 | dev_err(&client->dev, | ||
311 | "device id mismatch. 0x000b != 0x%04x\n", ret); | ||
312 | ret = -ENODEV; | ||
313 | goto err_free_name; | ||
314 | } | ||
315 | |||
316 | if (gpio_is_valid(charger->pdata->status_gpio)) { | ||
317 | ret = devm_gpio_request(&client->dev, | ||
318 | charger->pdata->status_gpio, | ||
319 | name); | ||
320 | if (ret) { | ||
321 | dev_err(&client->dev, | ||
322 | "Failed GPIO request for GPIO %d: %d\n", | ||
323 | charger->pdata->status_gpio, ret); | ||
324 | } | ||
325 | |||
326 | charger->pdata->status_gpio_valid = !ret; | ||
327 | } | ||
328 | |||
329 | ret = bq24735_config_charger(charger); | ||
330 | if (ret < 0) { | ||
331 | dev_err(&client->dev, "failed in configuring charger"); | ||
332 | goto err_free_name; | ||
333 | } | ||
334 | |||
335 | /* check for AC adapter presence */ | ||
336 | if (bq24735_charger_is_present(charger)) { | ||
337 | ret = bq24735_enable_charging(charger); | ||
338 | if (ret < 0) { | ||
339 | dev_err(&client->dev, "Failed to enable charging\n"); | ||
340 | goto err_free_name; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | ret = power_supply_register(&client->dev, supply); | ||
345 | if (ret < 0) { | ||
346 | dev_err(&client->dev, "Failed to register power supply: %d\n", | ||
347 | ret); | ||
348 | goto err_free_name; | ||
349 | } | ||
350 | |||
351 | if (client->irq) { | ||
352 | ret = devm_request_threaded_irq(&client->dev, client->irq, | ||
353 | NULL, bq24735_charger_isr, | ||
354 | IRQF_TRIGGER_RISING | | ||
355 | IRQF_TRIGGER_FALLING | | ||
356 | IRQF_ONESHOT, | ||
357 | supply->name, supply); | ||
358 | if (ret) { | ||
359 | dev_err(&client->dev, | ||
360 | "Unable to register IRQ %d err %d\n", | ||
361 | client->irq, ret); | ||
362 | goto err_unregister_supply; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | return 0; | ||
367 | err_unregister_supply: | ||
368 | power_supply_unregister(supply); | ||
369 | err_free_name: | ||
370 | if (name != charger->pdata->name) | ||
371 | kfree(name); | ||
372 | |||
373 | return ret; | ||
374 | } | ||
375 | |||
376 | static int bq24735_charger_remove(struct i2c_client *client) | ||
377 | { | ||
378 | struct bq24735 *charger = i2c_get_clientdata(client); | ||
379 | |||
380 | if (charger->client->irq) | ||
381 | devm_free_irq(&charger->client->dev, charger->client->irq, | ||
382 | &charger->charger); | ||
383 | |||
384 | power_supply_unregister(&charger->charger); | ||
385 | |||
386 | if (charger->charger.name != charger->pdata->name) | ||
387 | kfree(charger->charger.name); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | static const struct i2c_device_id bq24735_charger_id[] = { | ||
393 | { "bq24735-charger", 0 }, | ||
394 | {} | ||
395 | }; | ||
396 | MODULE_DEVICE_TABLE(i2c, bq24735_charger_id); | ||
397 | |||
398 | static const struct of_device_id bq24735_match_ids[] = { | ||
399 | { .compatible = "ti,bq24735", }, | ||
400 | { /* end */ } | ||
401 | }; | ||
402 | MODULE_DEVICE_TABLE(of, bq24735_match_ids); | ||
403 | |||
404 | static struct i2c_driver bq24735_charger_driver = { | ||
405 | .driver = { | ||
406 | .name = "bq24735-charger", | ||
407 | .owner = THIS_MODULE, | ||
408 | .of_match_table = bq24735_match_ids, | ||
409 | }, | ||
410 | .probe = bq24735_charger_probe, | ||
411 | .remove = bq24735_charger_remove, | ||
412 | .id_table = bq24735_charger_id, | ||
413 | }; | ||
414 | |||
415 | module_i2c_driver(bq24735_charger_driver); | ||
416 | |||
417 | MODULE_DESCRIPTION("bq24735 battery charging driver"); | ||
418 | MODULE_AUTHOR("Darbha Sriharsha <dsriharsha@nvidia.com>"); | ||
419 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index e30e847600bb..7287c0efd6bf 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c | |||
@@ -1378,7 +1378,8 @@ static int charger_manager_register_sysfs(struct charger_manager *cm) | |||
1378 | charger = &desc->charger_regulators[i]; | 1378 | charger = &desc->charger_regulators[i]; |
1379 | 1379 | ||
1380 | snprintf(buf, 10, "charger.%d", i); | 1380 | snprintf(buf, 10, "charger.%d", i); |
1381 | str = kzalloc(sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); | 1381 | str = devm_kzalloc(cm->dev, |
1382 | sizeof(char) * (strlen(buf) + 1), GFP_KERNEL); | ||
1382 | if (!str) { | 1383 | if (!str) { |
1383 | ret = -ENOMEM; | 1384 | ret = -ENOMEM; |
1384 | goto err; | 1385 | goto err; |
@@ -1452,30 +1453,23 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1452 | rtc_dev = NULL; | 1453 | rtc_dev = NULL; |
1453 | dev_err(&pdev->dev, "Cannot get RTC %s\n", | 1454 | dev_err(&pdev->dev, "Cannot get RTC %s\n", |
1454 | g_desc->rtc_name); | 1455 | g_desc->rtc_name); |
1455 | ret = -ENODEV; | 1456 | return -ENODEV; |
1456 | goto err_alloc; | ||
1457 | } | 1457 | } |
1458 | } | 1458 | } |
1459 | 1459 | ||
1460 | if (!desc) { | 1460 | if (!desc) { |
1461 | dev_err(&pdev->dev, "No platform data (desc) found\n"); | 1461 | dev_err(&pdev->dev, "No platform data (desc) found\n"); |
1462 | ret = -ENODEV; | 1462 | return -ENODEV; |
1463 | goto err_alloc; | ||
1464 | } | 1463 | } |
1465 | 1464 | ||
1466 | cm = kzalloc(sizeof(struct charger_manager), GFP_KERNEL); | 1465 | cm = devm_kzalloc(&pdev->dev, |
1467 | if (!cm) { | 1466 | sizeof(struct charger_manager), GFP_KERNEL); |
1468 | ret = -ENOMEM; | 1467 | if (!cm) |
1469 | goto err_alloc; | 1468 | return -ENOMEM; |
1470 | } | ||
1471 | 1469 | ||
1472 | /* Basic Values. Unspecified are Null or 0 */ | 1470 | /* Basic Values. Unspecified are Null or 0 */ |
1473 | cm->dev = &pdev->dev; | 1471 | cm->dev = &pdev->dev; |
1474 | cm->desc = kmemdup(desc, sizeof(struct charger_desc), GFP_KERNEL); | 1472 | cm->desc = desc; |
1475 | if (!cm->desc) { | ||
1476 | ret = -ENOMEM; | ||
1477 | goto err_alloc_desc; | ||
1478 | } | ||
1479 | cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */ | 1473 | cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */ |
1480 | 1474 | ||
1481 | /* | 1475 | /* |
@@ -1498,27 +1492,23 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1498 | } | 1492 | } |
1499 | 1493 | ||
1500 | if (!desc->charger_regulators || desc->num_charger_regulators < 1) { | 1494 | if (!desc->charger_regulators || desc->num_charger_regulators < 1) { |
1501 | ret = -EINVAL; | ||
1502 | dev_err(&pdev->dev, "charger_regulators undefined\n"); | 1495 | dev_err(&pdev->dev, "charger_regulators undefined\n"); |
1503 | goto err_no_charger; | 1496 | return -EINVAL; |
1504 | } | 1497 | } |
1505 | 1498 | ||
1506 | if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) { | 1499 | if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) { |
1507 | dev_err(&pdev->dev, "No power supply defined\n"); | 1500 | dev_err(&pdev->dev, "No power supply defined\n"); |
1508 | ret = -EINVAL; | 1501 | return -EINVAL; |
1509 | goto err_no_charger_stat; | ||
1510 | } | 1502 | } |
1511 | 1503 | ||
1512 | /* Counting index only */ | 1504 | /* Counting index only */ |
1513 | while (desc->psy_charger_stat[i]) | 1505 | while (desc->psy_charger_stat[i]) |
1514 | i++; | 1506 | i++; |
1515 | 1507 | ||
1516 | cm->charger_stat = kzalloc(sizeof(struct power_supply *) * (i + 1), | 1508 | cm->charger_stat = devm_kzalloc(&pdev->dev, |
1517 | GFP_KERNEL); | 1509 | sizeof(struct power_supply *) * i, GFP_KERNEL); |
1518 | if (!cm->charger_stat) { | 1510 | if (!cm->charger_stat) |
1519 | ret = -ENOMEM; | 1511 | return -ENOMEM; |
1520 | goto err_no_charger_stat; | ||
1521 | } | ||
1522 | 1512 | ||
1523 | for (i = 0; desc->psy_charger_stat[i]; i++) { | 1513 | for (i = 0; desc->psy_charger_stat[i]; i++) { |
1524 | cm->charger_stat[i] = power_supply_get_by_name( | 1514 | cm->charger_stat[i] = power_supply_get_by_name( |
@@ -1526,8 +1516,7 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1526 | if (!cm->charger_stat[i]) { | 1516 | if (!cm->charger_stat[i]) { |
1527 | dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", | 1517 | dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", |
1528 | desc->psy_charger_stat[i]); | 1518 | desc->psy_charger_stat[i]); |
1529 | ret = -ENODEV; | 1519 | return -ENODEV; |
1530 | goto err_chg_stat; | ||
1531 | } | 1520 | } |
1532 | } | 1521 | } |
1533 | 1522 | ||
@@ -1535,21 +1524,18 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1535 | if (!cm->fuel_gauge) { | 1524 | if (!cm->fuel_gauge) { |
1536 | dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", | 1525 | dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n", |
1537 | desc->psy_fuel_gauge); | 1526 | desc->psy_fuel_gauge); |
1538 | ret = -ENODEV; | 1527 | return -ENODEV; |
1539 | goto err_chg_stat; | ||
1540 | } | 1528 | } |
1541 | 1529 | ||
1542 | if (desc->polling_interval_ms == 0 || | 1530 | if (desc->polling_interval_ms == 0 || |
1543 | msecs_to_jiffies(desc->polling_interval_ms) <= CM_JIFFIES_SMALL) { | 1531 | msecs_to_jiffies(desc->polling_interval_ms) <= CM_JIFFIES_SMALL) { |
1544 | dev_err(&pdev->dev, "polling_interval_ms is too small\n"); | 1532 | dev_err(&pdev->dev, "polling_interval_ms is too small\n"); |
1545 | ret = -EINVAL; | 1533 | return -EINVAL; |
1546 | goto err_chg_stat; | ||
1547 | } | 1534 | } |
1548 | 1535 | ||
1549 | if (!desc->temperature_out_of_range) { | 1536 | if (!desc->temperature_out_of_range) { |
1550 | dev_err(&pdev->dev, "there is no temperature_out_of_range\n"); | 1537 | dev_err(&pdev->dev, "there is no temperature_out_of_range\n"); |
1551 | ret = -EINVAL; | 1538 | return -EINVAL; |
1552 | goto err_chg_stat; | ||
1553 | } | 1539 | } |
1554 | 1540 | ||
1555 | if (!desc->charging_max_duration_ms || | 1541 | if (!desc->charging_max_duration_ms || |
@@ -1570,14 +1556,13 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1570 | cm->charger_psy.name = cm->psy_name_buf; | 1556 | cm->charger_psy.name = cm->psy_name_buf; |
1571 | 1557 | ||
1572 | /* Allocate for psy properties because they may vary */ | 1558 | /* Allocate for psy properties because they may vary */ |
1573 | cm->charger_psy.properties = kzalloc(sizeof(enum power_supply_property) | 1559 | cm->charger_psy.properties = devm_kzalloc(&pdev->dev, |
1560 | sizeof(enum power_supply_property) | ||
1574 | * (ARRAY_SIZE(default_charger_props) + | 1561 | * (ARRAY_SIZE(default_charger_props) + |
1575 | NUM_CHARGER_PSY_OPTIONAL), | 1562 | NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL); |
1576 | GFP_KERNEL); | 1563 | if (!cm->charger_psy.properties) |
1577 | if (!cm->charger_psy.properties) { | 1564 | return -ENOMEM; |
1578 | ret = -ENOMEM; | 1565 | |
1579 | goto err_chg_stat; | ||
1580 | } | ||
1581 | memcpy(cm->charger_psy.properties, default_charger_props, | 1566 | memcpy(cm->charger_psy.properties, default_charger_props, |
1582 | sizeof(enum power_supply_property) * | 1567 | sizeof(enum power_supply_property) * |
1583 | ARRAY_SIZE(default_charger_props)); | 1568 | ARRAY_SIZE(default_charger_props)); |
@@ -1614,7 +1599,7 @@ static int charger_manager_probe(struct platform_device *pdev) | |||
1614 | if (ret) { | 1599 | if (ret) { |
1615 | dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n", | 1600 | dev_err(&pdev->dev, "Cannot register charger-manager with name \"%s\"\n", |
1616 | cm->charger_psy.name); | 1601 | cm->charger_psy.name); |
1617 | goto err_register; | 1602 | return ret; |
1618 | } | 1603 | } |
1619 | 1604 | ||
1620 | /* Register extcon device for charger cable */ | 1605 | /* Register extcon device for charger cable */ |
@@ -1655,8 +1640,6 @@ err_reg_sysfs: | |||
1655 | charger = &desc->charger_regulators[i]; | 1640 | charger = &desc->charger_regulators[i]; |
1656 | sysfs_remove_group(&cm->charger_psy.dev->kobj, | 1641 | sysfs_remove_group(&cm->charger_psy.dev->kobj, |
1657 | &charger->attr_g); | 1642 | &charger->attr_g); |
1658 | |||
1659 | kfree(charger->attr_g.name); | ||
1660 | } | 1643 | } |
1661 | err_reg_extcon: | 1644 | err_reg_extcon: |
1662 | for (i = 0; i < desc->num_charger_regulators; i++) { | 1645 | for (i = 0; i < desc->num_charger_regulators; i++) { |
@@ -1674,16 +1657,7 @@ err_reg_extcon: | |||
1674 | } | 1657 | } |
1675 | 1658 | ||
1676 | power_supply_unregister(&cm->charger_psy); | 1659 | power_supply_unregister(&cm->charger_psy); |
1677 | err_register: | 1660 | |
1678 | kfree(cm->charger_psy.properties); | ||
1679 | err_chg_stat: | ||
1680 | kfree(cm->charger_stat); | ||
1681 | err_no_charger_stat: | ||
1682 | err_no_charger: | ||
1683 | kfree(cm->desc); | ||
1684 | err_alloc_desc: | ||
1685 | kfree(cm); | ||
1686 | err_alloc: | ||
1687 | return ret; | 1661 | return ret; |
1688 | } | 1662 | } |
1689 | 1663 | ||
@@ -1718,11 +1692,6 @@ static int charger_manager_remove(struct platform_device *pdev) | |||
1718 | 1692 | ||
1719 | try_charger_enable(cm, false); | 1693 | try_charger_enable(cm, false); |
1720 | 1694 | ||
1721 | kfree(cm->charger_psy.properties); | ||
1722 | kfree(cm->charger_stat); | ||
1723 | kfree(cm->desc); | ||
1724 | kfree(cm); | ||
1725 | |||
1726 | return 0; | 1695 | return 0; |
1727 | } | 1696 | } |
1728 | 1697 | ||
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c index fc04d191579b..1bb3a91b1acc 100644 --- a/drivers/power/isp1704_charger.c +++ b/drivers/power/isp1704_charger.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * ISP1704 USB Charger Detection driver | 2 | * ISP1704 USB Charger Detection driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Nokia Corporation | 4 | * Copyright (C) 2010 Nokia Corporation |
5 | * Copyright (C) 2012 - 2013 Pali Rohár <pali.rohar@gmail.com> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * 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 | * it under the terms of the GNU General Public License as published by |
@@ -65,10 +66,6 @@ struct isp1704_charger { | |||
65 | unsigned present:1; | 66 | unsigned present:1; |
66 | unsigned online:1; | 67 | unsigned online:1; |
67 | unsigned current_max; | 68 | unsigned current_max; |
68 | |||
69 | /* temp storage variables */ | ||
70 | unsigned long event; | ||
71 | unsigned max_power; | ||
72 | }; | 69 | }; |
73 | 70 | ||
74 | static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) | 71 | static inline int isp1704_read(struct isp1704_charger *isp, u32 reg) |
@@ -231,56 +228,59 @@ static inline int isp1704_charger_detect(struct isp1704_charger *isp) | |||
231 | return ret; | 228 | return ret; |
232 | } | 229 | } |
233 | 230 | ||
231 | static inline int isp1704_charger_detect_dcp(struct isp1704_charger *isp) | ||
232 | { | ||
233 | if (isp1704_charger_detect(isp) && | ||
234 | isp1704_charger_type(isp) == POWER_SUPPLY_TYPE_USB_DCP) | ||
235 | return true; | ||
236 | else | ||
237 | return false; | ||
238 | } | ||
239 | |||
234 | static void isp1704_charger_work(struct work_struct *data) | 240 | static void isp1704_charger_work(struct work_struct *data) |
235 | { | 241 | { |
236 | int detect; | ||
237 | unsigned long event; | ||
238 | unsigned power; | ||
239 | struct isp1704_charger *isp = | 242 | struct isp1704_charger *isp = |
240 | container_of(data, struct isp1704_charger, work); | 243 | container_of(data, struct isp1704_charger, work); |
241 | static DEFINE_MUTEX(lock); | 244 | static DEFINE_MUTEX(lock); |
242 | 245 | ||
243 | event = isp->event; | ||
244 | power = isp->max_power; | ||
245 | |||
246 | mutex_lock(&lock); | 246 | mutex_lock(&lock); |
247 | 247 | ||
248 | if (event != USB_EVENT_NONE) | 248 | switch (isp->phy->last_event) { |
249 | isp1704_charger_set_power(isp, 1); | ||
250 | |||
251 | switch (event) { | ||
252 | case USB_EVENT_VBUS: | 249 | case USB_EVENT_VBUS: |
253 | isp->online = true; | 250 | /* do not call wall charger detection more times */ |
251 | if (!isp->present) { | ||
252 | isp->online = true; | ||
253 | isp->present = 1; | ||
254 | isp1704_charger_set_power(isp, 1); | ||
255 | |||
256 | /* detect wall charger */ | ||
257 | if (isp1704_charger_detect_dcp(isp)) { | ||
258 | isp->psy.type = POWER_SUPPLY_TYPE_USB_DCP; | ||
259 | isp->current_max = 1800; | ||
260 | } else { | ||
261 | isp->psy.type = POWER_SUPPLY_TYPE_USB; | ||
262 | isp->current_max = 500; | ||
263 | } | ||
254 | 264 | ||
255 | /* detect charger */ | 265 | /* enable data pullups */ |
256 | detect = isp1704_charger_detect(isp); | 266 | if (isp->phy->otg->gadget) |
257 | 267 | usb_gadget_connect(isp->phy->otg->gadget); | |
258 | if (detect) { | ||
259 | isp->present = detect; | ||
260 | isp->psy.type = isp1704_charger_type(isp); | ||
261 | } | 268 | } |
262 | 269 | ||
263 | switch (isp->psy.type) { | 270 | if (isp->psy.type != POWER_SUPPLY_TYPE_USB_DCP) { |
264 | case POWER_SUPPLY_TYPE_USB_DCP: | ||
265 | isp->current_max = 1800; | ||
266 | break; | ||
267 | case POWER_SUPPLY_TYPE_USB_CDP: | ||
268 | /* | 271 | /* |
269 | * Only 500mA here or high speed chirp | 272 | * Only 500mA here or high speed chirp |
270 | * handshaking may break | 273 | * handshaking may break |
271 | */ | 274 | */ |
272 | isp->current_max = 500; | 275 | if (isp->current_max > 500) |
273 | /* FALLTHROUGH */ | 276 | isp->current_max = 500; |
274 | case POWER_SUPPLY_TYPE_USB: | 277 | |
275 | default: | 278 | if (isp->current_max > 100) |
276 | /* enable data pullups */ | 279 | isp->psy.type = POWER_SUPPLY_TYPE_USB_CDP; |
277 | if (isp->phy->otg->gadget) | ||
278 | usb_gadget_connect(isp->phy->otg->gadget); | ||
279 | } | 280 | } |
280 | break; | 281 | break; |
281 | case USB_EVENT_NONE: | 282 | case USB_EVENT_NONE: |
282 | isp->online = false; | 283 | isp->online = false; |
283 | isp->current_max = 0; | ||
284 | isp->present = 0; | 284 | isp->present = 0; |
285 | isp->current_max = 0; | 285 | isp->current_max = 0; |
286 | isp->psy.type = POWER_SUPPLY_TYPE_USB; | 286 | isp->psy.type = POWER_SUPPLY_TYPE_USB; |
@@ -298,12 +298,6 @@ static void isp1704_charger_work(struct work_struct *data) | |||
298 | 298 | ||
299 | isp1704_charger_set_power(isp, 0); | 299 | isp1704_charger_set_power(isp, 0); |
300 | break; | 300 | break; |
301 | case USB_EVENT_ENUMERATED: | ||
302 | if (isp->present) | ||
303 | isp->current_max = 1800; | ||
304 | else | ||
305 | isp->current_max = power; | ||
306 | break; | ||
307 | default: | 301 | default: |
308 | goto out; | 302 | goto out; |
309 | } | 303 | } |
@@ -314,16 +308,11 @@ out: | |||
314 | } | 308 | } |
315 | 309 | ||
316 | static int isp1704_notifier_call(struct notifier_block *nb, | 310 | static int isp1704_notifier_call(struct notifier_block *nb, |
317 | unsigned long event, void *power) | 311 | unsigned long val, void *v) |
318 | { | 312 | { |
319 | struct isp1704_charger *isp = | 313 | struct isp1704_charger *isp = |
320 | container_of(nb, struct isp1704_charger, nb); | 314 | container_of(nb, struct isp1704_charger, nb); |
321 | 315 | ||
322 | isp->event = event; | ||
323 | |||
324 | if (power) | ||
325 | isp->max_power = *((unsigned *)power); | ||
326 | |||
327 | schedule_work(&isp->work); | 316 | schedule_work(&isp->work); |
328 | 317 | ||
329 | return NOTIFY_OK; | 318 | return NOTIFY_OK; |
@@ -462,13 +451,13 @@ static int isp1704_charger_probe(struct platform_device *pdev) | |||
462 | if (isp->phy->otg->gadget) | 451 | if (isp->phy->otg->gadget) |
463 | usb_gadget_disconnect(isp->phy->otg->gadget); | 452 | usb_gadget_disconnect(isp->phy->otg->gadget); |
464 | 453 | ||
454 | if (isp->phy->last_event == USB_EVENT_NONE) | ||
455 | isp1704_charger_set_power(isp, 0); | ||
456 | |||
465 | /* Detect charger if VBUS is valid (the cable was already plugged). */ | 457 | /* Detect charger if VBUS is valid (the cable was already plugged). */ |
466 | ret = isp1704_read(isp, ULPI_USB_INT_STS); | 458 | if (isp->phy->last_event == USB_EVENT_VBUS && |
467 | isp1704_charger_set_power(isp, 0); | 459 | !isp->phy->otg->default_a) |
468 | if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) { | ||
469 | isp->event = USB_EVENT_VBUS; | ||
470 | schedule_work(&isp->work); | 460 | schedule_work(&isp->work); |
471 | } | ||
472 | 461 | ||
473 | return 0; | 462 | return 0; |
474 | fail2: | 463 | fail2: |
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c index d664ef58afa7..e0b22f9b6fdd 100644 --- a/drivers/power/max17042_battery.c +++ b/drivers/power/max17042_battery.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/power_supply.h> | 33 | #include <linux/power_supply.h> |
34 | #include <linux/power/max17042_battery.h> | 34 | #include <linux/power/max17042_battery.h> |
35 | #include <linux/of.h> | 35 | #include <linux/of.h> |
36 | #include <linux/regmap.h> | ||
36 | 37 | ||
37 | /* Status register bits */ | 38 | /* Status register bits */ |
38 | #define STATUS_POR_BIT (1 << 1) | 39 | #define STATUS_POR_BIT (1 << 1) |
@@ -67,6 +68,7 @@ | |||
67 | 68 | ||
68 | struct max17042_chip { | 69 | struct max17042_chip { |
69 | struct i2c_client *client; | 70 | struct i2c_client *client; |
71 | struct regmap *regmap; | ||
70 | struct power_supply battery; | 72 | struct power_supply battery; |
71 | enum max170xx_chip_type chip_type; | 73 | enum max170xx_chip_type chip_type; |
72 | struct max17042_platform_data *pdata; | 74 | struct max17042_platform_data *pdata; |
@@ -74,35 +76,6 @@ struct max17042_chip { | |||
74 | int init_complete; | 76 | int init_complete; |
75 | }; | 77 | }; |
76 | 78 | ||
77 | static int max17042_write_reg(struct i2c_client *client, u8 reg, u16 value) | ||
78 | { | ||
79 | int ret = i2c_smbus_write_word_data(client, reg, value); | ||
80 | |||
81 | if (ret < 0) | ||
82 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static int max17042_read_reg(struct i2c_client *client, u8 reg) | ||
88 | { | ||
89 | int ret = i2c_smbus_read_word_data(client, reg); | ||
90 | |||
91 | if (ret < 0) | ||
92 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | ||
93 | |||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static void max17042_set_reg(struct i2c_client *client, | ||
98 | struct max17042_reg_data *data, int size) | ||
99 | { | ||
100 | int i; | ||
101 | |||
102 | for (i = 0; i < size; i++) | ||
103 | max17042_write_reg(client, data[i].addr, data[i].data); | ||
104 | } | ||
105 | |||
106 | static enum power_supply_property max17042_battery_props[] = { | 79 | static enum power_supply_property max17042_battery_props[] = { |
107 | POWER_SUPPLY_PROP_PRESENT, | 80 | POWER_SUPPLY_PROP_PRESENT, |
108 | POWER_SUPPLY_PROP_CYCLE_COUNT, | 81 | POWER_SUPPLY_PROP_CYCLE_COUNT, |
@@ -125,96 +98,98 @@ static int max17042_get_property(struct power_supply *psy, | |||
125 | { | 98 | { |
126 | struct max17042_chip *chip = container_of(psy, | 99 | struct max17042_chip *chip = container_of(psy, |
127 | struct max17042_chip, battery); | 100 | struct max17042_chip, battery); |
101 | struct regmap *map = chip->regmap; | ||
128 | int ret; | 102 | int ret; |
103 | u32 data; | ||
129 | 104 | ||
130 | if (!chip->init_complete) | 105 | if (!chip->init_complete) |
131 | return -EAGAIN; | 106 | return -EAGAIN; |
132 | 107 | ||
133 | switch (psp) { | 108 | switch (psp) { |
134 | case POWER_SUPPLY_PROP_PRESENT: | 109 | case POWER_SUPPLY_PROP_PRESENT: |
135 | ret = max17042_read_reg(chip->client, MAX17042_STATUS); | 110 | ret = regmap_read(map, MAX17042_STATUS, &data); |
136 | if (ret < 0) | 111 | if (ret < 0) |
137 | return ret; | 112 | return ret; |
138 | 113 | ||
139 | if (ret & MAX17042_STATUS_BattAbsent) | 114 | if (data & MAX17042_STATUS_BattAbsent) |
140 | val->intval = 0; | 115 | val->intval = 0; |
141 | else | 116 | else |
142 | val->intval = 1; | 117 | val->intval = 1; |
143 | break; | 118 | break; |
144 | case POWER_SUPPLY_PROP_CYCLE_COUNT: | 119 | case POWER_SUPPLY_PROP_CYCLE_COUNT: |
145 | ret = max17042_read_reg(chip->client, MAX17042_Cycles); | 120 | ret = regmap_read(map, MAX17042_Cycles, &data); |
146 | if (ret < 0) | 121 | if (ret < 0) |
147 | return ret; | 122 | return ret; |
148 | 123 | ||
149 | val->intval = ret; | 124 | val->intval = data; |
150 | break; | 125 | break; |
151 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: | 126 | case POWER_SUPPLY_PROP_VOLTAGE_MAX: |
152 | ret = max17042_read_reg(chip->client, MAX17042_MinMaxVolt); | 127 | ret = regmap_read(map, MAX17042_MinMaxVolt, &data); |
153 | if (ret < 0) | 128 | if (ret < 0) |
154 | return ret; | 129 | return ret; |
155 | 130 | ||
156 | val->intval = ret >> 8; | 131 | val->intval = data >> 8; |
157 | val->intval *= 20000; /* Units of LSB = 20mV */ | 132 | val->intval *= 20000; /* Units of LSB = 20mV */ |
158 | break; | 133 | break; |
159 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: | 134 | case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: |
160 | if (chip->chip_type == MAX17042) | 135 | if (chip->chip_type == MAX17042) |
161 | ret = max17042_read_reg(chip->client, MAX17042_V_empty); | 136 | ret = regmap_read(map, MAX17042_V_empty, &data); |
162 | else | 137 | else |
163 | ret = max17042_read_reg(chip->client, MAX17047_V_empty); | 138 | ret = regmap_read(map, MAX17047_V_empty, &data); |
164 | if (ret < 0) | 139 | if (ret < 0) |
165 | return ret; | 140 | return ret; |
166 | 141 | ||
167 | val->intval = ret >> 7; | 142 | val->intval = data >> 7; |
168 | val->intval *= 10000; /* Units of LSB = 10mV */ | 143 | val->intval *= 10000; /* Units of LSB = 10mV */ |
169 | break; | 144 | break; |
170 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 145 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
171 | ret = max17042_read_reg(chip->client, MAX17042_VCELL); | 146 | ret = regmap_read(map, MAX17042_VCELL, &data); |
172 | if (ret < 0) | 147 | if (ret < 0) |
173 | return ret; | 148 | return ret; |
174 | 149 | ||
175 | val->intval = ret * 625 / 8; | 150 | val->intval = data * 625 / 8; |
176 | break; | 151 | break; |
177 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: | 152 | case POWER_SUPPLY_PROP_VOLTAGE_AVG: |
178 | ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL); | 153 | ret = regmap_read(map, MAX17042_AvgVCELL, &data); |
179 | if (ret < 0) | 154 | if (ret < 0) |
180 | return ret; | 155 | return ret; |
181 | 156 | ||
182 | val->intval = ret * 625 / 8; | 157 | val->intval = data * 625 / 8; |
183 | break; | 158 | break; |
184 | case POWER_SUPPLY_PROP_VOLTAGE_OCV: | 159 | case POWER_SUPPLY_PROP_VOLTAGE_OCV: |
185 | ret = max17042_read_reg(chip->client, MAX17042_OCVInternal); | 160 | ret = regmap_read(map, MAX17042_OCVInternal, &data); |
186 | if (ret < 0) | 161 | if (ret < 0) |
187 | return ret; | 162 | return ret; |
188 | 163 | ||
189 | val->intval = ret * 625 / 8; | 164 | val->intval = data * 625 / 8; |
190 | break; | 165 | break; |
191 | case POWER_SUPPLY_PROP_CAPACITY: | 166 | case POWER_SUPPLY_PROP_CAPACITY: |
192 | ret = max17042_read_reg(chip->client, MAX17042_RepSOC); | 167 | ret = regmap_read(map, MAX17042_RepSOC, &data); |
193 | if (ret < 0) | 168 | if (ret < 0) |
194 | return ret; | 169 | return ret; |
195 | 170 | ||
196 | val->intval = ret >> 8; | 171 | val->intval = data >> 8; |
197 | break; | 172 | break; |
198 | case POWER_SUPPLY_PROP_CHARGE_FULL: | 173 | case POWER_SUPPLY_PROP_CHARGE_FULL: |
199 | ret = max17042_read_reg(chip->client, MAX17042_FullCAP); | 174 | ret = regmap_read(map, MAX17042_FullCAP, &data); |
200 | if (ret < 0) | 175 | if (ret < 0) |
201 | return ret; | 176 | return ret; |
202 | 177 | ||
203 | val->intval = ret * 1000 / 2; | 178 | val->intval = data * 1000 / 2; |
204 | break; | 179 | break; |
205 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: | 180 | case POWER_SUPPLY_PROP_CHARGE_COUNTER: |
206 | ret = max17042_read_reg(chip->client, MAX17042_QH); | 181 | ret = regmap_read(map, MAX17042_QH, &data); |
207 | if (ret < 0) | 182 | if (ret < 0) |
208 | return ret; | 183 | return ret; |
209 | 184 | ||
210 | val->intval = ret * 1000 / 2; | 185 | val->intval = data * 1000 / 2; |
211 | break; | 186 | break; |
212 | case POWER_SUPPLY_PROP_TEMP: | 187 | case POWER_SUPPLY_PROP_TEMP: |
213 | ret = max17042_read_reg(chip->client, MAX17042_TEMP); | 188 | ret = regmap_read(map, MAX17042_TEMP, &data); |
214 | if (ret < 0) | 189 | if (ret < 0) |
215 | return ret; | 190 | return ret; |
216 | 191 | ||
217 | val->intval = ret; | 192 | val->intval = data; |
218 | /* The value is signed. */ | 193 | /* The value is signed. */ |
219 | if (val->intval & 0x8000) { | 194 | if (val->intval & 0x8000) { |
220 | val->intval = (0x7fff & ~val->intval) + 1; | 195 | val->intval = (0x7fff & ~val->intval) + 1; |
@@ -226,11 +201,11 @@ static int max17042_get_property(struct power_supply *psy, | |||
226 | break; | 201 | break; |
227 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 202 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
228 | if (chip->pdata->enable_current_sense) { | 203 | if (chip->pdata->enable_current_sense) { |
229 | ret = max17042_read_reg(chip->client, MAX17042_Current); | 204 | ret = regmap_read(map, MAX17042_Current, &data); |
230 | if (ret < 0) | 205 | if (ret < 0) |
231 | return ret; | 206 | return ret; |
232 | 207 | ||
233 | val->intval = ret; | 208 | val->intval = data; |
234 | if (val->intval & 0x8000) { | 209 | if (val->intval & 0x8000) { |
235 | /* Negative */ | 210 | /* Negative */ |
236 | val->intval = ~val->intval & 0x7fff; | 211 | val->intval = ~val->intval & 0x7fff; |
@@ -244,12 +219,11 @@ static int max17042_get_property(struct power_supply *psy, | |||
244 | break; | 219 | break; |
245 | case POWER_SUPPLY_PROP_CURRENT_AVG: | 220 | case POWER_SUPPLY_PROP_CURRENT_AVG: |
246 | if (chip->pdata->enable_current_sense) { | 221 | if (chip->pdata->enable_current_sense) { |
247 | ret = max17042_read_reg(chip->client, | 222 | ret = regmap_read(map, MAX17042_AvgCurrent, &data); |
248 | MAX17042_AvgCurrent); | ||
249 | if (ret < 0) | 223 | if (ret < 0) |
250 | return ret; | 224 | return ret; |
251 | 225 | ||
252 | val->intval = ret; | 226 | val->intval = data; |
253 | if (val->intval & 0x8000) { | 227 | if (val->intval & 0x8000) { |
254 | /* Negative */ | 228 | /* Negative */ |
255 | val->intval = ~val->intval & 0x7fff; | 229 | val->intval = ~val->intval & 0x7fff; |
@@ -267,16 +241,15 @@ static int max17042_get_property(struct power_supply *psy, | |||
267 | return 0; | 241 | return 0; |
268 | } | 242 | } |
269 | 243 | ||
270 | static int max17042_write_verify_reg(struct i2c_client *client, | 244 | static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value) |
271 | u8 reg, u16 value) | ||
272 | { | 245 | { |
273 | int retries = 8; | 246 | int retries = 8; |
274 | int ret; | 247 | int ret; |
275 | u16 read_value; | 248 | u32 read_value; |
276 | 249 | ||
277 | do { | 250 | do { |
278 | ret = i2c_smbus_write_word_data(client, reg, value); | 251 | ret = regmap_write(map, reg, value); |
279 | read_value = max17042_read_reg(client, reg); | 252 | regmap_read(map, reg, &read_value); |
280 | if (read_value != value) { | 253 | if (read_value != value) { |
281 | ret = -EIO; | 254 | ret = -EIO; |
282 | retries--; | 255 | retries--; |
@@ -284,50 +257,51 @@ static int max17042_write_verify_reg(struct i2c_client *client, | |||
284 | } while (retries && read_value != value); | 257 | } while (retries && read_value != value); |
285 | 258 | ||
286 | if (ret < 0) | 259 | if (ret < 0) |
287 | dev_err(&client->dev, "%s: err %d\n", __func__, ret); | 260 | pr_err("%s: err %d\n", __func__, ret); |
288 | 261 | ||
289 | return ret; | 262 | return ret; |
290 | } | 263 | } |
291 | 264 | ||
292 | static inline void max17042_override_por( | 265 | static inline void max17042_override_por(struct regmap *map, |
293 | struct i2c_client *client, u8 reg, u16 value) | 266 | u8 reg, u16 value) |
294 | { | 267 | { |
295 | if (value) | 268 | if (value) |
296 | max17042_write_reg(client, reg, value); | 269 | regmap_write(map, reg, value); |
297 | } | 270 | } |
298 | 271 | ||
299 | static inline void max10742_unlock_model(struct max17042_chip *chip) | 272 | static inline void max10742_unlock_model(struct max17042_chip *chip) |
300 | { | 273 | { |
301 | struct i2c_client *client = chip->client; | 274 | struct regmap *map = chip->regmap; |
302 | max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_UNLOCK1); | 275 | regmap_write(map, MAX17042_MLOCKReg1, MODEL_UNLOCK1); |
303 | max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_UNLOCK2); | 276 | regmap_write(map, MAX17042_MLOCKReg2, MODEL_UNLOCK2); |
304 | } | 277 | } |
305 | 278 | ||
306 | static inline void max10742_lock_model(struct max17042_chip *chip) | 279 | static inline void max10742_lock_model(struct max17042_chip *chip) |
307 | { | 280 | { |
308 | struct i2c_client *client = chip->client; | 281 | struct regmap *map = chip->regmap; |
309 | max17042_write_reg(client, MAX17042_MLOCKReg1, MODEL_LOCK1); | 282 | |
310 | max17042_write_reg(client, MAX17042_MLOCKReg2, MODEL_LOCK2); | 283 | regmap_write(map, MAX17042_MLOCKReg1, MODEL_LOCK1); |
284 | regmap_write(map, MAX17042_MLOCKReg2, MODEL_LOCK2); | ||
311 | } | 285 | } |
312 | 286 | ||
313 | static inline void max17042_write_model_data(struct max17042_chip *chip, | 287 | static inline void max17042_write_model_data(struct max17042_chip *chip, |
314 | u8 addr, int size) | 288 | u8 addr, int size) |
315 | { | 289 | { |
316 | struct i2c_client *client = chip->client; | 290 | struct regmap *map = chip->regmap; |
317 | int i; | 291 | int i; |
318 | for (i = 0; i < size; i++) | 292 | for (i = 0; i < size; i++) |
319 | max17042_write_reg(client, addr + i, | 293 | regmap_write(map, addr + i, |
320 | chip->pdata->config_data->cell_char_tbl[i]); | 294 | chip->pdata->config_data->cell_char_tbl[i]); |
321 | } | 295 | } |
322 | 296 | ||
323 | static inline void max17042_read_model_data(struct max17042_chip *chip, | 297 | static inline void max17042_read_model_data(struct max17042_chip *chip, |
324 | u8 addr, u16 *data, int size) | 298 | u8 addr, u32 *data, int size) |
325 | { | 299 | { |
326 | struct i2c_client *client = chip->client; | 300 | struct regmap *map = chip->regmap; |
327 | int i; | 301 | int i; |
328 | 302 | ||
329 | for (i = 0; i < size; i++) | 303 | for (i = 0; i < size; i++) |
330 | data[i] = max17042_read_reg(client, addr + i); | 304 | regmap_read(map, addr + i, &data[i]); |
331 | } | 305 | } |
332 | 306 | ||
333 | static inline int max17042_model_data_compare(struct max17042_chip *chip, | 307 | static inline int max17042_model_data_compare(struct max17042_chip *chip, |
@@ -350,7 +324,7 @@ static int max17042_init_model(struct max17042_chip *chip) | |||
350 | { | 324 | { |
351 | int ret; | 325 | int ret; |
352 | int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); | 326 | int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); |
353 | u16 *temp_data; | 327 | u32 *temp_data; |
354 | 328 | ||
355 | temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); | 329 | temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); |
356 | if (!temp_data) | 330 | if (!temp_data) |
@@ -365,7 +339,7 @@ static int max17042_init_model(struct max17042_chip *chip) | |||
365 | ret = max17042_model_data_compare( | 339 | ret = max17042_model_data_compare( |
366 | chip, | 340 | chip, |
367 | chip->pdata->config_data->cell_char_tbl, | 341 | chip->pdata->config_data->cell_char_tbl, |
368 | temp_data, | 342 | (u16 *)temp_data, |
369 | table_size); | 343 | table_size); |
370 | 344 | ||
371 | max10742_lock_model(chip); | 345 | max10742_lock_model(chip); |
@@ -378,7 +352,7 @@ static int max17042_verify_model_lock(struct max17042_chip *chip) | |||
378 | { | 352 | { |
379 | int i; | 353 | int i; |
380 | int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); | 354 | int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl); |
381 | u16 *temp_data; | 355 | u32 *temp_data; |
382 | int ret = 0; | 356 | int ret = 0; |
383 | 357 | ||
384 | temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); | 358 | temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL); |
@@ -398,40 +372,38 @@ static int max17042_verify_model_lock(struct max17042_chip *chip) | |||
398 | static void max17042_write_config_regs(struct max17042_chip *chip) | 372 | static void max17042_write_config_regs(struct max17042_chip *chip) |
399 | { | 373 | { |
400 | struct max17042_config_data *config = chip->pdata->config_data; | 374 | struct max17042_config_data *config = chip->pdata->config_data; |
375 | struct regmap *map = chip->regmap; | ||
401 | 376 | ||
402 | max17042_write_reg(chip->client, MAX17042_CONFIG, config->config); | 377 | regmap_write(map, MAX17042_CONFIG, config->config); |
403 | max17042_write_reg(chip->client, MAX17042_LearnCFG, config->learn_cfg); | 378 | regmap_write(map, MAX17042_LearnCFG, config->learn_cfg); |
404 | max17042_write_reg(chip->client, MAX17042_FilterCFG, | 379 | regmap_write(map, MAX17042_FilterCFG, |
405 | config->filter_cfg); | 380 | config->filter_cfg); |
406 | max17042_write_reg(chip->client, MAX17042_RelaxCFG, config->relax_cfg); | 381 | regmap_write(map, MAX17042_RelaxCFG, config->relax_cfg); |
407 | if (chip->chip_type == MAX17047) | 382 | if (chip->chip_type == MAX17047) |
408 | max17042_write_reg(chip->client, MAX17047_FullSOCThr, | 383 | regmap_write(map, MAX17047_FullSOCThr, |
409 | config->full_soc_thresh); | 384 | config->full_soc_thresh); |
410 | } | 385 | } |
411 | 386 | ||
412 | static void max17042_write_custom_regs(struct max17042_chip *chip) | 387 | static void max17042_write_custom_regs(struct max17042_chip *chip) |
413 | { | 388 | { |
414 | struct max17042_config_data *config = chip->pdata->config_data; | 389 | struct max17042_config_data *config = chip->pdata->config_data; |
390 | struct regmap *map = chip->regmap; | ||
415 | 391 | ||
416 | max17042_write_verify_reg(chip->client, MAX17042_RCOMP0, | 392 | max17042_write_verify_reg(map, MAX17042_RCOMP0, config->rcomp0); |
417 | config->rcomp0); | 393 | max17042_write_verify_reg(map, MAX17042_TempCo, config->tcompc0); |
418 | max17042_write_verify_reg(chip->client, MAX17042_TempCo, | 394 | max17042_write_verify_reg(map, MAX17042_ICHGTerm, config->ichgt_term); |
419 | config->tcompc0); | ||
420 | max17042_write_verify_reg(chip->client, MAX17042_ICHGTerm, | ||
421 | config->ichgt_term); | ||
422 | if (chip->chip_type == MAX17042) { | 395 | if (chip->chip_type == MAX17042) { |
423 | max17042_write_reg(chip->client, MAX17042_EmptyTempCo, | 396 | regmap_write(map, MAX17042_EmptyTempCo, config->empty_tempco); |
424 | config->empty_tempco); | 397 | max17042_write_verify_reg(map, MAX17042_K_empty0, |
425 | max17042_write_verify_reg(chip->client, MAX17042_K_empty0, | ||
426 | config->kempty0); | 398 | config->kempty0); |
427 | } else { | 399 | } else { |
428 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl00, | 400 | max17042_write_verify_reg(map, MAX17047_QRTbl00, |
429 | config->qrtbl00); | 401 | config->qrtbl00); |
430 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl10, | 402 | max17042_write_verify_reg(map, MAX17047_QRTbl10, |
431 | config->qrtbl10); | 403 | config->qrtbl10); |
432 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl20, | 404 | max17042_write_verify_reg(map, MAX17047_QRTbl20, |
433 | config->qrtbl20); | 405 | config->qrtbl20); |
434 | max17042_write_verify_reg(chip->client, MAX17047_QRTbl30, | 406 | max17042_write_verify_reg(map, MAX17047_QRTbl30, |
435 | config->qrtbl30); | 407 | config->qrtbl30); |
436 | } | 408 | } |
437 | } | 409 | } |
@@ -439,58 +411,60 @@ static void max17042_write_custom_regs(struct max17042_chip *chip) | |||
439 | static void max17042_update_capacity_regs(struct max17042_chip *chip) | 411 | static void max17042_update_capacity_regs(struct max17042_chip *chip) |
440 | { | 412 | { |
441 | struct max17042_config_data *config = chip->pdata->config_data; | 413 | struct max17042_config_data *config = chip->pdata->config_data; |
414 | struct regmap *map = chip->regmap; | ||
442 | 415 | ||
443 | max17042_write_verify_reg(chip->client, MAX17042_FullCAP, | 416 | max17042_write_verify_reg(map, MAX17042_FullCAP, |
444 | config->fullcap); | 417 | config->fullcap); |
445 | max17042_write_reg(chip->client, MAX17042_DesignCap, | 418 | regmap_write(map, MAX17042_DesignCap, config->design_cap); |
446 | config->design_cap); | 419 | max17042_write_verify_reg(map, MAX17042_FullCAPNom, |
447 | max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, | ||
448 | config->fullcapnom); | 420 | config->fullcapnom); |
449 | } | 421 | } |
450 | 422 | ||
451 | static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip) | 423 | static void max17042_reset_vfsoc0_reg(struct max17042_chip *chip) |
452 | { | 424 | { |
453 | u16 vfSoc; | 425 | unsigned int vfSoc; |
426 | struct regmap *map = chip->regmap; | ||
454 | 427 | ||
455 | vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC); | 428 | regmap_read(map, MAX17042_VFSOC, &vfSoc); |
456 | max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK); | 429 | regmap_write(map, MAX17042_VFSOC0Enable, VFSOC0_UNLOCK); |
457 | max17042_write_verify_reg(chip->client, MAX17042_VFSOC0, vfSoc); | 430 | max17042_write_verify_reg(map, MAX17042_VFSOC0, vfSoc); |
458 | max17042_write_reg(chip->client, MAX17042_VFSOC0Enable, VFSOC0_LOCK); | 431 | regmap_write(map, MAX17042_VFSOC0Enable, VFSOC0_LOCK); |
459 | } | 432 | } |
460 | 433 | ||
461 | static void max17042_load_new_capacity_params(struct max17042_chip *chip) | 434 | static void max17042_load_new_capacity_params(struct max17042_chip *chip) |
462 | { | 435 | { |
463 | u16 full_cap0, rep_cap, dq_acc, vfSoc; | 436 | u32 full_cap0, rep_cap, dq_acc, vfSoc; |
464 | u32 rem_cap; | 437 | u32 rem_cap; |
465 | 438 | ||
466 | struct max17042_config_data *config = chip->pdata->config_data; | 439 | struct max17042_config_data *config = chip->pdata->config_data; |
440 | struct regmap *map = chip->regmap; | ||
467 | 441 | ||
468 | full_cap0 = max17042_read_reg(chip->client, MAX17042_FullCAP0); | 442 | regmap_read(map, MAX17042_FullCAP0, &full_cap0); |
469 | vfSoc = max17042_read_reg(chip->client, MAX17042_VFSOC); | 443 | regmap_read(map, MAX17042_VFSOC, &vfSoc); |
470 | 444 | ||
471 | /* fg_vfSoc needs to shifted by 8 bits to get the | 445 | /* fg_vfSoc needs to shifted by 8 bits to get the |
472 | * perc in 1% accuracy, to get the right rem_cap multiply | 446 | * perc in 1% accuracy, to get the right rem_cap multiply |
473 | * full_cap0, fg_vfSoc and devide by 100 | 447 | * full_cap0, fg_vfSoc and devide by 100 |
474 | */ | 448 | */ |
475 | rem_cap = ((vfSoc >> 8) * full_cap0) / 100; | 449 | rem_cap = ((vfSoc >> 8) * full_cap0) / 100; |
476 | max17042_write_verify_reg(chip->client, MAX17042_RemCap, (u16)rem_cap); | 450 | max17042_write_verify_reg(map, MAX17042_RemCap, rem_cap); |
477 | 451 | ||
478 | rep_cap = (u16)rem_cap; | 452 | rep_cap = rem_cap; |
479 | max17042_write_verify_reg(chip->client, MAX17042_RepCap, rep_cap); | 453 | max17042_write_verify_reg(map, MAX17042_RepCap, rep_cap); |
480 | 454 | ||
481 | /* Write dQ_acc to 200% of Capacity and dP_acc to 200% */ | 455 | /* Write dQ_acc to 200% of Capacity and dP_acc to 200% */ |
482 | dq_acc = config->fullcap / dQ_ACC_DIV; | 456 | dq_acc = config->fullcap / dQ_ACC_DIV; |
483 | max17042_write_verify_reg(chip->client, MAX17042_dQacc, dq_acc); | 457 | max17042_write_verify_reg(map, MAX17042_dQacc, dq_acc); |
484 | max17042_write_verify_reg(chip->client, MAX17042_dPacc, dP_ACC_200); | 458 | max17042_write_verify_reg(map, MAX17042_dPacc, dP_ACC_200); |
485 | 459 | ||
486 | max17042_write_verify_reg(chip->client, MAX17042_FullCAP, | 460 | max17042_write_verify_reg(map, MAX17042_FullCAP, |
487 | config->fullcap); | 461 | config->fullcap); |
488 | max17042_write_reg(chip->client, MAX17042_DesignCap, | 462 | regmap_write(map, MAX17042_DesignCap, |
489 | config->design_cap); | 463 | config->design_cap); |
490 | max17042_write_verify_reg(chip->client, MAX17042_FullCAPNom, | 464 | max17042_write_verify_reg(map, MAX17042_FullCAPNom, |
491 | config->fullcapnom); | 465 | config->fullcapnom); |
492 | /* Update SOC register with new SOC */ | 466 | /* Update SOC register with new SOC */ |
493 | max17042_write_reg(chip->client, MAX17042_RepSOC, vfSoc); | 467 | regmap_write(map, MAX17042_RepSOC, vfSoc); |
494 | } | 468 | } |
495 | 469 | ||
496 | /* | 470 | /* |
@@ -500,59 +474,60 @@ static void max17042_load_new_capacity_params(struct max17042_chip *chip) | |||
500 | */ | 474 | */ |
501 | static inline void max17042_override_por_values(struct max17042_chip *chip) | 475 | static inline void max17042_override_por_values(struct max17042_chip *chip) |
502 | { | 476 | { |
503 | struct i2c_client *client = chip->client; | 477 | struct regmap *map = chip->regmap; |
504 | struct max17042_config_data *config = chip->pdata->config_data; | 478 | struct max17042_config_data *config = chip->pdata->config_data; |
505 | 479 | ||
506 | max17042_override_por(client, MAX17042_TGAIN, config->tgain); | 480 | max17042_override_por(map, MAX17042_TGAIN, config->tgain); |
507 | max17042_override_por(client, MAx17042_TOFF, config->toff); | 481 | max17042_override_por(map, MAx17042_TOFF, config->toff); |
508 | max17042_override_por(client, MAX17042_CGAIN, config->cgain); | 482 | max17042_override_por(map, MAX17042_CGAIN, config->cgain); |
509 | max17042_override_por(client, MAX17042_COFF, config->coff); | 483 | max17042_override_por(map, MAX17042_COFF, config->coff); |
510 | 484 | ||
511 | max17042_override_por(client, MAX17042_VALRT_Th, config->valrt_thresh); | 485 | max17042_override_por(map, MAX17042_VALRT_Th, config->valrt_thresh); |
512 | max17042_override_por(client, MAX17042_TALRT_Th, config->talrt_thresh); | 486 | max17042_override_por(map, MAX17042_TALRT_Th, config->talrt_thresh); |
513 | max17042_override_por(client, MAX17042_SALRT_Th, | 487 | max17042_override_por(map, MAX17042_SALRT_Th, |
514 | config->soc_alrt_thresh); | 488 | config->soc_alrt_thresh); |
515 | max17042_override_por(client, MAX17042_CONFIG, config->config); | 489 | max17042_override_por(map, MAX17042_CONFIG, config->config); |
516 | max17042_override_por(client, MAX17042_SHDNTIMER, config->shdntimer); | 490 | max17042_override_por(map, MAX17042_SHDNTIMER, config->shdntimer); |
517 | 491 | ||
518 | max17042_override_por(client, MAX17042_DesignCap, config->design_cap); | 492 | max17042_override_por(map, MAX17042_DesignCap, config->design_cap); |
519 | max17042_override_por(client, MAX17042_ICHGTerm, config->ichgt_term); | 493 | max17042_override_por(map, MAX17042_ICHGTerm, config->ichgt_term); |
520 | 494 | ||
521 | max17042_override_por(client, MAX17042_AtRate, config->at_rate); | 495 | max17042_override_por(map, MAX17042_AtRate, config->at_rate); |
522 | max17042_override_por(client, MAX17042_LearnCFG, config->learn_cfg); | 496 | max17042_override_por(map, MAX17042_LearnCFG, config->learn_cfg); |
523 | max17042_override_por(client, MAX17042_FilterCFG, config->filter_cfg); | 497 | max17042_override_por(map, MAX17042_FilterCFG, config->filter_cfg); |
524 | max17042_override_por(client, MAX17042_RelaxCFG, config->relax_cfg); | 498 | max17042_override_por(map, MAX17042_RelaxCFG, config->relax_cfg); |
525 | max17042_override_por(client, MAX17042_MiscCFG, config->misc_cfg); | 499 | max17042_override_por(map, MAX17042_MiscCFG, config->misc_cfg); |
526 | max17042_override_por(client, MAX17042_MaskSOC, config->masksoc); | 500 | max17042_override_por(map, MAX17042_MaskSOC, config->masksoc); |
527 | 501 | ||
528 | max17042_override_por(client, MAX17042_FullCAP, config->fullcap); | 502 | max17042_override_por(map, MAX17042_FullCAP, config->fullcap); |
529 | max17042_override_por(client, MAX17042_FullCAPNom, config->fullcapnom); | 503 | max17042_override_por(map, MAX17042_FullCAPNom, config->fullcapnom); |
530 | if (chip->chip_type == MAX17042) | 504 | if (chip->chip_type == MAX17042) |
531 | max17042_override_por(client, MAX17042_SOC_empty, | 505 | max17042_override_por(map, MAX17042_SOC_empty, |
532 | config->socempty); | 506 | config->socempty); |
533 | max17042_override_por(client, MAX17042_LAvg_empty, config->lavg_empty); | 507 | max17042_override_por(map, MAX17042_LAvg_empty, config->lavg_empty); |
534 | max17042_override_por(client, MAX17042_dQacc, config->dqacc); | 508 | max17042_override_por(map, MAX17042_dQacc, config->dqacc); |
535 | max17042_override_por(client, MAX17042_dPacc, config->dpacc); | 509 | max17042_override_por(map, MAX17042_dPacc, config->dpacc); |
536 | 510 | ||
537 | if (chip->chip_type == MAX17042) | 511 | if (chip->chip_type == MAX17042) |
538 | max17042_override_por(client, MAX17042_V_empty, config->vempty); | 512 | max17042_override_por(map, MAX17042_V_empty, config->vempty); |
539 | else | 513 | else |
540 | max17042_override_por(client, MAX17047_V_empty, config->vempty); | 514 | max17042_override_por(map, MAX17047_V_empty, config->vempty); |
541 | max17042_override_por(client, MAX17042_TempNom, config->temp_nom); | 515 | max17042_override_por(map, MAX17042_TempNom, config->temp_nom); |
542 | max17042_override_por(client, MAX17042_TempLim, config->temp_lim); | 516 | max17042_override_por(map, MAX17042_TempLim, config->temp_lim); |
543 | max17042_override_por(client, MAX17042_FCTC, config->fctc); | 517 | max17042_override_por(map, MAX17042_FCTC, config->fctc); |
544 | max17042_override_por(client, MAX17042_RCOMP0, config->rcomp0); | 518 | max17042_override_por(map, MAX17042_RCOMP0, config->rcomp0); |
545 | max17042_override_por(client, MAX17042_TempCo, config->tcompc0); | 519 | max17042_override_por(map, MAX17042_TempCo, config->tcompc0); |
546 | if (chip->chip_type) { | 520 | if (chip->chip_type) { |
547 | max17042_override_por(client, MAX17042_EmptyTempCo, | 521 | max17042_override_por(map, MAX17042_EmptyTempCo, |
548 | config->empty_tempco); | 522 | config->empty_tempco); |
549 | max17042_override_por(client, MAX17042_K_empty0, | 523 | max17042_override_por(map, MAX17042_K_empty0, |
550 | config->kempty0); | 524 | config->kempty0); |
551 | } | 525 | } |
552 | } | 526 | } |
553 | 527 | ||
554 | static int max17042_init_chip(struct max17042_chip *chip) | 528 | static int max17042_init_chip(struct max17042_chip *chip) |
555 | { | 529 | { |
530 | struct regmap *map = chip->regmap; | ||
556 | int ret; | 531 | int ret; |
557 | int val; | 532 | int val; |
558 | 533 | ||
@@ -597,31 +572,32 @@ static int max17042_init_chip(struct max17042_chip *chip) | |||
597 | max17042_load_new_capacity_params(chip); | 572 | max17042_load_new_capacity_params(chip); |
598 | 573 | ||
599 | /* Init complete, Clear the POR bit */ | 574 | /* Init complete, Clear the POR bit */ |
600 | val = max17042_read_reg(chip->client, MAX17042_STATUS); | 575 | regmap_read(map, MAX17042_STATUS, &val); |
601 | max17042_write_reg(chip->client, MAX17042_STATUS, | 576 | regmap_write(map, MAX17042_STATUS, val & (~STATUS_POR_BIT)); |
602 | val & (~STATUS_POR_BIT)); | ||
603 | return 0; | 577 | return 0; |
604 | } | 578 | } |
605 | 579 | ||
606 | static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) | 580 | static void max17042_set_soc_threshold(struct max17042_chip *chip, u16 off) |
607 | { | 581 | { |
608 | u16 soc, soc_tr; | 582 | struct regmap *map = chip->regmap; |
583 | u32 soc, soc_tr; | ||
609 | 584 | ||
610 | /* program interrupt thesholds such that we should | 585 | /* program interrupt thesholds such that we should |
611 | * get interrupt for every 'off' perc change in the soc | 586 | * get interrupt for every 'off' perc change in the soc |
612 | */ | 587 | */ |
613 | soc = max17042_read_reg(chip->client, MAX17042_RepSOC) >> 8; | 588 | regmap_read(map, MAX17042_RepSOC, &soc); |
589 | soc >>= 8; | ||
614 | soc_tr = (soc + off) << 8; | 590 | soc_tr = (soc + off) << 8; |
615 | soc_tr |= (soc - off); | 591 | soc_tr |= (soc - off); |
616 | max17042_write_reg(chip->client, MAX17042_SALRT_Th, soc_tr); | 592 | regmap_write(map, MAX17042_SALRT_Th, soc_tr); |
617 | } | 593 | } |
618 | 594 | ||
619 | static irqreturn_t max17042_thread_handler(int id, void *dev) | 595 | static irqreturn_t max17042_thread_handler(int id, void *dev) |
620 | { | 596 | { |
621 | struct max17042_chip *chip = dev; | 597 | struct max17042_chip *chip = dev; |
622 | u16 val; | 598 | u32 val; |
623 | 599 | ||
624 | val = max17042_read_reg(chip->client, MAX17042_STATUS); | 600 | regmap_read(chip->regmap, MAX17042_STATUS, &val); |
625 | if ((val & STATUS_INTR_SOCMIN_BIT) || | 601 | if ((val & STATUS_INTR_SOCMIN_BIT) || |
626 | (val & STATUS_INTR_SOCMAX_BIT)) { | 602 | (val & STATUS_INTR_SOCMAX_BIT)) { |
627 | dev_info(&chip->client->dev, "SOC threshold INTR\n"); | 603 | dev_info(&chip->client->dev, "SOC threshold INTR\n"); |
@@ -682,13 +658,20 @@ max17042_get_pdata(struct device *dev) | |||
682 | } | 658 | } |
683 | #endif | 659 | #endif |
684 | 660 | ||
661 | static struct regmap_config max17042_regmap_config = { | ||
662 | .reg_bits = 8, | ||
663 | .val_bits = 16, | ||
664 | .val_format_endian = REGMAP_ENDIAN_NATIVE, | ||
665 | }; | ||
666 | |||
685 | static int max17042_probe(struct i2c_client *client, | 667 | static int max17042_probe(struct i2c_client *client, |
686 | const struct i2c_device_id *id) | 668 | const struct i2c_device_id *id) |
687 | { | 669 | { |
688 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 670 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
689 | struct max17042_chip *chip; | 671 | struct max17042_chip *chip; |
690 | int ret; | 672 | int ret; |
691 | int reg; | 673 | int i; |
674 | u32 val; | ||
692 | 675 | ||
693 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) | 676 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) |
694 | return -EIO; | 677 | return -EIO; |
@@ -698,6 +681,12 @@ static int max17042_probe(struct i2c_client *client, | |||
698 | return -ENOMEM; | 681 | return -ENOMEM; |
699 | 682 | ||
700 | chip->client = client; | 683 | chip->client = client; |
684 | chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config); | ||
685 | if (IS_ERR(chip->regmap)) { | ||
686 | dev_err(&client->dev, "Failed to initialize regmap\n"); | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
701 | chip->pdata = max17042_get_pdata(&client->dev); | 690 | chip->pdata = max17042_get_pdata(&client->dev); |
702 | if (!chip->pdata) { | 691 | if (!chip->pdata) { |
703 | dev_err(&client->dev, "no platform data provided\n"); | 692 | dev_err(&client->dev, "no platform data provided\n"); |
@@ -706,15 +695,15 @@ static int max17042_probe(struct i2c_client *client, | |||
706 | 695 | ||
707 | i2c_set_clientdata(client, chip); | 696 | i2c_set_clientdata(client, chip); |
708 | 697 | ||
709 | ret = max17042_read_reg(chip->client, MAX17042_DevName); | 698 | regmap_read(chip->regmap, MAX17042_DevName, &val); |
710 | if (ret == MAX17042_IC_VERSION) { | 699 | if (val == MAX17042_IC_VERSION) { |
711 | dev_dbg(&client->dev, "chip type max17042 detected\n"); | 700 | dev_dbg(&client->dev, "chip type max17042 detected\n"); |
712 | chip->chip_type = MAX17042; | 701 | chip->chip_type = MAX17042; |
713 | } else if (ret == MAX17047_IC_VERSION) { | 702 | } else if (val == MAX17047_IC_VERSION) { |
714 | dev_dbg(&client->dev, "chip type max17047/50 detected\n"); | 703 | dev_dbg(&client->dev, "chip type max17047/50 detected\n"); |
715 | chip->chip_type = MAX17047; | 704 | chip->chip_type = MAX17047; |
716 | } else { | 705 | } else { |
717 | dev_err(&client->dev, "device version mismatch: %x\n", ret); | 706 | dev_err(&client->dev, "device version mismatch: %x\n", val); |
718 | return -EIO; | 707 | return -EIO; |
719 | } | 708 | } |
720 | 709 | ||
@@ -733,13 +722,15 @@ static int max17042_probe(struct i2c_client *client, | |||
733 | chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; | 722 | chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR; |
734 | 723 | ||
735 | if (chip->pdata->init_data) | 724 | if (chip->pdata->init_data) |
736 | max17042_set_reg(client, chip->pdata->init_data, | 725 | for (i = 0; i < chip->pdata->num_init_data; i++) |
737 | chip->pdata->num_init_data); | 726 | regmap_write(chip->regmap, |
727 | chip->pdata->init_data[i].addr, | ||
728 | chip->pdata->init_data[i].data); | ||
738 | 729 | ||
739 | if (!chip->pdata->enable_current_sense) { | 730 | if (!chip->pdata->enable_current_sense) { |
740 | max17042_write_reg(client, MAX17042_CGAIN, 0x0000); | 731 | regmap_write(chip->regmap, MAX17042_CGAIN, 0x0000); |
741 | max17042_write_reg(client, MAX17042_MiscCFG, 0x0003); | 732 | regmap_write(chip->regmap, MAX17042_MiscCFG, 0x0003); |
742 | max17042_write_reg(client, MAX17042_LearnCFG, 0x0007); | 733 | regmap_write(chip->regmap, MAX17042_LearnCFG, 0x0007); |
743 | } | 734 | } |
744 | 735 | ||
745 | ret = power_supply_register(&client->dev, &chip->battery); | 736 | ret = power_supply_register(&client->dev, &chip->battery); |
@@ -754,9 +745,9 @@ static int max17042_probe(struct i2c_client *client, | |||
754 | IRQF_TRIGGER_FALLING, | 745 | IRQF_TRIGGER_FALLING, |
755 | chip->battery.name, chip); | 746 | chip->battery.name, chip); |
756 | if (!ret) { | 747 | if (!ret) { |
757 | reg = max17042_read_reg(client, MAX17042_CONFIG); | 748 | regmap_read(chip->regmap, MAX17042_CONFIG, &val); |
758 | reg |= CONFIG_ALRT_BIT_ENBL; | 749 | val |= CONFIG_ALRT_BIT_ENBL; |
759 | max17042_write_reg(client, MAX17042_CONFIG, reg); | 750 | regmap_write(chip->regmap, MAX17042_CONFIG, val); |
760 | max17042_set_soc_threshold(chip, 1); | 751 | max17042_set_soc_threshold(chip, 1); |
761 | } else { | 752 | } else { |
762 | client->irq = 0; | 753 | client->irq = 0; |
@@ -765,8 +756,8 @@ static int max17042_probe(struct i2c_client *client, | |||
765 | } | 756 | } |
766 | } | 757 | } |
767 | 758 | ||
768 | reg = max17042_read_reg(chip->client, MAX17042_STATUS); | 759 | regmap_read(chip->regmap, MAX17042_STATUS, &val); |
769 | if (reg & STATUS_POR_BIT) { | 760 | if (val & STATUS_POR_BIT) { |
770 | INIT_WORK(&chip->work, max17042_init_worker); | 761 | INIT_WORK(&chip->work, max17042_init_worker); |
771 | schedule_work(&chip->work); | 762 | schedule_work(&chip->work); |
772 | } else { | 763 | } else { |
@@ -786,7 +777,7 @@ static int max17042_remove(struct i2c_client *client) | |||
786 | return 0; | 777 | return 0; |
787 | } | 778 | } |
788 | 779 | ||
789 | #ifdef CONFIG_PM | 780 | #ifdef CONFIG_PM_SLEEP |
790 | static int max17042_suspend(struct device *dev) | 781 | static int max17042_suspend(struct device *dev) |
791 | { | 782 | { |
792 | struct max17042_chip *chip = dev_get_drvdata(dev); | 783 | struct max17042_chip *chip = dev_get_drvdata(dev); |
@@ -816,17 +807,11 @@ static int max17042_resume(struct device *dev) | |||
816 | 807 | ||
817 | return 0; | 808 | return 0; |
818 | } | 809 | } |
819 | |||
820 | static const struct dev_pm_ops max17042_pm_ops = { | ||
821 | .suspend = max17042_suspend, | ||
822 | .resume = max17042_resume, | ||
823 | }; | ||
824 | |||
825 | #define MAX17042_PM_OPS (&max17042_pm_ops) | ||
826 | #else | ||
827 | #define MAX17042_PM_OPS NULL | ||
828 | #endif | 810 | #endif |
829 | 811 | ||
812 | static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend, | ||
813 | max17042_resume); | ||
814 | |||
830 | #ifdef CONFIG_OF | 815 | #ifdef CONFIG_OF |
831 | static const struct of_device_id max17042_dt_match[] = { | 816 | static const struct of_device_id max17042_dt_match[] = { |
832 | { .compatible = "maxim,max17042" }, | 817 | { .compatible = "maxim,max17042" }, |
@@ -849,7 +834,7 @@ static struct i2c_driver max17042_i2c_driver = { | |||
849 | .driver = { | 834 | .driver = { |
850 | .name = "max17042", | 835 | .name = "max17042", |
851 | .of_match_table = of_match_ptr(max17042_dt_match), | 836 | .of_match_table = of_match_ptr(max17042_dt_match), |
852 | .pm = MAX17042_PM_OPS, | 837 | .pm = &max17042_pm_ops, |
853 | }, | 838 | }, |
854 | .probe = max17042_probe, | 839 | .probe = max17042_probe, |
855 | .remove = max17042_remove, | 840 | .remove = max17042_remove, |
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index ffa10ed83eb1..62c15af58c9a 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c | |||
@@ -205,7 +205,7 @@ static int pm2xxx_charger_batt_therm_mngt(struct pm2xxx_charger *pm2, int val) | |||
205 | } | 205 | } |
206 | 206 | ||
207 | 207 | ||
208 | int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val) | 208 | static int pm2xxx_charger_die_therm_mngt(struct pm2xxx_charger *pm2, int val) |
209 | { | 209 | { |
210 | queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work); | 210 | queue_work(pm2->charger_wq, &pm2->check_main_thermal_prot_work); |
211 | 211 | ||
@@ -722,8 +722,12 @@ static int pm2xxx_charger_ac_en(struct ux500_charger *charger, | |||
722 | 722 | ||
723 | dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset); | 723 | dev_dbg(pm2->dev, "Enable AC: %dmV %dmA\n", vset, iset); |
724 | if (!pm2->vddadc_en_ac) { | 724 | if (!pm2->vddadc_en_ac) { |
725 | regulator_enable(pm2->regu); | 725 | ret = regulator_enable(pm2->regu); |
726 | pm2->vddadc_en_ac = true; | 726 | if (ret) |
727 | dev_warn(pm2->dev, | ||
728 | "Failed to enable vddadc regulator\n"); | ||
729 | else | ||
730 | pm2->vddadc_en_ac = true; | ||
727 | } | 731 | } |
728 | 732 | ||
729 | ret = pm2xxx_charging_init(pm2); | 733 | ret = pm2xxx_charging_init(pm2); |
@@ -953,37 +957,24 @@ static int pm2xxx_runtime_suspend(struct device *dev) | |||
953 | { | 957 | { |
954 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); | 958 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); |
955 | struct pm2xxx_charger *pm2; | 959 | struct pm2xxx_charger *pm2; |
956 | int ret = 0; | ||
957 | 960 | ||
958 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); | 961 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); |
959 | if (!pm2) { | ||
960 | dev_err(pm2->dev, "no pm2xxx_charger data supplied\n"); | ||
961 | ret = -EINVAL; | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | clear_lpn_pin(pm2); | 962 | clear_lpn_pin(pm2); |
966 | 963 | ||
967 | return ret; | 964 | return 0; |
968 | } | 965 | } |
969 | 966 | ||
970 | static int pm2xxx_runtime_resume(struct device *dev) | 967 | static int pm2xxx_runtime_resume(struct device *dev) |
971 | { | 968 | { |
972 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); | 969 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); |
973 | struct pm2xxx_charger *pm2; | 970 | struct pm2xxx_charger *pm2; |
974 | int ret = 0; | ||
975 | 971 | ||
976 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); | 972 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); |
977 | if (!pm2) { | ||
978 | dev_err(pm2->dev, "no pm2xxx_charger data supplied\n"); | ||
979 | ret = -EINVAL; | ||
980 | return ret; | ||
981 | } | ||
982 | 973 | ||
983 | if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0) | 974 | if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0) |
984 | set_lpn_pin(pm2); | 975 | set_lpn_pin(pm2); |
985 | 976 | ||
986 | return ret; | 977 | return 0; |
987 | } | 978 | } |
988 | 979 | ||
989 | #endif | 980 | #endif |
diff --git a/drivers/power/tps65090-charger.c b/drivers/power/tps65090-charger.c index bdd7b9b2546a..8fc9d6df87f6 100644 --- a/drivers/power/tps65090-charger.c +++ b/drivers/power/tps65090-charger.c | |||
@@ -15,15 +15,17 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | #include <linux/delay.h> | ||
18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/of_device.h> |
24 | #include <linux/delay.h> | ||
25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
26 | #include <linux/power_supply.h> | 26 | #include <linux/power_supply.h> |
27 | #include <linux/slab.h> | ||
28 | |||
27 | #include <linux/mfd/tps65090.h> | 29 | #include <linux/mfd/tps65090.h> |
28 | 30 | ||
29 | #define TPS65090_REG_INTR_STS 0x00 | 31 | #define TPS65090_REG_INTR_STS 0x00 |
@@ -185,10 +187,6 @@ static irqreturn_t tps65090_charger_isr(int irq, void *dev_id) | |||
185 | return IRQ_HANDLED; | 187 | return IRQ_HANDLED; |
186 | } | 188 | } |
187 | 189 | ||
188 | #if defined(CONFIG_OF) | ||
189 | |||
190 | #include <linux/of_device.h> | ||
191 | |||
192 | static struct tps65090_platform_data * | 190 | static struct tps65090_platform_data * |
193 | tps65090_parse_dt_charger_data(struct platform_device *pdev) | 191 | tps65090_parse_dt_charger_data(struct platform_device *pdev) |
194 | { | 192 | { |
@@ -210,13 +208,6 @@ static struct tps65090_platform_data * | |||
210 | return pdata; | 208 | return pdata; |
211 | 209 | ||
212 | } | 210 | } |
213 | #else | ||
214 | static struct tps65090_platform_data * | ||
215 | tps65090_parse_dt_charger_data(struct platform_device *pdev) | ||
216 | { | ||
217 | return NULL; | ||
218 | } | ||
219 | #endif | ||
220 | 211 | ||
221 | static int tps65090_charger_probe(struct platform_device *pdev) | 212 | static int tps65090_charger_probe(struct platform_device *pdev) |
222 | { | 213 | { |
@@ -228,7 +219,7 @@ static int tps65090_charger_probe(struct platform_device *pdev) | |||
228 | 219 | ||
229 | pdata = dev_get_platdata(pdev->dev.parent); | 220 | pdata = dev_get_platdata(pdev->dev.parent); |
230 | 221 | ||
231 | if (!pdata && pdev->dev.of_node) | 222 | if (IS_ENABLED(CONFIG_OF) && !pdata && pdev->dev.of_node) |
232 | pdata = tps65090_parse_dt_charger_data(pdev); | 223 | pdata = tps65090_parse_dt_charger_data(pdev); |
233 | 224 | ||
234 | if (!pdata) { | 225 | if (!pdata) { |
@@ -277,13 +268,13 @@ static int tps65090_charger_probe(struct platform_device *pdev) | |||
277 | if (ret) { | 268 | if (ret) { |
278 | dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq, | 269 | dev_err(cdata->dev, "Unable to register irq %d err %d\n", irq, |
279 | ret); | 270 | ret); |
280 | goto fail_free_irq; | 271 | goto fail_unregister_supply; |
281 | } | 272 | } |
282 | 273 | ||
283 | ret = tps65090_config_charger(cdata); | 274 | ret = tps65090_config_charger(cdata); |
284 | if (ret < 0) { | 275 | if (ret < 0) { |
285 | dev_err(&pdev->dev, "charger config failed, err %d\n", ret); | 276 | dev_err(&pdev->dev, "charger config failed, err %d\n", ret); |
286 | goto fail_free_irq; | 277 | goto fail_unregister_supply; |
287 | } | 278 | } |
288 | 279 | ||
289 | /* Check for charger presence */ | 280 | /* Check for charger presence */ |
@@ -292,14 +283,14 @@ static int tps65090_charger_probe(struct platform_device *pdev) | |||
292 | if (ret < 0) { | 283 | if (ret < 0) { |
293 | dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__, | 284 | dev_err(cdata->dev, "%s(): Error in reading reg 0x%x", __func__, |
294 | TPS65090_REG_CG_STATUS1); | 285 | TPS65090_REG_CG_STATUS1); |
295 | goto fail_free_irq; | 286 | goto fail_unregister_supply; |
296 | } | 287 | } |
297 | 288 | ||
298 | if (status1 != 0) { | 289 | if (status1 != 0) { |
299 | ret = tps65090_enable_charging(cdata); | 290 | ret = tps65090_enable_charging(cdata); |
300 | if (ret < 0) { | 291 | if (ret < 0) { |
301 | dev_err(cdata->dev, "error enabling charger\n"); | 292 | dev_err(cdata->dev, "error enabling charger\n"); |
302 | goto fail_free_irq; | 293 | goto fail_unregister_supply; |
303 | } | 294 | } |
304 | cdata->ac_online = 1; | 295 | cdata->ac_online = 1; |
305 | power_supply_changed(&cdata->ac); | 296 | power_supply_changed(&cdata->ac); |
@@ -307,8 +298,6 @@ static int tps65090_charger_probe(struct platform_device *pdev) | |||
307 | 298 | ||
308 | return 0; | 299 | return 0; |
309 | 300 | ||
310 | fail_free_irq: | ||
311 | devm_free_irq(cdata->dev, irq, cdata); | ||
312 | fail_unregister_supply: | 301 | fail_unregister_supply: |
313 | power_supply_unregister(&cdata->ac); | 302 | power_supply_unregister(&cdata->ac); |
314 | 303 | ||
@@ -319,7 +308,6 @@ static int tps65090_charger_remove(struct platform_device *pdev) | |||
319 | { | 308 | { |
320 | struct tps65090_charger *cdata = platform_get_drvdata(pdev); | 309 | struct tps65090_charger *cdata = platform_get_drvdata(pdev); |
321 | 310 | ||
322 | devm_free_irq(cdata->dev, cdata->irq, cdata); | ||
323 | power_supply_unregister(&cdata->ac); | 311 | power_supply_unregister(&cdata->ac); |
324 | 312 | ||
325 | return 0; | 313 | return 0; |
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c index d98abe911e37..f14108844e1a 100644 --- a/drivers/power/twl4030_charger.c +++ b/drivers/power/twl4030_charger.c | |||
@@ -495,10 +495,38 @@ static enum power_supply_property twl4030_charger_props[] = { | |||
495 | POWER_SUPPLY_PROP_CURRENT_NOW, | 495 | POWER_SUPPLY_PROP_CURRENT_NOW, |
496 | }; | 496 | }; |
497 | 497 | ||
498 | #ifdef CONFIG_OF | ||
499 | static const struct twl4030_bci_platform_data * | ||
500 | twl4030_bci_parse_dt(struct device *dev) | ||
501 | { | ||
502 | struct device_node *np = dev->of_node; | ||
503 | struct twl4030_bci_platform_data *pdata; | ||
504 | u32 num; | ||
505 | |||
506 | if (!np) | ||
507 | return NULL; | ||
508 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
509 | if (!pdata) | ||
510 | return pdata; | ||
511 | |||
512 | if (of_property_read_u32(np, "ti,bb-uvolt", &num) == 0) | ||
513 | pdata->bb_uvolt = num; | ||
514 | if (of_property_read_u32(np, "ti,bb-uamp", &num) == 0) | ||
515 | pdata->bb_uamp = num; | ||
516 | return pdata; | ||
517 | } | ||
518 | #else | ||
519 | static inline const struct twl4030_bci_platform_data * | ||
520 | twl4030_bci_parse_dt(struct device *dev) | ||
521 | { | ||
522 | return NULL; | ||
523 | } | ||
524 | #endif | ||
525 | |||
498 | static int __init twl4030_bci_probe(struct platform_device *pdev) | 526 | static int __init twl4030_bci_probe(struct platform_device *pdev) |
499 | { | 527 | { |
500 | struct twl4030_bci *bci; | 528 | struct twl4030_bci *bci; |
501 | struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; | 529 | const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data; |
502 | int ret; | 530 | int ret; |
503 | u32 reg; | 531 | u32 reg; |
504 | 532 | ||
@@ -506,6 +534,9 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
506 | if (bci == NULL) | 534 | if (bci == NULL) |
507 | return -ENOMEM; | 535 | return -ENOMEM; |
508 | 536 | ||
537 | if (!pdata) | ||
538 | pdata = twl4030_bci_parse_dt(&pdev->dev); | ||
539 | |||
509 | bci->dev = &pdev->dev; | 540 | bci->dev = &pdev->dev; |
510 | bci->irq_chg = platform_get_irq(pdev, 0); | 541 | bci->irq_chg = platform_get_irq(pdev, 0); |
511 | bci->irq_bci = platform_get_irq(pdev, 1); | 542 | bci->irq_bci = platform_get_irq(pdev, 1); |
@@ -581,8 +612,11 @@ static int __init twl4030_bci_probe(struct platform_device *pdev) | |||
581 | 612 | ||
582 | twl4030_charger_enable_ac(true); | 613 | twl4030_charger_enable_ac(true); |
583 | twl4030_charger_enable_usb(bci, true); | 614 | twl4030_charger_enable_usb(bci, true); |
584 | twl4030_charger_enable_backup(pdata->bb_uvolt, | 615 | if (pdata) |
585 | pdata->bb_uamp); | 616 | twl4030_charger_enable_backup(pdata->bb_uvolt, |
617 | pdata->bb_uamp); | ||
618 | else | ||
619 | twl4030_charger_enable_backup(0, 0); | ||
586 | 620 | ||
587 | return 0; | 621 | return 0; |
588 | 622 | ||
@@ -631,10 +665,17 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev) | |||
631 | return 0; | 665 | return 0; |
632 | } | 666 | } |
633 | 667 | ||
668 | static const struct of_device_id twl_bci_of_match[] = { | ||
669 | {.compatible = "ti,twl4030-bci", }, | ||
670 | { } | ||
671 | }; | ||
672 | MODULE_DEVICE_TABLE(of, twl_bci_of_match); | ||
673 | |||
634 | static struct platform_driver twl4030_bci_driver = { | 674 | static struct platform_driver twl4030_bci_driver = { |
635 | .driver = { | 675 | .driver = { |
636 | .name = "twl4030_bci", | 676 | .name = "twl4030_bci", |
637 | .owner = THIS_MODULE, | 677 | .owner = THIS_MODULE, |
678 | .of_match_table = of_match_ptr(twl_bci_of_match), | ||
638 | }, | 679 | }, |
639 | .remove = __exit_p(twl4030_bci_remove), | 680 | .remove = __exit_p(twl4030_bci_remove), |
640 | }; | 681 | }; |
diff --git a/include/linux/power/bq24735-charger.h b/include/linux/power/bq24735-charger.h new file mode 100644 index 000000000000..f536164a6069 --- /dev/null +++ b/include/linux/power/bq24735-charger.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License as published by | ||
5 | * the Free Software Foundation; either version 2 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
16 | */ | ||
17 | |||
18 | #ifndef __CHARGER_BQ24735_H_ | ||
19 | #define __CHARGER_BQ24735_H_ | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/power_supply.h> | ||
23 | |||
24 | struct bq24735_platform { | ||
25 | uint32_t charge_current; | ||
26 | uint32_t charge_voltage; | ||
27 | uint32_t input_current; | ||
28 | |||
29 | const char *name; | ||
30 | |||
31 | int status_gpio; | ||
32 | int status_gpio_active_low; | ||
33 | bool status_gpio_valid; | ||
34 | |||
35 | char **supplied_to; | ||
36 | size_t num_supplicants; | ||
37 | }; | ||
38 | |||
39 | #endif /* __CHARGER_BQ24735_H_ */ | ||