mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
Merge tag 'for-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply
Pull power supply and reset updates from Sebastian Reichel: "Nothing special for the power-supply subystem this time. - power-supply core: remove faulty cooling logic - convert all sysfs show() handlers from *printf() use sysfs_emit() - bq25890: add dual-charger support required by Lenovo Yoga Tab 3 Pro - bq27xxx: fix reporting critical level - syscon-reboot: add priority property support - new rt9467 charger driver - new rt9471 charger driver - new Odroid Go Ultra poweroff driver - misc minor fixes and cleanups" * tag 'for-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (32 commits) power: reset: odroid-go-ultra: fix I2C dependency power: supply: leds: explicitly include linux/leds.h dt-bindings: power: supply: pm8941-coincell: Don't require charging properties dt-bindings: power: supply: pm8941-coincell: Add PM8998 compatible power: reset: add Odroid Go Ultra poweroff driver power: supply: rt9467: Fix spelling mistake "attache" -> "attach" power: supply: rt9471: fix using wrong ce_gpio in rt9471_probe() power: supply: max77650: Make max77650_charger_disable() return void Documentation: power: rt9467: Document exported sysfs entries power: supply: rt9467: Add Richtek RT9467 charger driver dt-bindings: power: supply: Add Richtek RT9467 battery charger Documentation: power: rt9471: Document exported sysfs entries power: supply: rt9471: Add Richtek RT9471 charger driver dt-bindings: power: supply: Add Richtek RT9471 battery charger power: supply: max1721x: Use strscpy() is more robust and safer power: supply: test-power: use strscpy() instead of strncpy() power: supply: bq27xxx: fix reporting critical level power: supply: bq256xx: Init ichg/vbat value with chip default value power: supply: collie_battery: Convert to GPIO descriptors (part 2) power: supply: remove faulty cooling logic ...
This commit is contained in:
19
Documentation/ABI/testing/sysfs-class-power-rt9467
Normal file
19
Documentation/ABI/testing/sysfs-class-power-rt9467
Normal file
@@ -0,0 +1,19 @@
|
||||
What: /sys/class/power_supply/rt9467-*/sysoff_enable
|
||||
Date: Feb 2023
|
||||
KernelVersion: 6.3
|
||||
Contact: ChiaEn Wu <chiaen_wu@richtek.com>
|
||||
Description:
|
||||
This entry allows enabling the sysoff mode of rt9467 charger
|
||||
devices.
|
||||
If enabled and the input is removed, the internal battery FET
|
||||
is turned off to reduce the leakage from the BAT pin. See
|
||||
device datasheet for details. It's commonly used when the
|
||||
product enter shipping stage. After entering shipping mode,
|
||||
only 'VBUS' or 'Power key" pressed can make it leave this mode.
|
||||
'Disable' also can help to leave it, but it's more like to
|
||||
abort the action before the device really enter shipping mode.
|
||||
|
||||
Access: Read, Write
|
||||
Valid values:
|
||||
- 1: enabled
|
||||
- 0: disabled
|
||||
32
Documentation/ABI/testing/sysfs-class-power-rt9471
Normal file
32
Documentation/ABI/testing/sysfs-class-power-rt9471
Normal file
@@ -0,0 +1,32 @@
|
||||
What: /sys/class/power_supply/rt9471-*/sysoff_enable
|
||||
Date: Feb 2023
|
||||
KernelVersion: 6.3
|
||||
Contact: ChiYuan Huang <cy_huang@richtek.com>
|
||||
Description:
|
||||
This entry allows enabling the sysoff mode of rt9471 charger devices.
|
||||
If enabled and the input is removed, the internal battery FET is turned
|
||||
off to reduce the leakage from the BAT pin. See device datasheet for details.
|
||||
It's commonly used when the product enter shipping stage. After entering
|
||||
shipping mode, only 'VBUS' or 'Power key" pressed can make it leave this
|
||||
mode. 'Disable' also can help to leave it, but it's more like to abort
|
||||
the action before the device really enter shipping mode.
|
||||
|
||||
Access: Read, Write
|
||||
Valid values:
|
||||
- 1: enabled
|
||||
- 0: disabled
|
||||
|
||||
What: /sys/class/power_supply/rt9471-*/port_detect_enable
|
||||
Date: Feb 2023
|
||||
KernelVersion: 6.3
|
||||
Contact: ChiYuan Huang <cy_huang@richtek.com>
|
||||
Description:
|
||||
This entry allows enabling the USB BC12 port detect function of rt9471 charger
|
||||
devices. If enabled and VBUS is inserted, device will start to do the BC12
|
||||
port detect and report the usb port type when port detect is done. See
|
||||
datasheet for details. Normally controlled when TypeC/USBPD port integrated.
|
||||
|
||||
Access: Read, Write
|
||||
Valid values:
|
||||
- 1: enabled
|
||||
- 0: disabled
|
||||
@@ -42,6 +42,9 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: The reset value written to the reboot register (32 bit access).
|
||||
|
||||
priority:
|
||||
default: 192
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- offset
|
||||
@@ -49,6 +52,7 @@ required:
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: restart-handler.yaml#
|
||||
- if:
|
||||
not:
|
||||
required:
|
||||
|
||||
@@ -16,18 +16,30 @@ maintainers:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,pm8941-coincell
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,pm8998-coincell
|
||||
- const: qcom,pm8941-coincell
|
||||
|
||||
- const: qcom,pm8941-coincell
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
qcom,rset-ohms:
|
||||
description: resistance (in ohms) for current-limiting resistor
|
||||
description: |
|
||||
Resistance (in ohms) for current-limiting resistor. If unspecified,
|
||||
inherit the previous configuration (e.g. from bootloader or hardware
|
||||
default value).
|
||||
enum: [ 800, 1200, 1700, 2100 ]
|
||||
|
||||
qcom,vset-millivolts:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: voltage (in millivolts) to apply for charging
|
||||
description: |
|
||||
Voltage (in millivolts) to apply for charging. If unspecified, inherit
|
||||
the previous configuration (e.g. from bootloader or hardware default
|
||||
value).
|
||||
enum: [ 2500, 3000, 3100, 3200 ]
|
||||
|
||||
qcom,charger-disable:
|
||||
@@ -37,8 +49,6 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- qcom,rset-ohms
|
||||
- qcom,vset-millivolts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/richtek,rt9467-charger.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Richtek RT9467 Switching Battery Charger with Power Path Management
|
||||
|
||||
maintainers:
|
||||
- ChiYuan Huang <cy_huang@richtek.com>
|
||||
- ChiaEn Wu <chiaen_wu@richtek.com>
|
||||
|
||||
description: |
|
||||
RT9467 is a switch-mode single cell Li-Ion/Li-Polymer battery charger for
|
||||
portable applications. It integrates a synchronous PWM controller, power
|
||||
MOSFETs, input current sensing and regulation, high-accuracy voltage
|
||||
regulation, and charge termination. The charge current is regulated through
|
||||
integrated sensing resistors.
|
||||
|
||||
The RT9467 also features USB On-The-Go (OTG) support. It also integrates
|
||||
D+/D- pin for USB host/charging port detection.
|
||||
|
||||
Datasheet is available at
|
||||
https://www.richtek.com/assets/product_file/RT9467/DS9467-01.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: richtek,rt9467-charger
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
charge-enable-gpios:
|
||||
description: GPIO is used to turn on and off charging.
|
||||
maxItems: 1
|
||||
|
||||
usb-otg-vbus-regulator:
|
||||
type: object
|
||||
description: OTG boost regulator.
|
||||
unevaluatedProperties: false
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
|
||||
properties:
|
||||
enable-gpios: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- wakeup-source
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
charger@5b {
|
||||
compatible = "richtek,rt9467-charger";
|
||||
reg = <0x5b>;
|
||||
wakeup-source;
|
||||
interrupts-extended = <&gpio_intc 32 IRQ_TYPE_LEVEL_LOW>;
|
||||
charge-enable-gpios = <&gpio26 1 GPIO_ACTIVE_LOW>;
|
||||
|
||||
rt9467_otg_vbus: usb-otg-vbus-regulator {
|
||||
regulator-name = "rt9467-usb-otg-vbus";
|
||||
regulator-min-microvolt = <4425000>;
|
||||
regulator-max-microvolt = <5825000>;
|
||||
regulator-min-microamp = <500000>;
|
||||
regulator-max-microamp = <3000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/richtek,rt9471.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Richtek RT9471 3A Single Cell Switching Battery charger
|
||||
|
||||
maintainers:
|
||||
- Alina Yu <alina_yu@richtek.com>
|
||||
- ChiYuan Huang <cy_huang@richtek.com>
|
||||
|
||||
description: |
|
||||
RT9471 is a switch-mode single cell Li-Ion/Li-Polymer battery charger for
|
||||
portable applications. It supports USB BC1.2 port detection, current and
|
||||
voltage regulations in both charging and boost mode.
|
||||
|
||||
Datasheet is available at
|
||||
https://www.richtek.com/assets/product_file/RT9471=RT9471D/DS9471D-02.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: richtek,rt9471
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
charge-enable-gpios:
|
||||
description: GPIO used to turn on and off charging.
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
usb-otg-vbus-regulator:
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- wakeup-source
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
charger@53 {
|
||||
compatible = "richtek,rt9471";
|
||||
reg = <0x53>;
|
||||
charge-enable-gpios = <&gpio26 1 GPIO_ACTIVE_LOW>;
|
||||
wakeup-source;
|
||||
interrupts-extended = <&gpio_intc 32 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
usb-otg-vbus-regulator {
|
||||
regulator-name = "usb-otg-vbus";
|
||||
regulator-min-microvolt = <4850000>;
|
||||
regulator-max-microvolt = <5300000>;
|
||||
regulator-min-microamp = <500000>;
|
||||
regulator-max-microamp = <1200000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -187,7 +187,7 @@ struct x86_dev_info {
|
||||
/* Generic / shared charger / battery settings */
|
||||
static const char * const tusb1211_chg_det_psy[] = { "tusb1211-charger-detect" };
|
||||
static const char * const bq24190_psy[] = { "bq24190-charger" };
|
||||
static const char * const bq25890_psy[] = { "bq25890-charger" };
|
||||
static const char * const bq25890_psy[] = { "bq25890-charger-0" };
|
||||
|
||||
static const struct property_entry fg_bq24190_supply_props[] = {
|
||||
PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
|
||||
|
||||
@@ -141,6 +141,13 @@ config POWER_RESET_OCELOT_RESET
|
||||
help
|
||||
This driver supports restart for Microsemi Ocelot SoC and similar.
|
||||
|
||||
config POWER_RESET_ODROID_GO_ULTRA_POWEROFF
|
||||
bool "Odroid Go Ultra power-off driver"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
depends on I2C=y && OF
|
||||
help
|
||||
This driver supports Power off for Odroid Go Ultra device.
|
||||
|
||||
config POWER_RESET_OXNAS
|
||||
bool "OXNAS SoC restart driver"
|
||||
depends on ARCH_OXNAS
|
||||
|
||||
@@ -17,6 +17,7 @@ obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o
|
||||
obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
|
||||
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
|
||||
obj-$(CONFIG_POWER_RESET_ODROID_GO_ULTRA_POWEROFF) += odroid-go-ultra-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
|
||||
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
|
||||
|
||||
177
drivers/power/reset/odroid-go-ultra-poweroff.c
Normal file
177
drivers/power/reset/odroid-go-ultra-poweroff.c
Normal file
@@ -0,0 +1,177 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2023 Neil Armstrong <neil.armstrong@linaro.org>
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/mfd/rk808.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
/*
|
||||
* The Odroid Go Ultra has 2 PMICs:
|
||||
* - RK818 (manages the battery and USB-C power supply)
|
||||
* - RK817
|
||||
* Both PMICs feeds power to the S922X SoC, so they must be powered-off in sequence.
|
||||
* Vendor does power-off the RK817 first, then the RK818 so here we follow this sequence.
|
||||
*/
|
||||
|
||||
struct odroid_go_ultra_poweroff_data {
|
||||
struct device *dev;
|
||||
struct device *rk817;
|
||||
struct device *rk818;
|
||||
};
|
||||
|
||||
static int odroid_go_ultra_poweroff_prepare(struct sys_off_data *data)
|
||||
{
|
||||
struct odroid_go_ultra_poweroff_data *poweroff_data = data->cb_data;
|
||||
struct regmap *rk817, *rk818;
|
||||
int ret;
|
||||
|
||||
/* RK817 Regmap */
|
||||
rk817 = dev_get_regmap(poweroff_data->rk817, NULL);
|
||||
if (!rk817) {
|
||||
dev_err(poweroff_data->dev, "failed to get rk817 regmap\n");
|
||||
return notifier_from_errno(-EINVAL);
|
||||
}
|
||||
|
||||
/* RK818 Regmap */
|
||||
rk818 = dev_get_regmap(poweroff_data->rk818, NULL);
|
||||
if (!rk818) {
|
||||
dev_err(poweroff_data->dev, "failed to get rk818 regmap\n");
|
||||
return notifier_from_errno(-EINVAL);
|
||||
}
|
||||
|
||||
dev_info(poweroff_data->dev, "Setting PMICs for power off");
|
||||
|
||||
/* RK817 */
|
||||
ret = regmap_update_bits(rk817, RK817_SYS_CFG(3), DEV_OFF, DEV_OFF);
|
||||
if (ret) {
|
||||
dev_err(poweroff_data->dev, "failed to poweroff rk817\n");
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
/* RK818 */
|
||||
ret = regmap_update_bits(rk818, RK818_DEVCTRL_REG, DEV_OFF, DEV_OFF);
|
||||
if (ret) {
|
||||
dev_err(poweroff_data->dev, "failed to poweroff rk818\n");
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void odroid_go_ultra_poweroff_put_pmic_device(void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
put_device(dev);
|
||||
}
|
||||
|
||||
static int odroid_go_ultra_poweroff_get_pmic_device(struct device *dev, const char *compatible,
|
||||
struct device **pmic)
|
||||
{
|
||||
struct device_node *pmic_node;
|
||||
struct i2c_client *pmic_client;
|
||||
|
||||
pmic_node = of_find_compatible_node(NULL, NULL, compatible);
|
||||
if (!pmic_node)
|
||||
return -ENODEV;
|
||||
|
||||
pmic_client = of_find_i2c_device_by_node(pmic_node);
|
||||
of_node_put(pmic_node);
|
||||
if (!pmic_client)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
*pmic = &pmic_client->dev;
|
||||
|
||||
return devm_add_action_or_reset(dev, odroid_go_ultra_poweroff_put_pmic_device, *pmic);
|
||||
}
|
||||
|
||||
static int odroid_go_ultra_poweroff_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct odroid_go_ultra_poweroff_data *poweroff_data;
|
||||
int ret;
|
||||
|
||||
poweroff_data = devm_kzalloc(&pdev->dev, sizeof(*poweroff_data), GFP_KERNEL);
|
||||
if (!poweroff_data)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, poweroff_data);
|
||||
|
||||
/* RK818 PMIC Device */
|
||||
ret = odroid_go_ultra_poweroff_get_pmic_device(&pdev->dev, "rockchip,rk818",
|
||||
&poweroff_data->rk818);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed to get rk818 mfd data\n");
|
||||
|
||||
/* RK817 PMIC Device */
|
||||
ret = odroid_go_ultra_poweroff_get_pmic_device(&pdev->dev, "rockchip,rk817",
|
||||
&poweroff_data->rk817);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed to get rk817 mfd data\n");
|
||||
|
||||
/* Register as SYS_OFF_MODE_POWER_OFF_PREPARE because regmap_update_bits may sleep */
|
||||
ret = devm_register_sys_off_handler(&pdev->dev,
|
||||
SYS_OFF_MODE_POWER_OFF_PREPARE,
|
||||
SYS_OFF_PRIO_DEFAULT,
|
||||
odroid_go_ultra_poweroff_prepare,
|
||||
poweroff_data);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed to register sys-off handler\n");
|
||||
|
||||
dev_info(&pdev->dev, "Registered Power-Off handler\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
static struct platform_device *pdev;
|
||||
|
||||
static struct platform_driver odroid_go_ultra_poweroff_driver = {
|
||||
.driver = {
|
||||
.name = "odroid-go-ultra-poweroff",
|
||||
},
|
||||
.probe = odroid_go_ultra_poweroff_probe,
|
||||
};
|
||||
|
||||
static int __init odroid_go_ultra_poweroff_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Only create when running on the Odroid Go Ultra device */
|
||||
if (!of_device_is_compatible(of_root, "hardkernel,odroid-go-ultra"))
|
||||
return -ENODEV;
|
||||
|
||||
ret = platform_driver_register(&odroid_go_ultra_poweroff_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pdev = platform_device_register_resndata(NULL, "odroid-go-ultra-poweroff", -1,
|
||||
NULL, 0, NULL, 0);
|
||||
|
||||
if (IS_ERR(pdev)) {
|
||||
platform_driver_unregister(&odroid_go_ultra_poweroff_driver);
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit odroid_go_ultra_poweroff_exit(void)
|
||||
{
|
||||
/* Only delete when running on the Odroid Go Ultra device */
|
||||
if (!of_device_is_compatible(of_root, "hardkernel,odroid-go-ultra"))
|
||||
return;
|
||||
|
||||
platform_device_unregister(pdev);
|
||||
platform_driver_unregister(&odroid_go_ultra_poweroff_driver);
|
||||
}
|
||||
|
||||
module_init(odroid_go_ultra_poweroff_init);
|
||||
module_exit(odroid_go_ultra_poweroff_exit);
|
||||
|
||||
MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
|
||||
MODULE_DESCRIPTION("Odroid Go Ultra poweroff driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -44,6 +44,7 @@ static int syscon_reboot_probe(struct platform_device *pdev)
|
||||
struct syscon_reboot_context *ctx;
|
||||
struct device *dev = &pdev->dev;
|
||||
int mask_err, value_err;
|
||||
int priority;
|
||||
int err;
|
||||
|
||||
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
@@ -57,6 +58,9 @@ static int syscon_reboot_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(ctx->map);
|
||||
}
|
||||
|
||||
if (of_property_read_s32(pdev->dev.of_node, "priority", &priority))
|
||||
priority = 192;
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "offset", &ctx->offset))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -77,7 +81,7 @@ static int syscon_reboot_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ctx->restart_handler.notifier_call = syscon_restart_handle;
|
||||
ctx->restart_handler.priority = 192;
|
||||
ctx->restart_handler.priority = priority;
|
||||
err = register_restart_handler(&ctx->restart_handler);
|
||||
if (err)
|
||||
dev_err(dev, "can't register restart notifier (err=%d)\n", err);
|
||||
|
||||
@@ -765,6 +765,41 @@ config CHARGER_RT9455
|
||||
help
|
||||
Say Y to enable support for Richtek RT9455 battery charger.
|
||||
|
||||
config CHARGER_RT9467
|
||||
tristate "Richtek RT9467 Battery Charger Driver"
|
||||
depends on I2C && GPIOLIB && REGULATOR
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select LINEAR_RANGES
|
||||
help
|
||||
Say Y here to enable RT9467 Battery Charger.
|
||||
RT9467 is a switch-mode single cell Li-Ion/Li-Polymer battery charger
|
||||
for portable applications. It integrates a synchronous PWM controller,
|
||||
power MOSFETs, input current sensing and regulation, high-accuracy
|
||||
voltage regulation, and charge termination. The charge current is
|
||||
regulated through integrated sensing resistors. It also features
|
||||
USB On-The-Go (OTG) support and integrates D+/D- pin for USB
|
||||
host/charging port detection.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called "rt9467-charger".
|
||||
|
||||
config CHARGER_RT9471
|
||||
tristate "Richtek RT9471 battery charger driver"
|
||||
depends on I2C && GPIOLIB && REGULATOR
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select LINEAR_RANGES
|
||||
help
|
||||
This adds support for Richtek RT9471 battery charger. RT9471 is
|
||||
highly-integrated switch mode battery charger which is system power
|
||||
patch manageable device for single cell Li-Ion and Li-polymer battery.
|
||||
It can support BC12 detection on DPDM, and current and voltage
|
||||
regulation on both charging and boost mode.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called rt9471.
|
||||
|
||||
config CHARGER_CROS_USBPD
|
||||
tristate "ChromeOS EC based USBPD charger"
|
||||
depends on CROS_USBPD_NOTIFY
|
||||
|
||||
@@ -54,6 +54,8 @@ obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
|
||||
obj-$(CONFIG_BATTERY_MAX1721X) += max1721x_battery.o
|
||||
obj-$(CONFIG_BATTERY_RT5033) += rt5033_battery.o
|
||||
obj-$(CONFIG_CHARGER_RT9455) += rt9455_charger.o
|
||||
obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o
|
||||
obj-$(CONFIG_CHARGER_RT9471) += rt9471.o
|
||||
obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o
|
||||
obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o
|
||||
obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
|
||||
|
||||
@@ -2453,7 +2453,7 @@ struct ab8500_fg_sysfs_entry {
|
||||
|
||||
static ssize_t charge_full_show(struct ab8500_fg *di, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", di->bat_cap.max_mah);
|
||||
return sysfs_emit(buf, "%d\n", di->bat_cap.max_mah);
|
||||
}
|
||||
|
||||
static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf,
|
||||
@@ -2472,7 +2472,7 @@ static ssize_t charge_full_store(struct ab8500_fg *di, const char *buf,
|
||||
|
||||
static ssize_t charge_now_show(struct ab8500_fg *di, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", di->bat_cap.prev_mah);
|
||||
return sysfs_emit(buf, "%d\n", di->bat_cap.prev_mah);
|
||||
}
|
||||
|
||||
static ssize_t charge_now_store(struct ab8500_fg *di, const char *buf,
|
||||
@@ -2594,7 +2594,7 @@ static ssize_t ab8505_powercut_flagtime_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0x7F));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2644,7 +2644,7 @@ static ssize_t ab8505_powercut_maxtime_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0x7F));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2695,7 +2695,7 @@ static ssize_t ab8505_powercut_restart_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF));
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0xF));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2746,7 +2746,7 @@ static ssize_t ab8505_powercut_timer_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7F));
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0x7F));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2769,7 +2769,7 @@ static ssize_t ab8505_powercut_restart_counter_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0xF0) >> 4);
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0xF0) >> 4);
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2790,7 +2790,7 @@ static ssize_t ab8505_powercut_read(struct device *dev,
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x1));
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0x1));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2841,7 +2841,7 @@ static ssize_t ab8505_powercut_flag_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x10) >> 4));
|
||||
return sysfs_emit(buf, "%d\n", ((reg_value & 0x10) >> 4));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2864,7 +2864,7 @@ static ssize_t ab8505_powercut_debounce_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", (reg_value & 0x7));
|
||||
return sysfs_emit(buf, "%d\n", (reg_value & 0x7));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
@@ -2914,7 +2914,7 @@ static ssize_t ab8505_powercut_enable_status_read(struct device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", ((reg_value & 0x20) >> 5));
|
||||
return sysfs_emit(buf, "%d\n", ((reg_value & 0x20) >> 5));
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
|
||||
@@ -1059,7 +1059,7 @@ static ssize_t bq2415x_sysfs_show_status(struct device *dev,
|
||||
ret = bq2415x_exec_command(bq, command);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
return sysfs_emit(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1098,11 +1098,11 @@ static ssize_t bq2415x_sysfs_show_timer(struct device *dev,
|
||||
struct bq2415x_device *bq = power_supply_get_drvdata(psy);
|
||||
|
||||
if (bq->timer_error)
|
||||
return sprintf(buf, "%s\n", bq->timer_error);
|
||||
return sysfs_emit(buf, "%s\n", bq->timer_error);
|
||||
|
||||
if (bq->autotimer)
|
||||
return sprintf(buf, "auto\n");
|
||||
return sprintf(buf, "off\n");
|
||||
return sysfs_emit(buf, "auto\n");
|
||||
return sysfs_emit(buf, "off\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1175,30 +1175,30 @@ static ssize_t bq2415x_sysfs_show_mode(struct device *dev,
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (bq->automode > 0)
|
||||
ret += sprintf(buf+ret, "auto (");
|
||||
ret += sysfs_emit_at(buf, ret, "auto (");
|
||||
|
||||
switch (bq->mode) {
|
||||
case BQ2415X_MODE_OFF:
|
||||
ret += sprintf(buf+ret, "off");
|
||||
ret += sysfs_emit_at(buf, ret, "off");
|
||||
break;
|
||||
case BQ2415X_MODE_NONE:
|
||||
ret += sprintf(buf+ret, "none");
|
||||
ret += sysfs_emit_at(buf, ret, "none");
|
||||
break;
|
||||
case BQ2415X_MODE_HOST_CHARGER:
|
||||
ret += sprintf(buf+ret, "host");
|
||||
ret += sysfs_emit_at(buf, ret, "host");
|
||||
break;
|
||||
case BQ2415X_MODE_DEDICATED_CHARGER:
|
||||
ret += sprintf(buf+ret, "dedicated");
|
||||
ret += sysfs_emit_at(buf, ret, "dedicated");
|
||||
break;
|
||||
case BQ2415X_MODE_BOOST:
|
||||
ret += sprintf(buf+ret, "boost");
|
||||
ret += sysfs_emit_at(buf, ret, "boost");
|
||||
break;
|
||||
}
|
||||
|
||||
if (bq->automode > 0)
|
||||
ret += sprintf(buf+ret, ")");
|
||||
ret += sysfs_emit_at(buf, ret, ")");
|
||||
|
||||
ret += sprintf(buf+ret, "\n");
|
||||
ret += sysfs_emit_at(buf, ret, "\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1215,15 +1215,15 @@ static ssize_t bq2415x_sysfs_show_reported_mode(struct device *dev,
|
||||
|
||||
switch (bq->reported_mode) {
|
||||
case BQ2415X_MODE_OFF:
|
||||
return sprintf(buf, "off\n");
|
||||
return sysfs_emit(buf, "off\n");
|
||||
case BQ2415X_MODE_NONE:
|
||||
return sprintf(buf, "none\n");
|
||||
return sysfs_emit(buf, "none\n");
|
||||
case BQ2415X_MODE_HOST_CHARGER:
|
||||
return sprintf(buf, "host\n");
|
||||
return sysfs_emit(buf, "host\n");
|
||||
case BQ2415X_MODE_DEDICATED_CHARGER:
|
||||
return sprintf(buf, "dedicated\n");
|
||||
return sysfs_emit(buf, "dedicated\n");
|
||||
case BQ2415X_MODE_BOOST:
|
||||
return sprintf(buf, "boost\n");
|
||||
return sysfs_emit(buf, "boost\n");
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
@@ -1261,8 +1261,8 @@ static ssize_t bq2415x_sysfs_print_reg(struct bq2415x_device *bq,
|
||||
int ret = bq2415x_i2c_read(bq, reg);
|
||||
|
||||
if (ret < 0)
|
||||
return sprintf(buf, "%#.2x=error %d\n", reg, ret);
|
||||
return sprintf(buf, "%#.2x=%#.2x\n", reg, ret);
|
||||
return sysfs_emit(buf, "%#.2x=error %d\n", reg, ret);
|
||||
return sysfs_emit(buf, "%#.2x=%#.2x\n", reg, ret);
|
||||
}
|
||||
|
||||
/* show all raw values of chip register, format per line: 'register=value' */
|
||||
@@ -1338,7 +1338,7 @@ static ssize_t bq2415x_sysfs_show_limit(struct device *dev,
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
return sysfs_emit(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
/* set *_enable entries */
|
||||
@@ -1401,7 +1401,7 @@ static ssize_t bq2415x_sysfs_show_enable(struct device *dev,
|
||||
ret = bq2415x_exec_command(bq, command);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return sprintf(buf, "%d\n", ret);
|
||||
return sysfs_emit(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(current_limit, S_IWUSR | S_IRUGO,
|
||||
|
||||
@@ -463,7 +463,7 @@ static ssize_t bq24190_sysfs_show(struct device *dev,
|
||||
if (ret)
|
||||
count = ret;
|
||||
else
|
||||
count = scnprintf(buf, PAGE_SIZE, "%hhx\n", v);
|
||||
count = sysfs_emit(buf, "%hhx\n", v);
|
||||
|
||||
pm_runtime_mark_last_busy(bdi->dev);
|
||||
pm_runtime_put_autosuspend(bdi->dev);
|
||||
|
||||
@@ -767,8 +767,7 @@ static ssize_t bq24257_show_ovp_voltage(struct device *dev,
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
bq24257_vovp_map[bq->init_data.vovp]);
|
||||
return sysfs_emit(buf, "%u\n", bq24257_vovp_map[bq->init_data.vovp]);
|
||||
}
|
||||
|
||||
static ssize_t bq24257_show_in_dpm_voltage(struct device *dev,
|
||||
@@ -778,8 +777,7 @@ static ssize_t bq24257_show_in_dpm_voltage(struct device *dev,
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct bq24257_device *bq = power_supply_get_drvdata(psy);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n",
|
||||
bq24257_vindpm_map[bq->init_data.vindpm]);
|
||||
return sysfs_emit(buf, "%u\n", bq24257_vindpm_map[bq->init_data.vindpm]);
|
||||
}
|
||||
|
||||
static ssize_t bq24257_sysfs_show_enable(struct device *dev,
|
||||
@@ -800,7 +798,7 @@ static ssize_t bq24257_sysfs_show_enable(struct device *dev,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
|
||||
return sysfs_emit(buf, "%d\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t bq24257_sysfs_set_enable(struct device *dev,
|
||||
|
||||
@@ -1563,7 +1563,7 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
|
||||
return ret;
|
||||
|
||||
ret = bq->chip_info->bq256xx_set_ichg(bq,
|
||||
bat_info->constant_charge_current_max_ua);
|
||||
bq->chip_info->bq256xx_def_ichg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1573,7 +1573,7 @@ static int bq256xx_hw_init(struct bq256xx_device *bq)
|
||||
return ret;
|
||||
|
||||
ret = bq->chip_info->bq256xx_set_vbatreg(bq,
|
||||
bat_info->constant_charge_voltage_max_uv);
|
||||
bq->chip_info->bq256xx_def_vbatreg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ struct bq25890_init_data {
|
||||
|
||||
struct bq25890_state {
|
||||
u8 online;
|
||||
u8 hiz;
|
||||
u8 chrg_status;
|
||||
u8 chrg_fault;
|
||||
u8 vsys_status;
|
||||
@@ -107,6 +108,10 @@ struct bq25890_device {
|
||||
struct i2c_client *client;
|
||||
struct device *dev;
|
||||
struct power_supply *charger;
|
||||
struct power_supply *secondary_chrg;
|
||||
struct power_supply_desc desc;
|
||||
char name[28]; /* "bq25890-charger-%d" */
|
||||
int id;
|
||||
|
||||
struct usb_phy *usb_phy;
|
||||
struct notifier_block usb_nb;
|
||||
@@ -119,7 +124,9 @@ struct bq25890_device {
|
||||
|
||||
bool skip_reset;
|
||||
bool read_back_init_data;
|
||||
bool force_hiz;
|
||||
u32 pump_express_vbus_max;
|
||||
u32 iinlim_percentage;
|
||||
enum bq25890_chip_version chip_version;
|
||||
struct bq25890_init_data init_data;
|
||||
struct bq25890_state state;
|
||||
@@ -127,6 +134,9 @@ struct bq25890_device {
|
||||
struct mutex lock; /* protect state data */
|
||||
};
|
||||
|
||||
static DEFINE_IDR(bq25890_id);
|
||||
static DEFINE_MUTEX(bq25890_id_mutex);
|
||||
|
||||
static const struct regmap_range bq25890_readonly_reg_ranges[] = {
|
||||
regmap_reg_range(0x0b, 0x0c),
|
||||
regmap_reg_range(0x0e, 0x13),
|
||||
@@ -454,20 +464,18 @@ static int bq25890_get_vbus_voltage(struct bq25890_device *bq)
|
||||
return bq25890_find_val(ret, TBL_VBUSV);
|
||||
}
|
||||
|
||||
static int bq25890_power_supply_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
static void bq25890_update_state(struct bq25890_device *bq,
|
||||
enum power_supply_property psp,
|
||||
struct bq25890_state *state)
|
||||
{
|
||||
struct bq25890_device *bq = power_supply_get_drvdata(psy);
|
||||
struct bq25890_state state;
|
||||
bool do_adc_conv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&bq->lock);
|
||||
/* update state in case we lost an interrupt */
|
||||
__bq25890_handle_irq(bq);
|
||||
state = bq->state;
|
||||
do_adc_conv = !state.online && bq25890_is_adc_property(psp);
|
||||
*state = bq->state;
|
||||
do_adc_conv = (!state->online || state->hiz) && bq25890_is_adc_property(psp);
|
||||
if (do_adc_conv)
|
||||
bq25890_field_write(bq, F_CONV_START, 1);
|
||||
mutex_unlock(&bq->lock);
|
||||
@@ -475,10 +483,21 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
|
||||
if (do_adc_conv)
|
||||
regmap_field_read_poll_timeout(bq->rmap_fields[F_CONV_START],
|
||||
ret, !ret, 25000, 1000000);
|
||||
}
|
||||
|
||||
static int bq25890_power_supply_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct bq25890_device *bq = power_supply_get_drvdata(psy);
|
||||
struct bq25890_state state;
|
||||
int ret;
|
||||
|
||||
bq25890_update_state(bq, psp, &state);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (!state.online)
|
||||
if (!state.online || state.hiz)
|
||||
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
else if (state.chrg_status == STATUS_NOT_CHARGING)
|
||||
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
@@ -493,7 +512,8 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
||||
if (!state.online || state.chrg_status == STATUS_NOT_CHARGING ||
|
||||
if (!state.online || state.hiz ||
|
||||
state.chrg_status == STATUS_NOT_CHARGING ||
|
||||
state.chrg_status == STATUS_TERMINATION_DONE)
|
||||
val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
|
||||
else if (state.chrg_status == STATUS_PRE_CHARGING)
|
||||
@@ -513,7 +533,7 @@ static int bq25890_power_supply_get_property(struct power_supply *psy,
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = state.online;
|
||||
val->intval = state.online && !state.hiz;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
@@ -667,7 +687,8 @@ static int bq25890_power_supply_set_property(struct power_supply *psy,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct bq25890_device *bq = power_supply_get_drvdata(psy);
|
||||
int maxval;
|
||||
struct bq25890_state state;
|
||||
int maxval, ret;
|
||||
u8 lval;
|
||||
|
||||
switch (psp) {
|
||||
@@ -682,6 +703,12 @@ static int bq25890_power_supply_set_property(struct power_supply *psy,
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
lval = bq25890_find_idx(val->intval, TBL_IINLIM);
|
||||
return bq25890_field_write(bq, F_IINLIM, lval);
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
ret = bq25890_field_write(bq, F_EN_HIZ, !val->intval);
|
||||
if (!ret)
|
||||
bq->force_hiz = !val->intval;
|
||||
bq25890_update_state(bq, psp, &state);
|
||||
return ret;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -694,12 +721,25 @@ static int bq25890_power_supply_property_is_writeable(struct power_supply *psy,
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are multiple chargers the maximum current the external power-supply
|
||||
* can deliver needs to be divided over the chargers. This is done according
|
||||
* to the bq->iinlim_percentage setting.
|
||||
*/
|
||||
static int bq25890_charger_get_scaled_iinlim_regval(struct bq25890_device *bq,
|
||||
int iinlim_ua)
|
||||
{
|
||||
iinlim_ua = iinlim_ua * bq->iinlim_percentage / 100;
|
||||
return bq25890_find_idx(iinlim_ua, TBL_IINLIM);
|
||||
}
|
||||
|
||||
/* On the BQ25892 try to get charger-type info from our supplier */
|
||||
static void bq25890_charger_external_power_changed(struct power_supply *psy)
|
||||
{
|
||||
@@ -718,7 +758,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy)
|
||||
|
||||
switch (val.intval) {
|
||||
case POWER_SUPPLY_USB_TYPE_DCP:
|
||||
input_current_limit = bq25890_find_idx(2000000, TBL_IINLIM);
|
||||
input_current_limit = bq25890_charger_get_scaled_iinlim_regval(bq, 2000000);
|
||||
if (bq->pump_express_vbus_max) {
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&bq->pump_express_work,
|
||||
@@ -727,11 +767,11 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy)
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_CDP:
|
||||
case POWER_SUPPLY_USB_TYPE_ACA:
|
||||
input_current_limit = bq25890_find_idx(1500000, TBL_IINLIM);
|
||||
input_current_limit = bq25890_charger_get_scaled_iinlim_regval(bq, 1500000);
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_SDP:
|
||||
default:
|
||||
input_current_limit = bq25890_find_idx(500000, TBL_IINLIM);
|
||||
input_current_limit = bq25890_charger_get_scaled_iinlim_regval(bq, 500000);
|
||||
}
|
||||
|
||||
bq25890_field_write(bq, F_IINLIM, input_current_limit);
|
||||
@@ -748,6 +788,7 @@ static int bq25890_get_chip_state(struct bq25890_device *bq,
|
||||
} state_fields[] = {
|
||||
{F_CHG_STAT, &state->chrg_status},
|
||||
{F_PG_STAT, &state->online},
|
||||
{F_EN_HIZ, &state->hiz},
|
||||
{F_VSYS_STAT, &state->vsys_status},
|
||||
{F_BOOST_FAULT, &state->boost_fault},
|
||||
{F_BAT_FAULT, &state->bat_fault},
|
||||
@@ -763,16 +804,18 @@ static int bq25890_get_chip_state(struct bq25890_device *bq,
|
||||
*state_fields[i].data = ret;
|
||||
}
|
||||
|
||||
dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n",
|
||||
state->chrg_status, state->online, state->vsys_status,
|
||||
state->chrg_fault, state->boost_fault, state->bat_fault,
|
||||
state->ntc_fault);
|
||||
dev_dbg(bq->dev, "S:CHG/PG/HIZ/VSYS=%d/%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n",
|
||||
state->chrg_status, state->online,
|
||||
state->hiz, state->vsys_status,
|
||||
state->chrg_fault, state->boost_fault,
|
||||
state->bat_fault, state->ntc_fault);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq)
|
||||
{
|
||||
bool adc_conv_rate, new_adc_conv_rate;
|
||||
struct bq25890_state new_state;
|
||||
int ret;
|
||||
|
||||
@@ -783,14 +826,23 @@ static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq)
|
||||
if (!memcmp(&bq->state, &new_state, sizeof(new_state)))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!new_state.online && bq->state.online) { /* power removed */
|
||||
/* disable ADC */
|
||||
ret = bq25890_field_write(bq, F_CONV_RATE, 0);
|
||||
/*
|
||||
* Restore HiZ bit in case it was set by user. The chip does not retain
|
||||
* this bit on cable replug, hence the bit must be reset manually here.
|
||||
*/
|
||||
if (new_state.online && !bq->state.online && bq->force_hiz) {
|
||||
ret = bq25890_field_write(bq, F_EN_HIZ, bq->force_hiz);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
} else if (new_state.online && !bq->state.online) { /* power inserted */
|
||||
/* enable ADC, to have control of charge current/voltage */
|
||||
ret = bq25890_field_write(bq, F_CONV_RATE, 1);
|
||||
new_state.hiz = 1;
|
||||
}
|
||||
|
||||
/* Should period ADC sampling be enabled? */
|
||||
adc_conv_rate = bq->state.online && !bq->state.hiz;
|
||||
new_adc_conv_rate = new_state.online && !new_state.hiz;
|
||||
|
||||
if (new_adc_conv_rate != adc_conv_rate) {
|
||||
ret = bq25890_field_write(bq, F_CONV_RATE, new_adc_conv_rate);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
}
|
||||
@@ -924,7 +976,7 @@ static int bq25890_hw_init(struct bq25890_device *bq)
|
||||
}
|
||||
|
||||
/* Configure ADC for continuous conversions when charging */
|
||||
ret = bq25890_field_write(bq, F_CONV_RATE, !!bq->state.online);
|
||||
ret = bq25890_field_write(bq, F_CONV_RATE, bq->state.online && !bq->state.hiz);
|
||||
if (ret < 0) {
|
||||
dev_dbg(bq->dev, "Config ADC failed %d\n", ret);
|
||||
return ret;
|
||||
@@ -957,7 +1009,6 @@ static char *bq25890_charger_supplied_to[] = {
|
||||
};
|
||||
|
||||
static const struct power_supply_desc bq25890_power_supply_desc = {
|
||||
.name = "bq25890-charger",
|
||||
.type = POWER_SUPPLY_TYPE_USB,
|
||||
.properties = bq25890_power_supply_props,
|
||||
.num_properties = ARRAY_SIZE(bq25890_power_supply_props),
|
||||
@@ -971,12 +1022,21 @@ static int bq25890_power_supply_init(struct bq25890_device *bq)
|
||||
{
|
||||
struct power_supply_config psy_cfg = { .drv_data = bq, };
|
||||
|
||||
/* Get ID for the device */
|
||||
mutex_lock(&bq25890_id_mutex);
|
||||
bq->id = idr_alloc(&bq25890_id, bq, 0, 0, GFP_KERNEL);
|
||||
mutex_unlock(&bq25890_id_mutex);
|
||||
if (bq->id < 0)
|
||||
return bq->id;
|
||||
|
||||
snprintf(bq->name, sizeof(bq->name), "bq25890-charger-%d", bq->id);
|
||||
bq->desc = bq25890_power_supply_desc;
|
||||
bq->desc.name = bq->name;
|
||||
|
||||
psy_cfg.supplied_to = bq25890_charger_supplied_to;
|
||||
psy_cfg.num_supplicants = ARRAY_SIZE(bq25890_charger_supplied_to);
|
||||
|
||||
bq->charger = devm_power_supply_register(bq->dev,
|
||||
&bq25890_power_supply_desc,
|
||||
&psy_cfg);
|
||||
bq->charger = devm_power_supply_register(bq->dev, &bq->desc, &psy_cfg);
|
||||
|
||||
return PTR_ERR_OR_ZERO(bq->charger);
|
||||
}
|
||||
@@ -996,10 +1056,17 @@ static void bq25890_pump_express_work(struct work_struct *data)
|
||||
{
|
||||
struct bq25890_device *bq =
|
||||
container_of(data, struct bq25890_device, pump_express_work.work);
|
||||
union power_supply_propval value;
|
||||
int voltage, i, ret;
|
||||
|
||||
dev_dbg(bq->dev, "Start to request input voltage increasing\n");
|
||||
|
||||
/* If there is a second charger put in Hi-Z mode */
|
||||
if (bq->secondary_chrg) {
|
||||
value.intval = 0;
|
||||
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &value);
|
||||
}
|
||||
|
||||
/* Enable current pulse voltage control protocol */
|
||||
ret = bq25890_field_write(bq, F_PUMPX_EN, 1);
|
||||
if (ret < 0)
|
||||
@@ -1031,6 +1098,11 @@ static void bq25890_pump_express_work(struct work_struct *data)
|
||||
|
||||
bq25890_field_write(bq, F_PUMPX_EN, 0);
|
||||
|
||||
if (bq->secondary_chrg) {
|
||||
value.intval = 1;
|
||||
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &value);
|
||||
}
|
||||
|
||||
dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n",
|
||||
voltage);
|
||||
|
||||
@@ -1077,6 +1149,17 @@ static int bq25890_usb_notifier(struct notifier_block *nb, unsigned long val,
|
||||
static int bq25890_vbus_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct bq25890_device *bq = rdev_get_drvdata(rdev);
|
||||
union power_supply_propval val = {
|
||||
.intval = 0,
|
||||
};
|
||||
|
||||
/*
|
||||
* When enabling 5V boost / Vbus output, we need to put the secondary
|
||||
* charger in Hi-Z mode to avoid it trying to charge the secondary
|
||||
* battery from the 5V boost output.
|
||||
*/
|
||||
if (bq->secondary_chrg)
|
||||
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &val);
|
||||
|
||||
return bq25890_set_otg_cfg(bq, 1);
|
||||
}
|
||||
@@ -1084,8 +1167,19 @@ static int bq25890_vbus_enable(struct regulator_dev *rdev)
|
||||
static int bq25890_vbus_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct bq25890_device *bq = rdev_get_drvdata(rdev);
|
||||
union power_supply_propval val = {
|
||||
.intval = 1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
return bq25890_set_otg_cfg(bq, 0);
|
||||
ret = bq25890_set_otg_cfg(bq, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (bq->secondary_chrg)
|
||||
power_supply_set_property(bq->secondary_chrg, POWER_SUPPLY_PROP_ONLINE, &val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bq25890_vbus_is_enabled(struct regulator_dev *rdev)
|
||||
@@ -1296,11 +1390,31 @@ static int bq25890_fw_probe(struct bq25890_device *bq)
|
||||
{
|
||||
int ret;
|
||||
struct bq25890_init_data *init = &bq->init_data;
|
||||
const char *str;
|
||||
u32 val;
|
||||
|
||||
ret = device_property_read_string(bq->dev, "linux,secondary-charger-name", &str);
|
||||
if (ret == 0) {
|
||||
bq->secondary_chrg = power_supply_get_by_name(str);
|
||||
if (!bq->secondary_chrg)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
/* Optional, left at 0 if property is not present */
|
||||
device_property_read_u32(bq->dev, "linux,pump-express-vbus-max",
|
||||
&bq->pump_express_vbus_max);
|
||||
|
||||
ret = device_property_read_u32(bq->dev, "linux,iinlim-percentage", &val);
|
||||
if (ret == 0) {
|
||||
if (val > 100) {
|
||||
dev_err(bq->dev, "Error linux,iinlim-percentage %u > 100\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
bq->iinlim_percentage = val;
|
||||
} else {
|
||||
bq->iinlim_percentage = 100;
|
||||
}
|
||||
|
||||
bq->skip_reset = device_property_read_bool(bq->dev, "linux,skip-reset");
|
||||
bq->read_back_init_data = device_property_read_bool(bq->dev,
|
||||
"linux,read-back-settings");
|
||||
@@ -1322,6 +1436,12 @@ static void bq25890_non_devm_cleanup(void *data)
|
||||
struct bq25890_device *bq = data;
|
||||
|
||||
cancel_delayed_work_sync(&bq->pump_express_work);
|
||||
|
||||
if (bq->id >= 0) {
|
||||
mutex_lock(&bq25890_id_mutex);
|
||||
idr_remove(&bq25890_id, bq->id);
|
||||
mutex_unlock(&bq25890_id_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int bq25890_probe(struct i2c_client *client)
|
||||
@@ -1336,6 +1456,7 @@ static int bq25890_probe(struct i2c_client *client)
|
||||
|
||||
bq->client = client;
|
||||
bq->dev = dev;
|
||||
bq->id = -1;
|
||||
|
||||
mutex_init(&bq->lock);
|
||||
INIT_DELAYED_WORK(&bq->pump_express_work, bq25890_pump_express_work);
|
||||
|
||||
@@ -1917,10 +1917,10 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
|
||||
if (di->opts & BQ27XXX_O_ZERO) {
|
||||
if (di->cache.flags & BQ27000_FLAG_FC)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
|
||||
else if (di->cache.flags & BQ27000_FLAG_EDV1)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
|
||||
else if (di->cache.flags & BQ27000_FLAG_EDVF)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
|
||||
else if (di->cache.flags & BQ27000_FLAG_EDV1)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
|
||||
else
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
|
||||
} else if (di->opts & BQ27Z561_O_BITS) {
|
||||
@@ -1933,10 +1933,10 @@ static int bq27xxx_battery_capacity_level(struct bq27xxx_device_info *di,
|
||||
} else {
|
||||
if (di->cache.flags & BQ27XXX_FLAG_FC)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
|
||||
else if (di->cache.flags & BQ27XXX_FLAG_SOC1)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
|
||||
else if (di->cache.flags & BQ27XXX_FLAG_SOCF)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
|
||||
else if (di->cache.flags & BQ27XXX_FLAG_SOC1)
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
|
||||
else
|
||||
level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user