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_ */ | ||
