mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 19:51:25 -04:00
Merge tag 'for-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel: "Core changes: - propagate of_node to child device - change from atomic to blocking notifier_call_chain New drivers: - pm8916 battery management system - mm8013 fuel gauge New features: - maxim max17040: add temperature support - gpio-poweroff: make priority configurable Cleanups: - simplify reset drivers using builtin_platform_driver() - convert all platform drivers to remove_new callback - replace all strncpy occurrences with strscpy - started converting drivers to i2c_get_match_data() - misc fixes and cleanups" * tag 'for-v6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (91 commits) power: reset: vexpress: Use device_get_match_data() power: supply: surface-charger: replace deprecated strncpy with strscpy power: supply: surface_battery: replace deprecated strncpy with strscpy power: supply: charger-manager: replace deprecated strncpy with strscpy power: supply: bq25980: replace deprecated strncpy with strscpy power: supply: bq256xx: replace deprecated strncpy with strscpy power: supply: bq2515x: replace deprecated strncpy with strscpy power: supply: bq24190_charger: replace deprecated strncpy with strscpy power: supply: cpcap: Drop non-DT driver matching power: reset: brcmstb: Depend on actual SoC dependencies power: reset: gpio-poweroff: make sys handler priority configurable dt-bindings: power: reset: gpio-poweroff: Add priority property power: reset: gpio-poweroff: use sys-off handler API power: reset: gpio-poweroff: use a struct to store the module variables power: supply: rt5033_charger: Replace "&pdev->dev" by "charger->dev" in probe power: supply: rt5033_charger: Simplify initialization of rt5033_charger_data power: supply: rt5033_charger: Add cable detection and USB OTG supply power: supply: core: remove opencoded string_lower() dt-bindings: power: supply: sbs-manager: Add missing unevaluatedProperties on child node schemas power: supply: mm8013: Fix an error checking issue in mm8013_checkdevice() ...
This commit is contained in:
@@ -18,6 +18,9 @@ description: >
|
||||
Finally the operating system assumes the power off failed if
|
||||
the system is still running after waiting some time (timeout-ms).
|
||||
|
||||
allOf:
|
||||
- $ref: restart-handler.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: gpio-poweroff
|
||||
@@ -40,6 +43,9 @@ properties:
|
||||
default: 100
|
||||
description: Delay to wait after driving gpio inactive
|
||||
|
||||
priority:
|
||||
default: 0
|
||||
|
||||
timeout-ms:
|
||||
default: 3000
|
||||
description: Time to wait before assuming the power off sequence failed.
|
||||
|
||||
@@ -15,6 +15,9 @@ description: |+
|
||||
defined by the register map pointed by syscon reference plus the offset
|
||||
with the value and mask defined in the poweroff node.
|
||||
Default will be little endian mode, 32 bit access only.
|
||||
The SYSCON register map is normally retrieved from the parental dt-node. So
|
||||
the SYSCON poweroff node should be represented as a sub-node of a "syscon",
|
||||
"simple-mfd" node.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -30,7 +33,10 @@ properties:
|
||||
|
||||
regmap:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: Phandle to the register map node.
|
||||
deprecated: true
|
||||
description:
|
||||
Phandle to the register map node. This property is deprecated in favor of
|
||||
the syscon-poweroff node being a child of a system controller node.
|
||||
|
||||
value:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
@@ -38,7 +44,6 @@ properties:
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- regmap
|
||||
- offset
|
||||
|
||||
additionalProperties: false
|
||||
@@ -56,7 +61,6 @@ examples:
|
||||
- |
|
||||
poweroff {
|
||||
compatible = "syscon-poweroff";
|
||||
regmap = <®mapnode>;
|
||||
offset = <0x0>;
|
||||
mask = <0x7a>;
|
||||
};
|
||||
|
||||
@@ -55,6 +55,14 @@ properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
io-channels:
|
||||
items:
|
||||
- description: battery temperature
|
||||
|
||||
io-channel-names:
|
||||
items:
|
||||
- const: temp
|
||||
|
||||
wakeup-source:
|
||||
type: boolean
|
||||
description: |
|
||||
@@ -95,3 +103,26 @@ examples:
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
fuel-gauge@36 {
|
||||
compatible = "maxim,max17043";
|
||||
reg = <0x36>;
|
||||
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <144 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
monitored-battery = <&battery>;
|
||||
power-supplies = <&charger>;
|
||||
|
||||
io-channels = <&adc 8>;
|
||||
io-channel-names = "temp";
|
||||
|
||||
maxim,alert-low-soc-level = <10>;
|
||||
wakeup-source;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/mitsumi,mm8013.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Mitsumi MM8013 fuel gauge
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konradybcio@kernel.org>
|
||||
|
||||
allOf:
|
||||
- $ref: power-supply.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mitsumi,mm8013
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
fuel-gauge@55 {
|
||||
compatible = "mitsumi,mm8013";
|
||||
reg = <0x55>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,83 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/qcom,pm8916-bms-vm.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Voltage Mode BMS
|
||||
|
||||
maintainers:
|
||||
- Nikita Travkin <nikita@trvn.ru>
|
||||
|
||||
description:
|
||||
Voltage Mode BMS is a hardware block found in some Qualcomm PMICs
|
||||
such as pm8916. This block performs battery voltage monitoring.
|
||||
|
||||
allOf:
|
||||
- $ref: power-supply.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,pm8916-bms-vm
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: BMS FSM left S3 mode
|
||||
- description: BMS FSM entered S2 mode
|
||||
- description: OCV measured in S3 mode
|
||||
- description: OCV below threshold
|
||||
- description: FIFO update done
|
||||
- description: BMS FSM switched state
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: cv_leave
|
||||
- const: cv_enter
|
||||
- const: ocv_good
|
||||
- const: ocv_thr
|
||||
- const: fifo
|
||||
- const: state_chg
|
||||
|
||||
monitored-battery: true
|
||||
|
||||
power-supplies: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- monitored-battery
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
pmic {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
battery@4000 {
|
||||
compatible = "qcom,pm8916-bms-vm";
|
||||
reg = <0x4000>;
|
||||
interrupts = <0x0 0x40 0 IRQ_TYPE_EDGE_RISING>,
|
||||
<0x0 0x40 1 IRQ_TYPE_EDGE_RISING>,
|
||||
<0x0 0x40 2 IRQ_TYPE_EDGE_RISING>,
|
||||
<0x0 0x40 3 IRQ_TYPE_EDGE_RISING>,
|
||||
<0x0 0x40 4 IRQ_TYPE_EDGE_RISING>,
|
||||
<0x0 0x40 5 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "cv_leave",
|
||||
"cv_enter",
|
||||
"ocv_good",
|
||||
"ocv_thr",
|
||||
"fifo",
|
||||
"state_chg";
|
||||
|
||||
monitored-battery = <&battery>;
|
||||
power-supplies = <&pm8916_charger>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/qcom,pm8916-lbc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Linear Battery Charger
|
||||
|
||||
maintainers:
|
||||
- Nikita Travkin <nikita@trvn.ru>
|
||||
|
||||
description:
|
||||
Linear Battery Charger hardware block, found in some Qualcomm PMICs
|
||||
such as pm8916. Implements a simple, autonomous CC/CV charger.
|
||||
|
||||
allOf:
|
||||
- $ref: power-supply.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,pm8916-lbc
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: Charger
|
||||
- description: Battery
|
||||
- description: USB
|
||||
- description: MISC
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: chgr
|
||||
- const: bat_if
|
||||
- const: usb
|
||||
- const: misc
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Battery detection
|
||||
- description: Fast charging
|
||||
- description: Charging failed
|
||||
- description: Charging done
|
||||
- description: Battery present
|
||||
- description: Battery temperature OK
|
||||
- description: USB coarse detection
|
||||
- description: USB IN valid
|
||||
- description: Charger gone
|
||||
- description: Overtemperature
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: vbat_det
|
||||
- const: fast_chg
|
||||
- const: chg_fail
|
||||
- const: chg_done
|
||||
- const: bat_pres
|
||||
- const: temp_ok
|
||||
- const: coarse_det
|
||||
- const: usb_vbus
|
||||
- const: chg_gone
|
||||
- const: overtemp
|
||||
|
||||
qcom,fast-charge-safe-voltage:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 4000000
|
||||
maximum: 4775000
|
||||
description:
|
||||
Maximum safe battery voltage in uV; May be pre-set by bootloader,
|
||||
in which case, setting this will harmlessly fail.
|
||||
|
||||
qcom,fast-charge-safe-current:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 90000
|
||||
maximum: 1440000
|
||||
description:
|
||||
Maximum safe battery charge current in uA; May be pre-set by
|
||||
bootloader, in which case setting this will harmlessly fail.
|
||||
|
||||
monitored-battery: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- qcom,fast-charge-safe-voltage
|
||||
- qcom,fast-charge-safe-current
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
pmic {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
charger@1000 {
|
||||
compatible = "qcom,pm8916-lbc";
|
||||
reg = <0x1000>, <0x1200>, <0x1300>, <0x1600>;
|
||||
reg-names = "chgr", "bat_if", "usb", "misc";
|
||||
|
||||
interrupts = <0x0 0x10 0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x10 5 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x10 6 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x10 7 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x12 0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x12 1 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x13 0 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x13 1 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x13 2 IRQ_TYPE_EDGE_BOTH>,
|
||||
<0x0 0x13 4 IRQ_TYPE_EDGE_BOTH>;
|
||||
interrupt-names = "vbat_det",
|
||||
"fast_chg",
|
||||
"chg_fail",
|
||||
"chg_done",
|
||||
"bat_pres",
|
||||
"temp_ok",
|
||||
"coarse_det",
|
||||
"usb_vbus",
|
||||
"chg_gone",
|
||||
"overtemp";
|
||||
monitored-battery = <&battery>;
|
||||
|
||||
qcom,fast-charge-safe-current = <900000>;
|
||||
qcom,fast-charge-safe-voltage = <4300000>;
|
||||
};
|
||||
};
|
||||
@@ -47,6 +47,12 @@ patternProperties:
|
||||
"^i2c@[1-4]$":
|
||||
type: object
|
||||
$ref: /schemas/i2c/i2c-controller.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 1
|
||||
maximum: 4
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
AB85000 PMIC contains a node, which contains shared
|
||||
information about the battery connected to the PMIC.
|
||||
The node has no compatible property.
|
||||
|
||||
Properties of this node are:
|
||||
|
||||
thermistor-on-batctrl:
|
||||
A boolean value indicating thermistor interface to battery
|
||||
|
||||
Note:
|
||||
'btemp' and 'batctrl' are the pins interfaced for battery temperature
|
||||
measurement, 'btemp' signal is used when NTC(negative temperature
|
||||
coefficient) resister is interfaced external to battery whereas
|
||||
'batctrl' pin is used when NTC resister is internal to battery.
|
||||
|
||||
Example:
|
||||
ab8500_battery: ab8500_battery {
|
||||
thermistor-on-batctrl;
|
||||
};
|
||||
indicates: NTC resister is internal to battery, 'batctrl' is used
|
||||
for thermal measurement.
|
||||
|
||||
The absence of property 'thermal-on-batctrl' indicates
|
||||
NTC resister is external to battery and 'btemp' signal is used
|
||||
for thermal measurement.
|
||||
|
||||
battery-type:
|
||||
This shall be the battery manufacturing technology type,
|
||||
allowed types are:
|
||||
"UNKNOWN" "NiMH" "LION" "LIPO" "LiFe" "NiCd" "LiMn"
|
||||
Example:
|
||||
ab8500_battery: ab8500_battery {
|
||||
stericsson,battery-type = "LIPO";
|
||||
}
|
||||
@@ -871,6 +871,8 @@ patternProperties:
|
||||
description: MiraMEMS Sensing Technology Co., Ltd.
|
||||
"^mitsubishi,.*":
|
||||
description: Mitsubishi Electric Corporation
|
||||
"^mitsumi,.*":
|
||||
description: Mitsumi Electric Co., Ltd.
|
||||
"^mixel,.*":
|
||||
description: Mixel, Inc.
|
||||
"^miyoo,.*":
|
||||
|
||||
@@ -14433,6 +14433,11 @@ W: https://linuxtv.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: drivers/media/radio/radio-miropcm20*
|
||||
|
||||
MITSUMI MM8013 FG DRIVER
|
||||
M: Konrad Dybcio <konradybcio@kernel.org>
|
||||
F: Documentation/devicetree/bindings/power/supply/mitsumi,mm8013.yaml
|
||||
F: drivers/power/supply/mm8013.c
|
||||
|
||||
MMP SUPPORT
|
||||
R: Lubomir Rintel <lkundrak@v3.sk>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
||||
@@ -66,7 +66,7 @@ config POWER_RESET_BRCMKONA
|
||||
|
||||
config POWER_RESET_BRCMSTB
|
||||
bool "Broadcom STB reset driver"
|
||||
depends on ARM || ARM64 || MIPS || COMPILE_TEST
|
||||
depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
|
||||
depends on MFD_SYSCON
|
||||
default ARCH_BRCMSTB || BMIPS_GENERIC
|
||||
help
|
||||
|
||||
@@ -80,9 +80,4 @@ static struct platform_driver axxia_reset_driver = {
|
||||
.of_match_table = of_match_ptr(of_axxia_reset_match),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init axxia_reset_init(void)
|
||||
{
|
||||
return platform_driver_register(&axxia_reset_driver);
|
||||
}
|
||||
device_initcall(axxia_reset_init);
|
||||
builtin_platform_driver(axxia_reset_driver);
|
||||
|
||||
@@ -15,50 +15,51 @@
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#define DEFAULT_TIMEOUT_MS 3000
|
||||
/*
|
||||
* Hold configuration here, cannot be more than one instance of the driver
|
||||
* since pm_power_off itself is global.
|
||||
*/
|
||||
static struct gpio_desc *reset_gpio;
|
||||
static u32 timeout = DEFAULT_TIMEOUT_MS;
|
||||
static u32 active_delay = 100;
|
||||
static u32 inactive_delay = 100;
|
||||
|
||||
static void gpio_poweroff_do_poweroff(void)
|
||||
struct gpio_poweroff {
|
||||
struct gpio_desc *reset_gpio;
|
||||
u32 timeout_ms;
|
||||
u32 active_delay_ms;
|
||||
u32 inactive_delay_ms;
|
||||
};
|
||||
|
||||
static int gpio_poweroff_do_poweroff(struct sys_off_data *data)
|
||||
{
|
||||
BUG_ON(!reset_gpio);
|
||||
struct gpio_poweroff *gpio_poweroff = data->cb_data;
|
||||
|
||||
/* drive it active, also inactive->active edge */
|
||||
gpiod_direction_output(reset_gpio, 1);
|
||||
mdelay(active_delay);
|
||||
gpiod_direction_output(gpio_poweroff->reset_gpio, 1);
|
||||
mdelay(gpio_poweroff->active_delay_ms);
|
||||
|
||||
/* drive inactive, also active->inactive edge */
|
||||
gpiod_set_value_cansleep(reset_gpio, 0);
|
||||
mdelay(inactive_delay);
|
||||
gpiod_set_value_cansleep(gpio_poweroff->reset_gpio, 0);
|
||||
mdelay(gpio_poweroff->inactive_delay_ms);
|
||||
|
||||
/* drive it active, also inactive->active edge */
|
||||
gpiod_set_value_cansleep(reset_gpio, 1);
|
||||
gpiod_set_value_cansleep(gpio_poweroff->reset_gpio, 1);
|
||||
|
||||
/* give it some time */
|
||||
mdelay(timeout);
|
||||
mdelay(gpio_poweroff->timeout_ms);
|
||||
|
||||
WARN_ON(1);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static int gpio_poweroff_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_poweroff *gpio_poweroff;
|
||||
bool input = false;
|
||||
enum gpiod_flags flags;
|
||||
int priority = SYS_OFF_PRIO_DEFAULT;
|
||||
int ret;
|
||||
|
||||
/* If a pm_power_off function has already been added, leave it alone */
|
||||
if (pm_power_off != NULL) {
|
||||
dev_err(&pdev->dev,
|
||||
"%s: pm_power_off function already registered\n",
|
||||
__func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
gpio_poweroff = devm_kzalloc(&pdev->dev, sizeof(*gpio_poweroff), GFP_KERNEL);
|
||||
if (!gpio_poweroff)
|
||||
return -ENOMEM;
|
||||
|
||||
input = device_property_read_bool(&pdev->dev, "input");
|
||||
if (input)
|
||||
@@ -66,23 +67,29 @@ static int gpio_poweroff_probe(struct platform_device *pdev)
|
||||
else
|
||||
flags = GPIOD_OUT_LOW;
|
||||
|
||||
device_property_read_u32(&pdev->dev, "active-delay-ms", &active_delay);
|
||||
|
||||
gpio_poweroff->active_delay_ms = 100;
|
||||
gpio_poweroff->inactive_delay_ms = 100;
|
||||
gpio_poweroff->timeout_ms = DEFAULT_TIMEOUT_MS;
|
||||
|
||||
device_property_read_u32(&pdev->dev, "active-delay-ms", &gpio_poweroff->active_delay_ms);
|
||||
device_property_read_u32(&pdev->dev, "inactive-delay-ms",
|
||||
&inactive_delay);
|
||||
device_property_read_u32(&pdev->dev, "timeout-ms", &timeout);
|
||||
&gpio_poweroff->inactive_delay_ms);
|
||||
device_property_read_u32(&pdev->dev, "timeout-ms", &gpio_poweroff->timeout_ms);
|
||||
device_property_read_u32(&pdev->dev, "priority", &priority);
|
||||
if (priority > 255) {
|
||||
dev_err(&pdev->dev, "Invalid priority property: %u\n", priority);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags);
|
||||
if (IS_ERR(reset_gpio))
|
||||
return PTR_ERR(reset_gpio);
|
||||
gpio_poweroff->reset_gpio = devm_gpiod_get(&pdev->dev, NULL, flags);
|
||||
if (IS_ERR(gpio_poweroff->reset_gpio))
|
||||
return PTR_ERR(gpio_poweroff->reset_gpio);
|
||||
|
||||
pm_power_off = &gpio_poweroff_do_poweroff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_poweroff_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (pm_power_off == &gpio_poweroff_do_poweroff)
|
||||
pm_power_off = NULL;
|
||||
ret = devm_register_sys_off_handler(&pdev->dev, SYS_OFF_MODE_POWER_OFF,
|
||||
priority, gpio_poweroff_do_poweroff, gpio_poweroff);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "Cannot register poweroff handler\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -95,7 +102,6 @@ MODULE_DEVICE_TABLE(of, of_gpio_poweroff_match);
|
||||
|
||||
static struct platform_driver gpio_poweroff_driver = {
|
||||
.probe = gpio_poweroff_probe,
|
||||
.remove = gpio_poweroff_remove,
|
||||
.driver = {
|
||||
.name = "poweroff-gpio",
|
||||
.of_match_table = of_gpio_poweroff_match,
|
||||
|
||||
@@ -59,9 +59,4 @@ static struct platform_driver msm_restart_driver = {
|
||||
.of_match_table = of_match_ptr(of_msm_restart_match),
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_restart_init(void)
|
||||
{
|
||||
return platform_driver_register(&msm_restart_driver);
|
||||
}
|
||||
device_initcall(msm_restart_init);
|
||||
builtin_platform_driver(msm_restart_driver);
|
||||
|
||||
@@ -45,8 +45,8 @@ static int nvmem_reboot_mode_probe(struct platform_device *pdev)
|
||||
|
||||
nvmem_rbm->cell = devm_nvmem_cell_get(&pdev->dev, "reboot-mode");
|
||||
if (IS_ERR(nvmem_rbm->cell)) {
|
||||
dev_err(&pdev->dev, "failed to get the nvmem cell reboot-mode\n");
|
||||
return PTR_ERR(nvmem_rbm->cell);
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(nvmem_rbm->cell),
|
||||
"failed to get the nvmem cell reboot-mode\n");
|
||||
}
|
||||
|
||||
ret = devm_reboot_mode_register(&pdev->dev, &nvmem_rbm->reboot);
|
||||
|
||||
@@ -100,12 +100,7 @@ static struct platform_driver st_reset_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init st_reset_init(void)
|
||||
{
|
||||
return platform_driver_register(&st_reset_driver);
|
||||
}
|
||||
|
||||
device_initcall(st_reset_init);
|
||||
builtin_platform_driver(st_reset_driver);
|
||||
|
||||
MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
|
||||
MODULE_DESCRIPTION("STMicroelectronics Power off Restart driver");
|
||||
|
||||
@@ -32,23 +32,27 @@ static void syscon_poweroff(void)
|
||||
|
||||
static int syscon_poweroff_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int mask_err, value_err;
|
||||
|
||||
map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
|
||||
map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(&pdev->dev, "unable to get syscon");
|
||||
return PTR_ERR(map);
|
||||
map = syscon_node_to_regmap(dev->parent->of_node);
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(dev, "unable to get syscon");
|
||||
return PTR_ERR(map);
|
||||
}
|
||||
}
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "offset", &offset)) {
|
||||
dev_err(&pdev->dev, "unable to read 'offset'");
|
||||
if (of_property_read_u32(dev->of_node, "offset", &offset)) {
|
||||
dev_err(dev, "unable to read 'offset'");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
value_err = of_property_read_u32(pdev->dev.of_node, "value", &value);
|
||||
mask_err = of_property_read_u32(pdev->dev.of_node, "mask", &mask);
|
||||
value_err = of_property_read_u32(dev->of_node, "value", &value);
|
||||
mask_err = of_property_read_u32(dev->of_node, "mask", &mask);
|
||||
if (value_err && mask_err) {
|
||||
dev_err(&pdev->dev, "unable to read 'value' and 'mask'");
|
||||
dev_err(dev, "unable to read 'value' and 'mask'");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -62,7 +66,7 @@ static int syscon_poweroff_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
if (pm_power_off) {
|
||||
dev_err(&pdev->dev, "pm_power_off already claimed for %ps",
|
||||
dev_err(dev, "pm_power_off already claimed for %ps",
|
||||
pm_power_off);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -93,9 +97,4 @@ static struct platform_driver syscon_poweroff_driver = {
|
||||
.of_match_table = syscon_poweroff_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init syscon_poweroff_register(void)
|
||||
{
|
||||
return platform_driver_register(&syscon_poweroff_driver);
|
||||
}
|
||||
device_initcall(syscon_poweroff_register);
|
||||
builtin_platform_driver(syscon_poweroff_driver);
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/vexpress.h>
|
||||
@@ -108,20 +108,17 @@ static int _vexpress_register_restart_handler(struct device *dev)
|
||||
|
||||
static int vexpress_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *match =
|
||||
of_match_device(vexpress_reset_of_match, &pdev->dev);
|
||||
enum vexpress_reset_func func;
|
||||
struct regmap *regmap;
|
||||
int ret = 0;
|
||||
|
||||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
regmap = devm_regmap_init_vexpress_config(&pdev->dev);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
dev_set_drvdata(&pdev->dev, regmap);
|
||||
|
||||
switch ((uintptr_t)match->data) {
|
||||
func = (uintptr_t)device_get_match_data(&pdev->dev);
|
||||
switch (func) {
|
||||
case FUNC_SHUTDOWN:
|
||||
vexpress_power_off_device = &pdev->dev;
|
||||
pm_power_off = vexpress_power_off;
|
||||
|
||||
@@ -87,9 +87,4 @@ static struct platform_driver xgene_reboot_driver = {
|
||||
.of_match_table = xgene_reboot_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init xgene_reboot_init(void)
|
||||
{
|
||||
return platform_driver_register(&xgene_reboot_driver);
|
||||
}
|
||||
device_initcall(xgene_reboot_init);
|
||||
builtin_platform_driver(xgene_reboot_driver);
|
||||
|
||||
@@ -921,12 +921,12 @@ static int pm860x_battery_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
info->irq_cc = platform_get_irq(pdev, 0);
|
||||
if (info->irq_cc <= 0)
|
||||
return -EINVAL;
|
||||
if (info->irq_cc < 0)
|
||||
return info->irq_cc;
|
||||
|
||||
info->irq_batt = platform_get_irq(pdev, 1);
|
||||
if (info->irq_batt <= 0)
|
||||
return -EINVAL;
|
||||
if (info->irq_batt < 0)
|
||||
return info->irq_batt;
|
||||
|
||||
info->chip = chip;
|
||||
info->i2c =
|
||||
|
||||
@@ -374,7 +374,7 @@ config AXP288_FUEL_GAUGE
|
||||
|
||||
config BATTERY_MAX17040
|
||||
tristate "Maxim MAX17040/17041/17043 family Fuel Gauge"
|
||||
depends on I2C
|
||||
depends on I2C && IIO
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Driver supports Maxim fuel-gauge systems for lithium-ion (Li+)
|
||||
@@ -629,6 +629,29 @@ config CHARGER_QCOM_SMBB
|
||||
documentation for more detail. The base name for this driver is
|
||||
'pm8941_charger'.
|
||||
|
||||
config BATTERY_PM8916_BMS_VM
|
||||
tristate "Qualcomm PM8916 BMS-VM support"
|
||||
depends on MFD_SPMI_PMIC || COMPILE_TEST
|
||||
help
|
||||
Say Y to add support for Voltage Mode BMS block found in some
|
||||
Qualcomm PMICs such as PM8916. This hardware block provides
|
||||
battery voltage monitoring for the system.
|
||||
|
||||
To compile this driver as module, choose M here: the
|
||||
module will be called pm8916_bms_vm.
|
||||
|
||||
config CHARGER_PM8916_LBC
|
||||
tristate "Qualcomm PM8916 Linear Battery Charger support"
|
||||
depends on MFD_SPMI_PMIC || COMPILE_TEST
|
||||
depends on EXTCON || !EXTCON
|
||||
help
|
||||
Say Y here to add support for Linear Battery Charger block
|
||||
found in some Qualcomm PMICs such as PM8916. This hardware
|
||||
blokc provides simple CC/CV battery charger.
|
||||
|
||||
To compile this driver as module, choose M here: the
|
||||
module will be called pm8916_lbc.
|
||||
|
||||
config CHARGER_BQ2415X
|
||||
tristate "TI BQ2415x battery charger driver"
|
||||
depends on I2C
|
||||
@@ -952,4 +975,13 @@ config CHARGER_QCOM_SMB2
|
||||
adds support for the SMB2 switch mode battery charger found
|
||||
in PMI8998 and related PMICs.
|
||||
|
||||
config FUEL_GAUGE_MM8013
|
||||
tristate "Mitsumi MM8013 fuel gauge driver"
|
||||
depends on I2C
|
||||
help
|
||||
Say Y here to enable the Mitsumi MM8013 fuel gauge driver.
|
||||
It enables the monitoring of many battery parameters, including
|
||||
the state of charge, temperature, cycle count, actual and design
|
||||
capacity, etc.
|
||||
|
||||
endif # POWER_SUPPLY
|
||||
|
||||
@@ -84,6 +84,8 @@ obj-$(CONFIG_CHARGER_MP2629) += mp2629_charger.o
|
||||
obj-$(CONFIG_CHARGER_MT6360) += mt6360_charger.o
|
||||
obj-$(CONFIG_CHARGER_MT6370) += mt6370-charger.o
|
||||
obj-$(CONFIG_CHARGER_QCOM_SMBB) += qcom_smbb.o
|
||||
obj-$(CONFIG_BATTERY_PM8916_BMS_VM) += pm8916_bms_vm.o
|
||||
obj-$(CONFIG_CHARGER_PM8916_LBC) += pm8916_lbc.o
|
||||
obj-$(CONFIG_CHARGER_BQ2415X) += bq2415x_charger.o
|
||||
obj-$(CONFIG_CHARGER_BQ24190) += bq24190_charger.o
|
||||
obj-$(CONFIG_CHARGER_BQ24257) += bq24257_charger.o
|
||||
@@ -111,3 +113,4 @@ obj-$(CONFIG_BATTERY_SURFACE) += surface_battery.o
|
||||
obj-$(CONFIG_CHARGER_SURFACE) += surface_charger.o
|
||||
obj-$(CONFIG_BATTERY_UG3105) += ug3105_battery.o
|
||||
obj-$(CONFIG_CHARGER_QCOM_SMB2) += qcom_pmi8998_charger.o
|
||||
obj-$(CONFIG_FUEL_GAUGE_MM8013) += mm8013.o
|
||||
|
||||
@@ -804,11 +804,9 @@ static int ab8500_btemp_probe(struct platform_device *pdev)
|
||||
return component_add(dev, &ab8500_btemp_component_ops);
|
||||
}
|
||||
|
||||
static int ab8500_btemp_remove(struct platform_device *pdev)
|
||||
static void ab8500_btemp_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &ab8500_btemp_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume);
|
||||
@@ -821,7 +819,7 @@ MODULE_DEVICE_TABLE(of, ab8500_btemp_match);
|
||||
|
||||
struct platform_driver ab8500_btemp_driver = {
|
||||
.probe = ab8500_btemp_probe,
|
||||
.remove = ab8500_btemp_remove,
|
||||
.remove_new = ab8500_btemp_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-btemp",
|
||||
.of_match_table = ab8500_btemp_match,
|
||||
|
||||
@@ -1824,11 +1824,9 @@ static int ab8500_chargalg_probe(struct platform_device *pdev)
|
||||
return component_add(dev, &ab8500_chargalg_component_ops);
|
||||
}
|
||||
|
||||
static int ab8500_chargalg_remove(struct platform_device *pdev)
|
||||
static void ab8500_chargalg_remove(struct platform_device *pdev)
|
||||
{
|
||||
component_del(&pdev->dev, &ab8500_chargalg_component_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ab8500_chargalg_pm_ops, ab8500_chargalg_suspend, ab8500_chargalg_resume);
|
||||
@@ -1840,7 +1838,7 @@ static const struct of_device_id ab8500_chargalg_match[] = {
|
||||
|
||||
struct platform_driver ab8500_chargalg_driver = {
|
||||
.probe = ab8500_chargalg_probe,
|
||||
.remove = ab8500_chargalg_remove,
|
||||
.remove_new = ab8500_chargalg_remove,
|
||||
.driver = {
|
||||
.name = "ab8500_chargalg",
|
||||
.of_match_table = ab8500_chargalg_match,
|
||||
|
||||
@@ -3679,7 +3679,7 @@ static int ab8500_charger_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ab8500_charger_remove(struct platform_device *pdev)
|
||||
static void ab8500_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ab8500_charger *di = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -3688,8 +3688,6 @@ static int ab8500_charger_remove(struct platform_device *pdev)
|
||||
usb_unregister_notifier(di->usb_phy, &di->nb);
|
||||
ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
|
||||
usb_put_phy(di->usb_phy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, ab8500_charger_resume);
|
||||
@@ -3702,7 +3700,7 @@ MODULE_DEVICE_TABLE(of, ab8500_charger_match);
|
||||
|
||||
static struct platform_driver ab8500_charger_driver = {
|
||||
.probe = ab8500_charger_probe,
|
||||
.remove = ab8500_charger_remove,
|
||||
.remove_new = ab8500_charger_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-charger",
|
||||
.of_match_table = ab8500_charger_match,
|
||||
|
||||
@@ -3227,7 +3227,7 @@ static int ab8500_fg_probe(struct platform_device *pdev)
|
||||
return component_add(dev, &ab8500_fg_component_ops);
|
||||
}
|
||||
|
||||
static int ab8500_fg_remove(struct platform_device *pdev)
|
||||
static void ab8500_fg_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ab8500_fg *di = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -3236,8 +3236,6 @@ static int ab8500_fg_remove(struct platform_device *pdev)
|
||||
list_del(&di->node);
|
||||
ab8500_fg_sysfs_exit(di);
|
||||
ab8500_fg_sysfs_psy_remove_attrs(di);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ab8500_fg_pm_ops, ab8500_fg_suspend, ab8500_fg_resume);
|
||||
@@ -3250,7 +3248,7 @@ MODULE_DEVICE_TABLE(of, ab8500_fg_match);
|
||||
|
||||
struct platform_driver ab8500_fg_driver = {
|
||||
.probe = ab8500_fg_probe,
|
||||
.remove = ab8500_fg_remove,
|
||||
.remove_new = ab8500_fg_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-fg",
|
||||
.of_match_table = ab8500_fg_match,
|
||||
|
||||
@@ -251,13 +251,11 @@ static int a500_battery_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a500_battery_remove(struct platform_device *pdev)
|
||||
static void a500_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct a500_battery *bat = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
cancel_delayed_work_sync(&bat->poll_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused a500_battery_suspend(struct device *dev)
|
||||
@@ -287,7 +285,7 @@ static struct platform_driver a500_battery_driver = {
|
||||
.pm = &a500_battery_pm_ops,
|
||||
},
|
||||
.probe = a500_battery_probe,
|
||||
.remove = a500_battery_remove,
|
||||
.remove_new = a500_battery_remove,
|
||||
};
|
||||
module_platform_driver(a500_battery_driver);
|
||||
|
||||
|
||||
@@ -638,14 +638,12 @@ static int act8945a_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int act8945a_charger_remove(struct platform_device *pdev)
|
||||
static void act8945a_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct act8945a_charger *charger = platform_get_drvdata(pdev);
|
||||
|
||||
charger->init_done = false;
|
||||
cancel_work_sync(&charger->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver act8945a_charger_driver = {
|
||||
@@ -653,7 +651,7 @@ static struct platform_driver act8945a_charger_driver = {
|
||||
.name = "act8945a-charger",
|
||||
},
|
||||
.probe = act8945a_charger_probe,
|
||||
.remove = act8945a_charger_remove,
|
||||
.remove_new = act8945a_charger_remove,
|
||||
};
|
||||
module_platform_driver(act8945a_charger_driver);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ struct axp20x_ac_power {
|
||||
struct iio_channel *acin_i;
|
||||
bool has_acin_path_sel;
|
||||
unsigned int num_irqs;
|
||||
unsigned int irqs[];
|
||||
unsigned int irqs[] __counted_by(num_irqs);
|
||||
};
|
||||
|
||||
static irqreturn_t axp20x_ac_power_irq(int irq, void *devid)
|
||||
|
||||
@@ -73,7 +73,7 @@ struct axp20x_usb_power {
|
||||
unsigned int old_status;
|
||||
unsigned int online;
|
||||
unsigned int num_irqs;
|
||||
unsigned int irqs[];
|
||||
unsigned int irqs[] __counted_by(num_irqs);
|
||||
};
|
||||
|
||||
static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power)
|
||||
|
||||
@@ -1803,7 +1803,7 @@ static int bq24190_probe(struct i2c_client *client)
|
||||
|
||||
bdi->client = client;
|
||||
bdi->dev = dev;
|
||||
strncpy(bdi->model_name, id->name, I2C_NAME_SIZE);
|
||||
strscpy(bdi->model_name, id->name, sizeof(bdi->model_name));
|
||||
mutex_init(&bdi->f_reg_lock);
|
||||
bdi->charge_type = POWER_SUPPLY_CHARGE_TYPE_FAST;
|
||||
bdi->f_reg = 0;
|
||||
|
||||
@@ -35,20 +35,15 @@
|
||||
|
||||
#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",
|
||||
struct bq2425x_chip_info {
|
||||
const char *const name;
|
||||
enum bq2425x_chip chip;
|
||||
};
|
||||
|
||||
enum bq24257_fields {
|
||||
@@ -84,7 +79,7 @@ struct bq24257_device {
|
||||
struct device *dev;
|
||||
struct power_supply *charger;
|
||||
|
||||
enum bq2425x_chip chip;
|
||||
const struct bq2425x_chip_info *info;
|
||||
|
||||
struct regmap *rmap;
|
||||
struct regmap_field *rmap_fields[F_MAX_FIELDS];
|
||||
@@ -329,7 +324,7 @@ static int bq24257_power_supply_get_property(struct power_supply *psy,
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||
val->strval = bq2425x_chip_name[bq->chip];
|
||||
val->strval = bq->info->name;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
@@ -947,10 +942,8 @@ static int bq24257_fw_probe(struct bq24257_device *bq)
|
||||
|
||||
static int bq24257_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
struct device *dev = &client->dev;
|
||||
const struct acpi_device_id *acpi_id;
|
||||
struct bq24257_device *bq;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -967,17 +960,9 @@ 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;
|
||||
}
|
||||
bq->info = i2c_get_match_data(client);
|
||||
if (!bq->info)
|
||||
return dev_err_probe(dev, -ENODEV, "Failed to match device\n");
|
||||
|
||||
mutex_init(&bq->lock);
|
||||
|
||||
@@ -1015,7 +1000,7 @@ static int bq24257_probe(struct i2c_client *client)
|
||||
* used for the automatic setting of the input current limit setting so
|
||||
* explicitly disable that feature.
|
||||
*/
|
||||
if (bq->chip == BQ24250)
|
||||
if (bq->info->chip == BQ24250)
|
||||
bq->iilimit_autoset_enable = false;
|
||||
|
||||
if (bq->iilimit_autoset_enable)
|
||||
@@ -1028,7 +1013,7 @@ static int bq24257_probe(struct i2c_client *client)
|
||||
* 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)
|
||||
if (bq->info->chip != BQ24250)
|
||||
bq24257_pg_gpio_probe(bq);
|
||||
|
||||
if (PTR_ERR(bq->pg) == -EPROBE_DEFER)
|
||||
@@ -1066,7 +1051,7 @@ static int bq24257_probe(struct i2c_client *client)
|
||||
bq24257_irq_handler_thread,
|
||||
IRQF_TRIGGER_FALLING |
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
bq2425x_chip_name[bq->chip], bq);
|
||||
bq->info->name, bq);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request IRQ #%d\n", client->irq);
|
||||
return ret;
|
||||
@@ -1132,28 +1117,43 @@ static const struct dev_pm_ops bq24257_pm = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(bq24257_suspend, bq24257_resume)
|
||||
};
|
||||
|
||||
static const struct bq2425x_chip_info bq24250_info = {
|
||||
.name = "bq24250",
|
||||
.chip = BQ24250,
|
||||
};
|
||||
|
||||
static const struct bq2425x_chip_info bq24251_info = {
|
||||
.name = "bq24251",
|
||||
.chip = BQ24251,
|
||||
};
|
||||
|
||||
static const struct bq2425x_chip_info bq24257_info = {
|
||||
.name = "bq24257",
|
||||
.chip = BQ24257,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id bq24257_i2c_ids[] = {
|
||||
{ "bq24250", BQ24250 },
|
||||
{ "bq24251", BQ24251 },
|
||||
{ "bq24257", BQ24257 },
|
||||
{},
|
||||
{ "bq24250", (kernel_ulong_t)&bq24250_info },
|
||||
{ "bq24251", (kernel_ulong_t)&bq24251_info },
|
||||
{ "bq24257", (kernel_ulong_t)&bq24257_info },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bq24257_i2c_ids);
|
||||
|
||||
static const struct of_device_id bq24257_of_match[] __maybe_unused = {
|
||||
{ .compatible = "ti,bq24250", },
|
||||
{ .compatible = "ti,bq24251", },
|
||||
{ .compatible = "ti,bq24257", },
|
||||
{ },
|
||||
{ .compatible = "ti,bq24250", &bq24250_info },
|
||||
{ .compatible = "ti,bq24251", &bq24251_info },
|
||||
{ .compatible = "ti,bq24257", &bq24257_info },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bq24257_of_match);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static const struct acpi_device_id bq24257_acpi_match[] = {
|
||||
{ "BQ242500", BQ24250 },
|
||||
{ "BQ242510", BQ24251 },
|
||||
{ "BQ242570", BQ24257 },
|
||||
{},
|
||||
{ "BQ242500", (kernel_ulong_t)&bq24250_info },
|
||||
{ "BQ242510", (kernel_ulong_t)&bq24251_info },
|
||||
{ "BQ242570", (kernel_ulong_t)&bq24257_info },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bq24257_acpi_match);
|
||||
#endif
|
||||
|
||||
@@ -147,9 +147,14 @@ struct bq2515x_init_data {
|
||||
int iprechg;
|
||||
};
|
||||
|
||||
enum bq2515x_id {
|
||||
BQ25150,
|
||||
BQ25155,
|
||||
/**
|
||||
* struct bq2515x_info -
|
||||
* @regmap_config: register map config
|
||||
* @ilim: input current limit
|
||||
*/
|
||||
struct bq2515x_info {
|
||||
const struct regmap_config *regmap_config;
|
||||
int ilim;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -164,8 +169,8 @@ enum bq2515x_id {
|
||||
* @ac_detect_gpio: power good (PG) pin
|
||||
* @ce_gpio: charge enable (CE) pin
|
||||
*
|
||||
* @info: device info
|
||||
* @model_name: string value describing device model
|
||||
* @device_id: value of device_id
|
||||
* @mains_online: boolean value indicating power supply online
|
||||
*
|
||||
* @init_data: charger initialization data structure
|
||||
@@ -181,8 +186,8 @@ struct bq2515x_device {
|
||||
struct gpio_desc *ac_detect_gpio;
|
||||
struct gpio_desc *ce_gpio;
|
||||
|
||||
const struct bq2515x_info *info;
|
||||
char model_name[I2C_NAME_SIZE];
|
||||
int device_id;
|
||||
bool mains_online;
|
||||
|
||||
struct bq2515x_init_data init_data;
|
||||
@@ -998,16 +1003,8 @@ static int bq2515x_read_properties(struct bq2515x_device *bq2515x)
|
||||
ret = device_property_read_u32(bq2515x->dev,
|
||||
"input-current-limit-microamp",
|
||||
&bq2515x->init_data.ilim);
|
||||
if (ret) {
|
||||
switch (bq2515x->device_id) {
|
||||
case BQ25150:
|
||||
bq2515x->init_data.ilim = BQ25150_DEFAULT_ILIM_UA;
|
||||
break;
|
||||
case BQ25155:
|
||||
bq2515x->init_data.ilim = BQ25155_DEFAULT_ILIM_UA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
bq2515x->init_data.ilim = bq2515x->info->ilim;
|
||||
|
||||
bq2515x->ac_detect_gpio = devm_gpiod_get_optional(bq2515x->dev,
|
||||
"ac-detect", GPIOD_IN);
|
||||
@@ -1092,21 +1089,11 @@ static int bq2515x_probe(struct i2c_client *client)
|
||||
|
||||
bq2515x->dev = dev;
|
||||
|
||||
strncpy(bq2515x->model_name, id->name, I2C_NAME_SIZE);
|
||||
|
||||
bq2515x->device_id = id->driver_data;
|
||||
|
||||
switch (bq2515x->device_id) {
|
||||
case BQ25150:
|
||||
bq2515x->regmap = devm_regmap_init_i2c(client,
|
||||
&bq25150_regmap_config);
|
||||
break;
|
||||
case BQ25155:
|
||||
bq2515x->regmap = devm_regmap_init_i2c(client,
|
||||
&bq25155_regmap_config);
|
||||
break;
|
||||
}
|
||||
strscpy(bq2515x->model_name, id->name, sizeof(bq2515x->model_name));
|
||||
|
||||
bq2515x->info = i2c_get_match_data(client);
|
||||
bq2515x->regmap = devm_regmap_init_i2c(client,
|
||||
bq2515x->info->regmap_config);
|
||||
if (IS_ERR(bq2515x->regmap)) {
|
||||
dev_err(dev, "failed to allocate register map\n");
|
||||
return PTR_ERR(bq2515x->regmap);
|
||||
@@ -1139,17 +1126,27 @@ static int bq2515x_probe(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct bq2515x_info bq25150 = {
|
||||
.regmap_config = &bq25150_regmap_config,
|
||||
.ilim = BQ25150_DEFAULT_ILIM_UA,
|
||||
};
|
||||
|
||||
static const struct bq2515x_info bq25155 = {
|
||||
.regmap_config = &bq25155_regmap_config,
|
||||
.ilim = BQ25155_DEFAULT_ILIM_UA,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id bq2515x_i2c_ids[] = {
|
||||
{ "bq25150", BQ25150, },
|
||||
{ "bq25155", BQ25155, },
|
||||
{},
|
||||
{ "bq25150", (kernel_ulong_t)&bq25150 },
|
||||
{ "bq25155", (kernel_ulong_t)&bq25155 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bq2515x_i2c_ids);
|
||||
|
||||
static const struct of_device_id bq2515x_of_match[] = {
|
||||
{ .compatible = "ti,bq25150", },
|
||||
{ .compatible = "ti,bq25155", },
|
||||
{ },
|
||||
{ .compatible = "ti,bq25150", .data = &bq25150 },
|
||||
{ .compatible = "ti,bq25155", .data = &bq25155 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bq2515x_of_match);
|
||||
|
||||
|
||||
@@ -1702,11 +1702,11 @@ static int bq256xx_probe(struct i2c_client *client)
|
||||
|
||||
bq->client = client;
|
||||
bq->dev = dev;
|
||||
bq->chip_info = &bq256xx_chip_info_tbl[id->driver_data];
|
||||
bq->chip_info = i2c_get_match_data(client);
|
||||
|
||||
mutex_init(&bq->lock);
|
||||
|
||||
strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
|
||||
strscpy(bq->model_name, id->name, sizeof(bq->model_name));
|
||||
|
||||
bq->regmap = devm_regmap_init_i2c(client,
|
||||
bq->chip_info->bq256xx_regmap_config);
|
||||
@@ -1771,38 +1771,38 @@ static int bq256xx_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static const struct i2c_device_id bq256xx_i2c_ids[] = {
|
||||
{ "bq25600", BQ25600 },
|
||||
{ "bq25600d", BQ25600D },
|
||||
{ "bq25601", BQ25601 },
|
||||
{ "bq25601d", BQ25601D },
|
||||
{ "bq25611d", BQ25611D },
|
||||
{ "bq25618", BQ25618 },
|
||||
{ "bq25619", BQ25619 },
|
||||
{},
|
||||
{ "bq25600", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] },
|
||||
{ "bq25600d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] },
|
||||
{ "bq25601", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] },
|
||||
{ "bq25601d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] },
|
||||
{ "bq25611d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] },
|
||||
{ "bq25618", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] },
|
||||
{ "bq25619", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, bq256xx_i2c_ids);
|
||||
|
||||
static const struct of_device_id bq256xx_of_match[] = {
|
||||
{ .compatible = "ti,bq25600", .data = (void *)BQ25600 },
|
||||
{ .compatible = "ti,bq25600d", .data = (void *)BQ25600D },
|
||||
{ .compatible = "ti,bq25601", .data = (void *)BQ25601 },
|
||||
{ .compatible = "ti,bq25601d", .data = (void *)BQ25601D },
|
||||
{ .compatible = "ti,bq25611d", .data = (void *)BQ25611D },
|
||||
{ .compatible = "ti,bq25618", .data = (void *)BQ25618 },
|
||||
{ .compatible = "ti,bq25619", .data = (void *)BQ25619 },
|
||||
{ },
|
||||
{ .compatible = "ti,bq25600", .data = &bq256xx_chip_info_tbl[BQ25600] },
|
||||
{ .compatible = "ti,bq25600d", .data = &bq256xx_chip_info_tbl[BQ25600D] },
|
||||
{ .compatible = "ti,bq25601", .data = &bq256xx_chip_info_tbl[BQ25601] },
|
||||
{ .compatible = "ti,bq25601d", .data = &bq256xx_chip_info_tbl[BQ25601D] },
|
||||
{ .compatible = "ti,bq25611d", .data = &bq256xx_chip_info_tbl[BQ25611D] },
|
||||
{ .compatible = "ti,bq25618", .data = &bq256xx_chip_info_tbl[BQ25618] },
|
||||
{ .compatible = "ti,bq25619", .data = &bq256xx_chip_info_tbl[BQ25619] },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bq256xx_of_match);
|
||||
|
||||
static const struct acpi_device_id bq256xx_acpi_match[] = {
|
||||
{ "bq25600", BQ25600 },
|
||||
{ "bq25600d", BQ25600D },
|
||||
{ "bq25601", BQ25601 },
|
||||
{ "bq25601d", BQ25601D },
|
||||
{ "bq25611d", BQ25611D },
|
||||
{ "bq25618", BQ25618 },
|
||||
{ "bq25619", BQ25619 },
|
||||
{},
|
||||
{ "bq25600", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600] },
|
||||
{ "bq25600d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25600D] },
|
||||
{ "bq25601", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601] },
|
||||
{ "bq25601d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25601D] },
|
||||
{ "bq25611d", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25611D] },
|
||||
{ "bq25618", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25618] },
|
||||
{ "bq25619", (kernel_ulong_t)&bq256xx_chip_info_tbl[BQ25619] },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bq256xx_acpi_match);
|
||||
|
||||
|
||||
@@ -1223,7 +1223,7 @@ static int bq25980_probe(struct i2c_client *client)
|
||||
|
||||
mutex_init(&bq->lock);
|
||||
|
||||
strncpy(bq->model_name, id->name, I2C_NAME_SIZE);
|
||||
strscpy(bq->model_name, id->name, sizeof(bq->model_name));
|
||||
bq->chip_info = &bq25980_chip_info_tbl[id->driver_data];
|
||||
|
||||
bq->regmap = devm_regmap_init_i2c(client,
|
||||
|
||||
@@ -1516,9 +1516,11 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||
memcpy(&cm->charger_psy_desc, &psy_default, sizeof(psy_default));
|
||||
|
||||
if (!desc->psy_name)
|
||||
strncpy(cm->psy_name_buf, psy_default.name, PSY_NAME_MAX);
|
||||
strscpy(cm->psy_name_buf, psy_default.name,
|
||||
sizeof(cm->psy_name_buf));
|
||||
else
|
||||
strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
|
||||
strscpy(cm->psy_name_buf, desc->psy_name,
|
||||
sizeof(cm->psy_name_buf));
|
||||
cm->charger_psy_desc.name = cm->psy_name_buf;
|
||||
|
||||
/* Allocate for psy properties because they may vary */
|
||||
@@ -1628,7 +1630,7 @@ static int charger_manager_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int charger_manager_remove(struct platform_device *pdev)
|
||||
static void charger_manager_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct charger_manager *cm = platform_get_drvdata(pdev);
|
||||
struct charger_desc *desc = cm->desc;
|
||||
@@ -1648,8 +1650,6 @@ static int charger_manager_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(cm->charger_psy);
|
||||
|
||||
try_charger_enable(cm, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id charger_manager_id[] = {
|
||||
@@ -1740,7 +1740,7 @@ static struct platform_driver charger_manager_driver = {
|
||||
.of_match_table = charger_manager_match,
|
||||
},
|
||||
.probe = charger_manager_probe,
|
||||
.remove = charger_manager_remove,
|
||||
.remove_new = charger_manager_remove,
|
||||
.id_table = charger_manager_id,
|
||||
};
|
||||
|
||||
|
||||
@@ -1151,7 +1151,7 @@ static int cpcap_battery_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpcap_battery_remove(struct platform_device *pdev)
|
||||
static void cpcap_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct cpcap_battery_ddata *ddata = platform_get_drvdata(pdev);
|
||||
int error;
|
||||
@@ -1161,8 +1161,6 @@ static int cpcap_battery_remove(struct platform_device *pdev)
|
||||
0xffff, 0);
|
||||
if (error)
|
||||
dev_err(&pdev->dev, "could not disable: %i\n", error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cpcap_battery_driver = {
|
||||
@@ -1171,7 +1169,7 @@ static struct platform_driver cpcap_battery_driver = {
|
||||
.of_match_table = of_match_ptr(cpcap_battery_id_table),
|
||||
},
|
||||
.probe = cpcap_battery_probe,
|
||||
.remove = cpcap_battery_remove,
|
||||
.remove_new = cpcap_battery_remove,
|
||||
};
|
||||
module_platform_driver(cpcap_battery_driver);
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -865,7 +864,6 @@ static const struct power_supply_desc cpcap_charger_usb_desc = {
|
||||
.property_is_writeable = cpcap_charger_property_is_writeable,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id cpcap_charger_id_table[] = {
|
||||
{
|
||||
.compatible = "motorola,mapphone-cpcap-charger",
|
||||
@@ -873,20 +871,13 @@ static const struct of_device_id cpcap_charger_id_table[] = {
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cpcap_charger_id_table);
|
||||
#endif
|
||||
|
||||
static int cpcap_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cpcap_charger_ddata *ddata;
|
||||
const struct of_device_id *of_id;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
int error;
|
||||
|
||||
of_id = of_match_device(of_match_ptr(cpcap_charger_id_table),
|
||||
&pdev->dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
@@ -966,21 +957,19 @@ static void cpcap_charger_shutdown(struct platform_device *pdev)
|
||||
cancel_delayed_work_sync(&ddata->detect_work);
|
||||
}
|
||||
|
||||
static int cpcap_charger_remove(struct platform_device *pdev)
|
||||
static void cpcap_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
cpcap_charger_shutdown(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cpcap_charger_driver = {
|
||||
.probe = cpcap_charger_probe,
|
||||
.driver = {
|
||||
.name = "cpcap-charger",
|
||||
.of_match_table = of_match_ptr(cpcap_charger_id_table),
|
||||
.of_match_table = cpcap_charger_id_table,
|
||||
},
|
||||
.shutdown = cpcap_charger_shutdown,
|
||||
.remove = cpcap_charger_remove,
|
||||
.remove_new = cpcap_charger_remove,
|
||||
};
|
||||
module_platform_driver(cpcap_charger_driver);
|
||||
|
||||
|
||||
@@ -552,7 +552,7 @@ static int da9030_battery_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9030_battery_remove(struct platform_device *dev)
|
||||
static void da9030_battery_remove(struct platform_device *dev)
|
||||
{
|
||||
struct da9030_charger *charger = platform_get_drvdata(dev);
|
||||
|
||||
@@ -564,8 +564,6 @@ static int da9030_battery_remove(struct platform_device *dev)
|
||||
cancel_delayed_work_sync(&charger->work);
|
||||
da9030_set_charge(charger, 0);
|
||||
power_supply_unregister(charger->psy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da903x_battery_driver = {
|
||||
@@ -573,7 +571,7 @@ static struct platform_driver da903x_battery_driver = {
|
||||
.name = "da903x-battery",
|
||||
},
|
||||
.probe = da9030_battery_probe,
|
||||
.remove = da9030_battery_remove,
|
||||
.remove_new = da9030_battery_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(da903x_battery_driver);
|
||||
|
||||
@@ -637,7 +637,7 @@ static s32 da9052_bat_probe(struct platform_device *pdev)
|
||||
|
||||
return ret;
|
||||
}
|
||||
static int da9052_bat_remove(struct platform_device *pdev)
|
||||
static void da9052_bat_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
struct da9052_battery *bat = platform_get_drvdata(pdev);
|
||||
@@ -646,13 +646,11 @@ static int da9052_bat_remove(struct platform_device *pdev)
|
||||
da9052_free_irq(bat->da9052, da9052_bat_irq_bits[i], bat);
|
||||
|
||||
power_supply_unregister(bat->psy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9052_bat_driver = {
|
||||
.probe = da9052_bat_probe,
|
||||
.remove = da9052_bat_remove,
|
||||
.remove_new = da9052_bat_remove,
|
||||
.driver = {
|
||||
.name = "da9052-bat",
|
||||
},
|
||||
|
||||
@@ -635,7 +635,7 @@ static int da9150_charger_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9150_charger_remove(struct platform_device *pdev)
|
||||
static void da9150_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9150_charger *charger = platform_get_drvdata(pdev);
|
||||
int irq;
|
||||
@@ -665,8 +665,6 @@ static int da9150_charger_remove(struct platform_device *pdev)
|
||||
iio_channel_release(charger->vbus_chan);
|
||||
iio_channel_release(charger->tjunc_chan);
|
||||
iio_channel_release(charger->vbat_chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9150_charger_driver = {
|
||||
@@ -674,7 +672,7 @@ static struct platform_driver da9150_charger_driver = {
|
||||
.name = "da9150-charger",
|
||||
},
|
||||
.probe = da9150_charger_probe,
|
||||
.remove = da9150_charger_remove,
|
||||
.remove_new = da9150_charger_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(da9150_charger_driver);
|
||||
|
||||
@@ -249,13 +249,12 @@ static int goldfish_battery_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int goldfish_battery_remove(struct platform_device *pdev)
|
||||
static void goldfish_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct goldfish_battery_data *data = platform_get_drvdata(pdev);
|
||||
|
||||
power_supply_unregister(data->battery);
|
||||
power_supply_unregister(data->ac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id goldfish_battery_of_match[] = {
|
||||
@@ -274,7 +273,7 @@ MODULE_DEVICE_TABLE(acpi, goldfish_battery_acpi_match);
|
||||
|
||||
static struct platform_driver goldfish_battery_device = {
|
||||
.probe = goldfish_battery_probe,
|
||||
.remove = goldfish_battery_remove,
|
||||
.remove_new = goldfish_battery_remove,
|
||||
.driver = {
|
||||
.name = "goldfish-battery",
|
||||
.of_match_table = goldfish_battery_of_match,
|
||||
|
||||
@@ -265,7 +265,7 @@ static int micro_batt_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int micro_batt_remove(struct platform_device *pdev)
|
||||
static void micro_batt_remove(struct platform_device *pdev)
|
||||
|
||||
{
|
||||
struct micro_battery *mb = platform_get_drvdata(pdev);
|
||||
@@ -274,8 +274,6 @@ static int micro_batt_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(micro_batt_power);
|
||||
cancel_delayed_work_sync(&mb->update);
|
||||
destroy_workqueue(mb->wq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused micro_batt_suspend(struct device *dev)
|
||||
@@ -304,7 +302,7 @@ static struct platform_driver micro_batt_device_driver = {
|
||||
.pm = µ_batt_dev_pm_ops,
|
||||
},
|
||||
.probe = micro_batt_probe,
|
||||
.remove = micro_batt_remove,
|
||||
.remove_new = micro_batt_remove,
|
||||
};
|
||||
module_platform_driver(micro_batt_device_driver);
|
||||
|
||||
|
||||
@@ -477,15 +477,13 @@ static int isp1704_charger_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isp1704_charger_remove(struct platform_device *pdev)
|
||||
static void isp1704_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct isp1704_charger *isp = platform_get_drvdata(pdev);
|
||||
|
||||
usb_unregister_notifier(isp->phy, &isp->nb);
|
||||
power_supply_unregister(isp->psy);
|
||||
isp1704_charger_set_power(isp, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
@@ -503,7 +501,7 @@ static struct platform_driver isp1704_charger_driver = {
|
||||
.of_match_table = of_match_ptr(omap_isp1704_of_match),
|
||||
},
|
||||
.probe = isp1704_charger_probe,
|
||||
.remove = isp1704_charger_remove,
|
||||
.remove_new = isp1704_charger_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(isp1704_charger_driver);
|
||||
|
||||
@@ -714,20 +714,18 @@ static int lp8788_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lp8788_charger_remove(struct platform_device *pdev)
|
||||
static void lp8788_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_charger *pchg = platform_get_drvdata(pdev);
|
||||
|
||||
flush_work(&pchg->charger_work);
|
||||
lp8788_irq_unregister(pdev, pchg);
|
||||
lp8788_psy_unregister(pchg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver lp8788_charger_driver = {
|
||||
.probe = lp8788_charger_probe,
|
||||
.remove = lp8788_charger_remove,
|
||||
.remove_new = lp8788_charger_remove,
|
||||
.driver = {
|
||||
.name = LP8788_DEV_CHARGER,
|
||||
},
|
||||
|
||||
@@ -606,14 +606,12 @@ static int max14577_charger_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max14577_charger_remove(struct platform_device *pdev)
|
||||
static void max14577_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max14577_charger *chg = platform_get_drvdata(pdev);
|
||||
|
||||
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
|
||||
power_supply_unregister(chg->charger);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id max14577_charger_id[] = {
|
||||
@@ -638,7 +636,7 @@ static struct platform_driver max14577_charger_driver = {
|
||||
.of_match_table = of_max14577_charger_dt_match,
|
||||
},
|
||||
.probe = max14577_charger_probe,
|
||||
.remove = max14577_charger_remove,
|
||||
.remove_new = max14577_charger_remove,
|
||||
.id_table = max14577_charger_id,
|
||||
};
|
||||
module_platform_driver(max14577_charger_driver);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
|
||||
#define MAX17040_VCELL 0x02
|
||||
#define MAX17040_SOC 0x04
|
||||
@@ -142,6 +143,7 @@ struct max17040_chip {
|
||||
struct delayed_work work;
|
||||
struct power_supply *battery;
|
||||
struct chip_data data;
|
||||
struct iio_channel *channel_temp;
|
||||
|
||||
/* battery capacity */
|
||||
int soc;
|
||||
@@ -389,6 +391,7 @@ static int max17040_get_property(struct power_supply *psy,
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = max17040_get_online(chip);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
@@ -400,6 +403,16 @@ static int max17040_get_property(struct power_supply *psy,
|
||||
case POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN:
|
||||
val->intval = chip->low_soc_alert;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
power_supply_get_property_from_supplier(psy, psp, val);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
if (!chip->channel_temp)
|
||||
return -ENODATA;
|
||||
|
||||
iio_read_channel_processed_scale(chip->channel_temp,
|
||||
&val->intval, 10);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -415,9 +428,12 @@ static const struct regmap_config max17040_regmap = {
|
||||
|
||||
static enum power_supply_property max17040_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CAPACITY,
|
||||
POWER_SUPPLY_PROP_CAPACITY_ALERT_MIN,
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc max17040_battery_desc = {
|
||||
@@ -463,6 +479,17 @@ static int max17040_probe(struct i2c_client *client)
|
||||
i2c_set_clientdata(client, chip);
|
||||
psy_cfg.drv_data = chip;
|
||||
|
||||
/* Switch to devm_iio_channel_get_optional when available */
|
||||
chip->channel_temp = devm_iio_channel_get(&client->dev, "temp");
|
||||
if (IS_ERR(chip->channel_temp)) {
|
||||
ret = PTR_ERR(chip->channel_temp);
|
||||
if (ret != -ENODEV)
|
||||
return dev_err_probe(&client->dev, PTR_ERR(chip->channel_temp),
|
||||
"failed to get temp\n");
|
||||
else
|
||||
chip->channel_temp = NULL;
|
||||
}
|
||||
|
||||
chip->battery = devm_power_supply_register(&client->dev,
|
||||
&max17040_battery_desc, &psy_cfg);
|
||||
if (IS_ERR(chip->battery)) {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#define STATUS_BR_BIT (1 << 15)
|
||||
|
||||
/* Interrupt mask bits */
|
||||
#define CONFIG_ALRT_BIT_ENBL (1 << 2)
|
||||
#define CFG_ALRT_BIT_ENBL (1 << 2)
|
||||
|
||||
#define VFSOC0_LOCK 0x0000
|
||||
#define VFSOC0_UNLOCK 0x0080
|
||||
@@ -1116,8 +1116,8 @@ static int max17042_probe(struct i2c_client *client)
|
||||
chip);
|
||||
if (!ret) {
|
||||
regmap_update_bits(chip->regmap, MAX17042_CONFIG,
|
||||
CONFIG_ALRT_BIT_ENBL,
|
||||
CONFIG_ALRT_BIT_ENBL);
|
||||
CFG_ALRT_BIT_ENBL,
|
||||
CFG_ALRT_BIT_ENBL);
|
||||
max17042_set_soc_threshold(chip, 1);
|
||||
} else {
|
||||
client->irq = 0;
|
||||
|
||||
@@ -345,13 +345,11 @@ static int max77650_charger_probe(struct platform_device *pdev)
|
||||
return max77650_charger_enable(chg);
|
||||
}
|
||||
|
||||
static int max77650_charger_remove(struct platform_device *pdev)
|
||||
static void max77650_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max77650_charger_data *chg = platform_get_drvdata(pdev);
|
||||
|
||||
max77650_charger_disable(chg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id max77650_charger_of_match[] = {
|
||||
@@ -366,7 +364,7 @@ static struct platform_driver max77650_charger_driver = {
|
||||
.of_match_table = max77650_charger_of_match,
|
||||
},
|
||||
.probe = max77650_charger_probe,
|
||||
.remove = max77650_charger_remove,
|
||||
.remove_new = max77650_charger_remove,
|
||||
};
|
||||
module_platform_driver(max77650_charger_driver);
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@ static int max77693_charger_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max77693_charger_remove(struct platform_device *pdev)
|
||||
static void max77693_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max77693_charger *chg = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -737,8 +737,6 @@ static int max77693_charger_remove(struct platform_device *pdev)
|
||||
device_remove_file(&pdev->dev, &dev_attr_fast_charge_timer);
|
||||
|
||||
power_supply_unregister(chg->charger);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id max77693_charger_id[] = {
|
||||
@@ -752,7 +750,7 @@ static struct platform_driver max77693_charger_driver = {
|
||||
.name = "max77693-charger",
|
||||
},
|
||||
.probe = max77693_charger_probe,
|
||||
.remove = max77693_charger_remove,
|
||||
.remove_new = max77693_charger_remove,
|
||||
.id_table = max77693_charger_id,
|
||||
};
|
||||
module_platform_driver(max77693_charger_driver);
|
||||
|
||||
@@ -566,7 +566,7 @@ static int max8925_power_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max8925_power_remove(struct platform_device *pdev)
|
||||
static void max8925_power_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max8925_power_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -576,12 +576,11 @@ static int max8925_power_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(info->battery);
|
||||
max8925_deinit_charger(info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver max8925_power_driver = {
|
||||
.probe = max8925_power_probe,
|
||||
.remove = max8925_power_remove,
|
||||
.remove_new = max8925_power_remove,
|
||||
.driver = {
|
||||
.name = "max8925-power",
|
||||
},
|
||||
|
||||
317
drivers/power/supply/mm8013.c
Normal file
317
drivers/power/supply/mm8013.c
Normal file
@@ -0,0 +1,317 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define REG_BATID 0x00 /* This one is very unclear */
|
||||
#define BATID_101 0x0101 /* 107kOhm */
|
||||
#define BATID_102 0x0102 /* 10kOhm */
|
||||
#define REG_TEMPERATURE 0x06
|
||||
#define REG_VOLTAGE 0x08
|
||||
#define REG_FLAGS 0x0a
|
||||
#define MM8013_FLAG_OTC BIT(15)
|
||||
#define MM8013_FLAG_OTD BIT(14)
|
||||
#define MM8013_FLAG_BATHI BIT(13)
|
||||
#define MM8013_FLAG_BATLOW BIT(12)
|
||||
#define MM8013_FLAG_CHG_INH BIT(11)
|
||||
#define MM8013_FLAG_FC BIT(9)
|
||||
#define MM8013_FLAG_CHG BIT(8)
|
||||
#define MM8013_FLAG_OCC BIT(6)
|
||||
#define MM8013_FLAG_ODC BIT(5)
|
||||
#define MM8013_FLAG_OT BIT(4)
|
||||
#define MM8013_FLAG_UT BIT(3)
|
||||
#define MM8013_FLAG_DSG BIT(0)
|
||||
#define REG_FULL_CHARGE_CAPACITY 0x0e
|
||||
#define REG_NOMINAL_CHARGE_CAPACITY 0x0c
|
||||
#define REG_AVERAGE_CURRENT 0x14
|
||||
#define REG_AVERAGE_TIME_TO_EMPTY 0x16
|
||||
#define REG_AVERAGE_TIME_TO_FULL 0x18
|
||||
#define REG_MAX_LOAD_CURRENT 0x1e
|
||||
#define REG_CYCLE_COUNT 0x2a
|
||||
#define REG_STATE_OF_CHARGE 0x2c
|
||||
#define REG_DESIGN_CAPACITY 0x3c
|
||||
/* TODO: 0x62-0x68 seem to contain 'MM8013C' in a length-prefixed, non-terminated string */
|
||||
|
||||
#define DECIKELVIN_TO_DECIDEGC(t) (t - 2731)
|
||||
|
||||
struct mm8013_chip {
|
||||
struct i2c_client *client;
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
static int mm8013_checkdevice(struct mm8013_chip *chip)
|
||||
{
|
||||
int battery_id, ret;
|
||||
u32 val;
|
||||
|
||||
ret = regmap_write(chip->regmap, REG_BATID, 0x0008);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(chip->regmap, REG_BATID, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (val == BATID_102)
|
||||
battery_id = 2;
|
||||
else if (val == BATID_101)
|
||||
battery_id = 1;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(&chip->client->dev, "battery_id: %d\n", battery_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum power_supply_property mm8013_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_CAPACITY,
|
||||
POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
|
||||
POWER_SUPPLY_PROP_CHARGE_FULL,
|
||||
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
|
||||
POWER_SUPPLY_PROP_CHARGE_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
POWER_SUPPLY_PROP_CYCLE_COUNT,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
|
||||
POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
};
|
||||
|
||||
static int mm8013_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct mm8013_chip *chip = psy->drv_data;
|
||||
int ret = 0;
|
||||
u32 regval;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
ret = regmap_read(chip->regmap, REG_STATE_OF_CHARGE, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
|
||||
ret = regmap_read(chip->regmap, REG_FLAGS, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (regval & MM8013_FLAG_CHG_INH)
|
||||
val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
||||
ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = 1000 * regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
|
||||
ret = regmap_read(chip->regmap, REG_DESIGN_CAPACITY, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = 1000 * regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_NOW:
|
||||
ret = regmap_read(chip->regmap, REG_NOMINAL_CHARGE_CAPACITY, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = 1000 * regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
ret = regmap_read(chip->regmap, REG_MAX_LOAD_CURRENT, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = -1000 * (s16)regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||
ret = regmap_read(chip->regmap, REG_AVERAGE_CURRENT, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = -1000 * (s16)regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CYCLE_COUNT:
|
||||
ret = regmap_read(chip->regmap, REG_CYCLE_COUNT, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
ret = regmap_read(chip->regmap, REG_FLAGS, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (regval & MM8013_FLAG_UT)
|
||||
val->intval = POWER_SUPPLY_HEALTH_COLD;
|
||||
else if (regval & (MM8013_FLAG_ODC | MM8013_FLAG_OCC))
|
||||
val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT;
|
||||
else if (regval & (MM8013_FLAG_BATLOW))
|
||||
val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
|
||||
else if (regval & MM8013_FLAG_BATHI)
|
||||
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||
else if (regval & (MM8013_FLAG_OT | MM8013_FLAG_OTD | MM8013_FLAG_OTC))
|
||||
val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_HEALTH_GOOD;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
ret = regmap_read(chip->regmap, REG_TEMPERATURE, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = ((s16)regval > 0);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
ret = regmap_read(chip->regmap, REG_FLAGS, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (regval & MM8013_FLAG_DSG)
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
else if (regval & MM8013_FLAG_CHG)
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else if (regval & MM8013_FLAG_FC)
|
||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
ret = regmap_read(chip->regmap, REG_TEMPERATURE, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = DECIKELVIN_TO_DECIDEGC(regval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
|
||||
ret = regmap_read(chip->regmap, REG_AVERAGE_TIME_TO_EMPTY, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* The estimation is not yet ready */
|
||||
if (regval == U16_MAX)
|
||||
return -ENODATA;
|
||||
|
||||
val->intval = regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
|
||||
ret = regmap_read(chip->regmap, REG_AVERAGE_TIME_TO_FULL, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* The estimation is not yet ready */
|
||||
if (regval == U16_MAX)
|
||||
return -ENODATA;
|
||||
|
||||
val->intval = regval;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = regmap_read(chip->regmap, REG_VOLTAGE, ®val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val->intval = 1000 * regval;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct power_supply_desc mm8013_desc = {
|
||||
.name = "mm8013",
|
||||
.type = POWER_SUPPLY_TYPE_BATTERY,
|
||||
.properties = mm8013_battery_props,
|
||||
.num_properties = ARRAY_SIZE(mm8013_battery_props),
|
||||
.get_property = mm8013_get_property,
|
||||
};
|
||||
|
||||
static const struct regmap_config mm8013_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 16,
|
||||
.max_register = 0x68,
|
||||
.use_single_read = true,
|
||||
.use_single_write = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static int mm8013_probe(struct i2c_client *client)
|
||||
{
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct device *dev = &client->dev;
|
||||
struct power_supply *psy;
|
||||
struct mm8013_chip *chip;
|
||||
int ret = 0;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return dev_err_probe(dev, -EIO,
|
||||
"I2C_FUNC_SMBUS_WORD_DATA not supported\n");
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(struct mm8013_chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->client = client;
|
||||
|
||||
chip->regmap = devm_regmap_init_i2c(client, &mm8013_regmap_config);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
ret = PTR_ERR(chip->regmap);
|
||||
return dev_err_probe(dev, ret, "Couldn't initialize regmap\n");
|
||||
}
|
||||
|
||||
ret = mm8013_checkdevice(chip);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "MM8013 not found\n");
|
||||
|
||||
psy_cfg.drv_data = chip;
|
||||
psy_cfg.of_node = dev->of_node;
|
||||
|
||||
psy = devm_power_supply_register(dev, &mm8013_desc, &psy_cfg);
|
||||
if (IS_ERR(psy))
|
||||
return PTR_ERR(psy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id mm8013_id_table[] = {
|
||||
{ "mm8013", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mm8013_id_table);
|
||||
|
||||
static const struct of_device_id mm8013_match_table[] = {
|
||||
{ .compatible = "mitsumi,mm8013" },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct i2c_driver mm8013_i2c_driver = {
|
||||
.probe = mm8013_probe,
|
||||
.id_table = mm8013_id_table,
|
||||
.driver = {
|
||||
.name = "mm8013",
|
||||
.of_match_table = mm8013_match_table,
|
||||
},
|
||||
};
|
||||
module_i2c_driver(mm8013_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("MM8013 fuel gauge driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -849,9 +849,7 @@ static int mt6370_chg_init_irq(struct mt6370_priv *priv)
|
||||
ret = platform_get_irq_byname(to_platform_device(priv->dev),
|
||||
mt6370_chg_irqs[i].name);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(priv->dev, ret,
|
||||
"Failed to get irq %s\n",
|
||||
mt6370_chg_irqs[i].name);
|
||||
return ret;
|
||||
|
||||
priv->irq_nums[i] = ret;
|
||||
ret = devm_request_threaded_irq(priv->dev, ret, NULL,
|
||||
|
||||
@@ -441,7 +441,7 @@ static int pcf50633_mbc_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcf50633_mbc_remove(struct platform_device *pdev)
|
||||
static void pcf50633_mbc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pcf50633_mbc *mbc = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@@ -453,8 +453,6 @@ static int pcf50633_mbc_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(mbc->usb);
|
||||
power_supply_unregister(mbc->adapter);
|
||||
power_supply_unregister(mbc->ac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver pcf50633_mbc_driver = {
|
||||
@@ -462,7 +460,7 @@ static struct platform_driver pcf50633_mbc_driver = {
|
||||
.name = "pcf50633-mbc",
|
||||
},
|
||||
.probe = pcf50633_mbc_probe,
|
||||
.remove = pcf50633_mbc_remove,
|
||||
.remove_new = pcf50633_mbc_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(pcf50633_mbc_driver);
|
||||
|
||||
305
drivers/power/supply/pm8916_bms_vm.c
Normal file
305
drivers/power/supply/pm8916_bms_vm.c
Normal file
@@ -0,0 +1,305 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023, Nikita Travkin <nikita@trvn.ru>
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timekeeping.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
#define PM8916_PERPH_TYPE 0x04
|
||||
#define PM8916_BMS_VM_TYPE 0x020D
|
||||
|
||||
#define PM8916_SEC_ACCESS 0xD0
|
||||
#define PM8916_SEC_MAGIC 0xA5
|
||||
|
||||
#define PM8916_BMS_VM_STATUS1 0x08
|
||||
#define PM8916_BMS_VM_FSM_STATE(x) (((x) & 0b00111000) >> 3)
|
||||
#define PM8916_BMS_VM_FSM_STATE_S2 0x2
|
||||
|
||||
#define PM8916_BMS_VM_MODE_CTL 0x40
|
||||
#define PM8916_BMS_VM_MODE_FORCE_S3 (BIT(0) | BIT(1))
|
||||
#define PM8916_BMS_VM_MODE_NORMAL (BIT(1) | BIT(3))
|
||||
|
||||
#define PM8916_BMS_VM_EN_CTL 0x46
|
||||
#define PM8916_BMS_ENABLED BIT(7)
|
||||
|
||||
#define PM8916_BMS_VM_FIFO_LENGTH_CTL 0x47
|
||||
#define PM8916_BMS_VM_S1_SAMPLE_INTERVAL_CTL 0x55
|
||||
#define PM8916_BMS_VM_S2_SAMPLE_INTERVAL_CTL 0x56
|
||||
#define PM8916_BMS_VM_S3_S7_OCV_DATA0 0x6A
|
||||
#define PM8916_BMS_VM_BMS_FIFO_REG_0_LSB 0xC0
|
||||
|
||||
/* Using only 1 fifo is broken in hardware */
|
||||
#define PM8916_BMS_VM_FIFO_COUNT 2 /* 2 .. 8 */
|
||||
|
||||
#define PM8916_BMS_VM_S1_SAMPLE_INTERVAL 10
|
||||
#define PM8916_BMS_VM_S2_SAMPLE_INTERVAL 10
|
||||
|
||||
struct pm8916_bms_vm_battery {
|
||||
struct device *dev;
|
||||
struct power_supply *battery;
|
||||
struct power_supply_battery_info *info;
|
||||
struct regmap *regmap;
|
||||
unsigned int reg;
|
||||
unsigned int last_ocv;
|
||||
time64_t last_ocv_time;
|
||||
unsigned int vbat_now;
|
||||
};
|
||||
|
||||
static int pm8916_bms_vm_battery_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct pm8916_bms_vm_battery *bat = power_supply_get_drvdata(psy);
|
||||
struct power_supply_battery_info *info = bat->info;
|
||||
int supplied;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
supplied = power_supply_am_i_supplied(psy);
|
||||
|
||||
if (supplied < 0 && supplied != -ENODEV)
|
||||
return supplied;
|
||||
else if (supplied && supplied != -ENODEV)
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
if (bat->vbat_now < info->voltage_min_design_uv)
|
||||
val->intval = POWER_SUPPLY_HEALTH_DEAD;
|
||||
else if (bat->vbat_now > info->voltage_max_design_uv)
|
||||
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_HEALTH_GOOD;
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
val->intval = bat->vbat_now;
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_OCV:
|
||||
/*
|
||||
* Hardware only reliably measures OCV when the system is off or suspended.
|
||||
* We expose the last known OCV value on boot, invalidating it after 180 seconds.
|
||||
*/
|
||||
if (ktime_get_seconds() - bat->last_ocv_time > 180)
|
||||
return -ENODATA;
|
||||
|
||||
val->intval = bat->last_ocv;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static enum power_supply_property pm8916_bms_vm_battery_properties[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_OCV,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
};
|
||||
|
||||
static irqreturn_t pm8916_bms_vm_fifo_update_done_irq(int irq, void *data)
|
||||
{
|
||||
struct pm8916_bms_vm_battery *bat = data;
|
||||
u16 vbat_data[PM8916_BMS_VM_FIFO_COUNT];
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(bat->regmap, bat->reg + PM8916_BMS_VM_BMS_FIFO_REG_0_LSB,
|
||||
&vbat_data, PM8916_BMS_VM_FIFO_COUNT * 2);
|
||||
if (ret)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/*
|
||||
* The VM-BMS hardware only collects voltage data and the software
|
||||
* has to process it to calculate the OCV and SoC. Hardware provides
|
||||
* up to 8 averaged measurements for software to take in account.
|
||||
*
|
||||
* Just use the last measured value for now to report the current
|
||||
* battery voltage.
|
||||
*/
|
||||
bat->vbat_now = vbat_data[PM8916_BMS_VM_FIFO_COUNT - 1] * 300;
|
||||
|
||||
power_supply_changed(bat->battery);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static const struct power_supply_desc pm8916_bms_vm_battery_psy_desc = {
|
||||
.name = "pm8916-bms-vm",
|
||||
.type = POWER_SUPPLY_TYPE_BATTERY,
|
||||
.properties = pm8916_bms_vm_battery_properties,
|
||||
.num_properties = ARRAY_SIZE(pm8916_bms_vm_battery_properties),
|
||||
.get_property = pm8916_bms_vm_battery_get_property,
|
||||
};
|
||||
|
||||
static int pm8916_bms_vm_battery_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct pm8916_bms_vm_battery *bat;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
int ret, irq;
|
||||
unsigned int tmp;
|
||||
|
||||
bat = devm_kzalloc(dev, sizeof(*bat), GFP_KERNEL);
|
||||
if (!bat)
|
||||
return -ENOMEM;
|
||||
|
||||
bat->dev = dev;
|
||||
|
||||
bat->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!bat->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
ret = device_property_read_u32(dev, "reg", &bat->reg);
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "fifo");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_bms_vm_fifo_update_done_irq,
|
||||
IRQF_ONESHOT, "pm8916_vm_bms", bat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(bat->regmap, bat->reg + PM8916_PERPH_TYPE, &tmp, 2);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
|
||||
if (tmp != PM8916_BMS_VM_TYPE)
|
||||
return dev_err_probe(dev, -ENODEV, "Device reported wrong type: 0x%X\n", tmp);
|
||||
|
||||
ret = regmap_write(bat->regmap, bat->reg + PM8916_BMS_VM_S1_SAMPLE_INTERVAL_CTL,
|
||||
PM8916_BMS_VM_S1_SAMPLE_INTERVAL);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
ret = regmap_write(bat->regmap, bat->reg + PM8916_BMS_VM_S2_SAMPLE_INTERVAL_CTL,
|
||||
PM8916_BMS_VM_S2_SAMPLE_INTERVAL);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
ret = regmap_write(bat->regmap, bat->reg + PM8916_BMS_VM_FIFO_LENGTH_CTL,
|
||||
PM8916_BMS_VM_FIFO_COUNT << 4 | PM8916_BMS_VM_FIFO_COUNT);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
ret = regmap_write(bat->regmap,
|
||||
bat->reg + PM8916_BMS_VM_EN_CTL, PM8916_BMS_ENABLED);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
|
||||
ret = regmap_bulk_read(bat->regmap,
|
||||
bat->reg + PM8916_BMS_VM_S3_S7_OCV_DATA0, &tmp, 2);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
|
||||
bat->last_ocv_time = ktime_get_seconds();
|
||||
bat->last_ocv = tmp * 300;
|
||||
bat->vbat_now = bat->last_ocv;
|
||||
|
||||
psy_cfg.drv_data = bat;
|
||||
psy_cfg.of_node = dev->of_node;
|
||||
|
||||
bat->battery = devm_power_supply_register(dev, &pm8916_bms_vm_battery_psy_desc, &psy_cfg);
|
||||
if (IS_ERR(bat->battery))
|
||||
return dev_err_probe(dev, PTR_ERR(bat->battery), "Unable to register battery\n");
|
||||
|
||||
ret = power_supply_get_battery_info(bat->battery, &bat->info);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Unable to get battery info\n");
|
||||
|
||||
platform_set_drvdata(pdev, bat);
|
||||
|
||||
return 0;
|
||||
|
||||
comm_error:
|
||||
return dev_err_probe(dev, ret, "Unable to communicate with device\n");
|
||||
}
|
||||
|
||||
static int pm8916_bms_vm_battery_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct pm8916_bms_vm_battery *bat = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Due to a hardware quirk the FSM doesn't switch states normally.
|
||||
* Instead we unlock the debug registers and force S3 (Measure OCV/Sleep)
|
||||
* mode every time we suspend.
|
||||
*/
|
||||
|
||||
ret = regmap_write(bat->regmap,
|
||||
bat->reg + PM8916_SEC_ACCESS, PM8916_SEC_MAGIC);
|
||||
if (ret)
|
||||
goto error;
|
||||
ret = regmap_write(bat->regmap,
|
||||
bat->reg + PM8916_BMS_VM_MODE_CTL, PM8916_BMS_VM_MODE_FORCE_S3);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dev_err(bat->dev, "Failed to force S3 mode: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pm8916_bms_vm_battery_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct pm8916_bms_vm_battery *bat = platform_get_drvdata(pdev);
|
||||
int ret;
|
||||
unsigned int tmp;
|
||||
|
||||
ret = regmap_bulk_read(bat->regmap,
|
||||
bat->reg + PM8916_BMS_VM_S3_S7_OCV_DATA0, &tmp, 2);
|
||||
|
||||
bat->last_ocv_time = ktime_get_seconds();
|
||||
bat->last_ocv = tmp * 300;
|
||||
|
||||
ret = regmap_write(bat->regmap,
|
||||
bat->reg + PM8916_SEC_ACCESS, PM8916_SEC_MAGIC);
|
||||
if (ret)
|
||||
goto error;
|
||||
ret = regmap_write(bat->regmap,
|
||||
bat->reg + PM8916_BMS_VM_MODE_CTL, PM8916_BMS_VM_MODE_NORMAL);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dev_err(bat->dev, "Failed to return normal mode: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id pm8916_bms_vm_battery_of_match[] = {
|
||||
{ .compatible = "qcom,pm8916-bms-vm", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pm8916_bms_vm_battery_of_match);
|
||||
|
||||
static struct platform_driver pm8916_bms_vm_battery_driver = {
|
||||
.driver = {
|
||||
.name = "pm8916-bms-vm",
|
||||
.of_match_table = pm8916_bms_vm_battery_of_match,
|
||||
},
|
||||
.probe = pm8916_bms_vm_battery_probe,
|
||||
.suspend = pm8916_bms_vm_battery_suspend,
|
||||
.resume = pm8916_bms_vm_battery_resume,
|
||||
};
|
||||
module_platform_driver(pm8916_bms_vm_battery_driver);
|
||||
|
||||
MODULE_DESCRIPTION("pm8916 BMS-VM driver");
|
||||
MODULE_AUTHOR("Nikita Travkin <nikita@trvn.ru>");
|
||||
MODULE_LICENSE("GPL");
|
||||
381
drivers/power/supply/pm8916_lbc.c
Normal file
381
drivers/power/supply/pm8916_lbc.c
Normal file
@@ -0,0 +1,381 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023, Nikita Travkin <nikita@trvn.ru>
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
/* Two bytes: type + subtype */
|
||||
#define PM8916_PERPH_TYPE 0x04
|
||||
#define PM8916_LBC_CHGR_TYPE 0x1502
|
||||
#define PM8916_LBC_BAT_IF_TYPE 0x1602
|
||||
#define PM8916_LBC_USB_TYPE 0x1702
|
||||
#define PM8916_LBC_MISC_TYPE 0x1802
|
||||
|
||||
#define PM8916_LBC_CHGR_CHG_OPTION 0x08
|
||||
#define PM8916_LBC_CHGR_PMIC_CHARGER BIT(7)
|
||||
|
||||
#define PM8916_LBC_CHGR_CHG_STATUS 0x09
|
||||
|
||||
#define PM8916_INT_RT_STS 0x10
|
||||
|
||||
#define PM8916_LBC_USB_USBIN_VALID BIT(1)
|
||||
|
||||
#define PM8916_LBC_CHGR_VDD_MAX 0x40
|
||||
#define PM8916_LBC_CHGR_VDD_SAFE 0x41
|
||||
#define PM8916_LBC_CHGR_IBAT_MAX 0x44
|
||||
#define PM8916_LBC_CHGR_IBAT_SAFE 0x45
|
||||
|
||||
#define PM8916_LBC_CHGR_TCHG_MAX_EN 0x60
|
||||
#define PM8916_LBC_CHGR_TCHG_MAX_ENABLED BIT(7)
|
||||
#define PM8916_LBC_CHGR_TCHG_MAX 0x61
|
||||
|
||||
#define PM8916_LBC_CHGR_CHG_CTRL 0x49
|
||||
#define PM8916_LBC_CHGR_CHG_EN BIT(7)
|
||||
#define PM8916_LBC_CHGR_PSTG_EN BIT(5)
|
||||
|
||||
#define PM8916_LBC_CHGR_MIN_CURRENT 90000
|
||||
#define PM8916_LBC_CHGR_MAX_CURRENT 1440000
|
||||
|
||||
#define PM8916_LBC_CHGR_MIN_VOLTAGE 4000000
|
||||
#define PM8916_LBC_CHGR_MAX_VOLTAGE 4775000
|
||||
#define PM8916_LBC_CHGR_VOLTAGE_STEP 25000
|
||||
|
||||
#define PM8916_LBC_CHGR_MIN_TIME 4
|
||||
#define PM8916_LBC_CHGR_MAX_TIME 256
|
||||
|
||||
struct pm8916_lbc_charger {
|
||||
struct device *dev;
|
||||
struct extcon_dev *edev;
|
||||
struct power_supply *charger;
|
||||
struct power_supply_battery_info *info;
|
||||
struct regmap *regmap;
|
||||
unsigned int reg[4];
|
||||
bool online;
|
||||
unsigned int charge_voltage_max;
|
||||
unsigned int charge_voltage_safe;
|
||||
unsigned int charge_current_max;
|
||||
unsigned int charge_current_safe;
|
||||
};
|
||||
|
||||
static const unsigned int pm8916_lbc_charger_cable[] = {
|
||||
EXTCON_USB,
|
||||
EXTCON_NONE,
|
||||
};
|
||||
|
||||
enum {
|
||||
LBC_CHGR = 0,
|
||||
LBC_BAT_IF,
|
||||
LBC_USB,
|
||||
LBC_MISC,
|
||||
};
|
||||
|
||||
static int pm8916_lbc_charger_configure(struct pm8916_lbc_charger *chg)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned int tmp;
|
||||
|
||||
chg->charge_voltage_max = clamp_t(u32, chg->charge_voltage_max,
|
||||
PM8916_LBC_CHGR_MIN_VOLTAGE, chg->charge_voltage_safe);
|
||||
|
||||
tmp = chg->charge_voltage_max - PM8916_LBC_CHGR_MIN_VOLTAGE;
|
||||
tmp /= PM8916_LBC_CHGR_VOLTAGE_STEP;
|
||||
chg->charge_voltage_max = PM8916_LBC_CHGR_MIN_VOLTAGE + tmp * PM8916_LBC_CHGR_VOLTAGE_STEP;
|
||||
|
||||
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_MAX, tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
chg->charge_current_max = min(chg->charge_current_max, chg->charge_current_safe);
|
||||
|
||||
tmp = clamp_t(u32, chg->charge_current_max,
|
||||
PM8916_LBC_CHGR_MIN_CURRENT, PM8916_LBC_CHGR_MAX_CURRENT);
|
||||
|
||||
tmp = chg->charge_current_max / PM8916_LBC_CHGR_MIN_CURRENT - 1;
|
||||
chg->charge_current_max = (tmp + 1) * PM8916_LBC_CHGR_MIN_CURRENT;
|
||||
|
||||
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_MAX, tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_CHG_CTRL,
|
||||
PM8916_LBC_CHGR_CHG_EN | PM8916_LBC_CHGR_PSTG_EN);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
dev_err(chg->dev, "Failed to configure charging: %pe\n", ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pm8916_lbc_charger_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct pm8916_lbc_charger *chg = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = chg->online;
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
|
||||
val->intval = chg->charge_voltage_max;
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
val->intval = chg->charge_current_max;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
static int pm8916_lbc_charger_set_property(struct power_supply *psy,
|
||||
enum power_supply_property prop,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct pm8916_lbc_charger *chg = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (prop) {
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
chg->charge_current_max = val->intval;
|
||||
return pm8916_lbc_charger_configure(chg);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int pm8916_lbc_charger_property_is_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static enum power_supply_property pm8916_lbc_charger_properties[] = {
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
|
||||
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
|
||||
};
|
||||
|
||||
static irqreturn_t pm8916_lbc_charger_state_changed_irq(int irq, void *data)
|
||||
{
|
||||
struct pm8916_lbc_charger *chg = data;
|
||||
unsigned int tmp;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(chg->regmap, chg->reg[LBC_USB] + PM8916_INT_RT_STS, &tmp);
|
||||
if (ret)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
chg->online = !!(tmp & PM8916_LBC_USB_USBIN_VALID);
|
||||
extcon_set_state_sync(chg->edev, EXTCON_USB, chg->online);
|
||||
|
||||
power_supply_changed(chg->charger);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int pm8916_lbc_charger_probe_dt(struct pm8916_lbc_charger *chg)
|
||||
{
|
||||
struct device *dev = chg->dev;
|
||||
int ret = 0;
|
||||
unsigned int tmp;
|
||||
|
||||
ret = device_property_read_u32(dev, "qcom,fast-charge-safe-voltage", &chg->charge_voltage_safe);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (chg->charge_voltage_safe < PM8916_LBC_CHGR_MIN_VOLTAGE)
|
||||
return -EINVAL;
|
||||
|
||||
chg->charge_voltage_safe = clamp_t(u32, chg->charge_voltage_safe,
|
||||
PM8916_LBC_CHGR_MIN_VOLTAGE, PM8916_LBC_CHGR_MAX_VOLTAGE);
|
||||
|
||||
tmp = chg->charge_voltage_safe - PM8916_LBC_CHGR_MIN_VOLTAGE;
|
||||
tmp /= PM8916_LBC_CHGR_VOLTAGE_STEP;
|
||||
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_VDD_SAFE, tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_property_read_u32(dev, "qcom,fast-charge-safe-current", &chg->charge_current_safe);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (chg->charge_current_safe < PM8916_LBC_CHGR_MIN_CURRENT)
|
||||
return -EINVAL;
|
||||
|
||||
chg->charge_current_safe = clamp_t(u32, chg->charge_current_safe,
|
||||
PM8916_LBC_CHGR_MIN_CURRENT, PM8916_LBC_CHGR_MAX_CURRENT);
|
||||
|
||||
chg->charge_current_max = chg->charge_current_safe;
|
||||
|
||||
tmp = chg->charge_current_safe / PM8916_LBC_CHGR_MIN_CURRENT - 1;
|
||||
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_IBAT_SAFE, tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Disable charger timeout. */
|
||||
ret = regmap_write(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_TCHG_MAX_EN, 0x00);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct power_supply_desc pm8916_lbc_charger_psy_desc = {
|
||||
.name = "pm8916-lbc-chgr",
|
||||
.type = POWER_SUPPLY_TYPE_USB,
|
||||
.properties = pm8916_lbc_charger_properties,
|
||||
.num_properties = ARRAY_SIZE(pm8916_lbc_charger_properties),
|
||||
.get_property = pm8916_lbc_charger_get_property,
|
||||
.set_property = pm8916_lbc_charger_set_property,
|
||||
.property_is_writeable = pm8916_lbc_charger_property_is_writeable,
|
||||
};
|
||||
|
||||
static int pm8916_lbc_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct pm8916_lbc_charger *chg;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
int ret, len, irq;
|
||||
unsigned int tmp;
|
||||
|
||||
chg = devm_kzalloc(dev, sizeof(*chg), GFP_KERNEL);
|
||||
if (!chg)
|
||||
return -ENOMEM;
|
||||
|
||||
chg->dev = dev;
|
||||
|
||||
chg->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!chg->regmap)
|
||||
return -ENODEV;
|
||||
|
||||
len = device_property_count_u32(dev, "reg");
|
||||
if (len < 0)
|
||||
return len;
|
||||
if (len != 4)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Wrong amount of reg values: %d (4 expected)\n", len);
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "usb_vbus");
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_lbc_charger_state_changed_irq,
|
||||
IRQF_ONESHOT, "pm8916_lbc", chg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_property_read_u32_array(dev, "reg", chg->reg, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_PERPH_TYPE, &tmp, 2);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
if (tmp != PM8916_LBC_CHGR_TYPE)
|
||||
goto type_error;
|
||||
|
||||
ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_BAT_IF] + PM8916_PERPH_TYPE, &tmp, 2);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
if (tmp != PM8916_LBC_BAT_IF_TYPE)
|
||||
goto type_error;
|
||||
|
||||
ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_USB] + PM8916_PERPH_TYPE, &tmp, 2);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
if (tmp != PM8916_LBC_USB_TYPE)
|
||||
goto type_error;
|
||||
|
||||
ret = regmap_bulk_read(chg->regmap, chg->reg[LBC_MISC] + PM8916_PERPH_TYPE, &tmp, 2);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
if (tmp != PM8916_LBC_MISC_TYPE)
|
||||
goto type_error;
|
||||
|
||||
ret = regmap_read(chg->regmap, chg->reg[LBC_CHGR] + PM8916_LBC_CHGR_CHG_OPTION, &tmp);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
if (tmp != PM8916_LBC_CHGR_PMIC_CHARGER)
|
||||
dev_err_probe(dev, -ENODEV, "The system is using an external charger\n");
|
||||
|
||||
ret = pm8916_lbc_charger_probe_dt(chg);
|
||||
if (ret)
|
||||
dev_err_probe(dev, ret, "Error while parsing device tree\n");
|
||||
|
||||
psy_cfg.drv_data = chg;
|
||||
psy_cfg.of_node = dev->of_node;
|
||||
|
||||
chg->charger = devm_power_supply_register(dev, &pm8916_lbc_charger_psy_desc, &psy_cfg);
|
||||
if (IS_ERR(chg->charger))
|
||||
return dev_err_probe(dev, PTR_ERR(chg->charger), "Unable to register charger\n");
|
||||
|
||||
ret = power_supply_get_battery_info(chg->charger, &chg->info);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Unable to get battery info\n");
|
||||
|
||||
chg->edev = devm_extcon_dev_allocate(dev, pm8916_lbc_charger_cable);
|
||||
if (IS_ERR(chg->edev))
|
||||
return PTR_ERR(chg->edev);
|
||||
|
||||
ret = devm_extcon_dev_register(dev, chg->edev);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "failed to register extcon device\n");
|
||||
|
||||
ret = regmap_read(chg->regmap, chg->reg[LBC_USB] + PM8916_INT_RT_STS, &tmp);
|
||||
if (ret)
|
||||
goto comm_error;
|
||||
|
||||
chg->online = !!(tmp & PM8916_LBC_USB_USBIN_VALID);
|
||||
extcon_set_state_sync(chg->edev, EXTCON_USB, chg->online);
|
||||
|
||||
chg->charge_voltage_max = chg->info->voltage_max_design_uv;
|
||||
ret = pm8916_lbc_charger_configure(chg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
comm_error:
|
||||
return dev_err_probe(dev, ret, "Unable to communicate with device\n");
|
||||
|
||||
type_error:
|
||||
return dev_err_probe(dev, -ENODEV, "Device reported wrong type: 0x%X\n", tmp);
|
||||
}
|
||||
|
||||
static const struct of_device_id pm8916_lbc_charger_of_match[] = {
|
||||
{ .compatible = "qcom,pm8916-lbc", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pm8916_lbc_charger_of_match);
|
||||
|
||||
static struct platform_driver pm8916_lbc_charger_driver = {
|
||||
.driver = {
|
||||
.name = "pm8916-lbc",
|
||||
.of_match_table = pm8916_lbc_charger_of_match,
|
||||
},
|
||||
.probe = pm8916_lbc_charger_probe,
|
||||
};
|
||||
module_platform_driver(pm8916_lbc_charger_driver);
|
||||
|
||||
MODULE_DESCRIPTION("pm8916 LBC driver");
|
||||
MODULE_AUTHOR("Nikita Travkin <nikita@trvn.ru>");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -29,8 +29,7 @@
|
||||
struct class *power_supply_class;
|
||||
EXPORT_SYMBOL_GPL(power_supply_class);
|
||||
|
||||
ATOMIC_NOTIFIER_HEAD(power_supply_notifier);
|
||||
EXPORT_SYMBOL_GPL(power_supply_notifier);
|
||||
static BLOCKING_NOTIFIER_HEAD(power_supply_notifier);
|
||||
|
||||
static struct device_type power_supply_dev_type;
|
||||
|
||||
@@ -97,7 +96,7 @@ static void power_supply_changed_work(struct work_struct *work)
|
||||
class_for_each_device(power_supply_class, NULL, psy,
|
||||
__power_supply_changed_work);
|
||||
power_supply_update_leds(psy);
|
||||
atomic_notifier_call_chain(&power_supply_notifier,
|
||||
blocking_notifier_call_chain(&power_supply_notifier,
|
||||
PSY_EVENT_PROP_CHANGED, psy);
|
||||
kobject_uevent(&psy->dev.kobj, KOBJ_CHANGE);
|
||||
spin_lock_irqsave(&psy->changed_lock, flags);
|
||||
@@ -1262,13 +1261,13 @@ static void power_supply_dev_release(struct device *dev)
|
||||
|
||||
int power_supply_reg_notifier(struct notifier_block *nb)
|
||||
{
|
||||
return atomic_notifier_chain_register(&power_supply_notifier, nb);
|
||||
return blocking_notifier_chain_register(&power_supply_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_reg_notifier);
|
||||
|
||||
void power_supply_unreg_notifier(struct notifier_block *nb)
|
||||
{
|
||||
atomic_notifier_chain_unregister(&power_supply_notifier, nb);
|
||||
blocking_notifier_chain_unregister(&power_supply_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_unreg_notifier);
|
||||
|
||||
@@ -1380,6 +1379,7 @@ __power_supply_register(struct device *parent,
|
||||
psy->drv_data = cfg->drv_data;
|
||||
psy->of_node =
|
||||
cfg->fwnode ? to_of_node(cfg->fwnode) : cfg->of_node;
|
||||
dev->of_node = psy->of_node;
|
||||
psy->supplied_to = cfg->supplied_to;
|
||||
psy->num_supplicants = cfg->num_supplicants;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/string_helpers.h>
|
||||
|
||||
#include "power_supply.h"
|
||||
|
||||
@@ -398,14 +399,6 @@ static const struct attribute_group *power_supply_attr_groups[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void str_to_lower(char *str)
|
||||
{
|
||||
while (*str) {
|
||||
*str = tolower(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void power_supply_init_attrs(struct device_type *dev_type)
|
||||
{
|
||||
int i;
|
||||
@@ -420,7 +413,8 @@ void power_supply_init_attrs(struct device_type *dev_type)
|
||||
__func__, i);
|
||||
sprintf(power_supply_attrs[i].attr_name, "_err_%d", i);
|
||||
} else {
|
||||
str_to_lower(power_supply_attrs[i].attr_name);
|
||||
string_lower(power_supply_attrs[i].attr_name,
|
||||
power_supply_attrs[i].attr_name);
|
||||
}
|
||||
|
||||
attr = &power_supply_attrs[i].dev_attr;
|
||||
|
||||
@@ -915,8 +915,7 @@ static int smb2_init_irq(struct smb2_chip *chip, int *irq, const char *name,
|
||||
|
||||
irqnum = platform_get_irq_byname(to_platform_device(chip->dev), name);
|
||||
if (irqnum < 0)
|
||||
return dev_err_probe(chip->dev, irqnum,
|
||||
"Couldn't get irq %s byname\n", name);
|
||||
return irqnum;
|
||||
|
||||
rc = devm_request_threaded_irq(chip->dev, irqnum, NULL, handler,
|
||||
IRQF_ONESHOT, name, chip);
|
||||
|
||||
@@ -1000,15 +1000,13 @@ static int smbb_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int smbb_charger_remove(struct platform_device *pdev)
|
||||
static void smbb_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct smbb_charger *chg;
|
||||
|
||||
chg = platform_get_drvdata(pdev);
|
||||
|
||||
regmap_update_bits(chg->regmap, chg->addr + SMBB_CHG_CTRL, CTRL_EN, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id smbb_charger_id_table[] = {
|
||||
@@ -1020,7 +1018,7 @@ MODULE_DEVICE_TABLE(of, smbb_charger_id_table);
|
||||
|
||||
static struct platform_driver smbb_charger_driver = {
|
||||
.probe = smbb_charger_probe,
|
||||
.remove = smbb_charger_remove,
|
||||
.remove_new = smbb_charger_remove,
|
||||
.driver = {
|
||||
.name = "qcom-smbb",
|
||||
.of_match_table = smbb_charger_id_table,
|
||||
|
||||
@@ -1207,11 +1207,24 @@ static int rk817_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rk817_resume(struct device *dev)
|
||||
{
|
||||
|
||||
struct rk817_charger *charger = dev_get_drvdata(dev);
|
||||
|
||||
/* force an immediate update */
|
||||
mod_delayed_work(system_wq, &charger->work, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rk817_charger_pm, NULL, rk817_resume);
|
||||
|
||||
static struct platform_driver rk817_charger_driver = {
|
||||
.probe = rk817_charger_probe,
|
||||
.driver = {
|
||||
.name = "rk817-charger",
|
||||
.pm = &rk817_charger_pm,
|
||||
},
|
||||
};
|
||||
module_platform_driver(rk817_charger_driver);
|
||||
|
||||
@@ -6,8 +6,12 @@
|
||||
* Author: Beomho Seo <beomho.seo@samsung.com>
|
||||
*/
|
||||
|
||||
#include <linux/devm-helpers.h>
|
||||
#include <linux/extcon.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -25,7 +29,15 @@ struct rt5033_charger {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct power_supply *psy;
|
||||
struct rt5033_charger_data *chg;
|
||||
struct rt5033_charger_data chg;
|
||||
struct extcon_dev *edev;
|
||||
struct notifier_block extcon_nb;
|
||||
struct work_struct extcon_work;
|
||||
struct mutex lock;
|
||||
bool online;
|
||||
bool otg;
|
||||
bool mivr_enabled;
|
||||
u8 cv_regval;
|
||||
};
|
||||
|
||||
static int rt5033_get_charger_state(struct rt5033_charger *charger)
|
||||
@@ -56,6 +68,10 @@ static int rt5033_get_charger_state(struct rt5033_charger *charger)
|
||||
state = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
/* For OTG mode, RT5033 would still report "charging" */
|
||||
if (charger->otg)
|
||||
state = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -115,7 +131,7 @@ static int rt5033_get_charger_const_voltage(struct rt5033_charger *charger)
|
||||
|
||||
static inline int rt5033_init_const_charge(struct rt5033_charger *charger)
|
||||
{
|
||||
struct rt5033_charger_data *chg = charger->chg;
|
||||
struct rt5033_charger_data *chg = &charger->chg;
|
||||
int ret;
|
||||
unsigned int val;
|
||||
u8 reg_data;
|
||||
@@ -147,6 +163,9 @@ static inline int rt5033_init_const_charge(struct rt5033_charger *charger)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Store that value for later usage */
|
||||
charger->cv_regval = reg_data;
|
||||
|
||||
/* Set end of charge current */
|
||||
if (chg->eoc_uamp < RT5033_CHARGER_EOC_MIN ||
|
||||
chg->eoc_uamp > RT5033_CHARGER_EOC_MAX) {
|
||||
@@ -186,7 +205,7 @@ static inline int rt5033_init_const_charge(struct rt5033_charger *charger)
|
||||
|
||||
static inline int rt5033_init_fast_charge(struct rt5033_charger *charger)
|
||||
{
|
||||
struct rt5033_charger_data *chg = charger->chg;
|
||||
struct rt5033_charger_data *chg = &charger->chg;
|
||||
int ret;
|
||||
unsigned int val;
|
||||
u8 reg_data;
|
||||
@@ -231,7 +250,7 @@ static inline int rt5033_init_fast_charge(struct rt5033_charger *charger)
|
||||
|
||||
static inline int rt5033_init_pre_charge(struct rt5033_charger *charger)
|
||||
{
|
||||
struct rt5033_charger_data *chg = charger->chg;
|
||||
struct rt5033_charger_data *chg = &charger->chg;
|
||||
int ret;
|
||||
unsigned int val;
|
||||
u8 reg_data;
|
||||
@@ -330,6 +349,162 @@ static int rt5033_charger_reg_init(struct rt5033_charger *charger)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5033_charger_set_otg(struct rt5033_charger *charger)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&charger->lock);
|
||||
|
||||
/* Set OTG boost v_out to 5 volts */
|
||||
ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL2,
|
||||
RT5033_CHGCTRL2_CV_MASK,
|
||||
0x37 << RT5033_CHGCTRL2_CV_SHIFT);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "Failed set OTG boost v_out\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* Set operation mode to OTG */
|
||||
ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1,
|
||||
RT5033_CHGCTRL1_MODE_MASK, RT5033_BOOST_MODE);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "Failed to update OTG mode.\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* In case someone switched from charging to OTG directly */
|
||||
if (charger->online)
|
||||
charger->online = false;
|
||||
|
||||
charger->otg = true;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&charger->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rt5033_charger_unset_otg(struct rt5033_charger *charger)
|
||||
{
|
||||
int ret;
|
||||
u8 data;
|
||||
|
||||
/* Restore constant voltage for charging */
|
||||
data = charger->cv_regval;
|
||||
ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL2,
|
||||
RT5033_CHGCTRL2_CV_MASK,
|
||||
data << RT5033_CHGCTRL2_CV_SHIFT);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "Failed to restore constant voltage\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Set operation mode to charging */
|
||||
ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL1,
|
||||
RT5033_CHGCTRL1_MODE_MASK, RT5033_CHARGER_MODE);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "Failed to update charger mode.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
charger->otg = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5033_charger_set_charging(struct rt5033_charger *charger)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&charger->lock);
|
||||
|
||||
/* In case someone switched from OTG to charging directly */
|
||||
if (charger->otg) {
|
||||
ret = rt5033_charger_unset_otg(charger);
|
||||
if (ret) {
|
||||
mutex_unlock(&charger->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
charger->online = true;
|
||||
|
||||
mutex_unlock(&charger->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5033_charger_set_mivr(struct rt5033_charger *charger)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mutex_lock(&charger->lock);
|
||||
|
||||
/*
|
||||
* When connected via USB connector type SDP (Standard Downstream Port),
|
||||
* the minimum input voltage regulation (MIVR) should be enabled. It
|
||||
* prevents an input voltage drop due to insufficient current provided
|
||||
* by the adapter or USB input. As a downside, it may reduces the
|
||||
* charging current and thus slows the charging.
|
||||
*/
|
||||
ret = regmap_update_bits(charger->regmap, RT5033_REG_CHG_CTRL4,
|
||||
RT5033_CHGCTRL4_MIVR_MASK, RT5033_CHARGER_MIVR_4600MV);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "Failed to set MIVR level.\n");
|
||||
mutex_unlock(&charger->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
charger->mivr_enabled = true;
|
||||
|
||||
mutex_unlock(&charger->lock);
|
||||
|
||||
/* Beyond this, do the same steps like setting charging */
|
||||
rt5033_charger_set_charging(charger);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5033_charger_set_disconnect(struct rt5033_charger *charger)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&charger->lock);
|
||||
|
||||
/* Disable MIVR if enabled */
|
||||
if (charger->mivr_enabled) {
|
||||
ret = regmap_update_bits(charger->regmap,
|
||||
RT5033_REG_CHG_CTRL4,
|
||||
RT5033_CHGCTRL4_MIVR_MASK,
|
||||
RT5033_CHARGER_MIVR_DISABLE);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "Failed to disable MIVR.\n");
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
charger->mivr_enabled = false;
|
||||
}
|
||||
|
||||
if (charger->otg) {
|
||||
ret = rt5033_charger_unset_otg(charger);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (charger->online)
|
||||
charger->online = false;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&charger->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum power_supply_property rt5033_charger_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE,
|
||||
@@ -366,8 +541,7 @@ static int rt5033_charger_get_property(struct power_supply *psy,
|
||||
val->strval = RT5033_MANUFACTURER;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = (rt5033_get_charger_state(charger) ==
|
||||
POWER_SUPPLY_STATUS_CHARGING);
|
||||
val->intval = charger->online;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -376,21 +550,16 @@ static int rt5033_charger_get_property(struct power_supply *psy,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rt5033_charger_data *rt5033_charger_dt_init(
|
||||
struct rt5033_charger *charger)
|
||||
static int rt5033_charger_dt_init(struct rt5033_charger *charger)
|
||||
{
|
||||
struct rt5033_charger_data *chg;
|
||||
struct rt5033_charger_data *chg = &charger->chg;
|
||||
struct power_supply_battery_info *info;
|
||||
int ret;
|
||||
|
||||
chg = devm_kzalloc(charger->dev, sizeof(*chg), GFP_KERNEL);
|
||||
if (!chg)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = power_supply_get_battery_info(charger->psy, &info);
|
||||
if (ret)
|
||||
return ERR_PTR(dev_err_probe(charger->dev, -EINVAL,
|
||||
"missing battery info\n"));
|
||||
return dev_err_probe(charger->dev, -EINVAL,
|
||||
"missing battery info\n");
|
||||
|
||||
/* Assign data. Validity will be checked in the init functions. */
|
||||
chg->pre_uamp = info->precharge_current_ua;
|
||||
@@ -399,7 +568,87 @@ static struct rt5033_charger_data *rt5033_charger_dt_init(
|
||||
chg->pre_uvolt = info->precharge_voltage_max_uv;
|
||||
chg->const_uvolt = info->constant_charge_voltage_max_uv;
|
||||
|
||||
return chg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rt5033_charger_extcon_work(struct work_struct *work)
|
||||
{
|
||||
struct rt5033_charger *charger =
|
||||
container_of(work, struct rt5033_charger, extcon_work);
|
||||
struct extcon_dev *edev = charger->edev;
|
||||
int connector, state;
|
||||
int ret;
|
||||
|
||||
for (connector = EXTCON_USB_HOST; connector <= EXTCON_CHG_USB_PD;
|
||||
connector++) {
|
||||
state = extcon_get_state(edev, connector);
|
||||
if (state == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adding a delay between extcon notification and extcon action. This
|
||||
* makes extcon action execution more reliable. Without the delay the
|
||||
* execution sometimes fails, possibly because the chip is busy or not
|
||||
* ready.
|
||||
*/
|
||||
msleep(100);
|
||||
|
||||
switch (connector) {
|
||||
case EXTCON_CHG_USB_SDP:
|
||||
ret = rt5033_charger_set_mivr(charger);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "failed to set USB mode\n");
|
||||
break;
|
||||
}
|
||||
dev_info(charger->dev, "USB mode. connector type: %d\n",
|
||||
connector);
|
||||
break;
|
||||
case EXTCON_CHG_USB_DCP:
|
||||
case EXTCON_CHG_USB_CDP:
|
||||
case EXTCON_CHG_USB_ACA:
|
||||
case EXTCON_CHG_USB_FAST:
|
||||
case EXTCON_CHG_USB_SLOW:
|
||||
case EXTCON_CHG_WPT:
|
||||
case EXTCON_CHG_USB_PD:
|
||||
ret = rt5033_charger_set_charging(charger);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "failed to set charging\n");
|
||||
break;
|
||||
}
|
||||
dev_info(charger->dev, "charging. connector type: %d\n",
|
||||
connector);
|
||||
break;
|
||||
case EXTCON_USB_HOST:
|
||||
ret = rt5033_charger_set_otg(charger);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "failed to set OTG\n");
|
||||
break;
|
||||
}
|
||||
dev_info(charger->dev, "OTG enabled\n");
|
||||
break;
|
||||
default:
|
||||
ret = rt5033_charger_set_disconnect(charger);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "failed to set disconnect\n");
|
||||
break;
|
||||
}
|
||||
dev_info(charger->dev, "disconnected\n");
|
||||
break;
|
||||
}
|
||||
|
||||
power_supply_changed(charger->psy);
|
||||
}
|
||||
|
||||
static int rt5033_charger_extcon_notifier(struct notifier_block *nb,
|
||||
unsigned long event, void *param)
|
||||
{
|
||||
struct rt5033_charger *charger =
|
||||
container_of(nb, struct rt5033_charger, extcon_nb);
|
||||
|
||||
schedule_work(&charger->extcon_work);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static const struct power_supply_desc rt5033_charger_desc = {
|
||||
@@ -414,6 +663,7 @@ static int rt5033_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rt5033_charger *charger;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct device_node *np_conn, *np_edev;
|
||||
int ret;
|
||||
|
||||
charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
|
||||
@@ -423,25 +673,53 @@ static int rt5033_charger_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, charger);
|
||||
charger->dev = &pdev->dev;
|
||||
charger->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
mutex_init(&charger->lock);
|
||||
|
||||
psy_cfg.of_node = pdev->dev.of_node;
|
||||
psy_cfg.drv_data = charger;
|
||||
|
||||
charger->psy = devm_power_supply_register(&pdev->dev,
|
||||
charger->psy = devm_power_supply_register(charger->dev,
|
||||
&rt5033_charger_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(charger->psy))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(charger->psy),
|
||||
return dev_err_probe(charger->dev, PTR_ERR(charger->psy),
|
||||
"Failed to register power supply\n");
|
||||
|
||||
charger->chg = rt5033_charger_dt_init(charger);
|
||||
if (IS_ERR_OR_NULL(charger->chg))
|
||||
return PTR_ERR(charger->chg);
|
||||
ret = rt5033_charger_dt_init(charger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rt5033_charger_reg_init(charger);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Extcon support is not vital for the charger to work. If no extcon
|
||||
* is available, just emit a warning and leave the probe function.
|
||||
*/
|
||||
np_conn = of_parse_phandle(pdev->dev.of_node, "richtek,usb-connector", 0);
|
||||
np_edev = of_get_parent(np_conn);
|
||||
charger->edev = extcon_find_edev_by_node(np_edev);
|
||||
if (IS_ERR(charger->edev)) {
|
||||
dev_warn(charger->dev, "no extcon device found in device-tree\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = devm_work_autocancel(charger->dev, &charger->extcon_work,
|
||||
rt5033_charger_extcon_work);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "failed to initialize extcon work\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
charger->extcon_nb.notifier_call = rt5033_charger_extcon_notifier;
|
||||
ret = devm_extcon_register_notifier_all(charger->dev, charger->edev,
|
||||
&charger->extcon_nb);
|
||||
if (ret) {
|
||||
dev_err(charger->dev, "failed to register extcon notifier\n");
|
||||
return ret;
|
||||
}
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ static int rx51_battery_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rx51_battery_remove(struct platform_device *pdev)
|
||||
static void rx51_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rx51_device_info *di = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -255,8 +255,6 @@ static int rx51_battery_remove(struct platform_device *pdev)
|
||||
iio_channel_release(di->channel_vbat);
|
||||
iio_channel_release(di->channel_bsi);
|
||||
iio_channel_release(di->channel_temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
@@ -269,7 +267,7 @@ MODULE_DEVICE_TABLE(of, n900_battery_of_match);
|
||||
|
||||
static struct platform_driver rx51_battery_driver = {
|
||||
.probe = rx51_battery_probe,
|
||||
.remove = rx51_battery_remove,
|
||||
.remove_new = rx51_battery_remove,
|
||||
.driver = {
|
||||
.name = "rx51-battery",
|
||||
.of_match_table = of_match_ptr(n900_battery_of_match),
|
||||
|
||||
@@ -1135,7 +1135,7 @@ static int sbs_probe(struct i2c_client *client)
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
chip->flags = (u32)(uintptr_t)device_get_match_data(&client->dev);
|
||||
chip->flags = (uintptr_t)i2c_get_match_data(client);
|
||||
chip->client = client;
|
||||
psy_cfg.of_node = client->dev.of_node;
|
||||
psy_cfg.drv_data = chip;
|
||||
@@ -1253,9 +1253,9 @@ static SIMPLE_DEV_PM_OPS(sbs_pm_ops, sbs_suspend, NULL);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id sbs_id[] = {
|
||||
{ "bq20z65", 0 },
|
||||
{ "bq20z75", 0 },
|
||||
{ "sbs-battery", 1 },
|
||||
{ "bq20z65", SBS_FLAGS_TI_BQ20ZX5 },
|
||||
{ "bq20z75", SBS_FLAGS_TI_BQ20ZX5 },
|
||||
{ "sbs-battery", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sbs_id);
|
||||
|
||||
@@ -511,13 +511,11 @@ static int sc2731_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sc2731_charger_remove(struct platform_device *pdev)
|
||||
static void sc2731_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct sc2731_charger_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
usb_unregister_notifier(info->usb_phy, &info->usb_notify);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sc2731_charger_of_match[] = {
|
||||
@@ -532,7 +530,7 @@ static struct platform_driver sc2731_charger_driver = {
|
||||
.of_match_table = sc2731_charger_of_match,
|
||||
},
|
||||
.probe = sc2731_charger_probe,
|
||||
.remove = sc2731_charger_remove,
|
||||
.remove_new = sc2731_charger_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(sc2731_charger_driver);
|
||||
|
||||
@@ -722,7 +722,7 @@ static void spwr_battery_init(struct spwr_battery_device *bat, struct ssam_devic
|
||||
struct ssam_event_registry registry, const char *name)
|
||||
{
|
||||
mutex_init(&bat->lock);
|
||||
strncpy(bat->name, name, ARRAY_SIZE(bat->name) - 1);
|
||||
strscpy(bat->name, name, sizeof(bat->name));
|
||||
|
||||
bat->sdev = sdev;
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ static void spwr_ac_init(struct spwr_ac_device *ac, struct ssam_device *sdev,
|
||||
struct ssam_event_registry registry, const char *name)
|
||||
{
|
||||
mutex_init(&ac->lock);
|
||||
strncpy(ac->name, name, ARRAY_SIZE(ac->name) - 1);
|
||||
strscpy(ac->name, name, sizeof(ac->name));
|
||||
|
||||
ac->sdev = sdev;
|
||||
|
||||
|
||||
@@ -328,15 +328,13 @@ static int tps65090_charger_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps65090_charger_remove(struct platform_device *pdev)
|
||||
static void tps65090_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65090_charger *cdata = platform_get_drvdata(pdev);
|
||||
|
||||
if (cdata->irq == -ENXIO)
|
||||
kthread_stop(cdata->poll_task);
|
||||
power_supply_unregister(cdata->ac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_tps65090_charger_match[] = {
|
||||
@@ -351,7 +349,7 @@ static struct platform_driver tps65090_charger_driver = {
|
||||
.of_match_table = of_tps65090_charger_match,
|
||||
},
|
||||
.probe = tps65090_charger_probe,
|
||||
.remove = tps65090_charger_remove,
|
||||
.remove_new = tps65090_charger_remove,
|
||||
};
|
||||
module_platform_driver(tps65090_charger_driver);
|
||||
|
||||
|
||||
@@ -253,14 +253,12 @@ static int tps65217_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tps65217_charger_remove(struct platform_device *pdev)
|
||||
static void tps65217_charger_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65217_charger *charger = platform_get_drvdata(pdev);
|
||||
|
||||
if (charger->poll_task)
|
||||
kthread_stop(charger->poll_task);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tps65217_charger_match_table[] = {
|
||||
@@ -271,7 +269,7 @@ MODULE_DEVICE_TABLE(of, tps65217_charger_match_table);
|
||||
|
||||
static struct platform_driver tps65217_charger_driver = {
|
||||
.probe = tps65217_charger_probe,
|
||||
.remove = tps65217_charger_remove,
|
||||
.remove_new = tps65217_charger_remove,
|
||||
.driver = {
|
||||
.name = "tps65217-charger",
|
||||
.of_match_table = of_match_ptr(tps65217_charger_match_table),
|
||||
|
||||
@@ -1108,7 +1108,7 @@ static int twl4030_bci_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twl4030_bci_remove(struct platform_device *pdev)
|
||||
static void twl4030_bci_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_bci *bci = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -1123,8 +1123,6 @@ static int twl4030_bci_remove(struct platform_device *pdev)
|
||||
TWL4030_INTERRUPTS_BCIIMR1A);
|
||||
twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
|
||||
TWL4030_INTERRUPTS_BCIIMR2A);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id twl_bci_of_match[] __maybe_unused = {
|
||||
@@ -1135,7 +1133,7 @@ MODULE_DEVICE_TABLE(of, twl_bci_of_match);
|
||||
|
||||
static struct platform_driver twl4030_bci_driver = {
|
||||
.probe = twl4030_bci_probe,
|
||||
.remove = twl4030_bci_remove,
|
||||
.remove_new = twl4030_bci_remove,
|
||||
.driver = {
|
||||
.name = "twl4030_bci",
|
||||
.of_match_table = of_match_ptr(twl_bci_of_match),
|
||||
|
||||
@@ -244,7 +244,7 @@ static int twl4030_madc_battery_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int twl4030_madc_battery_remove(struct platform_device *pdev)
|
||||
static void twl4030_madc_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct twl4030_madc_battery *bat = platform_get_drvdata(pdev);
|
||||
|
||||
@@ -253,8 +253,6 @@ static int twl4030_madc_battery_remove(struct platform_device *pdev)
|
||||
iio_channel_release(bat->channel_vbat);
|
||||
iio_channel_release(bat->channel_ichg);
|
||||
iio_channel_release(bat->channel_temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver twl4030_madc_battery_driver = {
|
||||
@@ -262,7 +260,7 @@ static struct platform_driver twl4030_madc_battery_driver = {
|
||||
.name = "twl4030_madc_battery",
|
||||
},
|
||||
.probe = twl4030_madc_battery_probe,
|
||||
.remove = twl4030_madc_battery_remove,
|
||||
.remove_new = twl4030_madc_battery_remove,
|
||||
};
|
||||
module_platform_driver(twl4030_madc_battery_driver);
|
||||
|
||||
|
||||
@@ -197,18 +197,16 @@ static int wm831x_backup_probe(struct platform_device *pdev)
|
||||
return PTR_ERR_OR_ZERO(devdata->backup);
|
||||
}
|
||||
|
||||
static int wm831x_backup_remove(struct platform_device *pdev)
|
||||
static void wm831x_backup_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_backup *devdata = platform_get_drvdata(pdev);
|
||||
|
||||
power_supply_unregister(devdata->backup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver wm831x_backup_driver = {
|
||||
.probe = wm831x_backup_probe,
|
||||
.remove = wm831x_backup_remove,
|
||||
.remove_new = wm831x_backup_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-backup",
|
||||
},
|
||||
|
||||
@@ -694,7 +694,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm831x_power_remove(struct platform_device *pdev)
|
||||
static void wm831x_power_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = wm831x_power->wm831x;
|
||||
@@ -722,12 +722,11 @@ static int wm831x_power_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(wm831x_power->battery);
|
||||
power_supply_unregister(wm831x_power->wall);
|
||||
power_supply_unregister(wm831x_power->usb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver wm831x_power_driver = {
|
||||
.probe = wm831x_power_probe,
|
||||
.remove = wm831x_power_remove,
|
||||
.remove_new = wm831x_power_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-power",
|
||||
},
|
||||
|
||||
@@ -579,7 +579,7 @@ static int wm8350_power_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm8350_power_remove(struct platform_device *pdev)
|
||||
static void wm8350_power_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
|
||||
struct wm8350_power *power = &wm8350->power;
|
||||
@@ -589,12 +589,11 @@ static int wm8350_power_remove(struct platform_device *pdev)
|
||||
power_supply_unregister(power->battery);
|
||||
power_supply_unregister(power->ac);
|
||||
power_supply_unregister(power->usb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver wm8350_power_driver = {
|
||||
.probe = wm8350_power_probe,
|
||||
.remove = wm8350_power_remove,
|
||||
.remove_new = wm8350_power_remove,
|
||||
.driver = {
|
||||
.name = "wm8350-power",
|
||||
},
|
||||
|
||||
@@ -248,14 +248,13 @@ static int wm97xx_bat_probe(struct platform_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wm97xx_bat_remove(struct platform_device *dev)
|
||||
static void wm97xx_bat_remove(struct platform_device *dev)
|
||||
{
|
||||
if (charge_gpiod)
|
||||
free_irq(gpiod_to_irq(charge_gpiod), dev);
|
||||
cancel_work_sync(&bat_work);
|
||||
power_supply_unregister(bat_psy);
|
||||
kfree(prop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver wm97xx_bat_driver = {
|
||||
@@ -266,7 +265,7 @@ static struct platform_driver wm97xx_bat_driver = {
|
||||
#endif
|
||||
},
|
||||
.probe = wm97xx_bat_probe,
|
||||
.remove = wm97xx_bat_remove,
|
||||
.remove_new = wm97xx_bat_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(wm97xx_bat_driver);
|
||||
|
||||
@@ -767,7 +767,6 @@ struct power_supply_battery_info {
|
||||
int bti_resistance_tolerance;
|
||||
};
|
||||
|
||||
extern struct atomic_notifier_head power_supply_notifier;
|
||||
extern int power_supply_reg_notifier(struct notifier_block *nb);
|
||||
extern void power_supply_unreg_notifier(struct notifier_block *nb);
|
||||
#if IS_ENABLED(CONFIG_POWER_SUPPLY)
|
||||
|
||||
Reference in New Issue
Block a user