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
  ...
This commit is contained in:
Linus Torvalds
2017-09-09 14:44:39 -07:00
27 changed files with 1492 additions and 659 deletions
@@ -0,0 +1,51 @@
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";
};
};
@@ -1,13 +1,14 @@
binding for LTC2941 and LTC2943 battery gauges
binding for LTC2941, LTC2942, LTC2943 and LTC2944 battery gauges
Both the LTC2941 and LTC2943 measure battery capacity.
The LTC2943 is compatible with the LTC2941, it adds voltage and
temperature monitoring, and uses a slightly different conversion
formula for the charge counter.
All chips measure battery capacity.
The LTC2942 is pin compatible with the LTC2941, it adds voltage and
temperature monitoring, and is runtime detected. LTC2943 and LTC2944
is software compatible, uses a slightly different conversion formula
for the charge counter and adds voltage, current and temperature monitoring.
Required properties:
- compatible: Should contain "lltc,ltc2941" or "lltc,ltc2943" which also
indicates the type of I2C chip attached.
- compatible: Should contain "lltc,ltc2941", "lltc,ltc2942", "lltc,ltc2943"
or "lltc,ltc2944" which also indicates the type of I2C chip attached.
- reg: The 7-bit I2C address.
- 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
+2 -2
View File
@@ -171,8 +171,8 @@ static u32 at91_shdwc_get_wakeup_input(struct platform_device *pdev,
for_each_child_of_node(np, cnp) {
if (of_property_read_u32(cnp, "reg", &wk_input)) {
dev_warn(&pdev->dev, "reg property is missing for %s\n",
cnp->full_name);
dev_warn(&pdev->dev, "reg property is missing for %pOF\n",
cnp);
continue;
}
+23
View File
@@ -198,6 +198,15 @@ config BATTERY_BQ27XXX_I2C
Say Y here to enable support for batteries with BQ27xxx chips
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
bool "BQ27xxx support for update of NVM/flash data memory"
depends on BATTERY_BQ27XXX_I2C
@@ -313,6 +322,19 @@ config BATTERY_MAX17042
with MAX17042. This driver also supports max17047/50 chips which are
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
tristate "Z2 battery driver"
depends on I2C && MACH_ZIPIT2
@@ -365,6 +387,7 @@ config BATTERY_RX51
config CHARGER_CPCAP
tristate "CPCAP PMIC Charger Driver"
depends on MFD_CPCAP && IIO
depends on OMAP_USB2 || (!OMAP_USB2 && COMPILE_TEST)
default MFD_CPCAP
help
Say Y to enable support for CPCAP PMIC charger driver for Motorola
+2
View File
@@ -38,12 +38,14 @@ obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_CHARGER_SBS) += sbs-charger.o
obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.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_DA9052) += da9052-battery.o
obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o
obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_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_RT5033) += rt5033_battery.o
obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o
+2 -2
View File
@@ -596,9 +596,9 @@ static int act8945a_charger_probe(struct platform_device *pdev)
return ret;
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");
return -EPROBE_DEFER;
return irq ?: -ENXIO;
}
ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+135
View File
@@ -0,0 +1,135 @@
/*
* 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));
+8 -8
View File
@@ -230,7 +230,7 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27210", BQ27010 },
{ "bq27500", BQ2750X },
{ "bq27510", BQ2751X },
{ "bq27520", BQ2751X },
{ "bq27520", BQ2752X },
{ "bq27500-1", BQ27500 },
{ "bq27510g1", BQ27510G1 },
{ "bq27510g2", BQ27510G2 },
@@ -240,16 +240,16 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27520g3", BQ27520G3 },
{ "bq27520g4", BQ27520G4 },
{ "bq27530", BQ27530 },
{ "bq27531", BQ27530 },
{ "bq27531", BQ27531 },
{ "bq27541", BQ27541 },
{ "bq27542", BQ27541 },
{ "bq27546", BQ27541 },
{ "bq27742", BQ27541 },
{ "bq27542", BQ27542 },
{ "bq27546", BQ27546 },
{ "bq27742", BQ27742 },
{ "bq27545", BQ27545 },
{ "bq27421", BQ27421 },
{ "bq27425", BQ27421 },
{ "bq27441", BQ27421 },
{ "bq27621", BQ27421 },
{ "bq27425", BQ27425 },
{ "bq27441", BQ27441 },
{ "bq27621", BQ27621 },
{},
};
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
+5 -4
View File
@@ -1632,8 +1632,7 @@ static int charger_manager_probe(struct platform_device *pdev)
return -ENODEV;
}
cm = devm_kzalloc(&pdev->dev,
sizeof(struct charger_manager), GFP_KERNEL);
cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL);
if (!cm)
return -ENOMEM;
@@ -1645,12 +1644,14 @@ static int charger_manager_probe(struct platform_device *pdev)
/* Initialize alarm timer */
if (alarmtimer_get_rtcdev()) {
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);
}
/*
* The following two do not need to be errors.
* Users may intentionally ignore those two features.
* Some of the following do not need to be errors.
* Users may intentionally ignore those features.
*/
if (desc->fullbatt_uV == 0) {
dev_info(&pdev->dev, "Ignoring full-battery voltage threshold as it is not supplied\n");
+2 -2
View File
@@ -663,7 +663,7 @@ static ssize_t ds2780_write_param_eeprom_bin(struct file *filp,
return count;
}
static struct bin_attribute ds2780_param_eeprom_bin_attr = {
static const struct bin_attribute ds2780_param_eeprom_bin_attr = {
.attr = {
.name = "param_eeprom",
.mode = S_IRUGO | S_IWUSR,
@@ -708,7 +708,7 @@ static ssize_t ds2780_write_user_eeprom_bin(struct file *filp,
return count;
}
static struct bin_attribute ds2780_user_eeprom_bin_attr = {
static const struct bin_attribute ds2780_user_eeprom_bin_attr = {
.attr = {
.name = "user_eeprom",
.mode = S_IRUGO | S_IWUSR,
+2 -2
View File
@@ -665,7 +665,7 @@ static ssize_t ds2781_write_param_eeprom_bin(struct file *filp,
return count;
}
static struct bin_attribute ds2781_param_eeprom_bin_attr = {
static const struct bin_attribute ds2781_param_eeprom_bin_attr = {
.attr = {
.name = "param_eeprom",
.mode = S_IRUGO | S_IWUSR,
@@ -711,7 +711,7 @@ static ssize_t ds2781_write_user_eeprom_bin(struct file *filp,
return count;
}
static struct bin_attribute ds2781_user_eeprom_bin_attr = {
static const struct bin_attribute ds2781_user_eeprom_bin_attr = {
.attr = {
.name = "user_eeprom",
.mode = S_IRUGO | S_IWUSR,
+12 -6
View File
@@ -626,7 +626,7 @@ static ssize_t lp8788_show_charger_status(struct device *dev,
{
struct lp8788_charger *pchg = dev_get_drvdata(dev);
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_WARM_UP] = "WARM UP",
[LP8788_LOW_INPUT] = "LOW INPUT STATE",
@@ -650,8 +650,10 @@ static ssize_t lp8788_show_eoc_time(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lp8788_charger *pchg = dev_get_drvdata(dev);
char *stime[] = { "400ms", "5min", "10min", "15min",
"20min", "25min", "30min", "No timeout" };
static const char * const stime[] = {
"400ms", "5min", "10min", "15min",
"20min", "25min", "30min", "No timeout"
};
u8 val;
lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val);
@@ -665,9 +667,13 @@ static ssize_t lp8788_show_eoc_level(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct lp8788_charger *pchg = dev_get_drvdata(dev);
char *abs_level[] = { "25mA", "49mA", "75mA", "98mA" };
char *relative_level[] = { "5%", "10%", "15%", "20%" };
char *level;
static const char * const abs_level[] = {
"25mA", "49mA", "75mA", "98mA"
};
static const char * const relative_level[] = {
"5%", "10%", "15%", "20%"
};
const char *level;
u8 val;
u8 mode;
+113 -43
View File
@@ -1,6 +1,6 @@
/*
* I2C client/driver for the Linear Technology LTC2941 and LTC2943
* Battery Gas Gauge IC
* I2C client/driver for the Linear Technology LTC2941, LTC2942, LTC2943
* and LTC2944 Battery Gas Gauge IC
*
* Copyright (C) 2014 Topic Embedded Systems
*
@@ -34,35 +34,39 @@ enum ltc294x_reg {
LTC294X_REG_CONTROL = 0x01,
LTC294X_REG_ACC_CHARGE_MSB = 0x02,
LTC294X_REG_ACC_CHARGE_LSB = 0x03,
LTC294X_REG_THRESH_HIGH_MSB = 0x04,
LTC294X_REG_THRESH_HIGH_LSB = 0x05,
LTC294X_REG_THRESH_LOW_MSB = 0x06,
LTC294X_REG_THRESH_LOW_LSB = 0x07,
LTC294X_REG_VOLTAGE_MSB = 0x08,
LTC294X_REG_VOLTAGE_LSB = 0x09,
LTC294X_REG_CURRENT_MSB = 0x0E,
LTC294X_REG_CURRENT_LSB = 0x0F,
LTC294X_REG_TEMPERATURE_MSB = 0x14,
LTC294X_REG_TEMPERATURE_LSB = 0x15,
LTC294X_REG_VOLTAGE_MSB = 0x08,
LTC294X_REG_VOLTAGE_LSB = 0x09,
LTC2942_REG_TEMPERATURE_MSB = 0x0C,
LTC2942_REG_TEMPERATURE_LSB = 0x0D,
LTC2943_REG_CURRENT_MSB = 0x0E,
LTC2943_REG_CURRENT_LSB = 0x0F,
LTC2943_REG_TEMPERATURE_MSB = 0x14,
LTC2943_REG_TEMPERATURE_LSB = 0x15,
};
#define LTC2943_REG_CONTROL_MODE_MASK (BIT(7) | BIT(6))
#define LTC2943_REG_CONTROL_MODE_SCAN BIT(7)
enum ltc294x_id {
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_SHUTDOWN_MASK (BIT(0))
#define LTC294X_REG_CONTROL_PRESCALER_SET(x) \
((x << 3) & LTC294X_REG_CONTROL_PRESCALER_MASK)
#define LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED 0
#define LTC2941_NUM_REGS 0x08
#define LTC2943_NUM_REGS 0x18
struct ltc294x_info {
struct i2c_client *client; /* I2C Client pointer */
struct power_supply *supply; /* Supply pointer */
struct power_supply_desc supply_desc; /* Supply description */
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 r_sense; /* mOhm */
int Qlsb; /* nAh */
@@ -145,9 +149,18 @@ static int ltc294x_reset(const struct ltc294x_info *info, int prescaler_exp)
control = LTC294X_REG_CONTROL_PRESCALER_SET(prescaler_exp) |
LTC294X_REG_CONTROL_ALCC_CONFIG_DISABLED;
/* Put the 2943 into "monitor" mode, so it measures every 10 sec */
if (info->num_regs == LTC2943_NUM_REGS)
/* Put device into "monitor" mode */
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;
break;
default:
break;
}
if (value != control) {
ret = ltc294x_write_regs(info->client,
@@ -252,7 +265,24 @@ static int ltc294x_get_voltage(const struct ltc294x_info *info, int *val)
ret = ltc294x_read_regs(info->client,
LTC294X_REG_VOLTAGE_MSB, &datar[0], 2);
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;
}
@@ -263,27 +293,38 @@ static int ltc294x_get_current(const struct ltc294x_info *info, int *val)
s32 value;
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 -= 0x7FFF;
if (info->id == LTC2944_ID)
value *= 64000;
else
value *= 60000;
/* Value is in range -32k..+32k, r_sense is usually 10..50 mOhm,
* the formula below keeps everything in s32 range while preserving
* enough digits */
*val = 1000 * ((60000 * value) / (info->r_sense * 0x7FFF)); /* in uA */
*val = 1000 * (value / (info->r_sense * 0x7FFF)); /* in uA */
return ret;
}
static int ltc294x_get_temperature(const struct ltc294x_info *info, int *val)
{
enum ltc294x_reg reg;
int ret;
u8 datar[2];
u32 value;
ret = ltc294x_read_regs(info->client,
LTC294X_REG_TEMPERATURE_MSB, &datar[0], 2);
value = (datar[0] << 8) | datar[1];
/* Full-scale is 510 Kelvin, convert to centidegrees */
*val = (((51000 * value) / 0xFFFF) - 27215);
if (info->id == LTC2942_ID) {
reg = LTC2942_REG_TEMPERATURE_MSB;
value = 60000; /* Full-scale is 600 Kelvin */
} else {
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;
}
@@ -357,8 +398,8 @@ static enum power_supply_property ltc294x_properties[] = {
POWER_SUPPLY_PROP_CHARGE_COUNTER,
POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_CURRENT_NOW,
};
static int ltc294x_i2c_remove(struct i2c_client *client)
@@ -375,10 +416,11 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
{
struct power_supply_config psy_cfg = {};
struct ltc294x_info *info;
struct device_node *np;
int ret;
u32 prescaler_exp;
s32 r_sense;
struct device_node *np;
u8 status;
info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
if (info == NULL)
@@ -388,7 +430,7 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
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;
/* 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,
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)
prescaler_exp = LTC2943_MAX_PRESCALER_EXP;
info->Qlsb = ((340 * 50000) / r_sense) /
@@ -421,21 +463,39 @@ static int ltc294x_i2c_probe(struct i2c_client *client,
(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->supply_desc.type = POWER_SUPPLY_TYPE_BATTERY;
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 =
ARRAY_SIZE(ltc294x_properties);
else if (info->num_regs >= LTC294X_REG_CURRENT_LSB)
break;
case LTC2942_ID:
info->supply_desc.num_properties =
ARRAY_SIZE(ltc294x_properties) - 1;
else if (info->num_regs >= LTC294X_REG_VOLTAGE_LSB)
info->supply_desc.num_properties =
ARRAY_SIZE(ltc294x_properties) - 2;
else
break;
case LTC2941_ID:
default:
info->supply_desc.num_properties =
ARRAY_SIZE(ltc294x_properties) - 3;
break;
}
info->supply_desc.get_property = ltc294x_get_property;
info->supply_desc.set_property = ltc294x_set_property;
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);
static const struct i2c_device_id ltc294x_i2c_id[] = {
{"ltc2941", LTC2941_NUM_REGS},
{"ltc2943", LTC2943_NUM_REGS},
{ "ltc2941", LTC2941_ID, },
{ "ltc2942", LTC2942_ID, },
{ "ltc2943", LTC2943_ID, },
{ "ltc2944", LTC2944_ID, },
{ },
};
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[] = {
{
.compatible = "lltc,ltc2941",
.data = (void *)LTC2941_NUM_REGS
.data = (void *)LTC2941_ID,
},
{
.compatible = "lltc,ltc2942",
.data = (void *)LTC2942_ID,
},
{
.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);
MODULE_AUTHOR("Auryn Verwegen, Topic Embedded Systems");
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");
+36 -6
View File
@@ -22,6 +22,7 @@
* This driver is based on max17040_battery.c
*/
#include <linux/acpi.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -982,6 +983,8 @@ static int max17042_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
struct power_supply_config psy_cfg = {};
const struct acpi_device_id *acpi_id = NULL;
struct device *dev = &client->dev;
struct max17042_chip *chip;
int ret;
int i;
@@ -995,7 +998,15 @@ static int max17042_probe(struct i2c_client *client,
return -ENOMEM;
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);
if (IS_ERR(chip->regmap)) {
dev_err(&client->dev, "Failed to initialize regmap\n");
@@ -1039,11 +1050,18 @@ static int max17042_probe(struct i2c_client *client,
}
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,
NULL,
max17042_thread_handler,
IRQF_TRIGGER_FALLING |
IRQF_ONESHOT,
max17042_thread_handler, flags,
chip->battery->desc->name,
chip);
if (!ret) {
@@ -1053,10 +1071,13 @@ static int max17042_probe(struct i2c_client *client,
max17042_set_soc_threshold(chip, 1);
} else {
client->irq = 0;
dev_err(&client->dev, "%s(): cannot get IRQ\n",
__func__);
if (ret != -EBUSY)
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);
if (val & STATUS_POR_BIT) {
@@ -1104,6 +1125,14 @@ static int max17042_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
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
static const struct of_device_id max17042_dt_match[] = {
{ .compatible = "maxim,max17042" },
@@ -1125,6 +1154,7 @@ MODULE_DEVICE_TABLE(i2c, max17042_id);
static struct i2c_driver max17042_i2c_driver = {
.driver = {
.name = "max17042",
.acpi_match_table = ACPI_PTR(max17042_acpi_match),
.of_match_table = of_match_ptr(max17042_dt_match),
.pm = &max17042_pm_ops,
},
+448
View File
@@ -0,0 +1,448 @@
/*
* 1-Wire implementation for Maxim Semiconductor
* MAX7211/MAX17215 stanalone fuel gauge chip
*
* Copyright (C) 2017 Radioavionica Corporation
* Author: Alex A. Mihaylov <minimumlaw@rambler.ru>
*
* Use consistent with the GNU GPL is permitted,
* provided that this copyright notice is
* preserved in its entirety in all copies and derived works.
*
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/w1.h>
#include <linux/regmap.h>
#include <linux/power_supply.h>
#define W1_MAX1721X_FAMILY_ID 0x26
#define DEF_DEV_NAME_MAX17211 "MAX17211"
#define DEF_DEV_NAME_MAX17215 "MAX17215"
#define DEF_DEV_NAME_UNKNOWN "UNKNOWN"
#define DEF_MFG_NAME "MAXIM"
#define PSY_MAX_NAME_LEN 32
/* Number of valid register addresses in W1 mode */
#define MAX1721X_MAX_REG_NR 0x1EF
/* Factory settings (nonvilatile registers) (W1 specific) */
#define MAX1721X_REG_NRSENSE 0x1CF /* RSense in 10^-5 Ohm */
/* Strings */
#define MAX1721X_REG_MFG_STR 0x1CC
#define MAX1721X_REG_MFG_NUMB 3
#define MAX1721X_REG_DEV_STR 0x1DB
#define MAX1721X_REG_DEV_NUMB 5
/* HEX Strings */
#define MAX1721X_REG_SER_HEX 0x1D8
/* MAX172XX Output Registers for W1 chips */
#define MAX172XX_REG_STATUS 0x000 /* status reg */
#define MAX172XX_BAT_PRESENT (1<<4) /* battery connected bit */
#define MAX172XX_REG_DEVNAME 0x021 /* chip config */
#define MAX172XX_DEV_MASK 0x000F /* chip type mask */
#define MAX172X1_DEV 0x0001
#define MAX172X5_DEV 0x0005
#define MAX172XX_REG_TEMP 0x008 /* Temperature */
#define MAX172XX_REG_BATT 0x0DA /* Battery voltage */
#define MAX172XX_REG_CURRENT 0x00A /* Actual current */
#define MAX172XX_REG_AVGCURRENT 0x00B /* Average current */
#define MAX172XX_REG_REPSOC 0x006 /* Percentage of charge */
#define MAX172XX_REG_DESIGNCAP 0x018 /* Design capacity */
#define MAX172XX_REG_REPCAP 0x005 /* Average capacity */
#define MAX172XX_REG_TTE 0x011 /* Time to empty */
#define MAX172XX_REG_TTF 0x020 /* Time to full */
struct max17211_device_info {
char name[PSY_MAX_NAME_LEN];
struct power_supply *bat;
struct power_supply_desc bat_desc;
struct device *w1_dev;
struct regmap *regmap;
/* battery design format */
unsigned int rsense; /* in tenths uOhm */
char DeviceName[2 * MAX1721X_REG_DEV_NUMB + 1];
char ManufacturerName[2 * MAX1721X_REG_MFG_NUMB + 1];
char SerialNumber[13]; /* see get_sn_str() later for comment */
};
/* Convert regs value to power_supply units */
static inline int max172xx_time_to_ps(unsigned int reg)
{
return reg * 5625 / 1000; /* in sec. */
}
static inline int max172xx_percent_to_ps(unsigned int reg)
{
return reg / 256; /* in percent from 0 to 100 */
}
static inline int max172xx_voltage_to_ps(unsigned int reg)
{
return reg * 1250; /* in uV */
}
static inline int max172xx_capacity_to_ps(unsigned int reg)
{
return reg * 500; /* in uAh */
}
/*
* Current and temperature is signed values, so unsigned regs
* value must be converted to signed type
*/
static inline int max172xx_temperature_to_ps(unsigned int reg)
{
int val = (int16_t)(reg);
return val * 10 / 256; /* in tenths of deg. C */
}
/*
* Calculating current registers resolution:
*
* RSense stored in 10^-5 Ohm, so mesaurment voltage must be
* in 10^-11 Volts for get current in uA.
* 16 bit current reg fullscale +/-51.2mV is 102400 uV.
* So: 102400 / 65535 * 10^5 = 156252
*/
static inline int max172xx_current_to_voltage(unsigned int reg)
{
int val = (int16_t)(reg);
return val * 156252;
}
static inline struct max17211_device_info *
to_device_info(struct power_supply *psy)
{
return power_supply_get_drvdata(psy);
}
static int max1721x_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct max17211_device_info *info = to_device_info(psy);
unsigned int reg = 0;
int ret = 0;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
/*
* POWER_SUPPLY_PROP_PRESENT will always readable via
* sysfs interface. Value return 0 if battery not
* present or unaccesable via W1.
*/
val->intval =
regmap_read(info->regmap, MAX172XX_REG_STATUS,
&reg) ? 0 : !(reg & MAX172XX_BAT_PRESENT);
break;
case POWER_SUPPLY_PROP_CAPACITY:
ret = regmap_read(info->regmap, MAX172XX_REG_REPSOC, &reg);
val->intval = max172xx_percent_to_ps(reg);
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
ret = regmap_read(info->regmap, MAX172XX_REG_BATT, &reg);
val->intval = max172xx_voltage_to_ps(reg);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
ret = regmap_read(info->regmap, MAX172XX_REG_DESIGNCAP, &reg);
val->intval = max172xx_capacity_to_ps(reg);
break;
case POWER_SUPPLY_PROP_CHARGE_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_REPCAP, &reg);
val->intval = max172xx_capacity_to_ps(reg);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_TTE, &reg);
val->intval = max172xx_time_to_ps(reg);
break;
case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_TTF, &reg);
val->intval = max172xx_time_to_ps(reg);
break;
case POWER_SUPPLY_PROP_TEMP:
ret = regmap_read(info->regmap, MAX172XX_REG_TEMP, &reg);
val->intval = max172xx_temperature_to_ps(reg);
break;
/* We need signed current, so must cast info->rsense to signed type */
case POWER_SUPPLY_PROP_CURRENT_NOW:
ret = regmap_read(info->regmap, MAX172XX_REG_CURRENT, &reg);
val->intval =
max172xx_current_to_voltage(reg) / (int)info->rsense;
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
ret = regmap_read(info->regmap, MAX172XX_REG_AVGCURRENT, &reg);
val->intval =
max172xx_current_to_voltage(reg) / (int)info->rsense;
break;
/*
* Strings already received and inited by probe.
* We do dummy read for check battery still available.
*/
case POWER_SUPPLY_PROP_MODEL_NAME:
ret = regmap_read(info->regmap, MAX1721X_REG_DEV_STR, &reg);
val->strval = info->DeviceName;
break;
case POWER_SUPPLY_PROP_MANUFACTURER:
ret = regmap_read(info->regmap, MAX1721X_REG_MFG_STR, &reg);
val->strval = info->ManufacturerName;
break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
ret = regmap_read(info->regmap, MAX1721X_REG_SER_HEX, &reg);
val->strval = info->SerialNumber;
break;
default:
ret = -EINVAL;
}
return ret;
}
static enum power_supply_property max1721x_battery_props[] = {
/* int */
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_AVG,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_AVG,
/* strings */
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_SERIAL_NUMBER,
};
static int get_string(struct max17211_device_info *info,
uint16_t reg, uint8_t nr, char *str)
{
unsigned int val;
if (!str || !(reg == MAX1721X_REG_MFG_STR ||
reg == MAX1721X_REG_DEV_STR))
return -EFAULT;
while (nr--) {
if (regmap_read(info->regmap, reg++, &val))
return -EFAULT;
*str++ = val>>8 & 0x00FF;
*str++ = val & 0x00FF;
}
return 0;
}
/* Maxim say: Serial number is a hex string up to 12 hex characters */
static int get_sn_string(struct max17211_device_info *info, char *str)
{
unsigned int val[3];
if (!str)
return -EFAULT;
if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX, &val[0]))
return -EFAULT;
if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 1, &val[1]))
return -EFAULT;
if (regmap_read(info->regmap, MAX1721X_REG_SER_HEX + 2, &val[2]))
return -EFAULT;
snprintf(str, 13, "%04X%04X%04X", val[0], val[1], val[2]);
return 0;
}
/*
* MAX1721x registers description for w1-regmap
*/
static const struct regmap_range max1721x_allow_range[] = {
regmap_reg_range(0, 0xDF), /* volatile data */
regmap_reg_range(0x180, 0x1DF), /* non-volatile memory */
regmap_reg_range(0x1E0, 0x1EF), /* non-volatile history (unused) */
};
static const struct regmap_range max1721x_deny_range[] = {
/* volatile data unused registers */
regmap_reg_range(0x24, 0x26),
regmap_reg_range(0x30, 0x31),
regmap_reg_range(0x33, 0x34),
regmap_reg_range(0x37, 0x37),
regmap_reg_range(0x3B, 0x3C),
regmap_reg_range(0x40, 0x41),
regmap_reg_range(0x43, 0x44),
regmap_reg_range(0x47, 0x49),
regmap_reg_range(0x4B, 0x4C),
regmap_reg_range(0x4E, 0xAF),
regmap_reg_range(0xB1, 0xB3),
regmap_reg_range(0xB5, 0xB7),
regmap_reg_range(0xBF, 0xD0),
regmap_reg_range(0xDB, 0xDB),
/* hole between volatile and non-volatile registers */
regmap_reg_range(0xE0, 0x17F),
};
static const struct regmap_access_table max1721x_regs = {
.yes_ranges = max1721x_allow_range,
.n_yes_ranges = ARRAY_SIZE(max1721x_allow_range),
.no_ranges = max1721x_deny_range,
.n_no_ranges = ARRAY_SIZE(max1721x_deny_range),
};
/*
* Model Gauge M5 Algorithm output register
* Volatile data (must not be cached)
*/
static const struct regmap_range max1721x_volatile_allow[] = {
regmap_reg_range(0, 0xDF),
};
static const struct regmap_access_table max1721x_volatile_regs = {
.yes_ranges = max1721x_volatile_allow,
.n_yes_ranges = ARRAY_SIZE(max1721x_volatile_allow),
};
/*
* W1-regmap config
*/
static const struct regmap_config max1721x_regmap_w1_config = {
.reg_bits = 16,
.val_bits = 16,
.rd_table = &max1721x_regs,
.volatile_table = &max1721x_volatile_regs,
.max_register = MAX1721X_MAX_REG_NR,
};
static int devm_w1_max1721x_add_device(struct w1_slave *sl)
{
struct power_supply_config psy_cfg = {};
struct max17211_device_info *info;
info = devm_kzalloc(&sl->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
sl->family_data = (void *)info;
info->w1_dev = &sl->dev;
/*
* power_supply class battery name translated from W1 slave device
* unical ID (look like 26-0123456789AB) to "max1721x-0123456789AB\0"
* so, 26 (device family) correcpondent to max1721x devices.
* Device name still unical for any numbers connected devices.
*/
snprintf(info->name, sizeof(info->name),
"max1721x-%012X", (unsigned int)sl->reg_num.id);
info->bat_desc.name = info->name;
/*
* FixMe: battery device name exceed max len for thermal_zone device
* name and translation to thermal_zone must be disabled.
*/
info->bat_desc.no_thermal = true;
info->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
info->bat_desc.properties = max1721x_battery_props;
info->bat_desc.num_properties = ARRAY_SIZE(max1721x_battery_props);
info->bat_desc.get_property = max1721x_battery_get_property;
psy_cfg.drv_data = info;
/* regmap init */
info->regmap = devm_regmap_init_w1(info->w1_dev,
&max1721x_regmap_w1_config);
if (IS_ERR(info->regmap)) {
int err = PTR_ERR(info->regmap);
dev_err(info->w1_dev, "Failed to allocate register map: %d\n",
err);
return err;
}
/* rsense init */
info->rsense = 0;
if (regmap_read(info->regmap, MAX1721X_REG_NRSENSE, &info->rsense)) {
dev_err(info->w1_dev, "Can't read RSense. Hardware error.\n");
return -ENODEV;
}
if (!info->rsense) {
dev_warn(info->w1_dev, "RSenese not calibrated, set 10 mOhms!\n");
info->rsense = 1000; /* in regs in 10^-5 */
}
dev_info(info->w1_dev, "RSense: %d mOhms.\n", info->rsense / 100);
if (get_string(info, MAX1721X_REG_MFG_STR,
MAX1721X_REG_MFG_NUMB, info->ManufacturerName)) {
dev_err(info->w1_dev, "Can't read manufacturer. Hardware error.\n");
return -ENODEV;
}
if (!info->ManufacturerName[0])
strncpy(info->ManufacturerName, DEF_MFG_NAME,
2 * MAX1721X_REG_MFG_NUMB);
if (get_string(info, MAX1721X_REG_DEV_STR,
MAX1721X_REG_DEV_NUMB, info->DeviceName)) {
dev_err(info->w1_dev, "Can't read device. Hardware error.\n");
return -ENODEV;
}
if (!info->DeviceName[0]) {
unsigned int dev_name;
if (regmap_read(info->regmap,
MAX172XX_REG_DEVNAME, &dev_name)) {
dev_err(info->w1_dev, "Can't read device name reg.\n");
return -ENODEV;
}
switch (dev_name & MAX172XX_DEV_MASK) {
case MAX172X1_DEV:
strncpy(info->DeviceName, DEF_DEV_NAME_MAX17211,
2 * MAX1721X_REG_DEV_NUMB);
break;
case MAX172X5_DEV:
strncpy(info->DeviceName, DEF_DEV_NAME_MAX17215,
2 * MAX1721X_REG_DEV_NUMB);
break;
default:
strncpy(info->DeviceName, DEF_DEV_NAME_UNKNOWN,
2 * MAX1721X_REG_DEV_NUMB);
}
}
if (get_sn_string(info, info->SerialNumber)) {
dev_err(info->w1_dev, "Can't read serial. Hardware error.\n");
return -ENODEV;
}
info->bat = devm_power_supply_register(&sl->dev, &info->bat_desc,
&psy_cfg);
if (IS_ERR(info->bat)) {
dev_err(info->w1_dev, "failed to register battery\n");
return PTR_ERR(info->bat);
}
return 0;
}
static struct w1_family_ops w1_max1721x_fops = {
.add_slave = devm_w1_max1721x_add_device,
};
static struct w1_family w1_max1721x_family = {
.fid = W1_MAX1721X_FAMILY_ID,
.fops = &w1_max1721x_fops,
};
module_w1_family(w1_max1721x_family);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex A. Mihaylov <minimumlaw@rambler.ru>");
MODULE_DESCRIPTION("Maxim MAX17211/MAX17215 Fuel Gauage IC driver");
MODULE_ALIAS("w1-family-" __stringify(W1_MAX1721X_FAMILY_ID));
+2 -2
View File
@@ -535,7 +535,7 @@ static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj,
return count;
}
static struct bin_attribute olpc_bat_eeprom = {
static const struct bin_attribute olpc_bat_eeprom = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
@@ -559,7 +559,7 @@ static ssize_t olpc_bat_error_read(struct device *dev,
return sprintf(buf, "%d\n", ec_byte);
}
static struct device_attribute olpc_bat_error = {
static const struct device_attribute olpc_bat_error = {
.attr = {
.name = "error",
.mode = S_IRUGO,
+1 -1
View File
@@ -254,7 +254,7 @@ static struct attribute *pcf50633_mbc_sysfs_entries[] = {
NULL,
};
static struct attribute_group mbc_attr_group = {
static const struct attribute_group mbc_attr_group = {
.name = NULL, /* put in device directory */
.attrs = pcf50633_mbc_sysfs_entries,
};
+46 -8
View File
@@ -259,18 +259,14 @@ static int power_supply_check_supplies(struct power_supply *psy)
/* All supplies found, allocate char ** array for filling */
psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(psy->supplied_from),
GFP_KERNEL);
if (!psy->supplied_from) {
dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
if (!psy->supplied_from)
return -ENOMEM;
}
*psy->supplied_from = devm_kzalloc(&psy->dev,
sizeof(char *) * (cnt - 1),
GFP_KERNEL);
if (!*psy->supplied_from) {
dev_err(&psy->dev, "Couldn't allocate memory for supply list\n");
if (!*psy->supplied_from)
return -ENOMEM;
}
return power_supply_populate_supplied_from(psy);
}
@@ -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 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,
&ret))
return ret.intval;
}
return 0;
}
@@ -374,6 +371,47 @@ int power_supply_is_system_supplied(void)
}
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)
{
if (atomic_read(&psy->use_cnt) >= 0 &&

Some files were not shown because too many files have changed in this diff Show More