Commit 449dc8c9 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull power supply and reset updates from Sebastian Reichel:
 "Power-supply core:
   - add COOL/WARM/HOT state from JEITA JISC8712:2015 specification
   - convert simple-battery DT binding to YAML
   - add long-life charging mode

 Battery/charger drivers:
   - bq25150: new charger driver
   - bq27xxx: add support for BQ27z561 and BQ28z610
   - max17040: support CAPACITY_ALERT_MIN
   - sbs-battery: add PEC support
   - wilco-ec: support long-life charging mode
   - bq25890: fix DT binding
   - misc. fixes and cleanups

 Reset drivers:
   - linkstation: new reset driver"

* tag 'for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (32 commits)
  power: supply: wilco_ec: Add long life charging mode
  power: supply: bq27xxx_battery: Add the BQ28z610 Battery monitor
  dt-bindings: power: Add BQ28z610 compatible
  power: supply: bq27xxx_battery: Add the BQ27Z561 Battery monitor
  dt-bindings: power: Add BQ27Z561 compatible
  power: supply: test_power: Fix battery_current initial value
  power: supply: Fix kerneldoc of power_supply_temp2resist_simple()
  power: supply: cpcap-battery: Fix kerneldoc of cpcap_battery_read_accumulated()
  dt-bindings: power: Convert battery.txt to battery.yaml
  power: supply: rt5033_battery: Fix error code in rt5033_battery_probe()
  power: supply: max17040: Add POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN
  power: supply: check if calc_soc succeeded in pm860x_init_battery
  power: supply: bq2xxxx: Replace HTTP links with HTTPS ones
  power: reset: add driver for LinkStation power off
  power: supply: sc27xx: prevent adc * 1000 from overflow
  math64: New DIV_S64_ROUND_CLOSEST helper
  power: fix duplicated words in bq2415x_charger.h
  power: Convert to DEFINE_SHOW_ATTRIBUTE
  power: reset: keystone-reset: Replace HTTP links with HTTPS ones
  power: supply: bq25150 introduce the bq25150
  ...
parents b79675e1 46cbd0b0
......@@ -205,7 +205,8 @@ Description:
Valid values: "Unknown", "Good", "Overheat", "Dead",
"Over voltage", "Unspecified failure", "Cold",
"Watchdog timer expire", "Safety timer expire",
"Over current", "Calibration required"
"Over current", "Calibration required", "Warm",
"Cool", "Hot"
What: /sys/class/power_supply/<supply_name>/precharge_current
Date: June 2017
......
......@@ -14,6 +14,10 @@ Description:
Charging begins when level drops below
charge_control_start_threshold, and ceases when
level is above charge_control_end_threshold.
Long Life: Customized charge rate for last longer battery life.
On Wilco device this mode is pre-configured in the factory
through EC's private PID. Swiching to a different mode will
be denied by Wilco EC when Long Life mode is enabled.
What: /sys/class/power_supply/wilco-charger/charge_control_start_threshold
Date: April 2019
......
Battery Characteristics
The devicetree battery node provides static battery characteristics.
In smart batteries, these are typically stored in non-volatile memory
on a fuel gauge chip. The battery node should be used where there is
no appropriate non-volatile memory, or it is unprogrammed/incorrect.
Upstream dts files should not include battery nodes, unless the battery
represented cannot easily be replaced in the system by one of a
different type. This prevents unpredictable, potentially harmful,
behavior should a replacement that changes the battery type occur
without a corresponding update to the dtb.
The contents of this file has been moved to battery.yaml
Please note that not all charger drivers respect all of the properties.
Required Properties:
- compatible: Must be "simple-battery"
Optional Properties:
- over-voltage-threshold-microvolt: battery over-voltage limit
- re-charge-voltage-microvolt: limit to automatically start charging again
- voltage-min-design-microvolt: drained battery voltage
- voltage-max-design-microvolt: fully charged battery voltage
- energy-full-design-microwatt-hours: battery design energy
- charge-full-design-microamp-hours: battery design capacity
- trickle-charge-current-microamp: current for trickle-charge phase
- precharge-current-microamp: current for pre-charge phase
- precharge-upper-limit-microvolt: limit when to change to constant charging
- charge-term-current-microamp: current for charge termination phase
- constant-charge-current-max-microamp: maximum constant input current
- constant-charge-voltage-max-microvolt: maximum constant input voltage
- factory-internal-resistance-micro-ohms: battery factory internal resistance
- ocv-capacity-table-0: An array providing the open circuit voltage (OCV)
of the battery and corresponding battery capacity percent, which is used
to look up battery capacity according to current OCV value. And the open
circuit voltage unit is microvolt.
- ocv-capacity-table-1: Same as ocv-capacity-table-0
......
- ocv-capacity-table-n: Same as ocv-capacity-table-0
- ocv-capacity-celsius: An array containing the temperature in degree Celsius,
for each of the battery capacity lookup table. The first temperature value
specifies the OCV table 0, and the second temperature value specifies the
OCV table 1, and so on.
- resistance-temp-table: An array providing the temperature in degree Celsius
and corresponding battery internal resistance percent, which is used to look
up the resistance percent according to current temperature to get a accurate
batterty internal resistance in different temperatures.
Battery properties are named, where possible, for the corresponding
elements in enum power_supply_property, defined in
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/power_supply.h
Batteries must be referenced by chargers and/or fuel-gauges
using a phandle. The phandle's property should be named
"monitored-battery".
Example:
bat: battery {
compatible = "simple-battery";
voltage-min-design-microvolt = <3200000>;
voltage-max-design-microvolt = <4200000>;
energy-full-design-microwatt-hours = <5290000>;
charge-full-design-microamp-hours = <1430000>;
precharge-current-microamp = <256000>;
charge-term-current-microamp = <128000>;
constant-charge-current-max-microamp = <900000>;
constant-charge-voltage-max-microvolt = <4200000>;
factory-internal-resistance-micro-ohms = <250000>;
ocv-capacity-celsius = <(-10) 0 10>;
ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>, ...;
ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>, ...;
ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>, ...;
resistance-temp-table = <20 100>, <10 90>, <0 80>, <(-10) 60>;
};
charger: charger@11 {
....
monitored-battery = <&bat>;
...
};
fuel_gauge: fuel-gauge@22 {
....
monitored-battery = <&bat>;
...
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/supply/battery.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Battery Characteristics
maintainers:
- Sebastian Reichel <sre@kernel.org>
description: |
The devicetree battery node provides static battery characteristics.
In smart batteries, these are typically stored in non-volatile memory
on a fuel gauge chip. The battery node should be used where there is
no appropriate non-volatile memory, or it is unprogrammed/incorrect.
Upstream dts files should not include battery nodes, unless the battery
represented cannot easily be replaced in the system by one of a
different type. This prevents unpredictable, potentially harmful,
behavior should a replacement that changes the battery type occur
without a corresponding update to the dtb.
Battery properties are named, where possible, for the corresponding elements
in enum power_supply_property, defined in include/linux/power_supply.h
Batteries must be referenced by chargers and/or fuel-gauges using a phandle.
The phandle's property should be named "monitored-battery".
properties:
compatible:
const: simple-battery
over-voltage-threshold-microvolt:
description: battery over-voltage limit
re-charge-voltage-microvolt:
description: limit to automatically start charging again
voltage-min-design-microvolt:
description: drained battery voltage
voltage-max-design-microvolt:
description: fully charged battery voltage
energy-full-design-microwatt-hours:
description: battery design energy
charge-full-design-microamp-hours:
description: battery design capacity
trickle-charge-current-microamp:
description: current for trickle-charge phase
precharge-current-microamp:
description: current for pre-charge phase
precharge-upper-limit-microvolt:
description: limit when to change to constant charging
charge-term-current-microamp:
description: current for charge termination phase
constant-charge-current-max-microamp:
description: maximum constant input current
constant-charge-voltage-max-microvolt:
description: maximum constant input voltage
factory-internal-resistance-micro-ohms:
description: battery factory internal resistance
resistance-temp-table:
description: |
An array providing the temperature in degree Celsius
and corresponding battery internal resistance percent, which is used to
look up the resistance percent according to current temperature to get an
accurate batterty internal resistance in different temperatures.
ocv-capacity-celsius:
description: |
An array containing the temperature in degree Celsius,
for each of the battery capacity lookup table.
required:
- compatible
patternProperties:
'^ocv-capacity-table-[0-9]+$':
$ref: /schemas/types.yaml#/definitions/uint32-matrix
description: |
An array providing the open circuit voltage (OCV)
of the battery and corresponding battery capacity percent, which is used
to look up battery capacity according to current OCV value. And the open
circuit voltage unit is microvolt.
maxItems: 100
items:
items:
- description: open circuit voltage (OCV) in microvolts
- description: battery capacity percent
maximum: 100
additionalProperties: false
examples:
- |
power {
#address-cells = <1>;
#size-cells = <0>;
battery: battery {
compatible = "simple-battery";
over-voltage-threshold-microvolt = <4500000>;
re-charge-voltage-microvolt = <250000>;
voltage-min-design-microvolt = <3200000>;
voltage-max-design-microvolt = <4200000>;
energy-full-design-microwatt-hours = <5290000>;
charge-full-design-microamp-hours = <1430000>;
precharge-current-microamp = <256000>;
precharge-upper-limit-microvolt = <2500000>;
charge-term-current-microamp = <128000>;
constant-charge-current-max-microamp = <900000>;
constant-charge-voltage-max-microvolt = <4200000>;
factory-internal-resistance-micro-ohms = <250000>;
ocv-capacity-celsius = <(-10) 0 10>;
/* table for -10 degree Celsius */
ocv-capacity-table-0 = <4185000 100>, <4113000 95>, <4066000 90>;
/* table for 0 degree Celsius */
ocv-capacity-table-1 = <4200000 100>, <4185000 95>, <4113000 90>;
/* table for 10 degree Celsius */
ocv-capacity-table-2 = <4250000 100>, <4200000 95>, <4185000 90>;
resistance-temp-table = <20 100>, <10 90>, <0 80>, <(-10) 60>;
};
charger@11 {
reg = <0x11>;
monitored-battery = <&battery>;
};
fuel-gauge@22 {
reg = <0x22>;
monitored-battery = <&battery>;
};
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright (C) 2020 Texas Instruments Incorporated
%YAML 1.2
---
$id: "http://devicetree.org/schemas/power/supply/bq2515x.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: TI bq2515x 500-mA Linear charger family
maintainers:
- Dan Murphy <dmurphy@ti.com>
- Ricardo Rivera-Matos <r-rivera-matos@ti.com>
description: |
The BQ2515x family is a highly integrated battery charge management IC that
integrates the most common functions for wearable devices, namely a charger,
an output voltage rail, ADC for battery and system monitoring, and
push-button controller.
Specifications about the charger can be found at:
http://www.ti.com/lit/ds/symlink/bq25150.pdf
http://www.ti.com/lit/ds/symlink/bq25155.pdf
properties:
compatible:
enum:
- ti,bq25150
- ti,bq25155
reg:
maxItems: 1
description: I2C address of the charger.
ac-detect-gpios:
description: |
GPIO used for connecting the bq2515x device PG (AC Detect)
pin.
maxItems: 1
reset-gpios:
description: GPIO used for hardware reset.
maxItems: 1
powerdown-gpios:
description: GPIO used for low power mode of IC.
maxItems: 1
charge-enable-gpios:
description: GPIO used to turn on and off charging.
maxItems: 1
input-current-limit-microamp:
$ref: /schemas/types.yaml#/definitions/uint32
description: Maximum input current in micro Amps.
minimum: 50000
maximum: 500000
monitored-battery:
$ref: /schemas/types.yaml#/definitions/phandle
description: phandle to the battery node being monitored
required:
- compatible
- reg
- monitored-battery
additionalProperties: false
examples:
- |
bat: battery {
compatible = "simple-battery";
constant-charge-current-max-microamp = <50000>;
precharge-current-microamp = <2500>;
constant-charge-voltage-max-microvolt = <4000000>;
};
#include <dt-bindings/gpio/gpio.h>
i2c0 {
#address-cells = <1>;
#size-cells = <0>;
bq25150: charger@6b {
compatible = "ti,bq25150";
reg = <0x6b>;
monitored-battery = <&bat>;
input-current-limit-microamp = <100000>;
ac-detect-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
powerdown-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
charge-enable-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
};
};
......@@ -10,6 +10,7 @@ Required properties:
* "ti,bq25895"
* "ti,bq25896"
- reg: integer, i2c address of the device.
- interrupts: interrupt line;
- 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
......@@ -36,17 +37,20 @@ Optional properties:
Example:
bq25890 {
compatible = "ti,bq25890";
reg = <0x6a>;
ti,battery-regulation-voltage = <4200000>;
ti,charge-current = <1000000>;
ti,termination-current = <50000>;
ti,precharge-current = <128000>;
ti,minimum-sys-voltage = <3600000>;
ti,boost-voltage = <5000000>;
ti,boost-max-current = <1000000>;
ti,use-ilim-pin;
ti,thermal-regulation-threshold = <120>;
compatible = "ti,bq25890";
reg = <0x6a>;
interrupt-parent = <&gpio1>;
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
ti,battery-regulation-voltage = <4200000>;
ti,charge-current = <1000000>;
ti,termination-current = <50000>;
ti,precharge-current = <128000>;
ti,minimum-sys-voltage = <3600000>;
ti,boost-voltage = <5000000>;
ti,boost-max-current = <1000000>;
ti,use-ilim-pin;
ti,thermal-regulation-threshold = <120>;
};
......@@ -49,6 +49,8 @@ properties:
- ti,bq27426
- ti,bq27441
- ti,bq27621
- ti,bq27z561
- ti,bq28z610
reg:
maxItems: 1
......
gpio-charger
Required properties :
- compatible : "gpio-charger"
- gpios : GPIO indicating the charger presence.
See GPIO binding in bindings/gpio/gpio.txt .
- charger-type : power supply type, one of
unknown
battery
ups
mains
usb-sdp (USB standard downstream port)
usb-dcp (USB dedicated charging port)
usb-cdp (USB charging downstream port)
usb-aca (USB accessory charger adapter)
Optional properties:
- charge-status-gpios: GPIO indicating whether a battery is charging.
Example:
usb_charger: charger {
compatible = "gpio-charger";
charger-type = "usb-sdp";
gpios = <&gpd 28 GPIO_ACTIVE_LOW>;
charge-status-gpios = <&gpc 27 GPIO_ACTIVE_LOW>;
};
battery {
power-supplies = <&usb_charger>;
};
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/supply/gpio-charger.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: simple battery chargers only communicating through GPIOs
maintainers:
- Sebastian Reichel <sre@kernel.org>
description:
This binding is for all chargers, which are working more or less
autonomously, only providing some status GPIOs and possibly some
GPIOs for limited control over the charging process.
properties:
compatible:
const: gpio-charger
charger-type:
enum:
- unknown
- battery
- ups
- mains
- usb-sdp # USB standard downstream port
- usb-dcp # USB dedicated charging port
- usb-cdp # USB charging downstream port
- usb-aca # USB accessory charger adapter
description:
Type of the charger, e.g. "mains" for a wall charger.
gpios:
maxItems: 1
description: GPIO indicating the charger presence
charge-status-gpios:
maxItems: 1
description: GPIO indicating the charging status
required:
- compatible
anyOf:
- required:
- gpios
- required:
- charge-status-gpios
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
charger {
compatible = "gpio-charger";
charger-type = "usb-sdp";
gpios = <&gpd 28 GPIO_ACTIVE_LOW>;
charge-status-gpios = <&gpc 27 GPIO_ACTIVE_LOW>;
};
......@@ -99,6 +99,17 @@ config POWER_RESET_HISI
help
Reboot support for Hisilicon boards.
config POWER_RESET_LINKSTATION
tristate "Buffalo LinkStation power-off driver"
depends on ARCH_MVEBU || COMPILE_TEST
depends on OF_MDIO && PHYLIB
help
This driver supports turning off some Buffalo LinkStations by
setting an output pin at the ethernet PHY to the correct state.
It also makes the device compatible with the WoL function.
Say Y here if you have a Buffalo LinkStation LS421D/E.
config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on ARCH_QCOM
......
......@@ -10,6 +10,7 @@ obj-$(CONFIG_POWER_RESET_GEMINI_POWEROFF) += gemini-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
obj-${CONFIG_POWER_RESET_LINKSTATION} += linkstation-poweroff.o
obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o
obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o
......
......@@ -2,7 +2,7 @@
/*
* TI keystone reboot driver
*
* Copyright (C) 2014 Texas Instruments Incorporated. http://www.ti.com/
* Copyright (C) 2014 Texas Instruments Incorporated. https://www.ti.com/
*
* Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
*/
......
// SPDX-License-Identifier: GPL-2.0
/*
* LinkStation power off restart driver
* Copyright (C) 2020 Daniel González Cabanelas <dgcbueu@gmail.com>
*/
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_mdio.h>
#include <linux/of_platform.h>
#include <linux/reboot.h>
#include <linux/phy.h>
/* Defines from the eth phy Marvell driver */
#define MII_MARVELL_COPPER_PAGE 0
#define MII_MARVELL_LED_PAGE 3
#define MII_MARVELL_WOL_PAGE 17
#define MII_MARVELL_PHY_PAGE 22
#define MII_PHY_LED_CTRL 16
#define MII_88E1318S_PHY_LED_TCR 18
#define MII_88E1318S_PHY_WOL_CTRL 16
#define MII_M1011_IEVENT 19
#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7)
#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15)
#define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS BIT(12)
#define LED2_FORCE_ON (0x8 << 8)
#define LEDMASK GENMASK(11,8)
static struct phy_device *phydev;
static void mvphy_reg_intn(u16 data)
{
int rc = 0, saved_page;
saved_page = phy_select_page(phydev, MII_MARVELL_LED_PAGE);
if (saved_page < 0)
goto err;
/* Force manual LED2 control to let INTn work */
__phy_modify(phydev, MII_PHY_LED_CTRL, LEDMASK, LED2_FORCE_ON);
/* Set the LED[2]/INTn pin to the required state */
__phy_modify(phydev, MII_88E1318S_PHY_LED_TCR,
MII_88E1318S_PHY_LED_TCR_FORCE_INT,
MII_88E1318S_PHY_LED_TCR_INTn_ENABLE | data);
if (!data) {
/* Clear interrupts to ensure INTn won't be holded in high state */
__phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_COPPER_PAGE);
__phy_read(phydev, MII_M1011_IEVENT);
/* If WOL was enabled and a magic packet was received before powering
* off, we won't be able to wake up by sending another magic packet.
* Clear WOL status.
*/
__phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_MARVELL_WOL_PAGE);
__phy_set_bits(phydev, MII_88E1318S_PHY_WOL_CTRL,
MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS);
}
err:
rc = phy_restore_page(phydev, saved_page, rc);
if (rc < 0)
dev_err(&phydev->mdio.dev, "Write register failed, %d\n", rc);
}
static int linkstation_reboot_notifier(struct notifier_block *nb,
unsigned long action, void *unused)
{
if (action == SYS_RESTART)
mvphy_reg_intn(MII_88E1318S_PHY_LED_TCR_FORCE_INT);
return NOTIFY_DONE;
}
static struct notifier_block linkstation_reboot_nb = {
.notifier_call = linkstation_reboot_notifier,
};
static void linkstation_poweroff(void)
{
unregister_reboot_notifier(&linkstation_reboot_nb);
mvphy_reg_intn(0);
kernel_restart("Power off");
}
static const struct of_device_id ls_poweroff_of_match[] = {
{ .compatible = "buffalo,ls421d" },
{ .compatible = "buffalo,ls421de" },
{ },
};
static int __init linkstation_poweroff_init(void)
{
struct mii_bus *bus;
struct device_node *dn;
dn = of_find_matching_node(NULL, ls_poweroff_of_match);
if (!dn)
return -ENODEV;
of_node_put(dn);
dn = of_find_node_by_name(NULL, "mdio");
if (!dn)
return -ENODEV;
bus = of_mdio_find_bus(dn);
of_node_put(dn);
if (!bus)
return -EPROBE_DEFER;
phydev = phy_find_first(bus);
if (!phydev)
return -EPROBE_DEFER;
register_reboot_notifier(&linkstation_reboot_nb);
pm_power_off = linkstation_poweroff;
return 0;
}
static void __exit linkstation_poweroff_exit(void)
{
pm_power_off = NULL;
unregister_reboot_notifier(&linkstation_reboot_nb);
}
module_init(linkstation_poweroff_init);
module_exit(linkstation_poweroff_exit);
MODULE_AUTHOR("Daniel González Cabanelas <dgcbueu@gmail.com>");
MODULE_DESCRIPTION("LinkStation power off driver");
MODULE_LICENSE("GPL v2");
......@@ -433,7 +433,7 @@ static void pm860x_init_battery(struct pm860x_battery_info *info)
int ret;
int data;
int bat_remove;
int soc;
int soc = 0;
/* measure enable on GPADC1 */
data = MEAS1_GP1;
......@@ -496,7 +496,9 @@ static void pm860x_init_battery(struct pm860x_battery_info *info)
}
mutex_unlock(&info->lock);
calc_soc(info, OCV_MODE_ACTIVE, &soc);
ret = calc_soc(info, OCV_MODE_ACTIVE, &soc);
if (ret < 0)
goto out;
data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG);
bat_remove = data & BAT_WU_LOG;
......
......@@ -610,6 +610,19 @@ config CHARGER_BQ24735
help
Say Y to enable support for the TI BQ24735 battery charger.
config CHARGER_BQ2515X
tristate "TI BQ2515X battery charger family"
depends on I2C
depends on GPIOLIB || COMPILE_TEST
select REGMAP_I2C
help
Say Y to enable support for the TI BQ2515X family of battery
charging integrated circuits. The BQ2515X are highly integrated
battery charge management ICs that integrate the most common
functions for wearable devices, namely a charger, an output voltage
rail, ADC for battery and system monitoring, and push-button
controller.
config CHARGER_BQ25890
tristate "TI BQ25890 battery charger driver"
depends on I2C
......
......@@ -82,6 +82,7 @@ obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o
obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o
obj-$(CONFIG_CHARGER_BQ24735) += bq24735-charger.o
obj-$(CONFIG_CHARGER_BQ2515X) += bq2515x_charger.o
obj-$(CONFIG_CHARGER_BQ25890) += bq25890_charger.o
obj-$(CONFIG_CHARGER_SMB347) += smb347-charger.o
obj-$(CONFIG_CHARGER_TPS65090) += tps65090-charger.o
......
......@@ -78,7 +78,7 @@ static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
/*
* Polling is only necessary while VBUS is offline. While online, a
* present->absent transition implies an online->offline transition
* and will triger the VBUS_REMOVAL IRQ.
* and will trigger the VBUS_REMOVAL IRQ.
*/
if (power->axp20x_id >= AXP221_ID && !power->online)
return true;
......
......@@ -5,14 +5,14 @@
* Copyright (C) 2011-2013 Pali Rohár <pali@kernel.org>
*
* Datasheets:
* http://www.ti.com/product/bq24150
* http://www.ti.com/product/bq24150a
* http://www.ti.com/product/bq24152
* http://www.ti.com/product/bq24153
* http://www.ti.com/product/bq24153a
* http://www.ti.com/product/bq24155
* http://www.ti.com/product/bq24157s
* http://www.ti.com/product/bq24158
* https://www.ti.com/product/bq24150
* https://www.ti.com/product/bq24150a
* https://www.ti.com/product/bq24152
* https://www.ti.com/product/bq24153
* https://www.ti.com/product/bq24153a
* https://www.ti.com/product/bq24155
* https://www.ti.com/product/bq24157s
* https://www.ti.com/product/bq24158
*/
#include <linux/kernel.h>
......
......@@ -481,8 +481,10 @@ static ssize_t bq24190_sysfs_store(struct device *dev,
return ret;
ret = pm_runtime_get_sync(bdi->dev);
if (ret < 0)
if (ret < 0) {
pm_runtime_put_noidle(bdi->dev);
return ret;
}
ret = bq24190_write_mask(bdi, info->reg, info->mask, info->shift, v);
if (ret)
......
......@@ -5,9 +5,9 @@
* Copyright (C) 2015 Intel Corporation
*
* Datasheets:
* http://www.ti.com/product/bq24250
* http://www.ti.com/product/bq24251
* http://www.ti.com/product/bq24257
* https://www.ti.com/product/bq24250
* https://www.ti.com/product/bq24251
* https://www.ti.com/product/bq24257
*/
#include <linux/module.h>
......
This diff is collapsed.
......@@ -18,31 +18,33 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Datasheets:
* http://www.ti.com/product/bq27000
* http://www.ti.com/product/bq27200
* http://www.ti.com/product/bq27010
* http://www.ti.com/product/bq27210
* http://www.ti.com/product/bq27500
* http://www.ti.com/product/bq27510-g1
* http://www.ti.com/product/bq27510-g2
* http://www.ti.com/product/bq27510-g3
* http://www.ti.com/product/bq27520-g1
* http://www.ti.com/product/bq27520-g2
* http://www.ti.com/product/bq27520-g3
* http://www.ti.com/product/bq27520-g4
* http://www.ti.com/product/bq27530-g1
* http://www.ti.com/product/bq27531-g1
* http://www.ti.com/product/bq27541-g1
* http://www.ti.com/product/bq27542-g1
* http://www.ti.com/product/bq27546-g1
* http://www.ti.com/product/bq27742-g1
* http://www.ti.com/product/bq27545-g1
* http://www.ti.com/product/bq27421-g1
* http://www.ti.com/product/bq27425-g1
* http://www.ti.com/product/bq27426
* http://www.ti.com/product/bq27411-g1
* http://www.ti.com/product/bq27441-g1
* http://www.ti.com/product/bq27621-g1
* https://www.ti.com/product/bq27000
* https://www.ti.com/product/bq27200
* https://www.ti.com/product/bq27010
* https://www.ti.com/product/bq27210
* https://www.ti.com/product/bq27500
* https://www.ti.com/product/bq27510-g1
* https://www.ti.com/product/bq27510-g2
* https://www.ti.com/product/bq27510-g3
* https://www.ti.com/product/bq27520-g1
* https://www.ti.com/product/bq27520-g2
* https://www.ti.com/product/bq27520-g3
* https://www.ti.com/product/bq27520-g4
* https://www.ti.com/product/bq27530-g1
* https://www.ti.com/product/bq27531-g1
* https://www.ti.com/product/bq27541-g1
* https://www.ti.com/product/bq27542-g1
* https://www.ti.com/product/bq27546-g1
* https://www.ti.com/product/bq27742-g1
* https://www.ti.com/product/bq27545-g1
* https://www.ti.com/product/bq27421-g1
* https://www.ti.com/product/bq27425-g1
* https://www.ti.com/product/bq27426
* https://www.ti.com/product/bq27411-g1
* https://www.ti.com/product/bq27441-g1
* https://www.ti.com/product/bq27621-g1
* https://www.ti.com/product/bq27z561
* https://www.ti.com/product/bq28z610
*/
#include <linux/device.h>
......@@ -79,6 +81,11 @@
#define BQ27000_FLAG_FC BIT(5)
#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
/* BQ27Z561 has different layout for Flags register */
#define BQ27Z561_FLAG_FDC BIT(4) /* Battery fully discharged */
#define BQ27Z561_FLAG_FC BIT(5) /* Battery fully charged */
#define BQ27Z561_FLAG_DIS_CH BIT(6) /* Battery is discharging */
/* control register params */
#define BQ27XXX_SEALED 0x20
#define BQ27XXX_SET_CFGUPDATE 0x13
......@@ -431,12 +438,52 @@ static u8
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = 0x18,
BQ27XXX_DM_REG_ROWS,
};
},
#define bq27411_regs bq27421_regs
#define bq27425_regs bq27421_regs
#define bq27426_regs bq27421_regs
#define bq27441_regs bq27421_regs
#define bq27621_regs bq27421_regs
bq27z561_regs[BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_CTRL] = 0x00,
[BQ27XXX_REG_TEMP] = 0x06,
[BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR,
[BQ27XXX_REG_VOLT] = 0x08,
[BQ27XXX_REG_AI] = 0x14,
[BQ27XXX_REG_FLAGS] = 0x0a,
[BQ27XXX_REG_TTE] = 0x16,
[BQ27XXX_REG_TTF] = 0x18,
[BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
[BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
[BQ27XXX_REG_NAC] = INVALID_REG_ADDR,
[BQ27XXX_REG_FCC] = 0x12,
[BQ27XXX_REG_CYCT] = 0x2a,
[BQ27XXX_REG_AE] = 0x22,
[BQ27XXX_REG_SOC] = 0x2c,
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = 0x22,
BQ27XXX_DM_REG_ROWS,
},
bq28z610_regs[BQ27XXX_REG_MAX] = {
[BQ27XXX_REG_CTRL] = 0x00,
[BQ27XXX_REG_TEMP] = 0x06,
[BQ27XXX_REG_INT_TEMP] = INVALID_REG_ADDR,
[BQ27XXX_REG_VOLT] = 0x08,
[BQ27XXX_REG_AI] = 0x14,
[BQ27XXX_REG_FLAGS] = 0x0a,
[BQ27XXX_REG_TTE] = 0x16,
[BQ27XXX_REG_TTF] = 0x18,
[BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
[BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
[BQ27XXX_REG_NAC] = INVALID_REG_ADDR,
[BQ27XXX_REG_FCC] = 0x12,
[BQ27XXX_REG_CYCT] = 0x2a,
[BQ27XXX_REG_AE] = 0x22,
[BQ27XXX_REG_SOC] = 0x2c,
[BQ27XXX_REG_DCAP] = 0x3c,
[BQ27XXX_REG_AP] = 0x22,
BQ27XXX_DM_REG_ROWS,
};
static enum power_supply_property bq27000_props[] = {
POWER_SUPPLY_PROP_STATUS,
......@@ -672,6 +719,44 @@ static enum power_supply_property bq27421_props[] = {
#define bq27441_props bq27421_props
#define bq27621_props bq27421_props
static enum power_supply_property bq27z561_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_TIME_TO_FULL_NOW,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_POWER_AVG,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_MANUFACTURER,
};
static enum power_supply_property bq28z610_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_TIME_TO_FULL_NOW,
POWER_SUPPLY_PROP_TECHNOLOGY,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CYCLE_COUNT,
POWER_SUPPLY_PROP_POWER_AVG,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_MANUFACTURER,
};
struct bq27xxx_dm_reg {
u8 subclass_id;
u8 offset;
......@@ -767,11 +852,15 @@ static struct bq27xxx_dm_reg bq27621_dm_regs[] = {
#define bq27621_dm_regs 0
#endif
#define bq27z561_dm_regs 0
#define bq28z610_dm_regs 0
#define BQ27XXX_O_ZERO 0x00000001
#define BQ27XXX_O_OTDC 0x00000002 /* has OTC/OTD overtemperature flags */
#define BQ27XXX_O_UTOT 0x00000004 /* has OT overtemperature flag */
#define BQ27XXX_O_CFGUP 0x00000008
#define BQ27XXX_O_RAM 0x00000010
#define BQ27Z561_O_BITS 0x00000020
#define BQ27XXX_DATA(ref, key, opt) { \
.opts = (opt), \
......@@ -816,6 +905,8 @@ static struct {
[BQ27426] = BQ27XXX_DATA(bq27426, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM),
[BQ27441] = BQ27XXX_DATA(bq27441, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM),
[BQ27621] = BQ27XXX_DATA(bq27621, 0x80008000, BQ27XXX_O_UTOT | BQ27XXX_O_CFGUP | BQ27XXX_O_RAM),
[BQ27Z561] = BQ27XXX_DATA(bq27z561, 0 , BQ27Z561_O_BITS),
[BQ28Z610] = BQ27XXX_DATA(bq28z610, 0 , BQ27Z561_O_BITS),
};
static DEFINE_MUTEX(bq27xxx_list_lock);
......@@ -1551,6 +1642,8 @@ static bool bq27xxx_battery_dead(struct bq27xxx_device_info *di, u16 flags)
{
if (di->opts & BQ27XXX_O_ZERO)
return flags & (BQ27000_FLAG_EDV1 | BQ27000_FLAG_EDVF);
else if (di->opts & BQ27Z561_O_BITS)
return flags & BQ27Z561_FLAG_FDC;
else
return flags & (BQ27XXX_FLAG_SOC1 | BQ27XXX_FLAG_SOCF);
}
......@@ -1595,6 +1688,7 @@ void bq27xxx_battery_update(struct bq27xxx_device_info *di)
cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
cache.charge_full = bq27xxx_battery_read_fcc(di);
cache.capacity = bq27xxx_battery_read_soc(di);
if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
......@@ -1682,6 +1776,13 @@ static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
status = POWER_SUPPLY_STATUS_NOT_CHARGING;
else
status = POWER_SUPPLY_STATUS_DISCHARGING;
} else if (di->opts & BQ27Z561_O_BITS) {
if (di->cache.flags & BQ27Z561_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
else if (di->cache.flags & BQ27Z561_FLAG_DIS_CH)
status = POWER_SUPPLY_STATUS_DISCHARGING;
else
status = POWER_SUPPLY_STATUS_CHARGING;
} else {
if (di->cache.flags & BQ27XXX_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
......@@ -1710,6 +1811,13 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
else
level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
} else if (di->opts & BQ27Z561_O_BITS) {
if (di->cache.flags & BQ27Z561_FLAG_FC)
level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
else if (di->cache.flags & BQ27Z561_FLAG_FDC)
level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
else
level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
} else {
if (di->cache.flags & BQ27XXX_FLAG_FC)
level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
......
/*
* BQ27xxx battery monitor HDQ/1-wire driver
*
* Copyright (C) 2007-2017 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (C) 2007-2017 Texas Instruments Incorporated - https://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......
/*
* BQ27xxx battery monitor I2C driver
*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/
* Andrew F. Davis <afd@ti.com>
*
* This program is free software; you can redistribute it and/or modify
......@@ -253,6 +253,8 @@ static const struct i2c_device_id bq27xxx_i2c_id_table[] = {
{ "bq27426", BQ27426 },
{ "bq27441", BQ27441 },
{ "bq27621", BQ27621 },
{ "bq27z561", BQ27Z561 },
{ "bq28z610", BQ28Z610 },
{},
};
MODULE_DEVICE_TABLE(i2c, bq27xxx_i2c_id_table);
......@@ -286,6 +288,8 @@ static const struct of_device_id bq27xxx_battery_i2c_of_match_table[] = {
{ .compatible = "ti,bq27426" },
{ .compatible = "ti,bq27441" },
{ .compatible = "ti,bq27621" },
{ .compatible = "ti,bq27z561" },
{ .compatible = "ti,bq28z610" },
{},
};
MODULE_DEVICE_TABLE(of, bq27xxx_battery_i2c_of_match_table);
......
......@@ -274,7 +274,7 @@ static int cpcap_battery_cc_to_ua(struct cpcap_battery_ddata *ddata,
/**
* cpcap_battery_read_accumulated - reads cpcap coulomb counter
* @ddata: device driver data
* @regs: coulomb counter values
* @ccd: coulomb counter values
*
* Based on Motorola mapphone kernel function data_read_regs().
* Looking at the registers, the coulomb counter seems similar to
......
......@@ -172,17 +172,7 @@ static int bat_debug_show(struct seq_file *s, void *data)
return 0;
}
static int debug_open(struct inode *inode, struct file *file)
{
return single_open(file, bat_debug_show, inode->i_private);
}
static const struct file_operations bat_debug_fops = {
.open = debug_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
DEFINE_SHOW_ATTRIBUTE(bat_debug);
static struct dentry *da9030_bat_create_debugfs(struct da9030_charger *charger)
{
......
......@@ -112,9 +112,14 @@ static int gpio_charger_get_irq(struct device *dev, void *dev_id,
return irq;
}
/*
* The entries will be overwritten by driver's probe routine depending
* on the available features. This list ensures, that the array is big
* enough for all optional features.
*/
static enum power_supply_property gpio_charger_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_STATUS /* Must always be last in the array. */
POWER_SUPPLY_PROP_STATUS,
};
static int gpio_charger_probe(struct platform_device *pdev)
......@@ -128,6 +133,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
int charge_status_irq;
unsigned long flags;
int ret;
int num_props = 0;
if (!pdata && !dev->of_node) {
dev_err(dev, "No platform data\n");
......@@ -142,13 +148,13 @@ static int gpio_charger_probe(struct platform_device *pdev)
* This will fetch a GPIO descriptor from device tree, ACPI or
* boardfile descriptor tables. It's good to try this first.
*/
gpio_charger->gpiod = devm_gpiod_get(dev, NULL, GPIOD_IN);
gpio_charger->gpiod = devm_gpiod_get_optional(dev, NULL, GPIOD_IN);
/*
* If this fails and we're not using device tree, try the
* legacy platform data method.
* Fallback to legacy platform data method, if no GPIO is specified
* using boardfile descriptor tables.
*/
if (IS_ERR(gpio_charger->gpiod) && !dev->of_node) {
if (!gpio_charger->gpiod && pdata) {
/* Non-DT: use legacy GPIO numbers */
if (!gpio_is_valid(pdata->gpio)) {
dev_err(dev, "Invalid gpio pin in pdata\n");
......@@ -173,17 +179,23 @@ static int gpio_charger_probe(struct platform_device *pdev)
return PTR_ERR(gpio_charger->gpiod);
}
if (gpio_charger->gpiod) {
gpio_charger_properties[num_props] = POWER_SUPPLY_PROP_ONLINE;
num_props++;
}
charge_status = devm_gpiod_get_optional(dev, "charge-status", GPIOD_IN);
gpio_charger->charge_status = charge_status;
if (IS_ERR(gpio_charger->charge_status))
return PTR_ERR(gpio_charger->charge_status);
if (IS_ERR(charge_status))
return PTR_ERR(charge_status);
if (charge_status) {
gpio_charger->charge_status = charge_status;
gpio_charger_properties[num_props] = POWER_SUPPLY_PROP_STATUS;
num_props++;
}
charger_desc = &gpio_charger->charger_desc;
charger_desc->properties = gpio_charger_properties;
charger_desc->num_properties = ARRAY_SIZE(gpio_charger_properties);
/* Remove POWER_SUPPLY_PROP_STATUS from the supported properties. */
if (!gpio_charger->charge_status)
charger_desc->num_properties -= 1;
charger_desc->num_properties = num_props;
charger_desc->get_property = gpio_charger_get_property;
psy_cfg.of_node = dev->of_node;
......@@ -269,6 +281,6 @@ static struct platform_driver gpio_charger_driver = {
module_platform_driver(gpio_charger_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO");
MODULE_DESCRIPTION("Driver for chargers only communicating via GPIO(s)");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-charger");
......@@ -69,6 +69,9 @@ static int max17040_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = chip->soc;
break;
case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
val->intval = chip->low_soc_alert;
break;
default:
return -EINVAL;
}
......@@ -256,19 +259,57 @@ static int max17040_enable_alert_irq(struct max17040_chip *chip)
return ret;
}
static int max17040_prop_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
switch (psp) {
case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
return 1;
default:
return 0;
}
}
static int max17040_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *val)
{
struct max17040_chip *chip = power_supply_get_drvdata(psy);
int ret;
switch (psp) {
case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
/* alert threshold can be programmed from 1% up to 32% */
if ((val->intval < 1) || (val->intval > 32)) {
ret = -EINVAL;
break;
}
ret = max17040_set_low_soc_alert(chip->client, val->intval);
chip->low_soc_alert = val->intval;
break;
default:
ret = -EINVAL;
}
return ret;
}
static enum power_supply_property max17040_battery_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN,
};
static const struct power_supply_desc max17040_battery_desc = {
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.get_property = max17040_get_property,
.properties = max17040_battery_props,
.num_properties = ARRAY_SIZE(max17040_battery_props),
.name = "battery",
.type = POWER_SUPPLY_TYPE_BATTERY,
.get_property = max17040_get_property,
.set_property = max17040_set_property,
.property_is_writeable = max17040_prop_writeable,
.properties = max17040_battery_props,
.num_properties = ARRAY_SIZE(max17040_battery_props),
};
static int max17040_probe(struct i2c_client *client,
......
......@@ -23,6 +23,7 @@ struct max8998_battery_data {
static enum power_supply_property max8998_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT, /* the presence of battery */
POWER_SUPPLY_PROP_ONLINE, /* charger is active or not */
POWER_SUPPLY_PROP_STATUS, /* charger is charging/discharging/full */
};
/* Note that the charger control is done by a current regulator "CHARGER" */
......@@ -49,10 +50,28 @@ static int max8998_battery_get_property(struct power_supply *psy,
ret = max8998_read_reg(i2c, MAX8998_REG_STATUS2, &reg);
if (ret)
return ret;
if (reg & (1 << 3))
val->intval = 0;
else
if (reg & (1 << 5))
val->intval = 1;
else
val->intval = 0;
break;
case POWER_SUPPLY_PROP_STATUS:
ret = max8998_read_reg(i2c, MAX8998_REG_STATUS2, &reg);
if (ret)
return ret;
if (!(reg & (1 << 5))) {
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
} else {
if (reg & (1 << 6))
val->intval = POWER_SUPPLY_STATUS_FULL;
else if (reg & (1 << 3))
val->intval = POWER_SUPPLY_STATUS_CHARGING;
else
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
break;
default:
return -EINVAL;
......
......@@ -733,7 +733,7 @@ EXPORT_SYMBOL_GPL(power_supply_put_battery_info);
* percent
* @table: Pointer to battery resistance temperature table
* @table_len: The table length
* @ocv: Current temperature
* @temp: Current temperature
*
* This helper function is used to look up battery internal resistance percent
* according to current temperature value from the resistance temperature table,
......
......@@ -87,6 +87,7 @@ static const char * const POWER_SUPPLY_CHARGE_TYPE_TEXT[] = {
[POWER_SUPPLY_CHARGE_TYPE_STANDARD] = "Standard",
[POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE] = "Adaptive",
[POWER_SUPPLY_CHARGE_TYPE_CUSTOM] = "Custom",
[POWER_SUPPLY_CHARGE_TYPE_LONGLIFE] = "Long Life",
};
static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
......@@ -101,6 +102,9 @@ static const char * const POWER_SUPPLY_HEALTH_TEXT[] = {
[POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE] = "Safety timer expire",
[POWER_SUPPLY_HEALTH_OVERCURRENT] = "Over current",
[POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED] = "Calibration required",
[POWER_SUPPLY_HEALTH_WARM] = "Warm",
[POWER_SUPPLY_HEALTH_COOL] = "Cool",
[POWER_SUPPLY_HEALTH_HOT] = "Hot",
};
static const char * const POWER_SUPPLY_TECHNOLOGY_TEXT[] = {
......@@ -343,7 +347,7 @@ static umode_t power_supply_attr_is_visible(struct kobject *kobj,
struct attribute *attr,
int attrno)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct device *dev = kobj_to_dev(kobj);
struct power_supply *psy = dev_get_drvdata(dev);
umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
int i;
......
......@@ -125,7 +125,7 @@ static int rt5033_battery_probe(struct i2c_client *client,
battery = devm_kzalloc(&client->dev, sizeof(*battery), GFP_KERNEL);
if (!battery)
return -EINVAL;
return -ENOMEM;
battery->client = client;
battery->regmap = devm_regmap_init_i2c(client,
......
......@@ -51,6 +51,14 @@ enum {
REG_CHARGE_VOLTAGE,
};
#define REG_ADDR_SPEC_INFO 0x1A
#define SPEC_INFO_VERSION_MASK GENMASK(7, 4)
#define SPEC_INFO_VERSION_SHIFT 4
#define SBS_VERSION_1_0 1
#define SBS_VERSION_1_1 2
#define SBS_VERSION_1_1_WITH_PEC 3
#define REG_ADDR_MANUFACTURE_DATE 0x1B
/* Battery Mode defines */
......@@ -224,14 +232,57 @@ static void sbs_disable_charger_broadcasts(struct sbs_info *chip)
static int sbs_update_presence(struct sbs_info *chip, bool is_present)
{
struct i2c_client *client = chip->client;
int retries = chip->i2c_retry_count;
s32 ret = 0;
u8 version;
if (chip->is_present == is_present)
return 0;
if (!is_present) {
chip->is_present = false;
/* Disable PEC when no device is present */
client->flags &= ~I2C_CLIENT_PEC;
return 0;
}
/* Check if device supports packet error checking and use it */
while (retries > 0) {
ret = i2c_smbus_read_word_data(client, REG_ADDR_SPEC_INFO);
if (ret >= 0)
break;
/*
* Some batteries trigger the detection pin before the
* I2C bus is properly connected. This works around the
* issue.
*/
msleep(100);
retries--;
}
if (ret < 0) {
dev_dbg(&client->dev, "failed to read spec info: %d\n", ret);
/* fallback to old behaviour */
client->flags &= ~I2C_CLIENT_PEC;
chip->is_present = true;
return ret;
}
version = (ret & SPEC_INFO_VERSION_MASK) >> SPEC_INFO_VERSION_SHIFT;
if (version == SBS_VERSION_1_1_WITH_PEC)
client->flags |= I2C_CLIENT_PEC;
else
client->flags &= ~I2C_CLIENT_PEC;
dev_dbg(&client->dev, "PEC: %s\n", (client->flags & I2C_CLIENT_PEC) ?
"enabled" : "disabled");
if (!chip->is_present && is_present && !chip->charger_broadcasts)
sbs_disable_charger_broadcasts(chip);
......@@ -263,8 +314,7 @@ static int sbs_read_word_data(struct i2c_client *client, u8 address)
return ret;
}
static int sbs_read_string_data(struct i2c_client *client, u8 address,
char *values)
static int sbs_read_string_data_fallback(struct i2c_client *client, u8 address, char *values)
{
struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0, block_length = 0;
......@@ -274,6 +324,9 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address,
retries_length = chip->i2c_retry_count;
retries_block = chip->i2c_retry_count;
dev_warn_once(&client->dev, "I2C adapter does not support I2C_FUNC_SMBUS_READ_BLOCK_DATA.\n"
"Fallback method does not support PEC.\n");
/* Adapter needs to support these two functions */
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA |
......@@ -329,6 +382,38 @@ static int sbs_read_string_data(struct i2c_client *client, u8 address,
return ret;
}
static int sbs_read_string_data(struct i2c_client *client, u8 address, char *values)
{
struct sbs_info *chip = i2c_get_clientdata(client);
int retries = chip->i2c_retry_count;
int ret = 0;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BLOCK_DATA)) {
bool pec = client->flags & I2C_CLIENT_PEC;
client->flags &= ~I2C_CLIENT_PEC;
ret = sbs_read_string_data_fallback(client, address, values);
if (pec)
client->flags |= I2C_CLIENT_PEC;
return ret;
}
while (retries > 0) {
ret = i2c_smbus_read_block_data(client, address, values);
if (ret >= 0)
break;
retries--;
}
if (ret < 0) {
dev_dbg(&client->dev, "failed to read block 0x%x: %d\n", address, ret);
return ret;
}
/* add string termination */
values[ret] = '\0';
return ret;
}
static int sbs_write_word_data(struct i2c_client *client, u8 address,
u16 value)
{
......
......@@ -5,6 +5,7 @@
#include <linux/iio/consumer.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of.h>
......@@ -133,14 +134,14 @@ static const char * const sc27xx_charger_supply_name[] = {
"sc2723_charger",
};
static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, int adc)
static int sc27xx_fgu_adc_to_current(struct sc27xx_fgu_data *data, s64 adc)
{
return DIV_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc);
return DIV_S64_ROUND_CLOSEST(adc * 1000, data->cur_1000ma_adc);
}
static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, int adc)
static int sc27xx_fgu_adc_to_voltage(struct sc27xx_fgu_data *data, s64 adc)
{
return DIV_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc);
return DIV_S64_ROUND_CLOSEST(adc * 1000, data->vol_1000mv_adc);
}
static int sc27xx_fgu_voltage_to_adc(struct sc27xx_fgu_data *data, int vol)
......
......@@ -34,7 +34,7 @@ static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION;
static int battery_capacity = 50;
static int battery_voltage = 3300;
static int battery_charge_counter = -1000;
static int battery_current = 1600;
static int battery_current = -1600;
static bool module_initialized;
......
......@@ -27,6 +27,7 @@ enum charge_mode {
CHARGE_MODE_AC = 3, /* Mostly AC use, used for Trickle */
CHARGE_MODE_AUTO = 4, /* Used for Adaptive */
CHARGE_MODE_CUSTOM = 5, /* Used for Custom */
CHARGE_MODE_LONGLIFE = 6, /* Used for Long Life */
};
#define CHARGE_LOWER_LIMIT_MIN 50
......@@ -48,6 +49,8 @@ static int psp_val_to_charge_mode(int psp_val)
return CHARGE_MODE_AUTO;
case POWER_SUPPLY_CHARGE_TYPE_CUSTOM:
return CHARGE_MODE_CUSTOM;
case POWER_SUPPLY_CHARGE_TYPE_LONGLIFE:
return CHARGE_MODE_LONGLIFE;
default:
return -EINVAL;
}
......@@ -67,6 +70,8 @@ static int charge_mode_to_psp_val(enum charge_mode mode)
return POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE;
case CHARGE_MODE_CUSTOM:
return POWER_SUPPLY_CHARGE_TYPE_CUSTOM;
case CHARGE_MODE_LONGLIFE:
return POWER_SUPPLY_CHARGE_TYPE_LONGLIFE;
default:
return -EINVAL;
}
......
......@@ -281,4 +281,23 @@ u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
#define DIV64_U64_ROUND_CLOSEST(dividend, divisor) \
({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
/*
* DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
* @dividend: signed 64bit dividend
* @divisor: signed 32bit divisor
*
* Divide signed 64bit dividend by signed 32bit divisor
* and round to closest integer.
*
* Return: dividend / divisor rounded to nearest integer
*/
#define DIV_S64_ROUND_CLOSEST(dividend, divisor)( \
{ \
s64 __x = (dividend); \
s32 __d = (divisor); \
((__x > 0) == (__d > 0)) ? \
div_s64((__x + (__d / 2)), __d) : \
div_s64((__x - (__d / 2)), __d); \
} \
)
#endif /* _LINUX_MATH64_H */
......@@ -14,8 +14,8 @@
* value is -1 then default chip value (specified in datasheet) will be
* used.
*
* Value resistor_sense is needed for for configuring charge and
* termination current. It it is less or equal to zero, configuring charge
* Value resistor_sense is needed for configuring charge and
* termination current. If it is less or equal to zero, configuring charge
* and termination current will not be possible.
*
* For automode support is needed to provide name of power supply device
......
......@@ -30,6 +30,8 @@ enum bq27xxx_chip {
BQ27426,
BQ27441,
BQ27621,
BQ27Z561,
BQ28Z610,
};
struct bq27xxx_device_info;
......
......@@ -48,6 +48,7 @@ enum {
POWER_SUPPLY_CHARGE_TYPE_STANDARD, /* normal speed */
POWER_SUPPLY_CHARGE_TYPE_ADAPTIVE, /* dynamically adjusted speed */
POWER_SUPPLY_CHARGE_TYPE_CUSTOM, /* use CHARGE_CONTROL_* props */
POWER_SUPPLY_CHARGE_TYPE_LONGLIFE, /* slow speed, longer life */
};
enum {
......@@ -62,6 +63,9 @@ enum {
POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE,
POWER_SUPPLY_HEALTH_OVERCURRENT,
POWER_SUPPLY_HEALTH_CALIBRATION_REQUIRED,
POWER_SUPPLY_HEALTH_WARM,
POWER_SUPPLY_HEALTH_COOL,
POWER_SUPPLY_HEALTH_HOT,
};
enum {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment