Commit 0ce5c79f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply

Pull power supply and reset changes from Sebastian Reichel:
 "New chip/feature support:
   - bq27xxx: support updating battery config from DT
   - bq24190: support loading battery charge info from DT
   - LTC2941: add LTC2942/LTC2944 support
   - max17042: add ACPI support
   - max1721x: new driver

  Misc:
   - Move bq27xxx w1 driver from w1 into power-supply subsystem
   - Introduce power_supply_set_input_current_limit_from_supplier
   - constify stuff
   - some minor fixes"

* tag 'for-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (39 commits)
  power: supply: bq27xxx: enable writing capacity values for bq27421
  power: supply: bq24190_charger: Get input_current_limit from our supplier
  power: supply: bq24190_charger: Export 5V boost converter as regulator
  power: supply: bq24190_charger: Add power_supply_battery_info support
  power: supply: bq24190_charger: Add property system-minimum-microvolt
  power: supply: bq24190_charger: Enable devicetree config
  dt-bindings: power: supply: Add docs for TI BQ24190 battery charger
  power: supply: bq27xxx: Remove duplicate chip data arrays
  power: supply: bq27xxx: Enable data memory update for certain chips
  power: supply: bq27xxx: Add chip IDs for previously shadowed chips
  power: supply: bq27xxx: Create single chip data table
  power: supply: bq24190_charger: Add ti,bq24192i to devicetree table
  power: supply: bq24190_charger: Add input_current_limit property
  power: supply: Add power_supply_set_input_current_limit_from_supplier helper
  power: supply: max17042_battery: Fix compiler warning
  power: supply: core: Delete two error messages for a failed memory allocation in power_supply_check_supplies()
  power: supply: make device_attribute const
  power: supply: max17042_battery: Fix ACPI interrupt issues
  power: supply: max17042_battery: Add support for ACPI enumeration
  power: supply: lp8788: Make several arrays static const * const
  ...
parents 7151202b 5d01fd38
TI BQ24190 Li-Ion Battery Charger
Required properties:
- compatible: contains one of the following:
* "ti,bq24190"
* "ti,bq24192i"
- reg: integer, I2C address of the charger.
- interrupts[-extended]: configuration for charger INT pin.
Optional properties:
- monitored-battery: phandle of battery characteristics devicetree node
The charger uses the following battery properties:
+ precharge-current-microamp: maximum charge current during precharge
phase (typically 20% of battery capacity).
+ charge-term-current-microamp: a charge cycle terminates when the
battery voltage is above recharge threshold, and the current is below
this setting (typically 10% of battery capacity).
See also Documentation/devicetree/bindings/power/supply/battery.txt
- ti,system-minimum-microvolt: when power is connected and the battery is below
minimum system voltage, the system will be regulated above this setting.
Notes:
- Some circuit boards wire the chip's "OTG" pin high (enabling 500mA default
charge current on USB SDP ports, among other features). To simulate this on
boards that wire the pin to a GPIO, set a gpio-hog.
Example:
bat: battery {
compatible = "simple-battery";
precharge-current-microamp = <256000>;
charge-term-current-microamp = <128000>;
// etc.
};
bq24190: charger@6a {
compatible = "ti,bq24190";
reg = <0x6a>;
interrupts-extended = <&gpiochip 10 IRQ_TYPE_EDGE_FALLING>;
monitored-battery = <&bat>;
ti,system-minimum-microvolt = <3200000>;
};
&twl_gpio {
otg {
gpio-hog;
gpios = <6 0>;
output-high;
line-name = "otg-gpio";
};
};
binding for LTC2941 and LTC2943 battery gauges binding for LTC2941, LTC2942, LTC2943 and LTC2944 battery gauges
Both the LTC2941 and LTC2943 measure battery capacity. All chips measure battery capacity.
The LTC2943 is compatible with the LTC2941, it adds voltage and The LTC2942 is pin compatible with the LTC2941, it adds voltage and
temperature monitoring, and uses a slightly different conversion temperature monitoring, and is runtime detected. LTC2943 and LTC2944
formula for the charge counter. is software compatible, uses a slightly different conversion formula
for the charge counter and adds voltage, current and temperature monitoring.
Required properties: Required properties:
- compatible: Should contain "lltc,ltc2941" or "lltc,ltc2943" which also - compatible: Should contain "lltc,ltc2941", "lltc,ltc2942", "lltc,ltc2943"
indicates the type of I2C chip attached. or "lltc,ltc2944" which also indicates the type of I2C chip attached.
- reg: The 7-bit I2C address. - reg: The 7-bit I2C address.
- lltc,resistor-sense: The sense resistor value in milli-ohms. Can be a 32-bit - lltc,resistor-sense: The sense resistor value in milli-ohms. Can be a 32-bit
negative value when the battery has been connected to the wrong end of the negative value when the battery has been connected to the wrong end of the
......
...@@ -171,8 +171,8 @@ static u32 at91_shdwc_get_wakeup_input(struct platform_device *pdev, ...@@ -171,8 +171,8 @@ static u32 at91_shdwc_get_wakeup_input(struct platform_device *pdev,
for_each_child_of_node(np, cnp) { for_each_child_of_node(np, cnp) {
if (of_property_read_u32(cnp, "reg", &wk_input)) { if (of_property_read_u32(cnp, "reg", &wk_input)) {
dev_warn(&pdev->dev, "reg property is missing for %s\n", dev_warn(&pdev->dev, "reg property is missing for %pOF\n",
cnp->full_name); cnp);
continue; continue;
} }
......
...@@ -198,6 +198,15 @@ config BATTERY_BQ27XXX_I2C ...@@ -198,6 +198,15 @@ config BATTERY_BQ27XXX_I2C
Say Y here to enable support for batteries with BQ27xxx chips Say Y here to enable support for batteries with BQ27xxx chips
connected over an I2C bus. connected over an I2C bus.
config BATTERY_BQ27XXX_HDQ
tristate "BQ27xxx HDQ support"
depends on BATTERY_BQ27XXX
depends on W1
default y
help
Say Y here to enable support for batteries with BQ27xxx chips
connected over an HDQ bus.
config BATTERY_BQ27XXX_DT_UPDATES_NVM config BATTERY_BQ27XXX_DT_UPDATES_NVM
bool "BQ27xxx support for update of NVM/flash data memory" bool "BQ27xxx support for update of NVM/flash data memory"
depends on BATTERY_BQ27XXX_I2C depends on BATTERY_BQ27XXX_I2C
...@@ -313,6 +322,19 @@ config BATTERY_MAX17042 ...@@ -313,6 +322,19 @@ config BATTERY_MAX17042
with MAX17042. This driver also supports max17047/50 chips which are with MAX17042. This driver also supports max17047/50 chips which are
improved version of max17042. improved version of max17042.
config BATTERY_MAX1721X
tristate "MAX17211/MAX17215 standalone gas-gauge"
depends on W1
select REGMAP_W1
help
MAX1721x is fuel-gauge systems for lithium-ion (Li+) batteries
in handheld and portable equipment. MAX17211 used with single cell
battery. MAX17215 designed for muticell battery. Both them have
OneWire (W1) host interface.
Say Y here to enable support for the MAX17211/MAX17215 standalone
battery gas-gauge.
config BATTERY_Z2 config BATTERY_Z2
tristate "Z2 battery driver" tristate "Z2 battery driver"
depends on I2C && MACH_ZIPIT2 depends on I2C && MACH_ZIPIT2
...@@ -365,6 +387,7 @@ config BATTERY_RX51 ...@@ -365,6 +387,7 @@ config BATTERY_RX51
config CHARGER_CPCAP config CHARGER_CPCAP
tristate "CPCAP PMIC Charger Driver" tristate "CPCAP PMIC Charger Driver"
depends on MFD_CPCAP && IIO depends on MFD_CPCAP && IIO
depends on OMAP_USB2 || (!OMAP_USB2 && COMPILE_TEST)
default MFD_CPCAP default MFD_CPCAP
help help
Say Y to enable support for CPCAP PMIC charger driver for Motorola Say Y to enable support for CPCAP PMIC charger driver for Motorola
......
...@@ -38,12 +38,14 @@ obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o ...@@ -38,12 +38,14 @@ obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_CHARGER_SBS) += sbs-charger.o obj-$(CONFIG_CHARGER_SBS) += sbs-charger.o
obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o obj-$(CONFIG_BATTERY_BQ27XXX_I2C) += bq27xxx_battery_i2c.o
obj-$(CONFIG_BATTERY_BQ27XXX_HDQ) += bq27xxx_battery_hdq.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o
obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_MAX1721X) += max1721x_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o
obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o
......
...@@ -596,9 +596,9 @@ static int act8945a_charger_probe(struct platform_device *pdev) ...@@ -596,9 +596,9 @@ static int act8945a_charger_probe(struct platform_device *pdev)
return ret; return ret;
irq = of_irq_get(pdev->dev.of_node, 0); irq = of_irq_get(pdev->dev.of_node, 0);
if (irq == -EPROBE_DEFER) { if (irq <= 0) {
dev_err(&pdev->dev, "failed to find IRQ number\n"); dev_err(&pdev->dev, "failed to find IRQ number\n");
return -EPROBE_DEFER; return irq ?: -ENXIO;
} }
ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed, ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
......
This diff is collapsed.
This diff is collapsed.
/*
* BQ27xxx battery monitor HDQ/1-wire driver
*
* Copyright (C) 2007-2017 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/power/bq27xxx_battery.h>
#include <linux/w1.h>
#define W1_FAMILY_BQ27000 0x01
#define HDQ_CMD_READ (0 << 7)
#define HDQ_CMD_WRITE (1 << 7)
static int F_ID;
module_param(F_ID, int, S_IRUSR);
MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ27xxx device");
static int w1_bq27000_read(struct w1_slave *sl, unsigned int reg)
{
u8 val;
mutex_lock(&sl->master->bus_mutex);
w1_write_8(sl->master, HDQ_CMD_READ | reg);
val = w1_read_8(sl->master);
mutex_unlock(&sl->master->bus_mutex);
return val;
}
static int bq27xxx_battery_hdq_read(struct bq27xxx_device_info *di, u8 reg,
bool single)
{
struct w1_slave *sl = dev_to_w1_slave(di->dev);
unsigned int timeout = 3;
int upper, lower;
int temp;
if (!single) {
/*
* Make sure the value has not changed in between reading the
* lower and the upper part
*/
upper = w1_bq27000_read(sl, reg + 1);
do {
temp = upper;
if (upper < 0)
return upper;
lower = w1_bq27000_read(sl, reg);
if (lower < 0)
return lower;
upper = w1_bq27000_read(sl, reg + 1);
} while (temp != upper && --timeout);
if (timeout == 0)
return -EIO;
return (upper << 8) | lower;
}
return w1_bq27000_read(sl, reg);
}
static int bq27xxx_battery_hdq_add_slave(struct w1_slave *sl)
{
struct bq27xxx_device_info *di;
di = devm_kzalloc(&sl->dev, sizeof(*di), GFP_KERNEL);
if (!di)
return -ENOMEM;
dev_set_drvdata(&sl->dev, di);
di->dev = &sl->dev;
di->chip = BQ27000;
di->name = "bq27000-battery";
di->bus.read = bq27xxx_battery_hdq_read;
return bq27xxx_battery_setup(di);
}
static void bq27xxx_battery_hdq_remove_slave(struct w1_slave *sl)
{
struct bq27xxx_device_info *di = dev_get_drvdata(&sl->dev);
bq27xxx_battery_teardown(di);
}
static struct w1_family_ops bq27xxx_battery_hdq_fops = {
.add_slave = bq27xxx_battery_hdq_add_slave,
.remove_slave = bq27xxx_battery_hdq_remove_slave,
};
static struct w1_family bq27xxx_battery_hdq_family = {
.fid = W1_FAMILY_BQ27000,
.fops = &bq27xxx_battery_hdq_fops,
};
static int __init bq27xxx_battery_hdq_init(void)
{
if (F_ID)
bq27xxx_battery_hdq_family.fid = F_ID;
return w1_register_family(&bq27xxx_battery_hdq_family);
}
module_init(bq27xxx_battery_hdq_init);
static void __exit bq27xxx_battery_hdq_exit(void)
{
w1_unregister_family(&bq27xxx_battery_hdq_family);
}
module_exit(bq27xxx_battery_hdq_exit);
MODULE_AUTHOR("Texas Instruments Ltd");
MODULE_DESCRIPTION("BQ27xxx battery monitor HDQ/1-wire driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000));
...@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { ...@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27210", BQ27010 }, { "bq27210", BQ27010 },
{ "bq27500", BQ2750X }, { "bq27500", BQ2750X },
{ "bq27510", BQ2751X }, { "bq27510", BQ2751X },
{ "bq27520", BQ2751X }, { "bq27520", BQ2752X },
{ "bq27500-1", BQ27500 }, { "bq27500-1", BQ27500 },
{ "bq27510g1", BQ27510G1 }, { "bq27510g1", BQ27510G1 },
{ "bq27510g2", BQ27510G2 }, { "bq27510g2", BQ27510G2 },
...@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = { ...@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27520g3", BQ27520G3 }, { "bq27520g3", BQ27520G3 },
{ "bq27520g4", BQ27520G4 }, { "bq27520g4", BQ27520G4 },
{ "bq27530", BQ27530 }, { "bq27530", BQ27530 },
{ "bq27531", BQ27530 }, { "bq27531", BQ27531 },
{ "bq27541", BQ27541 }, { "bq27541", BQ27541 },
{ "bq27542", BQ27541 }, { "bq27542", BQ27542 },
{ "bq27546", BQ27541 }, { "bq27546", BQ27546 },
{ "bq27742", BQ27541 }, { "bq27742", BQ27742 },
{ "bq27545", BQ27545 }, { "bq27545", BQ27545 },
{ "bq27421", BQ27421 }, { "bq27421", BQ27421 },
{ "bq27425", BQ27421 }, { "bq27425", BQ27425 },
{ "bq27441", BQ27421 }, { "bq27441", BQ27441 },
{ "bq27621", BQ27421 }, { "bq27621", BQ27621 },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table); MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
......
...@@ -1632,8 +1632,7 @@ static int charger_manager_probe(struct platform_device *pdev) ...@@ -1632,8 +1632,7 @@ static int charger_manager_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
cm = devm_kzalloc(&pdev->dev, cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL);
sizeof(struct charger_manager), GFP_KERNEL);
if (!cm) if (!cm)
return -ENOMEM; return -ENOMEM;
...@@ -1645,12 +1644,14 @@ static int charger_manager_probe(struct platform_device *pdev) ...@@ -1645,12 +1644,14 @@ static int charger_manager_probe(struct platform_device *pdev)
/* Initialize alarm timer */ /* Initialize alarm timer */
if (alarmtimer_get_rtcdev()) { if (alarmtimer_get_rtcdev()) {
cm_timer = devm_kzalloc(cm->dev, sizeof(*cm_timer), GFP_KERNEL); cm_timer = devm_kzalloc(cm->dev, sizeof(*cm_timer), GFP_KERNEL);
if (!cm_timer)
return -ENOMEM;
alarm_init(cm_timer, ALARM_BOOTTIME, cm_timer_func); alarm_init(cm_timer, ALARM_BOOTTIME, cm_timer_func);
} }
/* /*
* The following two do not need to be errors. * Some of the following do not need to be errors.
* Users may intentionally ignore those two features. * Users may intentionally ignore those features.
*/ */
if (desc->fullbatt_uV == 0) { if (desc->fullbatt_uV == 0) {
dev_info(&pdev->dev, "Ignoring full-battery voltage threshold as it is not supplied\n"); dev_info(&pdev->dev, "Ignoring full-battery voltage threshold as it is not supplied\n");
......
...@@ -663,7 +663,7 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp, ...@@ -663,7 +663,7 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
return count; return count;
} }
static struct bin_attribute ds2780_param_eeprom_bin_attr = { static const struct bin_attribute ds2780_param_eeprom_bin_attr = {
.attr = { .attr = {
.name = "param_eeprom", .name = "param_eeprom",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
...@@ -708,7 +708,7 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp, ...@@ -708,7 +708,7 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
return count; return count;
} }
static struct bin_attribute ds2780_user_eeprom_bin_attr = { static const struct bin_attribute ds2780_user_eeprom_bin_attr = {
.attr = { .attr = {
.name = "user_eeprom", .name = "user_eeprom",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
......
...@@ -665,7 +665,7 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp, ...@@ -665,7 +665,7 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp,
return count; return count;
} }
static struct bin_attribute ds2781_param_eeprom_bin_attr = { static const struct bin_attribute ds2781_param_eeprom_bin_attr = {
.attr = { .attr = {
.name = "param_eeprom", .name = "param_eeprom",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
...@@ -711,7 +711,7 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp, ...@@ -711,7 +711,7 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp,
return count; return count;
} }
static struct bin_attribute ds2781_user_eeprom_bin_attr = { static const struct bin_attribute ds2781_user_eeprom_bin_attr = {
.attr = { .attr = {
.name = "user_eeprom", .name = "user_eeprom",
.mode = S_IRUGO | S_IWUSR, .mode = S_IRUGO | S_IWUSR,
......
...@@ -626,7 +626,7 @@ static ssize_t lp8788_show_charger_status(struct device *dev, ...@@ -626,7 +626,7 @@ static ssize_t lp8788_show_charger_status(struct device *dev,
{ {
struct lp8788_charger *pchg = dev_get_drvdata(dev); struct lp8788_charger *pchg = dev_get_drvdata(dev);
enum lp8788_charging_state state; enum lp8788_charging_state state;
char *desc[LP8788_MAX_CHG_STATE] = { static const char * const desc[LP8788_MAX_CHG_STATE] = {
[LP8788_OFF] = "CHARGER OFF", [LP8788_OFF] = "CHARGER OFF",
[LP8788_WARM_UP] = "WARM UP", [LP8788_WARM_UP] = "WARM UP",
[LP8788_LOW_INPUT] = "LOW INPUT STATE", [LP8788_LOW_INPUT] = "LOW INPUT STATE",
...@@ -650,8 +650,10 @@ static ssize_t lp8788_show_eoc_time(struct device *dev, ...@@ -650,8 +650,10 @@ static ssize_t lp8788_show_eoc_time(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct lp8788_charger *pchg = dev_get_drvdata(dev); struct lp8788_charger *pchg = dev_get_drvdata(dev);
char *stime[] = { "400ms", "5min", "10min", "15min", static const char * const stime[] = {
"20min", "25min", "30min", "No timeout" }; "400ms", "5min", "10min", "15min",
"20min", "25min", "30min", "No timeout"
};
u8 val; u8 val;
lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val); lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
...@@ -665,9 +667,13 @@ static ssize_t lp8788_show_eoc_level(struct device *dev, ...@@ -665,9 +667,13 @@ static ssize_t lp8788_show_eoc_level(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct lp8788_charger *pchg = dev_get_drvdata(dev); struct lp8788_charger *pchg = dev_get_drvdata(dev);
char *abs_level[] = { "25mA", "49mA", "75mA", "98mA" }; static const char * const abs_level[] = {
char *relative_level[] = { "5%", "10%", "15%", "20%" }; "25mA", "49mA", "75mA", "98mA"
char *level; };
static const char * const relative_level[] = {
"5%", "10%", "15%", "20%"
};
const char *level;
u8 val; u8 val;
u8 mode; u8 mode;
......
/* /*
* I2C client/driver for the Linear Technology LTC2941 and LTC2943 * I2C client/driver for the Linear Technology LTC2941, LTC2942, LTC2943
* Battery Gas Gauge IC * and LTC2944 Battery Gas Gauge IC
* *
* Copyright (C) 2014 Topic Embedded Systems * Copyright (C) 2014 Topic Embedded Systems
* *
...@@ -34,35 +34,39 @@ enum ltc294x_reg { ...@@ -34,35 +34,39 @@ enum ltc294x_reg {
LTC294X_REG_CONTROL = 0x01, LTC294X_REG_CONTROL = 0x01,
LTC294X_REG_ACC_CHARGE_MSB = 0x02, LTC294X_REG_ACC_CHARGE_MSB = 0x02,
LTC294X_REG_ACC_CHARGE_LSB = 0x03, LTC294X_REG_ACC_CHARGE_LSB = 0x03,
LTC294X_REG_THRESH_HIGH_MSB = 0x04, LTC294X_REG_VOLTAGE_MSB = 0x08,
LTC294X_REG_THRESH_HIGH_LSB = 0x05, LTC294X_REG_VOLTAGE_LSB = 0x09,
LTC294X_REG_THRESH_LOW_MSB = 0x06, LTC2942_REG_TEMPERATURE_MSB = 0x0C,
LTC294X_REG_THRESH_LOW_LSB = 0x07, LTC2942_REG_TEMPERATURE_LSB = 0x0D,
LTC294X_REG_VOLTAGE_MSB = 0x08, LTC2943_REG_CURRENT_MSB = 0x0E,
LTC294X_REG_VOLTAGE_LSB = 0x09, LTC2943_REG_CURRENT_LSB = 0x0F,
LTC294X_REG_CURRENT_MSB = 0x0E, LTC2943_REG_TEMPERATURE_MSB = 0x14,
LTC294X_REG_CURRENT_LSB = 0x0F, LTC2943_REG_TEMPERATURE_LSB = 0x15,
LTC294X_REG_TEMPERATURE_MSB = 0x14,
LTC294X_REG_TEMPERATURE_LSB = 0x15,
}; };
#define LTC2943_REG_CONTROL_MODE_MASK (BIT(7) | BIT(6)) enum ltc294x_id {
#define LTC2943_REG_CONTROL_MODE_SCAN BIT(7) LTC2941_ID,
LTC2942_ID,
LTC2943_ID,
LTC2944_ID,
};
#define LTC2941_REG_STATUS_CHIP_ID BIT(7)
#define LTC2942_REG_CONTROL_MODE_SCAN (BIT(7) | BIT(6))
#define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
#define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3)) #define LTC294X_REG_CONTROL_PRESCALER_MASK (BIT(5) | BIT(4) | BIT(3))
#define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0)) #define LTC294X_REG_CONTROL_SHUTDOWN_MASK (BIT(0))
#define LTC294X_REG_CONTROL_PRESCALER_SET(x) \ #define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK) ((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK)
#define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0 #define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0
#define LTC2941_NUM_REGS 0x08
#define LTC2943_NUM_REGS 0x18
struct ltc294x_info { struct ltc294x_info {
struct i2c_client *client; /* I2C Client pointer */ struct i2c_client *client; /* I2C Client pointer */
struct power_supply *supply; /* Supply pointer */ struct power_supply *supply; /* Supply pointer */
struct power_supply_desc supply_desc; /* Supply description */ struct power_supply_desc supply_desc; /* Supply description */
struct delayed_work work; /* Work scheduler */ struct delayed_work work; /* Work scheduler */
unsigned long num_regs; /* Number of registers (chip type) */ enum ltc294x_id id; /* Chip type */
int charge; /* Last charge register content */ int charge; /* Last charge register content */
int r_sense; /* mOhm */ int r_sense; /* mOhm */
int Qlsb; /* nAh */ int Qlsb; /* nAh */
...@@ -145,9 +149,18 @@ static int ltc294x_reset(const struct ltc294x_info *info, int prescaler_exp) ...@@ -145,9 +149,18 @@ static int ltc294x_reset(const struct ltc294x_info *info, int prescaler_exp)
control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) | control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) |
LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED; LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED;
/* Put the 2943 into "monitor" mode, so it measures every 10 sec */ /* Put device into "monitor" mode */
if (info->num_regs == LTC2943_NUM_REGS) switch (info->id) {
case LTC2942_ID: /* 2942 measures every 2 sec */
control |= LTC2942_REG_CONTROL_MODE_SCAN;
break;
case LTC2943_ID:
case LTC2944_ID: /* 2943 and 2944 measure every 10 sec */
control |= LTC2943_REG_CONTROL_MODE_SCAN; control |= LTC2943_REG_CONTROL_MODE_SCAN;
break;
default:
break;
}
if (value != control) { if (value != control) {
ret = ltc294x_write_regs(info->client, ret = ltc294x_write_regs(info->client,
...@@ -252,7 +265,24 @@ static int ltc294x_get_voltage(const struct ltc294x_info *info, int *val) ...@@ -252,7 +265,24 @@ static int ltc294x_get_voltage(const struct ltc294x_info *info, int *val)
ret = ltc294x_read_regs(info->client, ret = ltc294x_read_regs(info->client,
LTC294X_REG_VOLTAGE_MSB, &datar[0], 2); LTC294X_REG_VOLTAGE_MSB, &datar[0], 2);
value = (datar[0] << 8) | datar[1]; value = (datar[0] << 8) | datar[1];
*val = ((value * 23600) / 0xFFFF) * 1000; /* in uV */ switch (info->id) {
case LTC2943_ID:
value *= 23600 * 2;
value /= 0xFFFF;
value *= 1000 / 2;
break;
case LTC2944_ID:
value *= 70800 / 5*4;
value /= 0xFFFF;
value *= 1000 * 5/4;
break;
default:
value *= 6000 * 10;
value /= 0xFFFF;
value *= 1000 / 10;
break;
}
*val = value;
return ret; return ret;
} }
...@@ -263,27 +293,38 @@ static int ltc294x_get_current(const struct ltc294x_info *info, int *val) ...@@ -263,27 +293,38 @@ static int ltc294x_get_current(const struct ltc294x_info *info, int *val)
s32 value; s32 value;
ret = ltc294x_read_regs(info->client, ret = ltc294x_read_regs(info->client,
LTC294X_REG_CURRENT_MSB, &datar[0], 2); LTC2943_REG_CURRENT_MSB, &datar[0], 2);
value = (datar[0] << 8) | datar[1]; value = (datar[0] << 8) | datar[1];
value -= 0x7FFF; value -= 0x7FFF;
if (info->id == LTC2944_ID)
value *= 64000;
else
value *= 60000;
/* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm, /* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
* the formula below keeps everything in s32 range while preserving * the formula below keeps everything in s32 range while preserving
* enough digits */ * enough digits */
*val = 1000 * ((60000 * value) / (info->r_sense * 0x7FFF)); /* in uA */ *val = 1000 * (value / (info->r_sense * 0x7FFF)); /* in uA */
return ret; return ret;
} }
static int ltc294x_get_temperature(const struct ltc294x_info *info, int *val) static int ltc294x_get_temperature(const struct ltc294x_info *info, int *val)
{ {
enum ltc294x_reg reg;
int ret; int ret;
u8 datar[2]; u8 datar[2];
u32 value; u32 value;
ret = ltc294x_read_regs(info->client, if (info->id == LTC2942_ID) {
LTC294X_REG_TEMPERATURE_MSB, &datar[0], 2); reg = LTC2942_REG_TEMPERATURE_MSB;
value = (datar[0] << 8) | datar[1]; value = 60000; /* Full-scale is 600 Kelvin */
/* Full-scale is 510 Kelvin, convert to centidegrees */ } else {
*val = (((51000 * value) / 0xFFFF) - 27215); reg = LTC2943_REG_TEMPERATURE_MSB;
value = 51000; /* Full-scale is 510 Kelvin */
}
ret = ltc294x_read_regs(info->client, reg, &datar[0], 2);
value *= (datar[0] << 8) | datar[1];
/* Convert to centidegrees */
*val = value / 0xFFFF - 27215;
return ret; return ret;
} }
...@@ -357,8 +398,8 @@ static enum power_supply_property ltc294x_properties[] = { ...@@ -357,8 +398,8 @@ static enum power_supply_property ltc294x_properties[] = {
POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_CHARGE_COUNTER,
POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_CURRENT_NOW,
}; };
static int ltc294x_i2c_remove(struct i2c_client *client) static int ltc294x_i2c_remove(struct i2c_client *client)
...@@ -375,10 +416,11 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -375,10 +416,11 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
{ {
struct power_supply_config psy_cfg = {}; struct power_supply_config psy_cfg = {};
struct ltc294x_info *info; struct ltc294x_info *info;
struct device_node *np;
int ret; int ret;
u32 prescaler_exp; u32 prescaler_exp;
s32 r_sense; s32 r_sense;
struct device_node *np; u8 status;
info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (info == NULL) if (info == NULL)
...@@ -388,7 +430,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -388,7 +430,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
np = of_node_get(client->dev.of_node); np = of_node_get(client->dev.of_node);
info->num_regs = (unsigned long)of_device_get_match_data(&client->dev); info->id = (enum ltc294x_id)of_device_get_match_data(&client->dev);
info->supply_desc.name = np->name; info->supply_desc.name = np->name;
/* r_sense can be negative, when sense+ is connected to the battery /* r_sense can be negative, when sense+ is connected to the battery
...@@ -409,7 +451,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -409,7 +451,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
prescaler_exp = LTC2941_MAX_PRESCALER_EXP; prescaler_exp = LTC2941_MAX_PRESCALER_EXP;
} }
if (info->num_regs == LTC2943_NUM_REGS) { if (info->id == LTC2943_ID) {
if (prescaler_exp > LTC2943_MAX_PRESCALER_EXP) if (prescaler_exp > LTC2943_MAX_PRESCALER_EXP)
prescaler_exp = LTC2943_MAX_PRESCALER_EXP; prescaler_exp = LTC2943_MAX_PRESCALER_EXP;
info->Qlsb = ((340 * 50000) / r_sense) / info->Qlsb = ((340 * 50000) / r_sense) /
...@@ -421,21 +463,39 @@ static int ltc294x_i2c_probe(struct i2c_client *client, ...@@ -421,21 +463,39 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
(128 / (1 << prescaler_exp)); (128 / (1 << prescaler_exp));
} }
/* Read status register to check for LTC2942 */
if (info->id == LTC2941_ID || info->id == LTC2942_ID) {
ret = ltc294x_read_regs(client, LTC294X_REG_STATUS, &status, 1);
if (ret < 0) {
dev_err(&client->dev,
"Could not read status register\n");
return ret;
}
if (status & LTC2941_REG_STATUS_CHIP_ID)
info->id = LTC2941_ID;
else
info->id = LTC2942_ID;
}
info->client = client; info->client = client;
info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY; info->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY;
info->supply_desc.properties = ltc294x_properties; info->supply_desc.properties = ltc294x_properties;
if (info->num_regs >= LTC294X_REG_TEMPERATURE_LSB) switch (info->id) {
case LTC2944_ID:
case LTC2943_ID:
info->supply_desc.num_properties = info->supply_desc.num_properties =
ARRAY_SIZE(ltc294x_properties); ARRAY_SIZE(ltc294x_properties);
else if (info->num_regs >= LTC294X_REG_CURRENT_LSB) break;
case LTC2942_ID:
info->supply_desc.num_properties = info->supply_desc.num_properties =
ARRAY_SIZE(ltc294x_properties) - 1; ARRAY_SIZE(ltc294x_properties) - 1;
else if (info->num_regs >= LTC294X_REG_VOLTAGE_LSB) break;
info->supply_desc.num_properties = case LTC2941_ID:
ARRAY_SIZE(ltc294x_properties) - 2; default:
else
info->supply_desc.num_properties = info->supply_desc.num_properties =
ARRAY_SIZE(ltc294x_properties) - 3; ARRAY_SIZE(ltc294x_properties) - 3;
break;
}
info->supply_desc.get_property = ltc294x_get_property; info->supply_desc.get_property = ltc294x_get_property;
info->supply_desc.set_property = ltc294x_set_property; info->supply_desc.set_property = ltc294x_set_property;
info->supply_desc.property_is_writeable = ltc294x_property_is_writeable; info->supply_desc.property_is_writeable = ltc294x_property_is_writeable;
...@@ -492,8 +552,10 @@ static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops, ltc294x_suspend, ltc294x_resume); ...@@ -492,8 +552,10 @@ static SIMPLE_DEV_PM_OPS(ltc294x_pm_ops, ltc294x_suspend, ltc294x_resume);
static const struct i2c_device_id ltc294x_i2c_id[] = { static const struct i2c_device_id ltc294x_i2c_id[] = {
{"ltc2941", LTC2941_NUM_REGS}, { "ltc2941", LTC2941_ID, },
{"ltc2943", LTC2943_NUM_REGS}, { "ltc2942", LTC2942_ID, },
{ "ltc2943", LTC2943_ID, },
{ "ltc2944", LTC2944_ID, },
{ }, { },
}; };
MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id); MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id);
...@@ -501,11 +563,19 @@ MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id); ...@@ -501,11 +563,19 @@ MODULE_DEVICE_TABLE(i2c, ltc294x_i2c_id);
static const struct of_device_id ltc294x_i2c_of_match[] = { static const struct of_device_id ltc294x_i2c_of_match[] = {
{ {
.compatible = "lltc,ltc2941", .compatible = "lltc,ltc2941",
.data = (void *)LTC2941_NUM_REGS .data = (void *)LTC2941_ID,
},
{
.compatible = "lltc,ltc2942",
.data = (void *)LTC2942_ID,
}, },
{ {
.compatible = "lltc,ltc2943", .compatible = "lltc,ltc2943",
.data = (void *)LTC2943_NUM_REGS .data = (void *)LTC2943_ID,
},
{
.compatible = "lltc,ltc2944",
.data = (void *)LTC2944_ID,
}, },
{ }, { },
}; };
...@@ -525,5 +595,5 @@ module_i2c_driver(ltc294x_driver); ...@@ -525,5 +595,5 @@ module_i2c_driver(ltc294x_driver);
MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems"); MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products"); MODULE_AUTHOR("Mike Looijmans, Topic Embedded Products");
MODULE_DESCRIPTION("LTC2941/LTC2943 Battery Gas Gauge IC driver"); MODULE_DESCRIPTION("LTC2941/LTC2942/LTC2943/LTC2944 Battery Gas Gauge IC driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* This driver is based on max17040_battery.c * This driver is based on max17040_battery.c
*/ */
#include <linux/acpi.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -982,6 +983,8 @@ static int max17042_probe(struct i2c_client *client, ...@@ -982,6 +983,8 @@ static int max17042_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
const struct power_supply_desc *max17042_desc = &max17042_psy_desc; const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
struct power_supply_config psy_cfg = {}; struct power_supply_config psy_cfg = {};
const struct acpi_device_id *acpi_id = NULL;
struct device *dev = &client->dev;
struct max17042_chip *chip; struct max17042_chip *chip;
int ret; int ret;
int i; int i;
...@@ -995,7 +998,15 @@ static int max17042_probe(struct i2c_client *client, ...@@ -995,7 +998,15 @@ static int max17042_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
chip->client = client; chip->client = client;
chip->chip_type = id->driver_data; if (id) {
chip->chip_type = id->driver_data;
} else {
acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!acpi_id)
return -ENODEV;
chip->chip_type = acpi_id->driver_data;
}
chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config); chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
if (IS_ERR(chip->regmap)) { if (IS_ERR(chip->regmap)) {
dev_err(&client->dev, "Failed to initialize regmap\n"); dev_err(&client->dev, "Failed to initialize regmap\n");
...@@ -1039,11 +1050,18 @@ static int max17042_probe(struct i2c_client *client, ...@@ -1039,11 +1050,18 @@ static int max17042_probe(struct i2c_client *client,
} }
if (client->irq) { if (client->irq) {
unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
/*
* On ACPI systems the IRQ may be handled by ACPI-event code,
* so we need to share (if the ACPI code is willing to share).
*/
if (acpi_id)
flags |= IRQF_SHARED | IRQF_PROBE_SHARED;
ret = devm_request_threaded_irq(&client->dev, client->irq, ret = devm_request_threaded_irq(&client->dev, client->irq,
NULL, NULL,
max17042_thread_handler, max17042_thread_handler, flags,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
chip->battery->desc->name, chip->battery->desc->name,
chip); chip);
if (!ret) { if (!ret) {
...@@ -1053,10 +1071,13 @@ static int max17042_probe(struct i2c_client *client, ...@@ -1053,10 +1071,13 @@ static int max17042_probe(struct i2c_client *client,
max17042_set_soc_threshold(chip, 1); max17042_set_soc_threshold(chip, 1);
} else { } else {
client->irq = 0; client->irq = 0;
dev_err(&client->dev, "%s(): cannot get IRQ\n", if (ret != -EBUSY)
__func__); dev_err(&client->dev, "Failed to get IRQ\n");
} }
} }
/* Not able to update the charge threshold when exceeded? -> disable */
if (!client->irq)
regmap_write(chip->regmap, MAX17042_SALRT_Th, 0xff00);
regmap_read(chip->regmap, MAX17042_STATUS, &val); regmap_read(chip->regmap, MAX17042_STATUS, &val);
if (val & STATUS_POR_BIT) { if (val & STATUS_POR_BIT) {
...@@ -1104,6 +1125,14 @@ static int max17042_resume(struct device *dev) ...@@ -1104,6 +1125,14 @@ static int max17042_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend, static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
max17042_resume); max17042_resume);
#ifdef CONFIG_ACPI
static const struct acpi_device_id max17042_acpi_match[] = {
{ "MAX17047", MAXIM_DEVICE_TYPE_MAX17047 },
{ }
};
MODULE_DEVICE_TABLE(acpi, max17042_acpi_match);
#endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
static const struct of_device_id max17042_dt_match[] = { static const struct of_device_id max17042_dt_match[] = {
{ .compatible = "maxim,max17042" }, { .compatible = "maxim,max17042" },
...@@ -1125,6 +1154,7 @@ MODULE_DEVICE_TABLE(i2c, max17042_id); ...@@ -1125,6 +1154,7 @@ MODULE_DEVICE_TABLE(i2c, max17042_id);
static struct i2c_driver max17042_i2c_driver = { static struct i2c_driver max17042_i2c_driver = {
.driver = { .driver = {
.name = "max17042", .name = "max17042",
.acpi_match_table = ACPI_PTR(max17042_acpi_match),
.of_match_table = of_match_ptr(max17042_dt_match), .of_match_table = of_match_ptr(max17042_dt_match),
.pm = &max17042_pm_ops, .pm = &max17042_pm_ops,
}, },
......
This diff is collapsed.
...@@ -535,7 +535,7 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj, ...@@ -535,7 +535,7 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj,
return count; return count;
} }
static struct bin_attribute olpc_bat_eeprom = { static const struct bin_attribute olpc_bat_eeprom = {
.attr = { .attr = {
.name = "eeprom", .name = "eeprom",
.mode = S_IRUGO, .mode = S_IRUGO,
...@@ -559,7 +559,7 @@ static ssize_t olpc_bat_error_read(struct device *dev, ...@@ -559,7 +559,7 @@ static ssize_t olpc_bat_error_read(struct device *dev,
return sprintf(buf, "%d\n", ec_byte); return sprintf(buf, "%d\n", ec_byte);
} }
static struct device_attribute olpc_bat_error = { static const struct device_attribute olpc_bat_error = {
.attr = { .attr = {
.name = "error", .name = "error",
.mode = S_IRUGO, .mode = S_IRUGO,
......
...@@ -254,7 +254,7 @@ static struct attribute *pcf50633_mbc_sysfs_entries[] = { ...@@ -254,7 +254,7 @@ static struct attribute *pcf50633_mbc_sysfs_entries[] = {
NULL, NULL,
}; };
static struct attribute_group mbc_attr_group = { static const struct attribute_group mbc_attr_group = {
.name = NULL, /* put in device directory */ .name = NULL, /* put in device directory */
.attrs = pcf50633_mbc_sysfs_entries, .attrs = pcf50633_mbc_sysfs_entries,
}; };
......
...@@ -259,18 +259,14 @@ static int power_supply_check_supplies(struct power_supply *psy) ...@@ -259,18 +259,14 @@ static int power_supply_check_supplies(struct power_supply *psy)
/* All supplies found, allocate char ** array for filling */ /* All supplies found, allocate char ** array for filling */
psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(psy->supplied_from), psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(psy->supplied_from),
GFP_KERNEL); GFP_KERNEL);
if (!psy->supplied_from) { if (!psy->supplied_from)
dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
return -ENOMEM; return -ENOMEM;
}
*psy->supplied_from = devm_kzalloc(&psy->dev, *psy->supplied_from = devm_kzalloc(&psy->dev,
sizeof(char *) * (cnt - 1), sizeof(char *) * (cnt - 1),
GFP_KERNEL); GFP_KERNEL);
if (!*psy->supplied_from) { if (!*psy->supplied_from)
dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
return -ENOMEM; return -ENOMEM;
}
return power_supply_populate_supplied_from(psy); return power_supply_populate_supplied_from(psy);
} }
...@@ -314,11 +310,12 @@ static int __power_supply_am_i_supplied(struct device *dev, void *_data) ...@@ -314,11 +310,12 @@ static int __power_supply_am_i_supplied(struct device *dev, void *_data)
struct power_supply *epsy = dev_get_drvdata(dev); struct power_supply *epsy = dev_get_drvdata(dev);
struct psy_am_i_supplied_data *data = _data; struct psy_am_i_supplied_data *data = _data;
data->count++; if (__power_supply_is_supplied_by(epsy, data->psy)) {
if (__power_supply_is_supplied_by(epsy, data->psy)) data->count++;
if (!epsy->desc->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, if (!epsy->desc->get_property(epsy, POWER_SUPPLY_PROP_ONLINE,
&ret)) &ret))
return ret.intval; return ret.intval;
}
return 0; return 0;
} }
...@@ -374,6 +371,47 @@ int power_supply_is_system_supplied(void) ...@@ -374,6 +371,47 @@ int power_supply_is_system_supplied(void)
} }
EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
static int __power_supply_get_supplier_max_current(struct device *dev,
void *data)
{
union power_supply_propval ret = {0,};
struct power_supply *epsy = dev_get_drvdata(dev);
struct power_supply *psy = data;
if (__power_supply_is_supplied_by(epsy, psy))
if (!epsy->desc->get_property(epsy,
POWER_SUPPLY_PROP_CURRENT_MAX,
&ret))
return ret.intval;
return 0;
}
int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy)
{
union power_supply_propval val = {0,};
int curr;
if (!psy->desc->set_property)
return -EINVAL;
/*
* This function is not intended for use with a supply with multiple
* suppliers, we simply pick the first supply to report a non 0
* max-current.
*/
curr = class_for_each_device(power_supply_class, NULL, psy,
__power_supply_get_supplier_max_current);
if (curr <= 0)
return (curr == 0) ? -ENODEV : curr;
val.intval = curr;
return psy->desc->set_property(psy,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
}
EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier);
int power_supply_set_battery_charged(struct power_supply *psy) int power_supply_set_battery_charged(struct power_supply *psy)
{ {
if (atomic_read(&psy->use_cnt) >= 0 && if (atomic_read(&psy->use_cnt) >= 0 &&
......
...@@ -12,25 +12,21 @@ ...@@ -12,25 +12,21 @@
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include <linux/init.h> #include <linux/delay.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/power_supply.h> #include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/slab.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/gpio/consumer.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/stat.h>
#include <linux/power/sbs-battery.h> #include <linux/power/sbs-battery.h>
#include <linux/power_supply.h>
#include <linux/slab.h>
#include <linux/stat.h>
enum { enum {
REG_MANUFACTURER_DATA, REG_MANUFACTURER_DATA,
...@@ -60,8 +56,8 @@ enum { ...@@ -60,8 +56,8 @@ enum {
#define BATTERY_MODE_OFFSET 0x03 #define BATTERY_MODE_OFFSET 0x03
#define BATTERY_MODE_MASK 0x8000 #define BATTERY_MODE_MASK 0x8000
enum sbs_battery_mode { enum sbs_battery_mode {
BATTERY_MODE_AMPS, BATTERY_MODE_AMPS = 0,
BATTERY_MODE_WATTS BATTERY_MODE_WATTS = 0x8000
}; };
/* manufacturer access defines */ /* manufacturer access defines */
...@@ -532,6 +528,8 @@ static enum sbs_battery_mode sbs_set_battery_mode(struct i2c_client *client, ...@@ -532,6 +528,8 @@ static enum sbs_battery_mode sbs_set_battery_mode(struct i2c_client *client,
if (ret < 0) if (ret < 0)
return ret; return ret;
usleep_range(1000, 2000);
return original_val & BATTERY_MODE_MASK; return original_val & BATTERY_MODE_MASK;
} }
......
...@@ -148,10 +148,4 @@ config W1_SLAVE_DS28E04 ...@@ -148,10 +148,4 @@ config W1_SLAVE_DS28E04
If you are unsure, say N. If you are unsure, say N.
config W1_SLAVE_BQ27000
tristate "BQ27000 slave support"
help
Say Y here if you want to use a hdq
bq27000 slave support.
endmenu endmenu
...@@ -16,5 +16,4 @@ obj-$(CONFIG_W1_SLAVE_DS2438) += w1_ds2438.o ...@@ -16,5 +16,4 @@ obj-$(CONFIG_W1_SLAVE_DS2438) += w1_ds2438.o
obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o
obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o obj-$(CONFIG_W1_SLAVE_DS2780) += w1_ds2780.o
obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o obj-$(CONFIG_W1_SLAVE_DS2781) += w1_ds2781.o
obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o
obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o
/*
* drivers/w1/slaves/w1_bq27000.c
*
* Copyright (C) 2007 Texas Instruments, Inc.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/power/bq27xxx_battery.h>
#include <linux/w1.h>
#define W1_FAMILY_BQ27000 0x01
#define HDQ_CMD_READ (0)
#define HDQ_CMD_WRITE (1<<7)
static int F_ID;
module_param(F_ID, int, S_IRUSR);
MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device");
static int w1_bq27000_read(struct device *dev, unsigned int reg)
{
u8 val;
struct w1_slave *sl = container_of(dev->parent, struct w1_slave, dev);
mutex_lock(&sl->master->bus_mutex);
w1_write_8(sl->master, HDQ_CMD_READ | reg);
val = w1_read_8(sl->master);
mutex_unlock(&sl->master->bus_mutex);
return val;
}
static struct bq27xxx_platform_data bq27000_battery_info = {
.read = w1_bq27000_read,
.name = "bq27000-battery",
.chip = BQ27000,
};
static int w1_bq27000_add_slave(struct w1_slave *sl)
{
int ret;
struct platform_device *pdev;
pdev = platform_device_alloc("bq27000-battery", -1);
if (!pdev) {
ret = -ENOMEM;
return ret;
}
ret = platform_device_add_data(pdev,
&bq27000_battery_info,
sizeof(bq27000_battery_info));
if (ret)
goto pdev_add_failed;
pdev->dev.parent = &sl->dev;
ret = platform_device_add(pdev);
if (ret)
goto pdev_add_failed;
dev_set_drvdata(&sl->dev, pdev);
goto success;
pdev_add_failed:
platform_device_put(pdev);
success:
return ret;
}
static void w1_bq27000_remove_slave(struct w1_slave *sl)
{
struct platform_device *pdev = dev_get_drvdata(&sl->dev);
platform_device_unregister(pdev);
}
static struct w1_family_ops w1_bq27000_fops = {
.add_slave = w1_bq27000_add_slave,
.remove_slave = w1_bq27000_remove_slave,
};
static struct w1_family w1_bq27000_family = {
.fid = W1_FAMILY_BQ27000,
.fops = &w1_bq27000_fops,
};
static int __init w1_bq27000_init(void)
{
if (F_ID)
w1_bq27000_family.fid = F_ID;
return w1_register_family(&w1_bq27000_family);
}
static void __exit w1_bq27000_exit(void)
{
w1_unregister_family(&w1_bq27000_family);
}
module_init(w1_bq27000_init);
module_exit(w1_bq27000_exit);
MODULE_AUTHOR("Texas Instruments Ltd");
MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip");
MODULE_LICENSE("GPL");
MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000));
/*
* Platform data for the TI bq24190 battery charger driver.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _BQ24190_CHARGER_H_
#define _BQ24190_CHARGER_H_
#include <linux/regulator/machine.h>
struct bq24190_platform_data {
const struct regulator_init_data *regulator_init_data;
};
#endif
...@@ -6,6 +6,7 @@ enum bq27xxx_chip { ...@@ -6,6 +6,7 @@ enum bq27xxx_chip {
BQ27010, /* bq27010, bq27210 */ BQ27010, /* bq27010, bq27210 */
BQ2750X, /* bq27500 deprecated alias */ BQ2750X, /* bq27500 deprecated alias */
BQ2751X, /* bq27510, bq27520 deprecated alias */ BQ2751X, /* bq27510, bq27520 deprecated alias */
BQ2752X,
BQ27500, /* bq27500/1 */ BQ27500, /* bq27500/1 */
BQ27510G1, /* bq27510G1 */ BQ27510G1, /* bq27510G1 */
BQ27510G2, /* bq27510G2 */ BQ27510G2, /* bq27510G2 */
...@@ -15,26 +16,16 @@ enum bq27xxx_chip { ...@@ -15,26 +16,16 @@ enum bq27xxx_chip {
BQ27520G3, /* bq27520G3 */ BQ27520G3, /* bq27520G3 */
BQ27520G4, /* bq27520G4 */ BQ27520G4, /* bq27520G4 */
BQ27530, /* bq27530, bq27531 */ BQ27530, /* bq27530, bq27531 */
BQ27531,
BQ27541, /* bq27541, bq27542, bq27546, bq27742 */ BQ27541, /* bq27541, bq27542, bq27546, bq27742 */
BQ27542,
BQ27546,
BQ27742,
BQ27545, /* bq27545 */ BQ27545, /* bq27545 */
BQ27421, /* bq27421, bq27425, bq27441, bq27621 */ BQ27421, /* bq27421, bq27425, bq27441, bq27621 */
}; BQ27425,
BQ27441,
/** BQ27621,
* struct bq27xxx_plaform_data - Platform data for bq27xxx devices
* @name: Name of the battery.
* @chip: Chip class number of this device.
* @read: HDQ read callback.
* This function should provide access to the HDQ bus the battery is
* connected to.
* The first parameter is a pointer to the battery device, the second the
* register to be read. The return value should either be the content of
* the passed register or an error value.
*/
struct bq27xxx_platform_data {
const char *name;
enum bq27xxx_chip chip;
int (*read)(struct device *dev, unsigned int);
}; };
struct bq27xxx_device_info; struct bq27xxx_device_info;
...@@ -63,7 +54,7 @@ struct bq27xxx_device_info { ...@@ -63,7 +54,7 @@ struct bq27xxx_device_info {
struct device *dev; struct device *dev;
int id; int id;
enum bq27xxx_chip chip; enum bq27xxx_chip chip;
bool ram_chip; u32 opts;
const char *name; const char *name;
struct bq27xxx_dm_reg *dm_regs; struct bq27xxx_dm_reg *dm_regs;
u32 unseal_key; u32 unseal_key;
......
...@@ -332,6 +332,8 @@ extern int power_supply_get_battery_info(struct power_supply *psy, ...@@ -332,6 +332,8 @@ extern int power_supply_get_battery_info(struct power_supply *psy,
struct power_supply_battery_info *info); struct power_supply_battery_info *info);
extern void power_supply_changed(struct power_supply *psy); extern void power_supply_changed(struct power_supply *psy);
extern int power_supply_am_i_supplied(struct power_supply *psy); extern int power_supply_am_i_supplied(struct power_supply *psy);
extern int power_supply_set_input_current_limit_from_supplier(
struct power_supply *psy);
extern int power_supply_set_battery_charged(struct power_supply *psy); extern int power_supply_set_battery_charged(struct power_supply *psy);
#ifdef CONFIG_POWER_SUPPLY #ifdef CONFIG_POWER_SUPPLY
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment