power supply and reset changes for the v4.4 series
* new AXP20X USB Power driver * new Qualcomm SMBB driver * new TPS65217 Charger driver * BQ24257: add BQ24250/BQ24251 support * overhaul bq27x00 battery driver, rename to bq27xxx * misc. fixes and cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCgAGBQJWOn8oAAoJENju1/PIO/qahrEP/RPHXvTxtYv8YvhaFbqcr07x 11gRB8RRthKK5woC3s70QKlMtcHijFeCwKuacut+7tfgK2oZDIm+Bd43Pl93aypU Yk4oTwop5OyrLsGIGiTIPPV9HTwr4q69Or2Q91mqUAUe2wGB5uCuJiJmCowUwfZs piv+ISLSOcH+i1bTx3hQ7h7axsdAlaSz2o1JprZaxm3rM67M8zF1ZHSK7wlpAeBa DiDrtUvEDCeLL8dmCA9xkFV4yFB9T+KNh0730N2RY+zlZS6WjSpzryqwsUWWyQ6h U9gFgcs+DjVaGHuMsIX2zm7xXfXHgUBtXdSQoCBhpSrZsdufMsT/8VQqVZ0yqpXL pQ2EXy63k6tXnXEyAKTA0tAOX/WZNfmmNblkea4JiyZULn7b/WH09waMZUBJqe84 Yn3SatVdGDN4nawsivzdiM3zR9/WTE9R3DmEeAE+g1RRsSraNwWlkzpDXcmnWmbc DoprnjLsDJfqL3/1ysF2V2I4B26Bws73qq6UUjJ4KEGWf8Y1fVawxrbcYmnrvg1K zW/saEgtl70FYqtee/0lIqTpjOZRX/O6QH5i8p7VC8cUzftX0Twc8MvfvpamDywX Cr1Y7pIMEhc6TFUP5lOzx9xJelA5PHJMpAT+02fh6YXMAzCcBUzL113rY5zBrVVl gce0iHDKAybmvww77z1r =0be4 -----END PGP SIGNATURE----- Merge tag 'for-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply Pull power supply and reset updates from Sebastian Reichel: - new AXP20X USB Power driver - new Qualcomm SMBB driver - new TPS65217 Charger driver - BQ24257: add BQ24250/BQ24251 support - overhaul bq27x00 battery driver, rename to bq27xxx - misc fixes and cleanups * tag 'for-v4.4' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (54 commits) power: bq27xxx_battery: Remove unneeded dependency in Kconfig power: bq27xxx_battery: move irq handler to i2c section power: bq27xxx_battery: fix platform probe twl4030_charger: add missing iio dependency power_supply: charger-manager: add missing of_node_put Documentation: power: bq24257: Document exported sysfs entries power: bq24257: Add various device-specific sysfs properties power: bq24257: Allow input current limit sysfs access power: bq24257: Add input DPM voltage threshold setting support power: bq24257: Add over voltage protection setting support power: bq24257: Add SW-based approach for Power Good determination power: bq24257: Allow manual setting of input current limit power: bq24257: Add bit definition for temp sense enable power: bq24257: Add basic support for bq24250/bq24251 dt: power: bq24257-charger: Cover additional devices power: bq24257: Simplify bq24257_power_supply_init() power: bq24257: Use managed power supply register power: bq24257: Streamline input current limit setup power: bq24257: Remove IRQ config through stat-gpios power: bq27xxx_battery: fix signedness bug in bq27xxx_battery_read_health() ...
This commit is contained in:
commit
400c5bd5a5
39 changed files with 3818 additions and 1474 deletions
|
|
@ -74,3 +74,61 @@ Description:
|
|||
|
||||
Valid values:
|
||||
- 0 - 70 (minutes), step by 10 (rounded down)
|
||||
|
||||
What: /sys/class/power_supply/bq24257-charger/ovp_voltage
|
||||
Date: October 2015
|
||||
KernelVersion: 4.4.0
|
||||
Contact: Andreas Dannenberg <dannenberg@ti.com>
|
||||
Description:
|
||||
This entry configures the overvoltage protection feature of bq24257-
|
||||
type charger devices. This feature protects the device and other
|
||||
components against damage from overvoltage on the input supply. See
|
||||
device datasheet for details.
|
||||
|
||||
Valid values:
|
||||
- 6000000, 6500000, 7000000, 8000000, 9000000, 9500000, 10000000,
|
||||
10500000 (all uV)
|
||||
|
||||
What: /sys/class/power_supply/bq24257-charger/in_dpm_voltage
|
||||
Date: October 2015
|
||||
KernelVersion: 4.4.0
|
||||
Contact: Andreas Dannenberg <dannenberg@ti.com>
|
||||
Description:
|
||||
This entry configures the input dynamic power path management voltage of
|
||||
bq24257-type charger devices. Once the supply drops to the configured
|
||||
voltage, the input current limit is reduced down to prevent the further
|
||||
drop of the supply. When the IC enters this mode, the charge current is
|
||||
lower than the set value. See device datasheet for details.
|
||||
|
||||
Valid values:
|
||||
- 4200000, 4280000, 4360000, 4440000, 4520000, 4600000, 4680000,
|
||||
4760000 (all uV)
|
||||
|
||||
What: /sys/class/power_supply/bq24257-charger/high_impedance_enable
|
||||
Date: October 2015
|
||||
KernelVersion: 4.4.0
|
||||
Contact: Andreas Dannenberg <dannenberg@ti.com>
|
||||
Description:
|
||||
This entry allows enabling the high-impedance mode of bq24257-type
|
||||
charger devices. If enabled, it places the charger IC into low power
|
||||
standby mode with the switch mode controller disabled. When disabled,
|
||||
the charger operates normally. See device datasheet for details.
|
||||
|
||||
Valid values:
|
||||
- 1: enabled
|
||||
- 0: disabled
|
||||
|
||||
What: /sys/class/power_supply/bq24257-charger/sysoff_enable
|
||||
Date: October 2015
|
||||
KernelVersion: 4.4.0
|
||||
Contact: Andreas Dannenberg <dannenberg@ti.com>
|
||||
Description:
|
||||
This entry allows enabling the sysoff mode of bq24257-type charger
|
||||
devices. If enabled and the input is removed, the internal battery FET
|
||||
is turned off in order to reduce the leakage from the BAT pin to less
|
||||
than 1uA. Note that on some devices/systems this disconnects the battery
|
||||
from the system. See device datasheet for details.
|
||||
|
||||
Valid values:
|
||||
- 1: enabled
|
||||
- 0: disabled
|
||||
|
|
|
|||
|
|
@ -1,21 +1,64 @@
|
|||
Binding for TI bq24257 Li-Ion Charger
|
||||
Binding for TI bq24250/bq24251/bq24257 Li-Ion Charger
|
||||
|
||||
Required properties:
|
||||
- compatible: Should contain one of the following:
|
||||
* "ti,bq24250"
|
||||
* "ti,bq24251"
|
||||
* "ti,bq24257"
|
||||
- reg: integer, i2c address of the device.
|
||||
- reg: integer, i2c address of the device.
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller. Use in
|
||||
conjunction with "interrupts".
|
||||
- interrupts: Interrupt mapping for GPIO IRQ (configure for both edges). Use in
|
||||
conjunction with "interrupt-parent".
|
||||
- ti,battery-regulation-voltage: integer, maximum charging voltage in uV.
|
||||
- ti,charge-current: integer, maximum charging current in uA.
|
||||
- ti,termination-current: integer, charge will be terminated when current in
|
||||
constant-voltage phase drops below this value (in uA).
|
||||
- ti,charge-current: integer, maximum charging current in uA.
|
||||
- ti,termination-current: integer, charge will be terminated when current in
|
||||
constant-voltage phase drops below this value (in uA).
|
||||
|
||||
Optional properties:
|
||||
- pg-gpios: GPIO used for connecting the bq2425x device PG (Power Good) pin.
|
||||
This pin is not available on all devices however it should be used if
|
||||
possible as this is the recommended way to obtain the charger's input PG
|
||||
state. If this pin is not specified a software-based approach for PG
|
||||
detection is used.
|
||||
- ti,current-limit: The maximum current to be drawn from the charger's input
|
||||
(in uA). If this property is not specified, the input limit current is
|
||||
set automatically using USB D+/D- signal based charger type detection.
|
||||
If the hardware does not support the D+/D- based detection, a default
|
||||
of 500,000 is used (=500mA) instead.
|
||||
- ti,ovp-voltage: Configures the over voltage protection voltage (in uV). If
|
||||
not specified a default of 6,5000,000 (=6.5V) is used.
|
||||
- ti,in-dpm-voltage: Configures the threshold input voltage for the dynamic
|
||||
power path management (in uV). If not specified a default of 4,360,000
|
||||
(=4.36V) is used.
|
||||
|
||||
Example:
|
||||
|
||||
bq24257 {
|
||||
compatible = "ti,bq24257";
|
||||
reg = <0x6a>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <16 IRQ_TYPE_EDGE_BOTH>;
|
||||
|
||||
pg-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
ti,battery-regulation-voltage = <4200000>;
|
||||
ti,charge-current = <1000000>;
|
||||
ti,termination-current = <50000>;
|
||||
};
|
||||
|
||||
Example:
|
||||
|
||||
bq24250 {
|
||||
compatible = "ti,bq24250";
|
||||
reg = <0x6a>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <16 IRQ_TYPE_EDGE_BOTH>;
|
||||
|
||||
ti,battery-regulation-voltage = <4200000>;
|
||||
ti,charge-current = <500000>;
|
||||
ti,termination-current = <50000>;
|
||||
ti,current-limit = <900000>;
|
||||
ti,ovp-voltage = <9500000>;
|
||||
ti,in-dpm-voltage = <4440000>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
AXP20x USB power supply
|
||||
|
||||
Required Properties:
|
||||
-compatible: "x-powers,axp202-usb-power-supply"
|
||||
|
||||
This node is a subnode of the axp20x PMIC.
|
||||
|
||||
Example:
|
||||
|
||||
axp209: pmic@34 {
|
||||
compatible = "x-powers,axp209";
|
||||
reg = <0x34>;
|
||||
interrupt-parent = <&nmi_intc>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
|
||||
regulators {
|
||||
x-powers,dcdc-freq = <1500>;
|
||||
|
||||
vdd_cpu: dcdc2 {
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1450000>;
|
||||
regulator-name = "vdd-cpu";
|
||||
};
|
||||
|
||||
...
|
||||
};
|
||||
|
||||
usb-power-supply: usb-power-supply {
|
||||
compatible = "x-powers,axp202-usb-power-supply";
|
||||
};
|
||||
};
|
||||
131
Documentation/devicetree/bindings/power_supply/qcom_smbb.txt
Normal file
131
Documentation/devicetree/bindings/power_supply/qcom_smbb.txt
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
Qualcomm Switch-Mode Battery Charger and Boost
|
||||
|
||||
PROPERTIES
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Description: Must be one of:
|
||||
- "qcom,pm8941-charger"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Description: Base address of registers for SMBB block
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Description: The format of the specifier is defined by the binding document
|
||||
describing the node's interrupt parent. Must contain one
|
||||
specifier for each of the following interrupts, in order:
|
||||
- charge done
|
||||
- charge fast mode
|
||||
- charge trickle mode
|
||||
- battery temperature ok
|
||||
- battery present
|
||||
- charger disconnected
|
||||
- USB-in valid
|
||||
- DC-in valid
|
||||
|
||||
- interrupt-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Description: Must contain the following list, strictly ordered:
|
||||
"chg-done",
|
||||
"chg-fast",
|
||||
"chg-trkl",
|
||||
"bat-temp-ok",
|
||||
"bat-present",
|
||||
"chg-gone",
|
||||
"usb-valid",
|
||||
"dc-valid"
|
||||
|
||||
- qcom,fast-charge-current-limit:
|
||||
Usage: optional (default: 1A, or pre-configured value)
|
||||
Value type: <u32>; uA; range [100mA : 3A]
|
||||
Description: Maximum charge current; May be clamped to safety limits.
|
||||
|
||||
- qcom,fast-charge-low-threshold-voltage:
|
||||
Usage: optional (default: 3.2V, or pre-configured value)
|
||||
Value type: <u32>; uV; range [2.1V : 3.6V]
|
||||
Description: Battery voltage limit above which fast charging may operate;
|
||||
Below this value linear or switch-mode auto-trickle-charging
|
||||
will operate.
|
||||
|
||||
- qcom,fast-charge-high-threshold-voltage:
|
||||
Usage: optional (default: 4.2V, or pre-configured value)
|
||||
Value type: <u32>; uV; range [3.24V : 5V]
|
||||
Description: Battery voltage limit below which fast charging may operate;
|
||||
The fast charger will attempt to charge the battery to this
|
||||
voltage. May be clamped to safety limits.
|
||||
|
||||
- qcom,fast-charge-safe-voltage:
|
||||
Usage: optional (default: 4.2V, or pre-configured value)
|
||||
Value type: <u32>; uV; range [3.24V : 5V]
|
||||
Description: Maximum safe battery voltage; May be pre-set by bootloader, in
|
||||
which case, setting this will harmlessly fail. The property
|
||||
'fast-charge-high-watermark' will be clamped by this value.
|
||||
|
||||
- qcom,fast-charge-safe-current:
|
||||
Usage: optional (default: 1A, or pre-configured value)
|
||||
Value type: <u32>; uA; range [100mA : 3A]
|
||||
Description: Maximum safe battery charge current; May pre-set by bootloader,
|
||||
in which case, setting this will harmlessly fail. The property
|
||||
'qcom,fast-charge-current-limit' will be clamped by this value.
|
||||
|
||||
- qcom,auto-recharge-threshold-voltage:
|
||||
Usage: optional (default: 4.1V, or pre-configured value)
|
||||
Value type: <u32>; uV; range [3.24V : 5V]
|
||||
Description: Battery voltage limit below which auto-recharge functionality
|
||||
will restart charging after end-of-charge; The high cutoff
|
||||
limit for auto-recharge is 5% above this value.
|
||||
|
||||
- qcom,minimum-input-voltage:
|
||||
Usage: optional (default: 4.3V, or pre-configured value)
|
||||
Value type: <u32>; uV; range [4.2V : 9.6V]
|
||||
Description: Input voltage level above which charging may operate
|
||||
|
||||
- qcom,dc-current-limit:
|
||||
Usage: optional (default: 100mA, or pre-configured value)
|
||||
Value type: <u32>; uA; range [100mA : 2.5A]
|
||||
Description: Default DC charge current limit
|
||||
|
||||
- qcom,disable-dc:
|
||||
Usage: optional (default: false)
|
||||
Value type: boolean: <u32> or <empty>
|
||||
Description: Disable DC charger
|
||||
|
||||
- qcom,jeita-extended-temp-range:
|
||||
Usage: optional (default: false)
|
||||
Value type: boolean: <u32> or <empty>
|
||||
Description: Enable JEITA extended temperature range; This does *not*
|
||||
adjust the maximum charge voltage or current in the extended
|
||||
temperature range. It only allows charging when the battery
|
||||
is in the extended temperature range. Voltage/current
|
||||
regulation must be done externally to fully comply with
|
||||
the JEITA safety guidelines if this flag is set.
|
||||
|
||||
EXAMPLE
|
||||
charger@1000 {
|
||||
compatible = "qcom,pm8941-charger";
|
||||
reg = <0x1000 0x700>;
|
||||
interrupts = <0x0 0x10 7 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x10 5 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x10 4 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x12 1 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x12 0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x13 2 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x13 1 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x14 1 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "chg-done",
|
||||
"chg-fast",
|
||||
"chg-trkl",
|
||||
"bat-temp-ok",
|
||||
"bat-present",
|
||||
"chg-gone",
|
||||
"usb-valid",
|
||||
"dc-valid";
|
||||
|
||||
qcom,fast-charge-current-limit = <1000000>;
|
||||
qcom,dc-charge-current-limit = <1000000>;
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
TPS65217 Charger
|
||||
|
||||
Required Properties:
|
||||
-compatible: "ti,tps65217-charger"
|
||||
|
||||
This node is a subnode of the tps65217 PMIC.
|
||||
|
||||
Example:
|
||||
|
||||
tps65217-charger {
|
||||
compatible = "ti,tps65090-charger";
|
||||
};
|
||||
|
|
@ -7505,10 +7505,10 @@ NOKIA N900 POWER SUPPLY DRIVERS
|
|||
M: Pali Rohár <pali.rohar@gmail.com>
|
||||
S: Maintained
|
||||
F: include/linux/power/bq2415x_charger.h
|
||||
F: include/linux/power/bq27x00_battery.h
|
||||
F: include/linux/power/bq27xxx_battery.h
|
||||
F: include/linux/power/isp1704_charger.h
|
||||
F: drivers/power/bq2415x_charger.c
|
||||
F: drivers/power/bq27x00_battery.c
|
||||
F: drivers/power/bq27xxx_battery.c
|
||||
F: drivers/power/isp1704_charger.c
|
||||
F: drivers/power/rx51_battery.c
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
charger: bci {
|
||||
compatible = "ti,twl4030-bci";
|
||||
interrupts = <9>, <2>;
|
||||
io-channels = <&twl4030_madc 11>;
|
||||
io-channel-name = "vac";
|
||||
bci3v1-supply = <&vusb3v1>;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ CONFIG_GPIO_TWL4030=y
|
|||
CONFIG_GPIO_PALMAS=y
|
||||
CONFIG_W1=m
|
||||
CONFIG_HDQ_MASTER_OMAP=m
|
||||
CONFIG_BATTERY_BQ27x00=m
|
||||
CONFIG_BATTERY_BQ27XXX=m
|
||||
CONFIG_CHARGER_ISP1704=m
|
||||
CONFIG_CHARGER_TWL4030=m
|
||||
CONFIG_CHARGER_BQ2415X=m
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ config I2C_BATTERY_BQ27200
|
|||
tristate "I2C Battery BQ27200 Support"
|
||||
select I2C_PUV3
|
||||
select POWER_SUPPLY
|
||||
select BATTERY_BQ27x00
|
||||
select BATTERY_BQ27XXX
|
||||
|
||||
config I2C_EEPROM_AT24
|
||||
tristate "I2C EEPROMs AT24 support"
|
||||
|
|
|
|||
|
|
@ -954,46 +954,32 @@ static int pm860x_battery_probe(struct platform_device *pdev)
|
|||
else
|
||||
info->resistor = 300; /* set default internal resistor */
|
||||
|
||||
info->battery = power_supply_register(&pdev->dev, &pm860x_battery_desc,
|
||||
NULL);
|
||||
info->battery = devm_power_supply_register(&pdev->dev,
|
||||
&pm860x_battery_desc,
|
||||
NULL);
|
||||
if (IS_ERR(info->battery))
|
||||
return PTR_ERR(info->battery);
|
||||
info->battery->dev.parent = &pdev->dev;
|
||||
|
||||
ret = request_threaded_irq(info->irq_cc, NULL,
|
||||
pm860x_coulomb_handler, IRQF_ONESHOT,
|
||||
"coulomb", info);
|
||||
ret = devm_request_threaded_irq(chip->dev, info->irq_cc, NULL,
|
||||
pm860x_coulomb_handler, IRQF_ONESHOT,
|
||||
"coulomb", info);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
|
||||
info->irq_cc, ret);
|
||||
goto out_reg;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(info->irq_batt, NULL, pm860x_batt_handler,
|
||||
IRQF_ONESHOT, "battery", info);
|
||||
ret = devm_request_threaded_irq(chip->dev, info->irq_batt, NULL,
|
||||
pm860x_batt_handler,
|
||||
IRQF_ONESHOT, "battery", info);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
|
||||
info->irq_batt, ret);
|
||||
goto out_coulomb;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
out_coulomb:
|
||||
free_irq(info->irq_cc, info);
|
||||
out_reg:
|
||||
power_supply_unregister(info->battery);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pm860x_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pm860x_battery_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
free_irq(info->irq_batt, info);
|
||||
free_irq(info->irq_cc, info);
|
||||
power_supply_unregister(info->battery);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1028,7 +1014,6 @@ static struct platform_driver pm860x_battery_driver = {
|
|||
.pm = &pm860x_battery_pm_ops,
|
||||
},
|
||||
.probe = pm860x_battery_probe,
|
||||
.remove = pm860x_battery_remove,
|
||||
};
|
||||
module_platform_driver(pm860x_battery_driver);
|
||||
|
||||
|
|
|
|||
|
|
@ -157,26 +157,25 @@ config BATTERY_SBS
|
|||
Say Y to include support for SBS battery driver for SBS-compliant
|
||||
gas gauges.
|
||||
|
||||
config BATTERY_BQ27x00
|
||||
tristate "BQ27x00 battery driver"
|
||||
depends on I2C || I2C=n
|
||||
config BATTERY_BQ27XXX
|
||||
tristate "BQ27xxx battery driver"
|
||||
help
|
||||
Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
|
||||
Say Y here to enable support for batteries with BQ27xxx (I2C/HDQ) chips.
|
||||
|
||||
config BATTERY_BQ27X00_I2C
|
||||
bool "BQ27200/BQ27500 support"
|
||||
depends on BATTERY_BQ27x00
|
||||
config BATTERY_BQ27XXX_I2C
|
||||
bool "BQ27xxx I2C support"
|
||||
depends on BATTERY_BQ27XXX
|
||||
depends on I2C
|
||||
default y
|
||||
help
|
||||
Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
|
||||
Say Y here to enable support for batteries with BQ27xxx (I2C) chips.
|
||||
|
||||
config BATTERY_BQ27X00_PLATFORM
|
||||
bool "BQ27000 support"
|
||||
depends on BATTERY_BQ27x00
|
||||
config BATTERY_BQ27XXX_PLATFORM
|
||||
bool "BQ27xxx HDQ support"
|
||||
depends on BATTERY_BQ27XXX
|
||||
default y
|
||||
help
|
||||
Say Y here to enable support for batteries with BQ27000 (HDQ) chips.
|
||||
Say Y here to enable support for batteries with BQ27xxx (HDQ) chips.
|
||||
|
||||
config BATTERY_DA9030
|
||||
tristate "DA9030 battery driver"
|
||||
|
|
@ -313,7 +312,7 @@ config CHARGER_MAX8903
|
|||
|
||||
config CHARGER_TWL4030
|
||||
tristate "OMAP TWL4030 BCI charger driver"
|
||||
depends on TWL4030_CORE
|
||||
depends on IIO && TWL4030_CORE
|
||||
help
|
||||
Say Y here to enable support for TWL4030 Battery Charge Interface.
|
||||
|
||||
|
|
@ -379,6 +378,18 @@ config CHARGER_MAX8998
|
|||
Say Y to enable support for the battery charger control sysfs and
|
||||
platform data of MAX8998/LP3974 PMICs.
|
||||
|
||||
config CHARGER_QCOM_SMBB
|
||||
tristate "Qualcomm Switch-Mode Battery Charger and Boost"
|
||||
depends on MFD_SPMI_PMIC || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
Say Y to include support for the Switch-Mode Battery Charger and
|
||||
Boost (SMBB) hardware found in Qualcomm PM8941 PMICs. The charger
|
||||
is an integrated, single-cell lithium-ion battery charger. DT
|
||||
configuration is required for loading, see the devicetree
|
||||
documentation for more detail. The base name for this driver is
|
||||
'pm8941_charger'.
|
||||
|
||||
config CHARGER_BQ2415X
|
||||
tristate "TI BQ2415x battery charger driver"
|
||||
depends on I2C
|
||||
|
|
@ -397,12 +408,13 @@ config CHARGER_BQ24190
|
|||
Say Y to enable support for the TI BQ24190 battery charger.
|
||||
|
||||
config CHARGER_BQ24257
|
||||
tristate "TI BQ24257 battery charger driver"
|
||||
tristate "TI BQ24250/24251/24257 battery charger driver"
|
||||
depends on I2C
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
depends on REGMAP_I2C
|
||||
help
|
||||
Say Y to enable support for the TI BQ24257 battery charger.
|
||||
Say Y to enable support for the TI BQ24250, BQ24251, and BQ24257 battery
|
||||
chargers.
|
||||
|
||||
config CHARGER_BQ24735
|
||||
tristate "TI BQ24735 battery charger support"
|
||||
|
|
@ -434,6 +446,13 @@ config CHARGER_TPS65090
|
|||
Say Y here to enable support for battery charging with TPS65090
|
||||
PMIC chips.
|
||||
|
||||
config CHARGER_TPS65217
|
||||
tristate "TPS65217 battery charger driver"
|
||||
depends on MFD_TPS65217
|
||||
help
|
||||
Say Y here to enable support for battery charging with TPS65217
|
||||
PMIC chips.
|
||||
|
||||
config BATTERY_GAUGE_LTC2941
|
||||
tristate "LTC2941/LTC2943 Battery Gauge Driver"
|
||||
depends on I2C
|
||||
|
|
@ -472,6 +491,13 @@ config CHARGER_RT9455
|
|||
help
|
||||
Say Y to enable support for Richtek RT9455 battery charger.
|
||||
|
||||
config AXP20X_POWER
|
||||
tristate "AXP20x power supply driver"
|
||||
depends on MFD_AXP20X
|
||||
help
|
||||
This driver provides support for the power supply features of
|
||||
AXP20x PMIC.
|
||||
|
||||
source "drivers/power/reset/Kconfig"
|
||||
|
||||
endif # POWER_SUPPLY
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o
|
|||
|
||||
obj-$(CONFIG_PDA_POWER) += pda_power.o
|
||||
obj-$(CONFIG_APM_POWER) += apm_power.o
|
||||
obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o
|
||||
obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
|
||||
obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
|
||||
obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
|
||||
|
|
@ -29,7 +30,7 @@ obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
|
|||
obj-$(CONFIG_BATTERY_IPAQ_MICRO) += ipaq_micro_battery.o
|
||||
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
|
||||
obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
|
||||
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
|
||||
obj-$(CONFIG_BATTERY_BQ27XXX) += bq27xxx_battery.o
|
||||
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
|
||||
obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
|
||||
obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o
|
||||
|
|
@ -57,6 +58,7 @@ obj-$(CONFIG_CHARGER_MAX14577) += max14577_charger.o
|
|||
obj-$(CONFIG_CHARGER_MAX77693) += max77693_charger.o
|
||||
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
|
||||
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
|
||||
obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o
|
||||
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
|
||||
obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o
|
||||
obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o
|
||||
|
|
@ -65,6 +67,7 @@ obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
|
|||
obj-$(CONFIG_POWER_AVS) += avs/
|
||||
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
|
||||
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
|
||||
obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
|
||||
obj-$(CONFIG_POWER_RESET) += reset/
|
||||
obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
|
||||
obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o
|
||||
|
|
|
|||
248
drivers/power/axp20x_usb_power.c
Normal file
248
drivers/power/axp20x_usb_power.c
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* AXP20x PMIC USB power supply status driver
|
||||
*
|
||||
* Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
|
||||
* Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/axp20x.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DRVNAME "axp20x-usb-power-supply"
|
||||
|
||||
#define AXP20X_PWR_STATUS_VBUS_PRESENT BIT(5)
|
||||
#define AXP20X_PWR_STATUS_VBUS_USED BIT(4)
|
||||
|
||||
#define AXP20X_USB_STATUS_VBUS_VALID BIT(2)
|
||||
|
||||
#define AXP20X_VBUS_VHOLD_uV(b) (4000000 + (((b) >> 3) & 7) * 100000)
|
||||
#define AXP20X_VBUS_CLIMIT_MASK 3
|
||||
#define AXP20X_VBUC_CLIMIT_900mA 0
|
||||
#define AXP20X_VBUC_CLIMIT_500mA 1
|
||||
#define AXP20X_VBUC_CLIMIT_100mA 2
|
||||
#define AXP20X_VBUC_CLIMIT_NONE 3
|
||||
|
||||
#define AXP20X_ADC_EN1_VBUS_CURR BIT(2)
|
||||
#define AXP20X_ADC_EN1_VBUS_VOLT BIT(3)
|
||||
|
||||
#define AXP20X_VBUS_MON_VBUS_VALID BIT(3)
|
||||
|
||||
struct axp20x_usb_power {
|
||||
struct regmap *regmap;
|
||||
struct power_supply *supply;
|
||||
};
|
||||
|
||||
static irqreturn_t axp20x_usb_power_irq(int irq, void *devid)
|
||||
{
|
||||
struct axp20x_usb_power *power = devid;
|
||||
|
||||
power_supply_changed(power->supply);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int axp20x_usb_power_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp, union power_supply_propval *val)
|
||||
{
|
||||
struct axp20x_usb_power *power = power_supply_get_drvdata(psy);
|
||||
unsigned int input, v;
|
||||
int ret;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
|
||||
ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val->intval = AXP20X_VBUS_VHOLD_uV(v);
|
||||
return 0;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = axp20x_read_variable_width(power->regmap,
|
||||
AXP20X_VBUS_V_ADC_H, 12);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = ret * 1700; /* 1 step = 1.7 mV */
|
||||
return 0;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (v & AXP20X_VBUS_CLIMIT_MASK) {
|
||||
case AXP20X_VBUC_CLIMIT_100mA:
|
||||
val->intval = 100000;
|
||||
break;
|
||||
case AXP20X_VBUC_CLIMIT_500mA:
|
||||
val->intval = 500000;
|
||||
break;
|
||||
case AXP20X_VBUC_CLIMIT_900mA:
|
||||
val->intval = 900000;
|
||||
break;
|
||||
case AXP20X_VBUC_CLIMIT_NONE:
|
||||
val->intval = -1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||
ret = axp20x_read_variable_width(power->regmap,
|
||||
AXP20X_VBUS_I_ADC_H, 12);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = ret * 375; /* 1 step = 0.375 mA */
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* All the properties below need the input-status reg value */
|
||||
ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
if (!(input & AXP20X_PWR_STATUS_VBUS_PRESENT)) {
|
||||
val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = regmap_read(power->regmap, AXP20X_USB_OTG_STATUS, &v);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(v & AXP20X_USB_STATUS_VBUS_VALID)) {
|
||||
val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
val->intval = POWER_SUPPLY_HEALTH_GOOD;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum power_supply_property axp20x_usb_power_properties[] = {
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_MIN,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc axp20x_usb_power_desc = {
|
||||
.name = "axp20x-usb",
|
||||
.type = POWER_SUPPLY_TYPE_USB,
|
||||
.properties = axp20x_usb_power_properties,
|
||||
.num_properties = ARRAY_SIZE(axp20x_usb_power_properties),
|
||||
.get_property = axp20x_usb_power_get_property,
|
||||
};
|
||||
|
||||
static int axp20x_usb_power_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct axp20x_usb_power *power;
|
||||
static const char * const irq_names[] = { "VBUS_PLUGIN",
|
||||
"VBUS_REMOVAL", "VBUS_VALID", "VBUS_NOT_VALID" };
|
||||
int i, irq, ret;
|
||||
|
||||
if (!of_device_is_available(pdev->dev.of_node))
|
||||
return -ENODEV;
|
||||
|
||||
if (!axp20x) {
|
||||
dev_err(&pdev->dev, "Parent drvdata not set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL);
|
||||
if (!power)
|
||||
return -ENOMEM;
|
||||
|
||||
power->regmap = axp20x->regmap;
|
||||
|
||||
/* Enable vbus valid checking */
|
||||
ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON,
|
||||
AXP20X_VBUS_MON_VBUS_VALID, AXP20X_VBUS_MON_VBUS_VALID);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable vbus voltage and current measurement */
|
||||
ret = regmap_update_bits(power->regmap, AXP20X_ADC_EN1,
|
||||
AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT,
|
||||
AXP20X_ADC_EN1_VBUS_CURR | AXP20X_ADC_EN1_VBUS_VOLT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
psy_cfg.of_node = pdev->dev.of_node;
|
||||
psy_cfg.drv_data = power;
|
||||
|
||||
power->supply = devm_power_supply_register(&pdev->dev,
|
||||
&axp20x_usb_power_desc, &psy_cfg);
|
||||
if (IS_ERR(power->supply))
|
||||
return PTR_ERR(power->supply);
|
||||
|
||||
/* Request irqs after registering, as irqs may trigger immediately */
|
||||
for (i = 0; i < ARRAY_SIZE(irq_names); i++) {
|
||||
irq = platform_get_irq_byname(pdev, irq_names[i]);
|
||||
if (irq < 0) {
|
||||
dev_warn(&pdev->dev, "No IRQ for %s: %d\n",
|
||||
irq_names[i], irq);
|
||||
continue;
|
||||
}
|
||||
irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq);
|
||||
ret = devm_request_any_context_irq(&pdev->dev, irq,
|
||||
axp20x_usb_power_irq, 0, DRVNAME, power);
|
||||
if (ret < 0)
|
||||
dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n",
|
||||
irq_names[i], ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id axp20x_usb_power_match[] = {
|
||||
{ .compatible = "x-powers,axp202-usb-power-supply" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, axp20x_usb_power_match);
|
||||
|
||||
static struct platform_driver axp20x_usb_power_driver = {
|
||||
.probe = axp20x_usb_power_probe,
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.of_match_table = axp20x_usb_power_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(axp20x_usb_power_driver);
|
||||
|
||||
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
|
||||
MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1704,7 +1704,7 @@ error_4:
|
|||
error_3:
|
||||
bq2415x_power_supply_exit(bq);
|
||||
error_2:
|
||||
if (bq->notify_node)
|
||||
if (bq && bq->notify_node)
|
||||
of_node_put(bq->notify_node);
|
||||
kfree(name);
|
||||
error_1:
|
||||
|
|
|
|||
|
|
@ -1543,5 +1543,4 @@ module_i2c_driver(bq24190_driver);
|
|||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mark A. Greer <mgreer@animalcreek.com>");
|
||||
MODULE_ALIAS("i2c:bq24190-charger");
|
||||
MODULE_DESCRIPTION("TI BQ24190 Charger Driver");
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Datasheets:
|
||||
* http://www.ti.com/product/bq24250
|
||||
* http://www.ti.com/product/bq24251
|
||||
* http://www.ti.com/product/bq24257
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
|
@ -36,18 +40,33 @@
|
|||
#define BQ24257_REG_7 0x06
|
||||
|
||||
#define BQ24257_MANUFACTURER "Texas Instruments"
|
||||
#define BQ24257_STAT_IRQ "stat"
|
||||
#define BQ24257_PG_GPIO "pg"
|
||||
|
||||
#define BQ24257_ILIM_SET_DELAY 1000 /* msec */
|
||||
|
||||
/*
|
||||
* When adding support for new devices make sure that enum bq2425x_chip and
|
||||
* bq2425x_chip_name[] always stay in sync!
|
||||
*/
|
||||
enum bq2425x_chip {
|
||||
BQ24250,
|
||||
BQ24251,
|
||||
BQ24257,
|
||||
};
|
||||
|
||||
static const char *const bq2425x_chip_name[] = {
|
||||
"bq24250",
|
||||
"bq24251",
|
||||
"bq24257",
|
||||
};
|
||||
|
||||
enum bq24257_fields {
|
||||
F_WD_FAULT, F_WD_EN, F_STAT, F_FAULT, /* REG 1 */
|
||||
F_RESET, F_IILIMIT, F_EN_STAT, F_EN_TERM, F_CE, F_HZ_MODE, /* REG 2 */
|
||||
F_VBAT, F_USB_DET, /* REG 3 */
|
||||
F_ICHG, F_ITERM, /* REG 4 */
|
||||
F_LOOP_STATUS, F_LOW_CHG, F_DPDM_EN, F_CE_STATUS, F_VINDPM, /* REG 5 */
|
||||
F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_STAT, /* REG 6 */
|
||||
F_X2_TMR_EN, F_TMR, F_SYSOFF, F_TS_EN, F_TS_STAT, /* REG 6 */
|
||||
F_VOVP, F_CLR_VDP, F_FORCE_BATDET, F_FORCE_PTM, /* REG 7 */
|
||||
|
||||
F_MAX_FIELDS
|
||||
|
|
@ -58,6 +77,9 @@ struct bq24257_init_data {
|
|||
u8 ichg; /* charge current */
|
||||
u8 vbat; /* regulation voltage */
|
||||
u8 iterm; /* termination current */
|
||||
u8 iilimit; /* input current limit */
|
||||
u8 vovp; /* over voltage protection voltage */
|
||||
u8 vindpm; /* VDMP input threshold voltage */
|
||||
};
|
||||
|
||||
struct bq24257_state {
|
||||
|
|
@ -71,6 +93,8 @@ struct bq24257_device {
|
|||
struct device *dev;
|
||||
struct power_supply *charger;
|
||||
|
||||
enum bq2425x_chip chip;
|
||||
|
||||
struct regmap *rmap;
|
||||
struct regmap_field *rmap_fields[F_MAX_FIELDS];
|
||||
|
||||
|
|
@ -82,6 +106,8 @@ struct bq24257_device {
|
|||
struct bq24257_state state;
|
||||
|
||||
struct mutex lock; /* protect state data */
|
||||
|
||||
bool iilimit_autoset_enable;
|
||||
};
|
||||
|
||||
static bool bq24257_is_volatile_reg(struct device *dev, unsigned int reg)
|
||||
|
|
@ -135,6 +161,7 @@ static const struct reg_field bq24257_reg_fields[] = {
|
|||
[F_X2_TMR_EN] = REG_FIELD(BQ24257_REG_6, 7, 7),
|
||||
[F_TMR] = REG_FIELD(BQ24257_REG_6, 5, 6),
|
||||
[F_SYSOFF] = REG_FIELD(BQ24257_REG_6, 4, 4),
|
||||
[F_TS_EN] = REG_FIELD(BQ24257_REG_6, 3, 3),
|
||||
[F_TS_STAT] = REG_FIELD(BQ24257_REG_6, 0, 2),
|
||||
/* REG 7 */
|
||||
[F_VOVP] = REG_FIELD(BQ24257_REG_7, 5, 7),
|
||||
|
|
@ -169,6 +196,26 @@ static const u32 bq24257_iterm_map[] = {
|
|||
|
||||
#define BQ24257_ITERM_MAP_SIZE ARRAY_SIZE(bq24257_iterm_map)
|
||||
|
||||
static const u32 bq24257_iilimit_map[] = {
|
||||
100000, 150000, 500000, 900000, 1500000, 2000000
|
||||
};
|
||||
|
||||
#define BQ24257_IILIMIT_MAP_SIZE ARRAY_SIZE(bq24257_iilimit_map)
|
||||
|
||||
static const u32 bq24257_vovp_map[] = {
|
||||
6000000, 6500000, 7000000, 8000000, 9000000, 9500000, 10000000,
|
||||
10500000
|
||||
};
|
||||
|
||||
#define BQ24257_VOVP_MAP_SIZE ARRAY_SIZE(bq24257_vovp_map)
|
||||
|
||||
static const u32 bq24257_vindpm_map[] = {
|
||||
4200000, 4280000, 4360000, 4440000, 4520000, 4600000, 4680000,
|
||||
4760000
|
||||
};
|
||||
|
||||
#define BQ24257_VINDPM_MAP_SIZE ARRAY_SIZE(bq24257_vindpm_map)
|
||||
|
||||
static int bq24257_field_read(struct bq24257_device *bq,
|
||||
enum bq24257_fields field_id)
|
||||
{
|
||||
|
|
@ -220,6 +267,47 @@ enum bq24257_fault {
|
|||
FAULT_INPUT_LDO_LOW,
|
||||
};
|
||||
|
||||
static int bq24257_get_input_current_limit(struct bq24257_device *bq,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bq24257_field_read(bq, F_IILIMIT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The "External ILIM" and "Production & Test" modes are not exposed
|
||||
* through this driver and not being covered by the lookup table.
|
||||
* Should such a mode have become active let's return an error rather
|
||||
* than exceeding the bounds of the lookup table and returning
|
||||
* garbage.
|
||||
*/
|
||||
if (ret >= BQ24257_IILIMIT_MAP_SIZE)
|
||||
return -ENODATA;
|
||||
|
||||
val->intval = bq24257_iilimit_map[ret];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bq24257_set_input_current_limit(struct bq24257_device *bq,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
/*
|
||||
* Address the case where the user manually sets an input current limit
|
||||
* while the charger auto-detection mechanism is is active. In this
|
||||
* case we want to abort and go straight to the user-specified value.
|
||||
*/
|
||||
if (bq->iilimit_autoset_enable)
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
|
||||
return bq24257_field_write(bq, F_IILIMIT,
|
||||
bq24257_find_idx(val->intval,
|
||||
bq24257_iilimit_map,
|
||||
BQ24257_IILIMIT_MAP_SIZE));
|
||||
}
|
||||
|
||||
static int bq24257_power_supply_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
|
|
@ -249,6 +337,10 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
|
|||
val->strval = BQ24257_MANUFACTURER;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||
val->strval = bq2425x_chip_name[bq->chip];
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = state.power_good;
|
||||
break;
|
||||
|
|
@ -300,6 +392,9 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
|
|||
val->intval = bq24257_iterm_map[bq->init_data.iterm];
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
return bq24257_get_input_current_limit(bq, val);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -307,6 +402,31 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bq24257_power_supply_set_property(struct power_supply *psy,
|
||||
enum power_supply_property prop,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (prop) {
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
return bq24257_set_input_current_limit(bq, val);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bq24257_power_supply_property_is_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int bq24257_get_chip_state(struct bq24257_device *bq,
|
||||
struct bq24257_state *state)
|
||||
{
|
||||
|
|
@ -324,7 +444,26 @@ static int bq24257_get_chip_state(struct bq24257_device *bq,
|
|||
|
||||
state->fault = ret;
|
||||
|
||||
state->power_good = !gpiod_get_value_cansleep(bq->pg);
|
||||
if (bq->pg)
|
||||
state->power_good = !gpiod_get_value_cansleep(bq->pg);
|
||||
else
|
||||
/*
|
||||
* If we have a chip without a dedicated power-good GPIO or
|
||||
* some other explicit bit that would provide this information
|
||||
* assume the power is good if there is no supply related
|
||||
* fault - and not good otherwise. There is a possibility for
|
||||
* other errors to mask that power in fact is not good but this
|
||||
* is probably the best we can do here.
|
||||
*/
|
||||
switch (state->fault) {
|
||||
case FAULT_INPUT_OVP:
|
||||
case FAULT_INPUT_UVLO:
|
||||
case FAULT_INPUT_LDO_LOW:
|
||||
state->power_good = false;
|
||||
break;
|
||||
default:
|
||||
state->power_good = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -361,6 +500,28 @@ enum bq24257_in_ilimit {
|
|||
IILIMIT_NONE,
|
||||
};
|
||||
|
||||
enum bq24257_vovp {
|
||||
VOVP_6000,
|
||||
VOVP_6500,
|
||||
VOVP_7000,
|
||||
VOVP_8000,
|
||||
VOVP_9000,
|
||||
VOVP_9500,
|
||||
VOVP_10000,
|
||||
VOVP_10500
|
||||
};
|
||||
|
||||
enum bq24257_vindpm {
|
||||
VINDPM_4200,
|
||||
VINDPM_4280,
|
||||
VINDPM_4360,
|
||||
VINDPM_4440,
|
||||
VINDPM_4520,
|
||||
VINDPM_4600,
|
||||
VINDPM_4680,
|
||||
VINDPM_4760
|
||||
};
|
||||
|
||||
enum bq24257_port_type {
|
||||
PORT_TYPE_DCP, /* Dedicated Charging Port */
|
||||
PORT_TYPE_CDP, /* Charging Downstream Port */
|
||||
|
|
@ -449,41 +610,43 @@ static void bq24257_handle_state_change(struct bq24257_device *bq,
|
|||
{
|
||||
int ret;
|
||||
struct bq24257_state old_state;
|
||||
bool reset_iilimit = false;
|
||||
bool config_iilimit = false;
|
||||
|
||||
mutex_lock(&bq->lock);
|
||||
old_state = bq->state;
|
||||
mutex_unlock(&bq->lock);
|
||||
|
||||
if (!new_state->power_good) { /* power removed */
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
/*
|
||||
* Handle BQ2425x state changes observing whether the D+/D- based input
|
||||
* current limit autoset functionality is enabled.
|
||||
*/
|
||||
if (!new_state->power_good) {
|
||||
dev_dbg(bq->dev, "Power removed\n");
|
||||
if (bq->iilimit_autoset_enable) {
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
|
||||
/* activate D+/D- port detection algorithm */
|
||||
ret = bq24257_field_write(bq, F_DPDM_EN, 1);
|
||||
/* activate D+/D- port detection algorithm */
|
||||
ret = bq24257_field_write(bq, F_DPDM_EN, 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
* When power is removed always return to the default input
|
||||
* current limit as configured during probe.
|
||||
*/
|
||||
ret = bq24257_field_write(bq, F_IILIMIT, bq->init_data.iilimit);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
} else if (!old_state.power_good) {
|
||||
dev_dbg(bq->dev, "Power inserted\n");
|
||||
|
||||
reset_iilimit = true;
|
||||
} else if (!old_state.power_good) { /* power inserted */
|
||||
config_iilimit = true;
|
||||
} else if (new_state->fault == FAULT_NO_BAT) { /* battery removed */
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
|
||||
reset_iilimit = true;
|
||||
} else if (old_state.fault == FAULT_NO_BAT) { /* battery connected */
|
||||
config_iilimit = true;
|
||||
} else if (new_state->fault == FAULT_TIMER) { /* safety timer expired */
|
||||
dev_err(bq->dev, "Safety timer expired! Battery dead?\n");
|
||||
}
|
||||
|
||||
if (reset_iilimit) {
|
||||
ret = bq24257_field_write(bq, F_IILIMIT, IILIMIT_500);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
} else if (config_iilimit) {
|
||||
schedule_delayed_work(&bq->iilimit_setup_work,
|
||||
if (bq->iilimit_autoset_enable)
|
||||
/* configure input current limit */
|
||||
schedule_delayed_work(&bq->iilimit_setup_work,
|
||||
msecs_to_jiffies(BQ24257_ILIM_SET_DELAY));
|
||||
} else if (new_state->fault == FAULT_NO_BAT) {
|
||||
dev_warn(bq->dev, "Battery removed\n");
|
||||
} else if (new_state->fault == FAULT_TIMER) {
|
||||
dev_err(bq->dev, "Safety timer expired! Battery dead?\n");
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -531,7 +694,9 @@ static int bq24257_hw_init(struct bq24257_device *bq)
|
|||
} init_data[] = {
|
||||
{F_ICHG, bq->init_data.ichg},
|
||||
{F_VBAT, bq->init_data.vbat},
|
||||
{F_ITERM, bq->init_data.iterm}
|
||||
{F_ITERM, bq->init_data.iterm},
|
||||
{F_VOVP, bq->init_data.vovp},
|
||||
{F_VINDPM, bq->init_data.vindpm},
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -558,7 +723,16 @@ static int bq24257_hw_init(struct bq24257_device *bq)
|
|||
bq->state = state;
|
||||
mutex_unlock(&bq->lock);
|
||||
|
||||
if (!state.power_good)
|
||||
if (!bq->iilimit_autoset_enable) {
|
||||
dev_dbg(bq->dev, "manually setting iilimit = %u\n",
|
||||
bq->init_data.iilimit);
|
||||
|
||||
/* program fixed input current limit */
|
||||
ret = bq24257_field_write(bq, F_IILIMIT,
|
||||
bq->init_data.iilimit);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (!state.power_good)
|
||||
/* activate D+/D- detection algorithm */
|
||||
ret = bq24257_field_write(bq, F_DPDM_EN, 1);
|
||||
else if (state.fault != FAULT_NO_BAT)
|
||||
|
|
@ -569,6 +743,7 @@ static int bq24257_hw_init(struct bq24257_device *bq)
|
|||
|
||||
static enum power_supply_property bq24257_power_supply_props[] = {
|
||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
|
|
@ -577,6 +752,7 @@ static enum power_supply_property bq24257_power_supply_props[] = {
|
|||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
|
||||
POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
|
||||
};
|
||||
|
||||
static char *bq24257_charger_supplied_to[] = {
|
||||
|
|
@ -589,6 +765,96 @@ static const struct power_supply_desc bq24257_power_supply_desc = {
|
|||
.properties = bq24257_power_supply_props,
|
||||
.num_properties = ARRAY_SIZE(bq24257_power_supply_props),
|
||||
.get_property = bq24257_power_supply_get_property,
|
||||
.set_property = bq24257_power_supply_set_property,
|
||||
.property_is_writeable = bq24257_power_supply_property_is_writeable,
|
||||
};
|
||||
|
||||
static ssize_t bq24257_show_ovp_voltage(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
bq24257_vovp_map[bq->init_data.vovp]);
|
||||
}
|
||||
|
||||
static ssize_t bq24257_show_in_dpm_voltage(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
bq24257_vindpm_map[bq->init_data.vindpm]);
|
||||
}
|
||||
|
||||
static ssize_t bq24257_sysfs_show_enable(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
int ret;
|
||||
|
||||
if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
|
||||
ret = bq24257_field_read(bq, F_HZ_MODE);
|
||||
else if (strcmp(attr->attr.name, "sysoff_enable") == 0)
|
||||
ret = bq24257_field_read(bq, F_SYSOFF);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t bq24257_sysfs_set_enable(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
long val;
|
||||
int ret;
|
||||
|
||||
if (kstrtol(buf, 10, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(attr->attr.name, "high_impedance_enable") == 0)
|
||||
ret = bq24257_field_write(bq, F_HZ_MODE, (bool)val);
|
||||
else if (strcmp(attr->attr.name, "sysoff_enable") == 0)
|
||||
ret = bq24257_field_write(bq, F_SYSOFF, (bool)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(ovp_voltage, S_IRUGO, bq24257_show_ovp_voltage, NULL);
|
||||
static DEVICE_ATTR(in_dpm_voltage, S_IRUGO, bq24257_show_in_dpm_voltage, NULL);
|
||||
static DEVICE_ATTR(high_impedance_enable, S_IWUSR | S_IRUGO,
|
||||
bq24257_sysfs_show_enable, bq24257_sysfs_set_enable);
|
||||
static DEVICE_ATTR(sysoff_enable, S_IWUSR | S_IRUGO,
|
||||
bq24257_sysfs_show_enable, bq24257_sysfs_set_enable);
|
||||
|
||||
static struct attribute *bq24257_charger_attr[] = {
|
||||
&dev_attr_ovp_voltage.attr,
|
||||
&dev_attr_in_dpm_voltage.attr,
|
||||
&dev_attr_high_impedance_enable.attr,
|
||||
&dev_attr_sysoff_enable.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group bq24257_attr_group = {
|
||||
.attrs = bq24257_charger_attr,
|
||||
};
|
||||
|
||||
static int bq24257_power_supply_init(struct bq24257_device *bq)
|
||||
|
|
@ -598,36 +864,28 @@ static int bq24257_power_supply_init(struct bq24257_device *bq)
|
|||
psy_cfg.supplied_to = bq24257_charger_supplied_to;
|
||||
psy_cfg.num_supplicants = ARRAY_SIZE(bq24257_charger_supplied_to);
|
||||
|
||||
bq->charger = power_supply_register(bq->dev, &bq24257_power_supply_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(bq->charger))
|
||||
return PTR_ERR(bq->charger);
|
||||
bq->charger = devm_power_supply_register(bq->dev,
|
||||
&bq24257_power_supply_desc,
|
||||
&psy_cfg);
|
||||
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(bq->charger);
|
||||
}
|
||||
|
||||
static int bq24257_irq_probe(struct bq24257_device *bq)
|
||||
static void bq24257_pg_gpio_probe(struct bq24257_device *bq)
|
||||
{
|
||||
struct gpio_desc *stat_irq;
|
||||
bq->pg = devm_gpiod_get_optional(bq->dev, BQ24257_PG_GPIO, GPIOD_IN);
|
||||
|
||||
stat_irq = devm_gpiod_get_index(bq->dev, BQ24257_STAT_IRQ, 0, GPIOD_IN);
|
||||
if (IS_ERR(stat_irq)) {
|
||||
dev_err(bq->dev, "could not probe stat_irq pin\n");
|
||||
return PTR_ERR(stat_irq);
|
||||
if (PTR_ERR(bq->pg) == -EPROBE_DEFER) {
|
||||
dev_info(bq->dev, "probe retry requested for PG pin\n");
|
||||
return;
|
||||
} else if (IS_ERR(bq->pg)) {
|
||||
dev_err(bq->dev, "error probing PG pin\n");
|
||||
bq->pg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
return gpiod_to_irq(stat_irq);
|
||||
}
|
||||
|
||||
static int bq24257_pg_gpio_probe(struct bq24257_device *bq)
|
||||
{
|
||||
bq->pg = devm_gpiod_get_index(bq->dev, BQ24257_PG_GPIO, 0, GPIOD_IN);
|
||||
if (IS_ERR(bq->pg)) {
|
||||
dev_err(bq->dev, "could not probe PG pin\n");
|
||||
return PTR_ERR(bq->pg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (bq->pg)
|
||||
dev_dbg(bq->dev, "probed PG pin = %d\n", desc_to_gpio(bq->pg));
|
||||
}
|
||||
|
||||
static int bq24257_fw_probe(struct bq24257_device *bq)
|
||||
|
|
@ -635,6 +893,7 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
|
|||
int ret;
|
||||
u32 property;
|
||||
|
||||
/* Required properties */
|
||||
ret = device_property_read_u32(bq->dev, "ti,charge-current", &property);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -658,6 +917,43 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
|
|||
bq->init_data.iterm = bq24257_find_idx(property, bq24257_iterm_map,
|
||||
BQ24257_ITERM_MAP_SIZE);
|
||||
|
||||
/* Optional properties. If not provided use reasonable default. */
|
||||
ret = device_property_read_u32(bq->dev, "ti,current-limit",
|
||||
&property);
|
||||
if (ret < 0) {
|
||||
bq->iilimit_autoset_enable = true;
|
||||
|
||||
/*
|
||||
* Explicitly set a default value which will be needed for
|
||||
* devices that don't support the automatic setting of the input
|
||||
* current limit through the charger type detection mechanism.
|
||||
*/
|
||||
bq->init_data.iilimit = IILIMIT_500;
|
||||
} else
|
||||
bq->init_data.iilimit =
|
||||
bq24257_find_idx(property,
|
||||
bq24257_iilimit_map,
|
||||
BQ24257_IILIMIT_MAP_SIZE);
|
||||
|
||||
ret = device_property_read_u32(bq->dev, "ti,ovp-voltage",
|
||||
&property);
|
||||
if (ret < 0)
|
||||
bq->init_data.vovp = VOVP_6500;
|
||||
else
|
||||
bq->init_data.vovp = bq24257_find_idx(property,
|
||||
bq24257_vovp_map,
|
||||
BQ24257_VOVP_MAP_SIZE);
|
||||
|
||||
ret = device_property_read_u32(bq->dev, "ti,in-dpm-voltage",
|
||||
&property);
|
||||
if (ret < 0)
|
||||
bq->init_data.vindpm = VINDPM_4360;
|
||||
else
|
||||
bq->init_data.vindpm =
|
||||
bq24257_find_idx(property,
|
||||
bq24257_vindpm_map,
|
||||
BQ24257_VINDPM_MAP_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -666,6 +962,7 @@ static int bq24257_probe(struct i2c_client *client,
|
|||
{
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
struct device *dev = &client->dev;
|
||||
const struct acpi_device_id *acpi_id;
|
||||
struct bq24257_device *bq;
|
||||
int ret;
|
||||
int i;
|
||||
|
|
@ -682,6 +979,18 @@ static int bq24257_probe(struct i2c_client *client,
|
|||
bq->client = client;
|
||||
bq->dev = dev;
|
||||
|
||||
if (ACPI_HANDLE(dev)) {
|
||||
acpi_id = acpi_match_device(dev->driver->acpi_match_table,
|
||||
&client->dev);
|
||||
if (!acpi_id) {
|
||||
dev_err(dev, "Failed to match ACPI device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
bq->chip = (enum bq2425x_chip)acpi_id->driver_data;
|
||||
} else {
|
||||
bq->chip = (enum bq2425x_chip)id->driver_data;
|
||||
}
|
||||
|
||||
mutex_init(&bq->lock);
|
||||
|
||||
bq->rmap = devm_regmap_init_i2c(client, &bq24257_regmap_config);
|
||||
|
|
@ -703,8 +1012,6 @@ static int bq24257_probe(struct i2c_client *client,
|
|||
|
||||
i2c_set_clientdata(client, bq);
|
||||
|
||||
INIT_DELAYED_WORK(&bq->iilimit_setup_work, bq24257_iilimit_setup_work);
|
||||
|
||||
if (!dev->platform_data) {
|
||||
ret = bq24257_fw_probe(bq);
|
||||
if (ret < 0) {
|
||||
|
|
@ -715,10 +1022,31 @@ static int bq24257_probe(struct i2c_client *client,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* we can only check Power Good status by probing the PG pin */
|
||||
ret = bq24257_pg_gpio_probe(bq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/*
|
||||
* The BQ24250 doesn't support the D+/D- based charger type detection
|
||||
* used for the automatic setting of the input current limit setting so
|
||||
* explicitly disable that feature.
|
||||
*/
|
||||
if (bq->chip == BQ24250)
|
||||
bq->iilimit_autoset_enable = false;
|
||||
|
||||
if (bq->iilimit_autoset_enable)
|
||||
INIT_DELAYED_WORK(&bq->iilimit_setup_work,
|
||||
bq24257_iilimit_setup_work);
|
||||
|
||||
/*
|
||||
* The BQ24250 doesn't have a dedicated Power Good (PG) pin so let's
|
||||
* not probe for it and instead use a SW-based approach to determine
|
||||
* the PG state. We also use a SW-based approach for all other devices
|
||||
* if the PG pin is either not defined or can't be probed.
|
||||
*/
|
||||
if (bq->chip != BQ24250)
|
||||
bq24257_pg_gpio_probe(bq);
|
||||
|
||||
if (PTR_ERR(bq->pg) == -EPROBE_DEFER)
|
||||
return PTR_ERR(bq->pg);
|
||||
else if (!bq->pg)
|
||||
dev_info(bq->dev, "using SW-based power-good detection\n");
|
||||
|
||||
/* reset all registers to defaults */
|
||||
ret = bq24257_field_write(bq, F_RESET, 1);
|
||||
|
|
@ -740,36 +1068,39 @@ static int bq24257_probe(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (client->irq <= 0)
|
||||
client->irq = bq24257_irq_probe(bq);
|
||||
|
||||
if (client->irq < 0) {
|
||||
dev_err(dev, "no irq resource found\n");
|
||||
return client->irq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||
bq24257_irq_handler_thread,
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
BQ24257_STAT_IRQ, bq);
|
||||
if (ret)
|
||||
bq2425x_chip_name[bq->chip], bq);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request IRQ #%d\n", client->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bq24257_power_supply_init(bq);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to register power supply\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
ret = sysfs_create_group(&bq->charger->dev.kobj, &bq24257_attr_group);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Can't create sysfs entries\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bq24257_remove(struct i2c_client *client)
|
||||
{
|
||||
struct bq24257_device *bq = i2c_get_clientdata(client);
|
||||
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
if (bq->iilimit_autoset_enable)
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
|
||||
power_supply_unregister(bq->charger);
|
||||
sysfs_remove_group(&bq->charger->dev.kobj, &bq24257_attr_group);
|
||||
|
||||
bq24257_field_write(bq, F_RESET, 1); /* reset to defaults */
|
||||
|
||||
|
|
@ -782,7 +1113,8 @@ static int bq24257_suspend(struct device *dev)
|
|||
struct bq24257_device *bq = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
if (bq->iilimit_autoset_enable)
|
||||
cancel_delayed_work_sync(&bq->iilimit_setup_work);
|
||||
|
||||
/* reset all registers to default (and activate standalone mode) */
|
||||
ret = bq24257_field_write(bq, F_RESET, 1);
|
||||
|
|
@ -823,19 +1155,25 @@ static const struct dev_pm_ops bq24257_pm = {
|
|||
};
|
||||
|
||||
static const struct i2c_device_id bq24257_i2c_ids[] = {
|
||||
{ "bq24257", 0 },
|
||||
{ "bq24250", BQ24250 },
|
||||
{ "bq24251", BQ24251 },
|
||||
{ "bq24257", BQ24257 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids);
|
||||
|
||||
static const struct of_device_id bq24257_of_match[] = {
|
||||
{ .compatible = "ti,bq24250", },
|
||||
{ .compatible = "ti,bq24251", },
|
||||
{ .compatible = "ti,bq24257", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bq24257_of_match);
|
||||
|
||||
static const struct acpi_device_id bq24257_acpi_match[] = {
|
||||
{"BQ242570", 0},
|
||||
{ "BQ242500", BQ24250 },
|
||||
{ "BQ242510", BQ24251 },
|
||||
{ "BQ242570", BQ24257 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
1375
drivers/power/bq27xxx_battery.c
Normal file
1375
drivers/power/bq27xxx_battery.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1581,8 +1581,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
|
|||
cables = devm_kzalloc(dev, sizeof(*cables)
|
||||
* chg_regs->num_cables,
|
||||
GFP_KERNEL);
|
||||
if (!cables)
|
||||
if (!cables) {
|
||||
of_node_put(child);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
chg_regs->cables = cables;
|
||||
|
||||
|
|
|
|||
|
|
@ -508,23 +508,23 @@ out:
|
|||
return param;
|
||||
}
|
||||
|
||||
static int lp8727_parse_dt(struct device *dev)
|
||||
static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *child;
|
||||
struct lp8727_platform_data *pdata;
|
||||
const char *type;
|
||||
|
||||
/* If charging parameter is not defined, just skip parsing the dt */
|
||||
if (of_get_child_count(np) == 0)
|
||||
goto out;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
of_property_read_u32(np, "debounce-ms", &pdata->debounce_msec);
|
||||
|
||||
/* If charging parameter is not defined, just skip parsing the dt */
|
||||
if (of_get_child_count(np) == 0)
|
||||
return pdata;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
of_property_read_string(child, "charger-type", &type);
|
||||
|
||||
|
|
@ -535,29 +535,30 @@ static int lp8727_parse_dt(struct device *dev)
|
|||
pdata->usb = lp8727_parse_charge_pdata(dev, child);
|
||||
}
|
||||
|
||||
dev->platform_data = pdata;
|
||||
out:
|
||||
return 0;
|
||||
return pdata;
|
||||
}
|
||||
#else
|
||||
static int lp8727_parse_dt(struct device *dev)
|
||||
static struct lp8727_platform_data *lp8727_parse_dt(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
||||
{
|
||||
struct lp8727_chg *pchg;
|
||||
struct lp8727_platform_data *pdata;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
|
||||
return -EIO;
|
||||
|
||||
if (cl->dev.of_node) {
|
||||
ret = lp8727_parse_dt(&cl->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
pdata = lp8727_parse_dt(&cl->dev);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
} else {
|
||||
pdata = dev_get_platdata(&cl->dev);
|
||||
}
|
||||
|
||||
pchg = devm_kzalloc(&cl->dev, sizeof(*pchg), GFP_KERNEL);
|
||||
|
|
@ -566,7 +567,7 @@ static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
|
|||
|
||||
pchg->client = cl;
|
||||
pchg->dev = &cl->dev;
|
||||
pchg->pdata = cl->dev.platform_data;
|
||||
pchg->pdata = pdata;
|
||||
i2c_set_clientdata(cl, pchg);
|
||||
|
||||
mutex_init(&pchg->xfer_lock);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue