You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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 = <®mapnode>;
|
||||||
|
offset = <0x0>;
|
||||||
|
mask = <0x1>;
|
||||||
|
};
|
||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user