Merge tag 'for-v3.18' of git://git.infradead.org/battery-2.6

Pull power supply and reset updates from Sebastian Reichel:
 - Initial support for the following chips
   * max77836 (charger)
   * max14577 (charger)
   * bq27742 (battery gauge)
   * ltc2952 (poweroff)
   * stih416 (restart)
   * syscon-reboot (restart)
   * gpio-restart (restart)
 - cleanup of power supply core
 - misc fixes in power supply and reset drivers

* tag 'for-v3.18' of git://git.infradead.org/battery-2.6: (48 commits)
  power: ab8500_fg: Fix build warning
  Documentation: charger: max14577: Update the date of introducing ABI
  power: reset: corrections for simple syscon reboot driver
  Documentation: power: reset: Add documentation for generic SYSCON reboot driver
  power: reset: Add generic SYSCON register mapped reset
  bq27x00_battery: Fix flag reading for bq27742
  power: reset: use restart_notifier mechanism for msm-poweroff
  power: Add simple gpio-restart driver
  power: reset: st: Provide DT bindings for ST's Power Reset driver
  power: reset: Add restart functionality for STiH41x platforms
  power: charger-manager: Fix NULL pointer exception with missing cm-fuel-gauge
  power: max14577: Fix circular config SYSFS dependency
  power: gpio-charger: do not use gpio value directly
  power: max8925: Use of_get_child_by_name
  power: max8925: Fix NULL ptr dereference on memory allocation failure
  bq27x00_battery: Add support to bq27742
  Documentation: charger: max14577: Document exported sysfs entry
  devicetree: mfd: max14577: Add device tree bindings document
  power: max17040: Add ID for MAX77836 Fuel Gauge block
  charger: max14577: Configure battery-dependent settings from DTS and sysfs
  ...

Conflicts:
	drivers/power/reset/Kconfig
	drivers/power/reset/Makefile
This commit is contained in:
Linus Torvalds
2014-10-15 06:56:23 +02:00
33 changed files with 1920 additions and 250 deletions
@@ -18,3 +18,17 @@ Description:
This file is writeable and can be used to set the assumed This file is writeable and can be used to set the assumed
battery 'full level'. As batteries age, this value has to be battery 'full level'. As batteries age, this value has to be
amended over time. amended over time.
What: /sys/class/power_supply/max14577-charger/device/fast_charge_timer
Date: October 2014
KernelVersion: 3.18.0
Contact: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Description:
This entry shows and sets the maximum time the max14577
charger operates in fast-charge mode. When the timer expires
the device will terminate fast-charge mode (charging current
will drop to 0 A) and will trigger interrupt.
Valid values:
- 5, 6 or 7 (hours),
- 0: disabled.
@@ -0,0 +1,54 @@
Drive a GPIO line that can be used to restart the system from a restart
handler.
This binding supports level and edge triggered reset. At driver load
time, the driver will request the given gpio line and install a restart
handler. If the optional properties 'open-source' is not found, the GPIO line
will be driven in the inactive state. Otherwise its not driven until
the restart is initiated.
When the system is restarted, the restart handler will be invoked in
priority order. The gpio is configured as an output, and driven active,
triggering a level triggered reset condition. This will also cause an
inactive->active edge condition, triggering positive edge triggered
reset. After a delay specified by active-delay, the GPIO is set to
inactive, thus causing an active->inactive edge, triggering negative edge
triggered reset. After a delay specified by inactive-delay, the GPIO
is driven active again. After a delay specified by wait-delay, the
restart handler completes allowing other restart handlers to be attempted.
Required properties:
- compatible : should be "gpio-restart".
- gpios : The GPIO to set high/low, see "gpios property" in
Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be
low to reset the board set it to "Active Low", otherwise set
gpio to "Active High".
Optional properties:
- open-source : Treat the GPIO as being open source and defer driving
it to when the restart is initiated. If this optional property is not
specified, the GPIO is initialized as an output in its inactive state.
- priority : A priority ranging from 0 to 255 (default 128) according to
the following guidelines:
0: Restart handler of last resort, with limited restart
capabilities
128: Default restart handler; use if no other restart handler is
expected to be available, and/or if restart functionality is
sufficient to restart the entire system
255: Highest priority restart handler, will preempt all other
restart handlers
- active-delay: Delay (default 100) to wait after driving gpio active [ms]
- inactive-delay: Delay (default 100) to wait after driving gpio inactive [ms]
- wait-delay: Delay (default 3000) to wait after completing restart
sequence [ms]
Examples:
gpio-restart {
compatible = "gpio-restart";
gpios = <&gpio 4 0>;
priority = <128>;
active-delay = <100>;
inactive-delay = <100>;
wait-delay = <3000>;
};
@@ -0,0 +1,146 @@
Maxim MAX14577/77836 Multi-Function Device
MAX14577 is a Multi-Function Device with Micro-USB Interface Circuit, Li+
Battery Charger and SFOUT LDO output for powering USB devices. It is
interfaced to host controller using I2C.
MAX77836 additionally contains PMIC (with two LDO regulators) and Fuel Gauge.
Required properties:
- compatible : Must be "maxim,max14577" or "maxim,max77836".
- reg : I2C slave address for the max14577 chip (0x25 for max14577/max77836)
- interrupts : IRQ line for the chip.
- interrupt-parent : The parent interrupt controller.
Required nodes:
- charger :
Node for configuring the charger driver.
Required properties:
- compatible : "maxim,max14577-charger"
or "maxim,max77836-charger"
- maxim,fast-charge-uamp : Current in uA for Fast Charge;
Valid values:
- for max14577: 90000 - 950000;
- for max77836: 45000 - 475000;
- maxim,eoc-uamp : Current in uA for End-Of-Charge mode;
Valid values:
- for max14577: 50000 - 200000;
- for max77836: 5000 - 100000;
- maxim,ovp-uvolt : OverVoltage Protection Threshold in uV;
In an overvoltage condition, INT asserts and charging
stops. Valid values:
- 6000000, 6500000, 7000000, 7500000;
- maxim,constant-uvolt : Battery Constant Voltage in uV;
Valid values:
- 4000000 - 4280000 (step by 20000);
- 4350000;
Optional nodes:
- max14577-muic/max77836-muic :
Node used only by extcon consumers.
Required properties:
- compatible : "maxim,max14577-muic" or "maxim,max77836-muic"
- regulators :
Required properties:
- compatible : "maxim,max14577-regulator"
or "maxim,max77836-regulator"
May contain a sub-node per regulator from the list below. Each
sub-node should contain the constraints and initialization information
for that regulator. See regulator.txt for a description of standard
properties for these sub-nodes.
List of valid regulator names:
- for max14577: CHARGER, SAFEOUT.
- for max77836: CHARGER, SAFEOUT, LDO1, LDO2.
The SAFEOUT is a fixed voltage regulator so there is no need to specify
voltages for it.
Example:
#include <dt-bindings/interrupt-controller/irq.h>
max14577@25 {
compatible = "maxim,max14577";
reg = <0x25>;
interrupt-parent = <&gpx1>;
interrupts = <5 IRQ_TYPE_NONE>;
muic: max14577-muic {
compatible = "maxim,max14577-muic";
};
regulators {
compatible = "maxim,max14577-regulator";
SAFEOUT {
regulator-name = "SAFEOUT";
};
CHARGER {
regulator-name = "CHARGER";
regulator-min-microamp = <90000>;
regulator-max-microamp = <950000>;
regulator-boot-on;
};
};
charger {
compatible = "maxim,max14577-charger";
maxim,constant-uvolt = <4350000>;
maxim,fast-charge-uamp = <450000>;
maxim,eoc-uamp = <50000>;
maxim,ovp-uvolt = <6500000>;
};
};
max77836@25 {
compatible = "maxim,max77836";
reg = <0x25>;
interrupt-parent = <&gpx1>;
interrupts = <5 IRQ_TYPE_NONE>;
muic: max77836-muic {
compatible = "maxim,max77836-muic";
};
regulators {
compatible = "maxim,max77836-regulator";
SAFEOUT {
regulator-name = "SAFEOUT";
};
CHARGER {
regulator-name = "CHARGER";
regulator-min-microamp = <90000>;
regulator-max-microamp = <950000>;
regulator-boot-on;
};
LDO1 {
regulator-name = "LDO1";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <2700000>;
};
LDO2 {
regulator-name = "LDO2";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <3950000>;
};
};
charger {
compatible = "maxim,max77836-charger";
maxim,constant-uvolt = <4350000>;
maxim,fast-charge-uamp = <225000>;
maxim,eoc-uamp = <7500>;
maxim,ovp-uvolt = <6500000>;
};
};
@@ -0,0 +1,26 @@
Binding for the LTC2952 PowerPath controller
This chip is used to externally trigger a system shut down. Once the trigger has
been sent, the chips' watchdog has to be reset to gracefully shut down.
If the Linux systems decides to shut down it powers off the platform via the
kill signal.
Required properties:
- compatible: Must contain: "lltc,ltc2952"
- trigger-gpios: phandle + gpio-specifier for the GPIO connected to the
chip's trigger line
- watchdog-gpios: phandle + gpio-specifier for the GPIO connected to the
chip's watchdog line
- kill-gpios: phandle + gpio-specifier for the GPIO connected to the
chip's kill line
Example:
ltc2952 {
compatible = "lltc,ltc2952";
trigger-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
watchdog-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
kill-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
};
@@ -0,0 +1,11 @@
*Device-Tree bindings for ST SW reset functionality
Required properties:
- compatible: should be "st,<chip>-restart".
- st,syscfg: should be a phandle of the syscfg node.
Example node:
restart {
compatible = "st,stih416-restart";
st,syscfg = <&syscfg_sbc>;
};
@@ -0,0 +1,23 @@
Generic SYSCON mapped register reset driver
This is a generic reset driver using syscon to map the reset register.
The reset is generally performed with a write to the reset register
defined by the register map pointed by syscon reference plus the offset
with the mask defined in the reboot node.
Required properties:
- compatible: should contain "syscon-reboot"
- regmap: this is phandle to the register map node
- offset: offset in the register map for the reboot register (in bytes)
- mask: the reset value written to the reboot register (32 bit access)
Default will be little endian mode, 32 bit access only.
Examples:
reboot {
compatible = "syscon-reboot";
regmap = <&regmapnode>;
offset = <0x0>;
mask = <0x1>;
};
+1 -1
View File
@@ -29,7 +29,7 @@ Charger Manager supports the following:
While the battery is being charged and the system is in suspend-to-RAM, While the battery is being charged and the system is in suspend-to-RAM,
we may need to monitor the battery health by looking at the ambient or we may need to monitor the battery health by looking at the ambient or
battery temperature. We can accomplish this by waking up the system battery temperature. We can accomplish this by waking up the system
periodically. However, such a method wakes up devices unncessary for periodically. However, such a method wakes up devices unnecessarily for
monitoring the battery health and tasks, and user processes that are monitoring the battery health and tasks, and user processes that are
supposed to be kept suspended. That, in turn, incurs unnecessary power supposed to be kept suspended. That, in turn, incurs unnecessary power
consumption and slow down charging process. Or even, such peak power consumption and slow down charging process. Or even, such peak power
@@ -101,6 +101,10 @@ VOLTAGE_MAX, VOLTAGE_MIN - same as _DESIGN voltage values except that
these ones should be used if hardware could only guess (measure and these ones should be used if hardware could only guess (measure and
retain) the thresholds of a given power supply. retain) the thresholds of a given power supply.
VOLTAGE_BOOT - Reports the voltage measured during boot
CURRENT_BOOT - Reports the current measured during boot
CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when CHARGE_FULL_DESIGN, CHARGE_EMPTY_DESIGN - design charge values, when
battery considered full/empty. battery considered full/empty.
@@ -123,6 +127,8 @@ the current drawn from a charging source.
CHARGE_TERM_CURRENT - Charge termination current used to detect the end of charge CHARGE_TERM_CURRENT - Charge termination current used to detect the end of charge
condition. condition.
CALIBRATE - battery or coulomb counter calibration status
CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger. CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
power supply object. power supply object.
+99 -1
View File
@@ -26,6 +26,87 @@
#include <linux/mfd/max14577.h> #include <linux/mfd/max14577.h>
#include <linux/mfd/max14577-private.h> #include <linux/mfd/max14577-private.h>
/*
* Table of valid charger currents for different Maxim chipsets.
* It is placed here because it is used by both charger and regulator driver.
*/
const struct maxim_charger_current maxim_charger_currents[] = {
[MAXIM_DEVICE_TYPE_UNKNOWN] = { 0, 0, 0, 0 },
[MAXIM_DEVICE_TYPE_MAX14577] = {
.min = MAX14577_CHARGER_CURRENT_LIMIT_MIN,
.high_start = MAX14577_CHARGER_CURRENT_LIMIT_HIGH_START,
.high_step = MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP,
.max = MAX14577_CHARGER_CURRENT_LIMIT_MAX,
},
[MAXIM_DEVICE_TYPE_MAX77836] = {
.min = MAX77836_CHARGER_CURRENT_LIMIT_MIN,
.high_start = MAX77836_CHARGER_CURRENT_LIMIT_HIGH_START,
.high_step = MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP,
.max = MAX77836_CHARGER_CURRENT_LIMIT_MAX,
},
};
EXPORT_SYMBOL_GPL(maxim_charger_currents);
/*
* maxim_charger_calc_reg_current - Calculate register value for current
* @limits: constraints for charger, matching the MBCICHWRC register
* @min_ua: minimal requested current, micro Amps
* @max_ua: maximum requested current, micro Amps
* @dst: destination to store calculated register value
*
* Calculates the value of MBCICHWRC (Fast Battery Charge Current) register
* for given current and stores it under pointed 'dst'. The stored value
* combines low bit (MBCICHWRCL) and high bits (MBCICHWRCH). It is also
* properly shifted.
*
* The calculated register value matches the current which:
* - is always between <limits.min, limits.max>;
* - is always less or equal to max_ua;
* - is the highest possible value;
* - may be lower than min_ua.
*
* On success returns 0. On error returns -EINVAL (requested min/max current
* is outside of given charger limits) and 'dst' is not set.
*/
int maxim_charger_calc_reg_current(const struct maxim_charger_current *limits,
unsigned int min_ua, unsigned int max_ua, u8 *dst)
{
unsigned int current_bits = 0xf;
if (min_ua > max_ua)
return -EINVAL;
if (min_ua > limits->max || max_ua < limits->min)
return -EINVAL;
if (max_ua < limits->high_start) {
/*
* Less than high_start, so set the minimal current
* (turn Low Bit off, 0 as high bits).
*/
*dst = 0x0;
return 0;
}
/* max_ua is in range: <high_start, infinite>, cut it to limits.max */
max_ua = min(limits->max, max_ua);
max_ua -= limits->high_start;
/*
* There is no risk of overflow 'max_ua' here because:
* - max_ua >= limits.high_start
* - BUILD_BUG checks that 'limits' are: max >= high_start + high_step
*/
current_bits = max_ua / limits->high_step;
/* Turn Low Bit on (use range <limits.high_start, limits.max>) ... */
*dst = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT;
/* and set proper High Bits */
*dst |= current_bits << CHGCTRL4_MBCICHWRCH_SHIFT;
return 0;
}
EXPORT_SYMBOL_GPL(maxim_charger_calc_reg_current);
static const struct mfd_cell max14577_devs[] = { static const struct mfd_cell max14577_devs[] = {
{ {
.name = "max14577-muic", .name = "max14577-muic",
@@ -35,7 +116,10 @@ static const struct mfd_cell max14577_devs[] = {
.name = "max14577-regulator", .name = "max14577-regulator",
.of_compatible = "maxim,max14577-regulator", .of_compatible = "maxim,max14577-regulator",
}, },
{ .name = "max14577-charger", }, {
.name = "max14577-charger",
.of_compatible = "maxim,max14577-charger",
},
}; };
static const struct mfd_cell max77836_devs[] = { static const struct mfd_cell max77836_devs[] = {
@@ -463,6 +547,20 @@ static int __init max14577_i2c_init(void)
BUILD_BUG_ON(ARRAY_SIZE(max14577_i2c_id) != MAXIM_DEVICE_TYPE_NUM); BUILD_BUG_ON(ARRAY_SIZE(max14577_i2c_id) != MAXIM_DEVICE_TYPE_NUM);
BUILD_BUG_ON(ARRAY_SIZE(max14577_dt_match) != MAXIM_DEVICE_TYPE_NUM); BUILD_BUG_ON(ARRAY_SIZE(max14577_dt_match) != MAXIM_DEVICE_TYPE_NUM);
/* Valid charger current values must be provided for each chipset */
BUILD_BUG_ON(ARRAY_SIZE(maxim_charger_currents) != MAXIM_DEVICE_TYPE_NUM);
/* Check for valid values for charger */
BUILD_BUG_ON(MAX14577_CHARGER_CURRENT_LIMIT_HIGH_START +
MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP * 0xf !=
MAX14577_CHARGER_CURRENT_LIMIT_MAX);
BUILD_BUG_ON(MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP == 0);
BUILD_BUG_ON(MAX77836_CHARGER_CURRENT_LIMIT_HIGH_START +
MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP * 0xf !=
MAX77836_CHARGER_CURRENT_LIMIT_MAX);
BUILD_BUG_ON(MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP == 0);
return i2c_add_driver(&max14577_i2c_driver); return i2c_add_driver(&max14577_i2c_driver);
} }
subsys_initcall(max14577_i2c_init); subsys_initcall(max14577_i2c_init);
+3 -2
View File
@@ -325,11 +325,12 @@ config CHARGER_MANAGER
with help of suspend_again support. with help of suspend_again support.
config CHARGER_MAX14577 config CHARGER_MAX14577
tristate "Maxim MAX14577 MUIC battery charger driver" tristate "Maxim MAX14577/77836 battery charger driver"
depends on MFD_MAX14577 depends on MFD_MAX14577
depends on SYSFS
help help
Say Y to enable support for the battery charger control sysfs and Say Y to enable support for the battery charger control sysfs and
platform data of MAX14577 MUICs. platform data of MAX14577/77836 MUICs.
config CHARGER_MAX8997 config CHARGER_MAX8997
tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver" tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
+5 -4
View File
@@ -2969,7 +2969,7 @@ static struct device_attribute ab8505_fg_sysfs_psy_attrs[] = {
static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev) static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev)
{ {
unsigned int i, j; unsigned int i;
struct power_supply *psy = dev_get_drvdata(dev); struct power_supply *psy = dev_get_drvdata(dev);
struct ab8500_fg *di; struct ab8500_fg *di;
@@ -2978,14 +2978,15 @@ static int ab8500_fg_sysfs_psy_create_attrs(struct device *dev)
if (((is_ab8505(di->parent) || is_ab9540(di->parent)) && if (((is_ab8505(di->parent) || is_ab9540(di->parent)) &&
abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0) abx500_get_chip_id(dev->parent) >= AB8500_CUT2P0)
|| is_ab8540(di->parent)) { || is_ab8540(di->parent)) {
for (j = 0; j < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); j++) for (i = 0; i < ARRAY_SIZE(ab8505_fg_sysfs_psy_attrs); i++)
if (device_create_file(dev, &ab8505_fg_sysfs_psy_attrs[j])) if (device_create_file(dev,
&ab8505_fg_sysfs_psy_attrs[i]))
goto sysfs_psy_create_attrs_failed_ab8505; goto sysfs_psy_create_attrs_failed_ab8505;
} }
return 0; return 0;
sysfs_psy_create_attrs_failed_ab8505: sysfs_psy_create_attrs_failed_ab8505:
dev_err(dev, "Failed creating sysfs psy attrs for ab8505.\n"); dev_err(dev, "Failed creating sysfs psy attrs for ab8505.\n");
while (j--) while (i--)
device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]); device_remove_file(dev, &ab8505_fg_sysfs_psy_attrs[i]);
return -EIO; return -EIO;
+48 -9
View File
@@ -23,6 +23,7 @@
* http://focus.ti.com/docs/prod/folders/print/bq27000.html * http://focus.ti.com/docs/prod/folders/print/bq27000.html
* http://focus.ti.com/docs/prod/folders/print/bq27500.html * http://focus.ti.com/docs/prod/folders/print/bq27500.html
* http://www.ti.com/product/bq27425-g1 * http://www.ti.com/product/bq27425-g1
* http://www.ti.com/product/BQ27742-G1
*/ */
#include <linux/device.h> #include <linux/device.h>
@@ -71,6 +72,8 @@
#define BQ27500_FLAG_FC BIT(9) #define BQ27500_FLAG_FC BIT(9)
#define BQ27500_FLAG_OTC BIT(15) #define BQ27500_FLAG_OTC BIT(15)
#define BQ27742_POWER_AVG 0x76
/* bq27425 register addresses are same as bq27x00 addresses minus 4 */ /* bq27425 register addresses are same as bq27x00 addresses minus 4 */
#define BQ27425_REG_OFFSET 0x04 #define BQ27425_REG_OFFSET 0x04
#define BQ27425_REG_SOC 0x18 /* Register address plus offset */ #define BQ27425_REG_SOC 0x18 /* Register address plus offset */
@@ -83,7 +86,7 @@ struct bq27x00_access_methods {
int (*read)(struct bq27x00_device_info *di, u8 reg, bool single); int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
}; };
enum bq27x00_chip { BQ27000, BQ27500, BQ27425}; enum bq27x00_chip { BQ27000, BQ27500, BQ27425, BQ27742};
struct bq27x00_reg_cache { struct bq27x00_reg_cache {
int temperature; int temperature;
@@ -152,6 +155,24 @@ static enum power_supply_property bq27425_battery_props[] = {
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
}; };
static enum power_supply_property bq27742_battery_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_NOW,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_POWER_AVG,
POWER_SUPPLY_PROP_HEALTH,
};
static unsigned int poll_interval = 360; static unsigned int poll_interval = 360;
module_param(poll_interval, uint, 0644); module_param(poll_interval, uint, 0644);
MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \ MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
@@ -176,7 +197,7 @@ static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
*/ */
static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di) static bool bq27xxx_is_chip_version_higher(struct bq27x00_device_info *di)
{ {
if (di->chip == BQ27425 || di->chip == BQ27500) if (di->chip == BQ27425 || di->chip == BQ27500 || di->chip == BQ27742)
return true; return true;
return false; return false;
} }
@@ -189,7 +210,7 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
{ {
int rsoc; int rsoc;
if (di->chip == BQ27500) if (di->chip == BQ27500 || di->chip == BQ27742)
rsoc = bq27x00_read(di, BQ27500_REG_SOC, false); rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
else if (di->chip == BQ27425) else if (di->chip == BQ27425)
rsoc = bq27x00_read(di, BQ27425_REG_SOC, false); rsoc = bq27x00_read(di, BQ27425_REG_SOC, false);
@@ -233,9 +254,11 @@ static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
{ {
int flags; int flags;
bool is_bq27500 = di->chip == BQ27500; bool is_bq27500 = di->chip == BQ27500;
bool is_bq27742 = di->chip == BQ27742;
bool is_higher = bq27xxx_is_chip_version_higher(di); bool is_higher = bq27xxx_is_chip_version_higher(di);
bool flags_1b = !(is_bq27500 || is_bq27742);
flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b);
if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI)) if (flags >= 0 && !is_higher && (flags & BQ27000_FLAG_CI))
return -ENODATA; return -ENODATA;
@@ -414,13 +437,15 @@ static void bq27x00_update(struct bq27x00_device_info *di)
struct bq27x00_reg_cache cache = {0, }; struct bq27x00_reg_cache cache = {0, };
bool is_bq27500 = di->chip == BQ27500; bool is_bq27500 = di->chip == BQ27500;
bool is_bq27425 = di->chip == BQ27425; bool is_bq27425 = di->chip == BQ27425;
bool is_bq27742 = di->chip == BQ27742;
bool flags_1b = !(is_bq27500 || is_bq27742);
cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, flags_1b);
if ((cache.flags & 0xff) == 0xff) if ((cache.flags & 0xff) == 0xff)
/* read error */ /* read error */
cache.flags = -1; cache.flags = -1;
if (cache.flags >= 0) { if (cache.flags >= 0) {
if (!is_bq27500 && !is_bq27425 if (!is_bq27500 && !is_bq27425 && !is_bq27742
&& (cache.flags & BQ27000_FLAG_CI)) { && (cache.flags & BQ27000_FLAG_CI)) {
dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
cache.capacity = -ENODATA; cache.capacity = -ENODATA;
@@ -432,7 +457,11 @@ static void bq27x00_update(struct bq27x00_device_info *di)
cache.health = -ENODATA; cache.health = -ENODATA;
} else { } else {
cache.capacity = bq27x00_battery_read_rsoc(di); cache.capacity = bq27x00_battery_read_rsoc(di);
if (!is_bq27425) { if (is_bq27742)
cache.time_to_empty =
bq27x00_battery_read_time(di,
BQ27x00_REG_TTE);
else if (!is_bq27425) {
cache.energy = bq27x00_battery_read_energy(di); cache.energy = bq27x00_battery_read_energy(di);
cache.time_to_empty = cache.time_to_empty =
bq27x00_battery_read_time(di, bq27x00_battery_read_time(di,
@@ -450,8 +479,14 @@ static void bq27x00_update(struct bq27x00_device_info *di)
cache.temperature = bq27x00_battery_read_temperature(di); cache.temperature = bq27x00_battery_read_temperature(di);
if (!is_bq27425) if (!is_bq27425)
cache.cycle_count = bq27x00_battery_read_cyct(di); cache.cycle_count = bq27x00_battery_read_cyct(di);
cache.power_avg = if (is_bq27742)
bq27x00_battery_read_pwr_avg(di, BQ27x00_POWER_AVG); cache.power_avg =
bq27x00_battery_read_pwr_avg(di,
BQ27742_POWER_AVG);
else
cache.power_avg =
bq27x00_battery_read_pwr_avg(di,
BQ27x00_POWER_AVG);
/* We only have to read charge design full once */ /* We only have to read charge design full once */
if (di->charge_design_full <= 0) if (di->charge_design_full <= 0)
@@ -702,6 +737,9 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
if (di->chip == BQ27425) { if (di->chip == BQ27425) {
di->bat.properties = bq27425_battery_props; di->bat.properties = bq27425_battery_props;
di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props); di->bat.num_properties = ARRAY_SIZE(bq27425_battery_props);
} else if (di->chip == BQ27742) {
di->bat.properties = bq27742_battery_props;
di->bat.num_properties = ARRAY_SIZE(bq27742_battery_props);
} else { } else {
di->bat.properties = bq27x00_battery_props; di->bat.properties = bq27x00_battery_props;
di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props); di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
@@ -858,6 +896,7 @@ static const struct i2c_device_id bq27x00_id[] = {
{ "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */ { "bq27200", BQ27000 }, /* bq27200 is same as bq27000, but with i2c */
{ "bq27500", BQ27500 }, { "bq27500", BQ27500 },
{ "bq27425", BQ27425 }, { "bq27425", BQ27425 },
{ "bq27742", BQ27742 },
{}, {},
}; };
MODULE_DEVICE_TABLE(i2c, bq27x00_id); MODULE_DEVICE_TABLE(i2c, bq27x00_id);
+14 -2
View File
@@ -1656,7 +1656,7 @@ static inline struct charger_desc *cm_get_drv_data(struct platform_device *pdev)
{ {
if (pdev->dev.of_node) if (pdev->dev.of_node)
return of_cm_parse_desc(&pdev->dev); return of_cm_parse_desc(&pdev->dev);
return (struct charger_desc *)dev_get_platdata(&pdev->dev); return dev_get_platdata(&pdev->dev);
} }
static int charger_manager_probe(struct platform_device *pdev) static int charger_manager_probe(struct platform_device *pdev)
@@ -1677,7 +1677,7 @@ static int charger_manager_probe(struct platform_device *pdev)
} }
} }
if (!desc) { if (IS_ERR(desc)) {
dev_err(&pdev->dev, "No platform data (desc) found\n"); dev_err(&pdev->dev, "No platform data (desc) found\n");
return -ENODEV; return -ENODEV;
} }
@@ -1720,6 +1720,11 @@ static int charger_manager_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
if (!desc->psy_fuel_gauge) {
dev_err(&pdev->dev, "No fuel gauge power supply defined\n");
return -EINVAL;
}
/* Counting index only */ /* Counting index only */
while (desc->psy_charger_stat[i]) while (desc->psy_charger_stat[i])
i++; i++;
@@ -1839,6 +1844,13 @@ static int charger_manager_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, true); device_init_wakeup(&pdev->dev, true);
device_set_wakeup_capable(&pdev->dev, false); device_set_wakeup_capable(&pdev->dev, false);
/*
* Charger-manager have to check the charging state right after
* tialization of charger-manager and then update current charging
* state.
*/
cm_monitor();
schedule_work(&setup_polling); schedule_work(&setup_polling);
return 0; return 0;
+1 -1
View File
@@ -55,7 +55,7 @@ static int gpio_charger_get_property(struct power_supply *psy,
switch (psp) { switch (psp) {
case POWER_SUPPLY_PROP_ONLINE: case POWER_SUPPLY_PROP_ONLINE:
val->intval = gpio_get_value_cansleep(pdata->gpio); val->intval = !!gpio_get_value_cansleep(pdata->gpio);
val->intval ^= pdata->gpio_active_low; val->intval ^= pdata->gpio_active_low;
break; break;
default: default:
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -277,7 +277,8 @@ static SIMPLE_DEV_PM_OPS(max17040_pm_ops, max17040_suspend, max17040_resume);
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
static const struct i2c_device_id max17040_id[] = { static const struct i2c_device_id max17040_id[] = {
{ "max17040", 0 }, { "max17040" },
{ "max77836-battery" },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, max17040_id); MODULE_DEVICE_TABLE(i2c, max17040_id);
+5 -2
View File
@@ -443,7 +443,7 @@ max8925_power_dt_init(struct platform_device *pdev)
if (!nproot) if (!nproot)
return pdev->dev.platform_data; return pdev->dev.platform_data;
np = of_find_node_by_name(nproot, "charger"); np = of_get_child_by_name(nproot, "charger");
if (!np) { if (!np) {
dev_err(&pdev->dev, "failed to find charger node\n"); dev_err(&pdev->dev, "failed to find charger node\n");
return NULL; return NULL;
@@ -452,13 +452,14 @@ max8925_power_dt_init(struct platform_device *pdev)
pdata = devm_kzalloc(&pdev->dev, pdata = devm_kzalloc(&pdev->dev,
sizeof(struct max8925_power_pdata), sizeof(struct max8925_power_pdata),
GFP_KERNEL); GFP_KERNEL);
if (!pdata)
goto ret;
of_property_read_u32(np, "topoff-threshold", &topoff_threshold); of_property_read_u32(np, "topoff-threshold", &topoff_threshold);
of_property_read_u32(np, "batt-detect", &batt_detect); of_property_read_u32(np, "batt-detect", &batt_detect);
of_property_read_u32(np, "fast-charge", &fast_charge); of_property_read_u32(np, "fast-charge", &fast_charge);
of_property_read_u32(np, "no-insert-detect", &no_insert_detect); of_property_read_u32(np, "no-insert-detect", &no_insert_detect);
of_property_read_u32(np, "no-temp-support", &no_temp_support); of_property_read_u32(np, "no-temp-support", &no_temp_support);
of_node_put(np);
pdata->batt_detect = batt_detect; pdata->batt_detect = batt_detect;
pdata->fast_charge = fast_charge; pdata->fast_charge = fast_charge;
@@ -466,6 +467,8 @@ max8925_power_dt_init(struct platform_device *pdev)
pdata->no_insert_detect = no_insert_detect; pdata->no_insert_detect = no_insert_detect;
pdata->no_temp_support = no_temp_support; pdata->no_temp_support = no_temp_support;
ret:
of_node_put(np);
return pdata; return pdata;
} }
#else #else
+48 -54
View File
@@ -58,7 +58,7 @@ static bool __power_supply_is_supplied_by(struct power_supply *supplier,
static int __power_supply_changed_work(struct device *dev, void *data) static int __power_supply_changed_work(struct device *dev, void *data)
{ {
struct power_supply *psy = (struct power_supply *)data; struct power_supply *psy = data;
struct power_supply *pst = dev_get_drvdata(dev); struct power_supply *pst = dev_get_drvdata(dev);
if (__power_supply_is_supplied_by(psy, pst)) { if (__power_supply_is_supplied_by(psy, pst)) {
@@ -78,7 +78,14 @@ static void power_supply_changed_work(struct work_struct *work)
dev_dbg(psy->dev, "%s\n", __func__); dev_dbg(psy->dev, "%s\n", __func__);
spin_lock_irqsave(&psy->changed_lock, flags); spin_lock_irqsave(&psy->changed_lock, flags);
if (psy->changed) { /*
* Check 'changed' here to avoid issues due to race between
* power_supply_changed() and this routine. In worst case
* power_supply_changed() can be called again just before we take above
* lock. During the first call of this routine we will mark 'changed' as
* false and it will stay false for the next call as well.
*/
if (likely(psy->changed)) {
psy->changed = false; psy->changed = false;
spin_unlock_irqrestore(&psy->changed_lock, flags); spin_unlock_irqrestore(&psy->changed_lock, flags);
class_for_each_device(power_supply_class, NULL, psy, class_for_each_device(power_supply_class, NULL, psy,
@@ -89,12 +96,13 @@ static void power_supply_changed_work(struct work_struct *work)
kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE);
spin_lock_irqsave(&psy->changed_lock, flags); spin_lock_irqsave(&psy->changed_lock, flags);
} }
/* /*
* Dependent power supplies (e.g. battery) may have changed state * Hold the wakeup_source until all events are processed.
* as a result of this event, so poll again and hold the * power_supply_changed() might have called again and have set 'changed'
* wakeup_source until all events are processed. * to true.
*/ */
if (!psy->changed) if (likely(!psy->changed))
pm_relax(psy->dev); pm_relax(psy->dev);
spin_unlock_irqrestore(&psy->changed_lock, flags); spin_unlock_irqrestore(&psy->changed_lock, flags);
} }
@@ -119,7 +127,7 @@ EXPORT_SYMBOL_GPL(power_supply_changed);
static int __power_supply_populate_supplied_from(struct device *dev, static int __power_supply_populate_supplied_from(struct device *dev,
void *data) void *data)
{ {
struct power_supply *psy = (struct power_supply *)data; struct power_supply *psy = data;
struct power_supply *epsy = dev_get_drvdata(dev); struct power_supply *epsy = dev_get_drvdata(dev);
struct device_node *np; struct device_node *np;
int i = 0; int i = 0;
@@ -127,7 +135,7 @@ static int __power_supply_populate_supplied_from(struct device *dev,
do { do {
np = of_parse_phandle(psy->of_node, "power-supplies", i++); np = of_parse_phandle(psy->of_node, "power-supplies", i++);
if (!np) if (!np)
continue; break;
if (np == epsy->of_node) { if (np == epsy->of_node) {
dev_info(psy->dev, "%s: Found supply : %s\n", dev_info(psy->dev, "%s: Found supply : %s\n",
@@ -158,12 +166,12 @@ static int power_supply_populate_supplied_from(struct power_supply *psy)
static int __power_supply_find_supply_from_node(struct device *dev, static int __power_supply_find_supply_from_node(struct device *dev,
void *data) void *data)
{ {
struct device_node *np = (struct device_node *)data; struct device_node *np = data;
struct power_supply *epsy = dev_get_drvdata(dev); struct power_supply *epsy = dev_get_drvdata(dev);
/* return error breaks out of class_for_each_device loop */ /* returning non-zero breaks out of class_for_each_device loop */
if (epsy->of_node == np) if (epsy->of_node == np)
return -EINVAL; return 1;
return 0; return 0;
} }
@@ -171,30 +179,21 @@ static int __power_supply_find_supply_from_node(struct device *dev,
static int power_supply_find_supply_from_node(struct device_node *supply_node) static int power_supply_find_supply_from_node(struct device_node *supply_node)
{ {
int error; int error;
struct device *dev;
struct class_dev_iter iter;
/* /*
* Use iterator to see if any other device is registered. * class_for_each_device() either returns its own errors or values
* This is required since class_for_each_device returns 0 * returned by __power_supply_find_supply_from_node().
* if there are no devices registered. *
*/ * __power_supply_find_supply_from_node() will return 0 (no match)
class_dev_iter_init(&iter, power_supply_class, NULL, NULL); * or 1 (match).
dev = class_dev_iter_next(&iter); *
* We return 0 if class_for_each_device() returned 1, -EPROBE_DEFER if
if (!dev) * it returned 0, or error as returned by it.
return -EPROBE_DEFER;
/*
* We have to treat the return value as inverted, because if
* we return error on not found, then it won't continue looking.
* So we trick it by returning error on success to stop looking
* once the matching device is found.
*/ */
error = class_for_each_device(power_supply_class, NULL, supply_node, error = class_for_each_device(power_supply_class, NULL, supply_node,
__power_supply_find_supply_from_node); __power_supply_find_supply_from_node);
return error ? 0 : -EPROBE_DEFER; return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER;
} }
static int power_supply_check_supplies(struct power_supply *psy) static int power_supply_check_supplies(struct power_supply *psy)
@@ -215,17 +214,21 @@ static int power_supply_check_supplies(struct power_supply *psy)
np = of_parse_phandle(psy->of_node, "power-supplies", cnt++); np = of_parse_phandle(psy->of_node, "power-supplies", cnt++);
if (!np) if (!np)
continue; break;
ret = power_supply_find_supply_from_node(np); ret = power_supply_find_supply_from_node(np);
if (ret) {
dev_dbg(psy->dev, "Failed to find supply, defer!\n");
of_node_put(np);
return -EPROBE_DEFER;
}
of_node_put(np); of_node_put(np);
if (ret) {
dev_dbg(psy->dev, "Failed to find supply!\n");
return ret;
}
} while (np); } while (np);
/* Missing valid "power-supplies" entries */
if (cnt == 1)
return 0;
/* 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);
@@ -234,7 +237,7 @@ static int power_supply_check_supplies(struct power_supply *psy)
return -ENOMEM; return -ENOMEM;
} }
*psy->supplied_from = devm_kzalloc(psy->dev, sizeof(char *) * cnt, *psy->supplied_from = devm_kzalloc(psy->dev, 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"); dev_err(psy->dev, "Couldn't allocate memory for supply list\n");
@@ -253,14 +256,12 @@ static inline int power_supply_check_supplies(struct power_supply *psy)
static int __power_supply_am_i_supplied(struct device *dev, void *data) static int __power_supply_am_i_supplied(struct device *dev, void *data)
{ {
union power_supply_propval ret = {0,}; union power_supply_propval ret = {0,};
struct power_supply *psy = (struct power_supply *)data; struct power_supply *psy = data;
struct power_supply *epsy = dev_get_drvdata(dev); struct power_supply *epsy = dev_get_drvdata(dev);
if (__power_supply_is_supplied_by(epsy, psy)) if (__power_supply_is_supplied_by(epsy, psy))
if (!epsy->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, &ret)) { if (!epsy->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, &ret))
if (ret.intval) return ret.intval;
return ret.intval;
}
return 0; return 0;
} }
@@ -285,12 +286,10 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
unsigned int *count = data; unsigned int *count = data;
(*count)++; (*count)++;
if (psy->type != POWER_SUPPLY_TYPE_BATTERY) { if (psy->type != POWER_SUPPLY_TYPE_BATTERY)
if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) if (!psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
return 0;
if (ret.intval)
return ret.intval; return ret.intval;
}
return 0; return 0;
} }
@@ -423,9 +422,7 @@ static int psy_register_thermal(struct power_supply *psy)
if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) {
psy->tzd = thermal_zone_device_register(psy->name, 0, 0, psy->tzd = thermal_zone_device_register(psy->name, 0, 0,
psy, &psy_tzd_ops, NULL, 0, 0); psy, &psy_tzd_ops, NULL, 0, 0);
if (IS_ERR(psy->tzd)) return PTR_ERR_OR_ZERO(psy->tzd);
return PTR_ERR(psy->tzd);
break;
} }
} }
return 0; return 0;
@@ -503,9 +500,7 @@ static int psy_register_cooler(struct power_supply *psy)
psy->tcd = thermal_cooling_device_register( psy->tcd = thermal_cooling_device_register(
(char *)psy->name, (char *)psy->name,
psy, &psy_tcd_ops); psy, &psy_tcd_ops);
if (IS_ERR(psy->tcd)) return PTR_ERR_OR_ZERO(psy->tcd);
return PTR_ERR(psy->tcd);
break;
} }
} }
return 0; return 0;
@@ -591,7 +586,7 @@ static int __power_supply_register(struct device *parent,
power_supply_changed(psy); power_supply_changed(psy);
goto success; return 0;
create_triggers_failed: create_triggers_failed:
psy_unregister_cooler(psy); psy_unregister_cooler(psy);
@@ -604,7 +599,6 @@ wakeup_init_failed:
check_supplies_failed: check_supplies_failed:
dev_set_name_failed: dev_set_name_failed:
put_device(dev); put_device(dev);
success:
return rc; return rc;
} }
+4 -15
View File
@@ -57,8 +57,6 @@ static void power_supply_update_bat_leds(struct power_supply *psy)
static int power_supply_create_bat_triggers(struct power_supply *psy) static int power_supply_create_bat_triggers(struct power_supply *psy)
{ {
int rc = 0;
psy->charging_full_trig_name = kasprintf(GFP_KERNEL, psy->charging_full_trig_name = kasprintf(GFP_KERNEL,
"%s-charging-or-full", psy->name); "%s-charging-or-full", psy->name);
if (!psy->charging_full_trig_name) if (!psy->charging_full_trig_name)
@@ -87,7 +85,7 @@ static int power_supply_create_bat_triggers(struct power_supply *psy)
led_trigger_register_simple(psy->charging_blink_full_solid_trig_name, led_trigger_register_simple(psy->charging_blink_full_solid_trig_name,
&psy->charging_blink_full_solid_trig); &psy->charging_blink_full_solid_trig);
goto success; return 0;
charging_blink_full_solid_failed: charging_blink_full_solid_failed:
kfree(psy->full_trig_name); kfree(psy->full_trig_name);
@@ -96,9 +94,7 @@ full_failed:
charging_failed: charging_failed:
kfree(psy->charging_full_trig_name); kfree(psy->charging_full_trig_name);
charging_full_failed: charging_full_failed:
rc = -ENOMEM; return -ENOMEM;
success:
return rc;
} }
static void power_supply_remove_bat_triggers(struct power_supply *psy) static void power_supply_remove_bat_triggers(struct power_supply *psy)
@@ -132,20 +128,13 @@ static void power_supply_update_gen_leds(struct power_supply *psy)
static int power_supply_create_gen_triggers(struct power_supply *psy) static int power_supply_create_gen_triggers(struct power_supply *psy)
{ {
int rc = 0;
psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online", psy->name); psy->online_trig_name = kasprintf(GFP_KERNEL, "%s-online", psy->name);
if (!psy->online_trig_name) if (!psy->online_trig_name)
goto online_failed; return -ENOMEM;
led_trigger_register_simple(psy->online_trig_name, &psy->online_trig); led_trigger_register_simple(psy->online_trig_name, &psy->online_trig);
goto success; return 0;
online_failed:
rc = -ENOMEM;
success:
return rc;
} }
static void power_supply_remove_gen_triggers(struct power_supply *psy) static void power_supply_remove_gen_triggers(struct power_supply *psy)
+14 -10
View File
@@ -73,19 +73,20 @@ static ssize_t power_supply_show_property(struct device *dev,
const ptrdiff_t off = attr - power_supply_attrs; const ptrdiff_t off = attr - power_supply_attrs;
union power_supply_propval value; union power_supply_propval value;
if (off == POWER_SUPPLY_PROP_TYPE) if (off == POWER_SUPPLY_PROP_TYPE) {
value.intval = psy->type; value.intval = psy->type;
else } else {
ret = psy->get_property(psy, off, &value); ret = psy->get_property(psy, off, &value);
if (ret < 0) { if (ret < 0) {
if (ret == -ENODATA) if (ret == -ENODATA)
dev_dbg(dev, "driver has no data for `%s' property\n", dev_dbg(dev, "driver has no data for `%s' property\n",
attr->attr.name); attr->attr.name);
else if (ret != -ENODEV) else if (ret != -ENODEV)
dev_err(dev, "driver failed to report `%s' property: %zd\n", dev_err(dev, "driver failed to report `%s' property: %zd\n",
attr->attr.name, ret); attr->attr.name, ret);
return ret; return ret;
}
} }
if (off == POWER_SUPPLY_PROP_STATUS) if (off == POWER_SUPPLY_PROP_STATUS)
@@ -149,9 +150,11 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(voltage_now), POWER_SUPPLY_ATTR(voltage_now),
POWER_SUPPLY_ATTR(voltage_avg), POWER_SUPPLY_ATTR(voltage_avg),
POWER_SUPPLY_ATTR(voltage_ocv), POWER_SUPPLY_ATTR(voltage_ocv),
POWER_SUPPLY_ATTR(voltage_boot),
POWER_SUPPLY_ATTR(current_max), POWER_SUPPLY_ATTR(current_max),
POWER_SUPPLY_ATTR(current_now), POWER_SUPPLY_ATTR(current_now),
POWER_SUPPLY_ATTR(current_avg), POWER_SUPPLY_ATTR(current_avg),
POWER_SUPPLY_ATTR(current_boot),
POWER_SUPPLY_ATTR(power_now), POWER_SUPPLY_ATTR(power_now),
POWER_SUPPLY_ATTR(power_avg), POWER_SUPPLY_ATTR(power_avg),
POWER_SUPPLY_ATTR(charge_full_design), POWER_SUPPLY_ATTR(charge_full_design),
@@ -193,6 +196,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(type), POWER_SUPPLY_ATTR(type),
POWER_SUPPLY_ATTR(scope), POWER_SUPPLY_ATTR(scope),
POWER_SUPPLY_ATTR(charge_term_current), POWER_SUPPLY_ATTR(charge_term_current),
POWER_SUPPLY_ATTR(calibrate),
/* Properties of type `const char *' */ /* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name), POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer), POWER_SUPPLY_ATTR(manufacturer),

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