mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-28 00:33:16 +00:00
power supply and reset changes for the 6.13 series
* power-supply core - replace power_supply_register_no_ws() with power_supply_register() and a new "no_wakeup_source" field in struct power_supply_config - constify battery info tables in the core and all drivers - switch back to remove callback for all platform drivers - allow power_supply_put() to be called from atomic context - mark attribute arrays read-only after init * power-supply drivers - new driver for TWL6030 and TWL6032 - rk817: improve battery capacity calibration - misc. small cleanups and fixes -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmdFLjIACgkQ2O7X88g7 +pqEKA//YiR8OHLOg+wAysQZmwpoOSKGA/P1PNYrlGE64DarHKGXGRgVs0Z+RjnC FC4UKAYPz6h+dIWxuFjcoFmgiB8ewkFEB7Kgys6d9E2pL/Z7k5pteoAT7aiKnF+A OcNPsXt18Nj4wUF1va45zc4wUEtbwNoFUpiofCNv2f3SO79ZxHmm0fRScBCHLgAt lfiV6Yp1bx8aJ6Z/lgpzz6ofmBVLKNTrzbrJ8c9gYFSNxeQxGPk9nWawhy8bJaHR olIcO+XVacRZ8P0D1XtJNgJCzPvl4Qo2fPej5PXKzzQTM1a56b9bFCR0/TSqzYAw PLceJQIxttvBZfUVUmS/+ur8R/cc4OoXGs5xILIW3CfXTljdPVxOvx+Y4ztiEQLx 72uPyT+cmlFEO4NvKK1JkypKfuS589vc4byrIrWquuPU3FPwgEbbYoFLpuBcKBq8 EKu7LuF5gIR1WxwhNYWivJRQUjGlcRuF8bglaB0o8S4+eB93Hq7Uhchqew/n3ofp Qm/YFtCpAjyHoDhTOWH8KvuSEmO/QVz74ffQQw/NuxT7/ul7cEsksN+uolGLt/z/ fGFj8W+ki1rdQWpFG1epzINSHv6spf9qu2JLAFoHMJlyxjXTLC7s6BVNe41rLNwD lGjUlsxIQ9b86tlh4qX1qpDqyKhbJzN6WGGWGmFLubFsjr39O30= =vpkz -----END PGP SIGNATURE----- Merge tag 'for-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply Pull power supply and reset updates from Sebastian Reichel: "Power-supply core: - replace power_supply_register_no_ws() with power_supply_register() and a new "no_wakeup_source" field in struct power_supply_config - constify battery info tables in the core and all drivers - switch back to remove callback for all platform drivers - allow power_supply_put() to be called from atomic context - mark attribute arrays read-only after init Power-supply drivers: - new driver for TWL6030 and TWL6032 - rk817: improve battery capacity calibration - misc small cleanups and fixes" * tag 'for-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (42 commits) power: reset: ep93xx: add AUXILIARY_BUS dependency dt-bindings: power: reset: Convert mode-.* properties to array power: supply: sc27xx: Fix battery detect GPIO probe dt-bindings: power: supply: sc27xx-fg: document deprecated bat-detect-gpio reset: keystone-reset: remove unused macros power: supply: axp20x_battery: Use scaled iio_read_channel power: supply: axp20x_usb_power: Use scaled iio_read_channel power: supply: generic-adc-battery: change my gmail power: supply: pmu_battery: Set power supply type to BATTERY power: Switch back to struct platform_driver::remove() power: supply: hwmon: move interface to private header power: supply: rk817: Update battery capacity calibration power: supply: rk817: stop updating info in suspend power: supply: rt9471: Use IC status regfield to report real charger status power: supply: rt9471: Fix wrong WDT function regfield declaration dt-bindings: power/supply: qcom,pmi8998-charger: Drop incorrect "#interrupt-cells" from example power: supply: core: mark attribute arrays as ro_after_init power: supply: core: unexport power_supply_property_is_writeable() power: supply: core: use device mutex wrappers power: supply: bq27xxx: Fix registers of bq27426 ...
This commit is contained in:
commit
448ecd5771
@ -31,6 +31,10 @@ properties:
|
||||
allOf:
|
||||
- $ref: reboot-mode.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^mode-.*$":
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- nvmem-cells
|
||||
|
@ -54,6 +54,10 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
patternProperties:
|
||||
"^mode-.*$":
|
||||
maxItems: 1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
@ -75,6 +79,9 @@ allOf:
|
||||
reg-names:
|
||||
items:
|
||||
- const: pon
|
||||
else:
|
||||
patternProperties:
|
||||
"^mode-.*$": false
|
||||
|
||||
# Special case for pm8941, which doesn't store reset mode
|
||||
- if:
|
||||
|
@ -28,13 +28,13 @@ description: |
|
||||
|
||||
properties:
|
||||
mode-normal:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description:
|
||||
Default value to set on a reboot if no command was provided.
|
||||
|
||||
patternProperties:
|
||||
"^mode-.*$":
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
|
@ -32,6 +32,10 @@ properties:
|
||||
allOf:
|
||||
- $ref: reboot-mode.yaml#
|
||||
|
||||
patternProperties:
|
||||
"^mode-.*$":
|
||||
maxItems: 1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
|
@ -31,6 +31,10 @@ properties:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Offset in the register map for the reboot register (in bytes).
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: Base address and size for the reboot register.
|
||||
|
||||
regmap:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
deprecated: true
|
||||
@ -45,9 +49,14 @@ properties:
|
||||
priority:
|
||||
default: 192
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- offset
|
||||
- required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- offset
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -60,7 +60,6 @@ examples:
|
||||
pmic {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <4>;
|
||||
|
||||
charger@1000 {
|
||||
compatible = "qcom,pmi8998-charger";
|
||||
|
@ -27,6 +27,11 @@ properties:
|
||||
battery-detect-gpios:
|
||||
maxItems: 1
|
||||
|
||||
bat-detect-gpio:
|
||||
maxItems: 1
|
||||
deprecated: true
|
||||
description: use battery-detect-gpios instead
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/power/supply/ti,twl6030-charger.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TWL6030/32 BCI (Battery Charger Interface)
|
||||
|
||||
description:
|
||||
The battery charger needs to be configured to do any charging besides of
|
||||
precharging. The GPADC in the PMIC has to be used to get the related
|
||||
voltages.
|
||||
|
||||
maintainers:
|
||||
- Andreas Kemnade <andreas@kemnade.info>
|
||||
|
||||
allOf:
|
||||
- $ref: power-supply.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: ti,twl6030-charger
|
||||
- items:
|
||||
- const: ti,twl6032-charger
|
||||
- const: ti,twl6030-charger
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Charger Control Interrupt
|
||||
- description: Charger Fault Interrupt
|
||||
|
||||
io-channels:
|
||||
items:
|
||||
- description: VBUS Voltage Channel
|
||||
|
||||
io-channel-names:
|
||||
items:
|
||||
- const: vusb
|
||||
|
||||
monitored-battery: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- monitored-battery
|
||||
|
||||
additionalProperties: false
|
@ -853,6 +853,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
|
||||
struct power_supply_config psy_cfg = {
|
||||
.drv_data = battery,
|
||||
.attr_grp = acpi_battery_groups,
|
||||
.no_wakeup_source = true,
|
||||
};
|
||||
bool full_cap_broken = false;
|
||||
|
||||
@ -888,7 +889,7 @@ static int sysfs_add_battery(struct acpi_battery *battery)
|
||||
battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
battery->bat_desc.get_property = acpi_battery_get_property;
|
||||
|
||||
battery->bat = power_supply_register_no_ws(&battery->device->dev,
|
||||
battery->bat = power_supply_register(&battery->device->dev,
|
||||
&battery->bat_desc, &psy_cfg);
|
||||
|
||||
if (IS_ERR(battery->bat)) {
|
||||
|
@ -79,6 +79,7 @@ config POWER_RESET_EP93XX
|
||||
bool "Cirrus EP93XX reset driver" if COMPILE_TEST
|
||||
depends on MFD_SYSCON
|
||||
default ARCH_EP93XX
|
||||
select AUXILIARY_BUS
|
||||
help
|
||||
This driver provides restart support for Cirrus EP93XX SoC.
|
||||
|
||||
|
@ -223,7 +223,7 @@ MODULE_DEVICE_TABLE(of, at91_poweroff_of_match);
|
||||
|
||||
static struct platform_driver at91_poweroff_driver = {
|
||||
.probe = at91_poweroff_probe,
|
||||
.remove_new = at91_poweroff_remove,
|
||||
.remove = at91_poweroff_remove,
|
||||
.driver = {
|
||||
.name = "at91-poweroff",
|
||||
.of_match_table = at91_poweroff_of_match,
|
||||
|
@ -427,7 +427,7 @@ static void at91_reset_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver at91_reset_driver = {
|
||||
.probe = at91_reset_probe,
|
||||
.remove_new = at91_reset_remove,
|
||||
.remove = at91_reset_remove,
|
||||
.driver = {
|
||||
.name = "at91-reset",
|
||||
.of_match_table = at91_reset_of_match,
|
||||
|
@ -441,7 +441,7 @@ static void at91_shdwc_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver at91_shdwc_driver = {
|
||||
.probe = at91_shdwc_probe,
|
||||
.remove_new = at91_shdwc_remove,
|
||||
.remove = at91_shdwc_remove,
|
||||
.driver = {
|
||||
.name = "at91-shdwc",
|
||||
.of_match_table = at91_shdwc_of_match,
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#define RSTYPE_RG 0x0
|
||||
#define RSCTRL_RG 0x4
|
||||
#define RSCFG_RG 0x8
|
||||
#define RSISO_RG 0xc
|
||||
@ -28,7 +27,6 @@
|
||||
#define RSMUX_OMODE_MASK 0xe
|
||||
#define RSMUX_OMODE_RESET_ON 0xa
|
||||
#define RSMUX_OMODE_RESET_OFF 0x0
|
||||
#define RSMUX_LOCK_MASK 0x1
|
||||
#define RSMUX_LOCK_SET 0x1
|
||||
|
||||
#define RSCFG_RSTYPE_SOFT 0x300f
|
||||
|
@ -305,7 +305,7 @@ MODULE_DEVICE_TABLE(of, of_ltc2952_poweroff_match);
|
||||
|
||||
static struct platform_driver ltc2952_poweroff_driver = {
|
||||
.probe = ltc2952_poweroff_probe,
|
||||
.remove_new = ltc2952_poweroff_remove,
|
||||
.remove = ltc2952_poweroff_remove,
|
||||
.driver = {
|
||||
.name = "ltc2952-poweroff",
|
||||
.of_match_table = of_ltc2952_poweroff_match,
|
||||
|
@ -118,7 +118,7 @@ static void qnap_power_off_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver qnap_power_off_driver = {
|
||||
.probe = qnap_power_off_probe,
|
||||
.remove_new = qnap_power_off_remove,
|
||||
.remove = qnap_power_off_remove,
|
||||
.driver = {
|
||||
.name = "qnap_power_off",
|
||||
.of_match_table = of_match_ptr(qnap_power_off_of_match_table),
|
||||
|
@ -61,7 +61,8 @@ static int syscon_reboot_probe(struct platform_device *pdev)
|
||||
priority = 192;
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "offset", &ctx->offset))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(pdev->dev.of_node, "reg", &ctx->offset))
|
||||
return -EINVAL;
|
||||
|
||||
value_err = of_property_read_u32(pdev->dev.of_node, "value", &ctx->value);
|
||||
mask_err = of_property_read_u32(pdev->dev.of_node, "mask", &ctx->mask);
|
||||
|
@ -422,7 +422,7 @@ static irqreturn_t pm860x_batt_handler(int irq, void *data)
|
||||
info->temp_type = PM860X_TEMP_TINT;
|
||||
}
|
||||
mutex_unlock(&info->lock);
|
||||
/* clear ccnt since battery is attached or dettached */
|
||||
/* clear ccnt since battery is attached or detached */
|
||||
clear_ccnt(info, &ccnt_data);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -566,7 +566,7 @@ static int measure_temp(struct pm860x_battery_info *info, int *data)
|
||||
ret = measure_12bit_voltage(info, PM8607_GPADC1_MEAS1, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* meausered Vtbat(mV) / Ibias_current(11uA)*/
|
||||
/* measured Vtbat(mV) / Ibias_current(11uA)*/
|
||||
*data = (*data * 1000) / GPBIAS2_GPADC1_UA;
|
||||
|
||||
if (*data > TBAT_NEG_25D) {
|
||||
|
@ -493,6 +493,16 @@ config CHARGER_TWL4030
|
||||
help
|
||||
Say Y here to enable support for TWL4030 Battery Charge Interface.
|
||||
|
||||
config CHARGER_TWL6030
|
||||
tristate "OMAP TWL6030 BCI charger driver"
|
||||
depends on IIO && TWL4030_CORE
|
||||
help
|
||||
Say Y here to enable support for TWL6030/6032 Battery Charge
|
||||
Interface.
|
||||
|
||||
This driver can be build as a module. If so, the module will be
|
||||
called twl6030_charger.
|
||||
|
||||
config CHARGER_LP8727
|
||||
tristate "TI/National Semiconductor LP8727 charger driver"
|
||||
depends on I2C
|
||||
|
@ -69,6 +69,7 @@ obj-$(CONFIG_CHARGER_CPCAP) += cpcap-charger.o
|
||||
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
|
||||
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
|
||||
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
|
||||
obj-$(CONFIG_CHARGER_TWL6030) += twl6030_charger.o
|
||||
obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
|
||||
obj-$(CONFIG_CHARGER_LP8788) += lp8788-charger.o
|
||||
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
|
||||
|
@ -16,7 +16,7 @@
|
||||
/* Default: temperature hysteresis */
|
||||
#define AB8500_TEMP_HYSTERESIS 3
|
||||
|
||||
static struct power_supply_battery_ocv_table ocv_cap_tbl[] = {
|
||||
static const struct power_supply_battery_ocv_table ocv_cap_tbl[] = {
|
||||
{ .ocv = 4186000, .capacity = 100},
|
||||
{ .ocv = 4163000, .capacity = 99},
|
||||
{ .ocv = 4114000, .capacity = 95},
|
||||
@ -48,7 +48,7 @@ static struct power_supply_battery_ocv_table ocv_cap_tbl[] = {
|
||||
* temperature values to work. Factory resistance is 300 mOhm and the
|
||||
* resistance values to the right are percentages of 300 mOhm.
|
||||
*/
|
||||
static struct power_supply_resistance_temp_table temp_to_batres_tbl_thermistor[] = {
|
||||
static const struct power_supply_resistance_temp_table temp_to_batres_tbl_thermistor[] = {
|
||||
{ .temp = 40, .resistance = 40 /* 120 mOhm */ },
|
||||
{ .temp = 30, .resistance = 45 /* 135 mOhm */ },
|
||||
{ .temp = 20, .resistance = 55 /* 165 mOhm */ },
|
||||
|
@ -283,7 +283,7 @@ static void ab8500_btemp_periodic_work(struct work_struct *work)
|
||||
dev_warn(di->dev, "failed to identify the battery\n");
|
||||
}
|
||||
|
||||
/* Failover if a reading is erroneous, use last meausurement */
|
||||
/* Failover if a reading is erroneous, use last measurement */
|
||||
ret = thermal_zone_get_temp(di->tz, &bat_temp);
|
||||
if (ret) {
|
||||
dev_err(di->dev, "error reading temperature\n");
|
||||
@ -818,7 +818,7 @@ MODULE_DEVICE_TABLE(of, ab8500_btemp_match);
|
||||
|
||||
struct platform_driver ab8500_btemp_driver = {
|
||||
.probe = ab8500_btemp_probe,
|
||||
.remove_new = ab8500_btemp_remove,
|
||||
.remove = ab8500_btemp_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-btemp",
|
||||
.of_match_table = ab8500_btemp_match,
|
||||
|
@ -1837,7 +1837,7 @@ static const struct of_device_id ab8500_chargalg_match[] = {
|
||||
|
||||
struct platform_driver ab8500_chargalg_driver = {
|
||||
.probe = ab8500_chargalg_probe,
|
||||
.remove_new = ab8500_chargalg_remove,
|
||||
.remove = ab8500_chargalg_remove,
|
||||
.driver = {
|
||||
.name = "ab8500_chargalg",
|
||||
.of_match_table = ab8500_chargalg_match,
|
||||
|
@ -3711,7 +3711,7 @@ MODULE_DEVICE_TABLE(of, ab8500_charger_match);
|
||||
|
||||
static struct platform_driver ab8500_charger_driver = {
|
||||
.probe = ab8500_charger_probe,
|
||||
.remove_new = ab8500_charger_remove,
|
||||
.remove = ab8500_charger_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-charger",
|
||||
.of_match_table = ab8500_charger_match,
|
||||
|
@ -3242,7 +3242,7 @@ MODULE_DEVICE_TABLE(of, ab8500_fg_match);
|
||||
|
||||
struct platform_driver ab8500_fg_driver = {
|
||||
.probe = ab8500_fg_probe,
|
||||
.remove_new = ab8500_fg_remove,
|
||||
.remove = ab8500_fg_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-fg",
|
||||
.of_match_table = ab8500_fg_match,
|
||||
|
@ -233,14 +233,15 @@ static int a500_battery_probe(struct platform_device *pdev)
|
||||
|
||||
psy_cfg.of_node = pdev->dev.parent->of_node;
|
||||
psy_cfg.drv_data = bat;
|
||||
psy_cfg.no_wakeup_source = true;
|
||||
|
||||
bat->regmap = dev_get_regmap(pdev->dev.parent, "KB930");
|
||||
if (!bat->regmap)
|
||||
return -EINVAL;
|
||||
|
||||
bat->psy = devm_power_supply_register_no_ws(&pdev->dev,
|
||||
&a500_battery_desc,
|
||||
&psy_cfg);
|
||||
bat->psy = devm_power_supply_register(&pdev->dev,
|
||||
&a500_battery_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(bat->psy))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(bat->psy),
|
||||
"failed to register battery\n");
|
||||
@ -285,7 +286,7 @@ static struct platform_driver a500_battery_driver = {
|
||||
.pm = &a500_battery_pm_ops,
|
||||
},
|
||||
.probe = a500_battery_probe,
|
||||
.remove_new = a500_battery_remove,
|
||||
.remove = a500_battery_remove,
|
||||
};
|
||||
module_platform_driver(a500_battery_driver);
|
||||
|
||||
|
@ -651,7 +651,7 @@ static struct platform_driver act8945a_charger_driver = {
|
||||
.name = "act8945a-charger",
|
||||
},
|
||||
.probe = act8945a_charger_probe,
|
||||
.remove_new = act8945a_charger_remove,
|
||||
.remove = act8945a_charger_remove,
|
||||
};
|
||||
module_platform_driver(act8945a_charger_driver);
|
||||
|
||||
|
@ -590,7 +590,7 @@ static int adp5061_get_property(struct power_supply *psy,
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
|
||||
/*
|
||||
* This property is used to set the VWEAK threshold
|
||||
* bellow this value, weak charge mode is entered
|
||||
* below this value, weak charge mode is entered
|
||||
* above this value, fast chargerge mode is entered
|
||||
*/
|
||||
return adp5061_get_vweak_th(st, val);
|
||||
|
@ -354,17 +354,18 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* IIO framework gives mA but Power Supply framework gives uA */
|
||||
if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
|
||||
ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
|
||||
ret = iio_read_channel_processed_scale(axp20x_batt->batt_chrg_i,
|
||||
&val->intval, 1000);
|
||||
} else {
|
||||
ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1);
|
||||
ret = iio_read_channel_processed_scale(axp20x_batt->batt_dischrg_i,
|
||||
&val1, 1000);
|
||||
val->intval = -val1;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* IIO framework gives mA but Power Supply framework gives uA */
|
||||
val->intval *= 1000;
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
@ -406,13 +407,12 @@ static int axp20x_battery_get_prop(struct power_supply *psy,
|
||||
break;
|
||||
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = iio_read_channel_processed(axp20x_batt->batt_v,
|
||||
&val->intval);
|
||||
/* IIO framework gives mV but Power Supply framework gives uV */
|
||||
ret = iio_read_channel_processed_scale(axp20x_batt->batt_v,
|
||||
&val->intval, 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* IIO framework gives mV but Power Supply framework gives uV */
|
||||
val->intval *= 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -519,13 +519,15 @@ static int axp717_battery_get_prop(struct power_supply *psy,
|
||||
* The offset of this value is currently unknown and is
|
||||
* not documented in the datasheet. Based on
|
||||
* observation it's assumed to be somewhere around
|
||||
* 450ma. I will leave the value raw for now.
|
||||
* 450ma. I will leave the value raw for now. Note that
|
||||
* IIO framework gives mA but Power Supply framework
|
||||
* gives uA.
|
||||
*/
|
||||
ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
|
||||
ret = iio_read_channel_processed_scale(axp20x_batt->batt_chrg_i,
|
||||
&val->intval, 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* IIO framework gives mA but Power Supply framework gives uA */
|
||||
val->intval *= 1000;
|
||||
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_CAPACITY:
|
||||
@ -564,13 +566,12 @@ static int axp717_battery_get_prop(struct power_supply *psy,
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
ret = iio_read_channel_processed(axp20x_batt->batt_v,
|
||||
&val->intval);
|
||||
/* IIO framework gives mV but Power Supply framework gives uV */
|
||||
ret = iio_read_channel_processed_scale(axp20x_batt->batt_v,
|
||||
&val->intval, 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* IIO framework gives mV but Power Supply framework gives uV */
|
||||
val->intval *= 1000;
|
||||
return 0;
|
||||
|
||||
case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
|
||||
|
@ -220,16 +220,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
|
||||
return 0;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
|
||||
ret = iio_read_channel_processed(power->vbus_v,
|
||||
&val->intval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* IIO framework gives mV but Power Supply framework
|
||||
* gives uV.
|
||||
*/
|
||||
val->intval *= 1000;
|
||||
ret = iio_read_channel_processed_scale(power->vbus_v,
|
||||
&val->intval, 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -253,16 +252,15 @@ static int axp20x_usb_power_get_property(struct power_supply *psy,
|
||||
return 0;
|
||||
case POWER_SUPPLY_PROP_CURRENT_NOW:
|
||||
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
|
||||
ret = iio_read_channel_processed(power->vbus_i,
|
||||
&val->intval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* IIO framework gives mA but Power Supply framework
|
||||
* gives uA.
|
||||
*/
|
||||
val->intval *= 1000;
|
||||
ret = iio_read_channel_processed_scale(power->vbus_i,
|
||||
&val->intval, 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -374,16 +372,15 @@ static int axp717_usb_power_get_property(struct power_supply *psy,
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
if (IS_ENABLED(CONFIG_AXP20X_ADC)) {
|
||||
ret = iio_read_channel_processed(power->vbus_v,
|
||||
&val->intval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* IIO framework gives mV but Power Supply framework
|
||||
* gives uV.
|
||||
*/
|
||||
val->intval *= 1000;
|
||||
ret = iio_read_channel_processed_scale(power->vbus_v,
|
||||
&val->intval, 1000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -449,9 +449,29 @@ static u8
|
||||
[BQ27XXX_REG_AP] = 0x18,
|
||||
BQ27XXX_DM_REG_ROWS,
|
||||
},
|
||||
bq27426_regs[BQ27XXX_REG_MAX] = {
|
||||
[BQ27XXX_REG_CTRL] = 0x00,
|
||||
[BQ27XXX_REG_TEMP] = 0x02,
|
||||
[BQ27XXX_REG_INT_TEMP] = 0x1e,
|
||||
[BQ27XXX_REG_VOLT] = 0x04,
|
||||
[BQ27XXX_REG_AI] = 0x10,
|
||||
[BQ27XXX_REG_FLAGS] = 0x06,
|
||||
[BQ27XXX_REG_TTE] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_TTF] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_TTES] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_TTECP] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_NAC] = 0x08,
|
||||
[BQ27XXX_REG_RC] = 0x0c,
|
||||
[BQ27XXX_REG_FCC] = 0x0e,
|
||||
[BQ27XXX_REG_CYCT] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_AE] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_SOC] = 0x1c,
|
||||
[BQ27XXX_REG_DCAP] = INVALID_REG_ADDR,
|
||||
[BQ27XXX_REG_AP] = 0x18,
|
||||
BQ27XXX_DM_REG_ROWS,
|
||||
},
|
||||
#define bq27411_regs bq27421_regs
|
||||
#define bq27425_regs bq27421_regs
|
||||
#define bq27426_regs bq27421_regs
|
||||
#define bq27441_regs bq27421_regs
|
||||
#define bq27621_regs bq27421_regs
|
||||
bq27z561_regs[BQ27XXX_REG_MAX] = {
|
||||
@ -769,10 +789,23 @@ static enum power_supply_property bq27421_props[] = {
|
||||
};
|
||||
#define bq27411_props bq27421_props
|
||||
#define bq27425_props bq27421_props
|
||||
#define bq27426_props bq27421_props
|
||||
#define bq27441_props bq27421_props
|
||||
#define bq27621_props bq27421_props
|
||||
|
||||
static enum power_supply_property bq27426_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
POWER_SUPPLY_PROP_CAPACITY,
|
||||
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_CHARGE_FULL,
|
||||
POWER_SUPPLY_PROP_CHARGE_NOW,
|
||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
};
|
||||
|
||||
static enum power_supply_property bq27z561_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
@ -2131,6 +2164,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
|
||||
struct power_supply_config psy_cfg = {
|
||||
.of_node = di->dev->of_node,
|
||||
.drv_data = di,
|
||||
.no_wakeup_source = true,
|
||||
};
|
||||
int ret;
|
||||
|
||||
@ -2157,7 +2191,7 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
|
||||
psy_desc->get_property = bq27xxx_battery_get_property;
|
||||
psy_desc->external_power_changed = bq27xxx_external_power_changed;
|
||||
|
||||
di->bat = devm_power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
|
||||
di->bat = devm_power_supply_register(di->dev, psy_desc, &psy_cfg);
|
||||
if (IS_ERR(di->bat))
|
||||
return dev_err_probe(di->dev, PTR_ERR(di->bat),
|
||||
"failed to register battery\n");
|
||||
|
@ -221,7 +221,7 @@ static bool is_charging(struct charger_manager *cm)
|
||||
|
||||
/* If at least one of the charger is charging, return yes */
|
||||
for (i = 0; cm->desc->psy_charger_stat[i]; i++) {
|
||||
/* 1. The charger sholuld not be DISABLED */
|
||||
/* 1. The charger should not be DISABLED */
|
||||
if (cm->emergency_stop)
|
||||
continue;
|
||||
if (!cm->charger_enabled)
|
||||
@ -1739,7 +1739,7 @@ static struct platform_driver charger_manager_driver = {
|
||||
.of_match_table = charger_manager_match,
|
||||
},
|
||||
.probe = charger_manager_probe,
|
||||
.remove_new = charger_manager_remove,
|
||||
.remove = charger_manager_remove,
|
||||
.id_table = charger_manager_id,
|
||||
};
|
||||
|
||||
|
@ -1169,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_new = cpcap_battery_remove,
|
||||
.remove = cpcap_battery_remove,
|
||||
};
|
||||
module_platform_driver(cpcap_battery_driver);
|
||||
|
||||
|
@ -969,7 +969,7 @@ static struct platform_driver cpcap_charger_driver = {
|
||||
.of_match_table = cpcap_charger_id_table,
|
||||
},
|
||||
.shutdown = cpcap_charger_shutdown,
|
||||
.remove_new = cpcap_charger_remove,
|
||||
.remove = cpcap_charger_remove,
|
||||
};
|
||||
module_platform_driver(cpcap_charger_driver);
|
||||
|
||||
|
@ -618,6 +618,7 @@ static int cros_usbpd_charger_probe(struct platform_device *pd)
|
||||
psy_desc->external_power_changed =
|
||||
cros_usbpd_charger_power_changed;
|
||||
psy_cfg.drv_data = port;
|
||||
psy_cfg.no_wakeup_source = true;
|
||||
|
||||
if (cros_usbpd_charger_port_is_dedicated(port)) {
|
||||
sprintf(port->name, CHARGER_DEDICATED_DIR_NAME);
|
||||
@ -644,8 +645,7 @@ static int cros_usbpd_charger_probe(struct platform_device *pd)
|
||||
|
||||
psy_desc->name = port->name;
|
||||
|
||||
psy = devm_power_supply_register_no_ws(dev, psy_desc,
|
||||
&psy_cfg);
|
||||
psy = devm_power_supply_register(dev, psy_desc, &psy_cfg);
|
||||
if (IS_ERR(psy)) {
|
||||
dev_err(dev, "Failed to register power supply\n");
|
||||
continue;
|
||||
|
@ -269,7 +269,7 @@ static void da9030_charger_check_state(struct da9030_charger *charger)
|
||||
}
|
||||
if (charger->adc.vchmax_res > charger->thresholds.vcharge_max ||
|
||||
charger->adc.vchmin_res < charger->thresholds.vcharge_min ||
|
||||
/* Tempreture readings are negative */
|
||||
/* Temperature readings are negative */
|
||||
charger->adc.tbat_res < charger->thresholds.tbat_high ||
|
||||
charger->adc.tbat_res > charger->thresholds.tbat_low) {
|
||||
/* disable charger */
|
||||
@ -470,7 +470,7 @@ static int da9030_battery_charger_init(struct da9030_charger *charger)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable auto ADC measuremnts */
|
||||
/* enable auto ADC measurements */
|
||||
return da903x_write(charger->master, DA9030_ADC_AUTO_CONTROL,
|
||||
DA9030_ADC_TBAT_ENABLE | DA9030_ADC_VBAT_IN_TXON |
|
||||
DA9030_ADC_VCH_ENABLE | DA9030_ADC_ICH_ENABLE |
|
||||
@ -571,7 +571,7 @@ static struct platform_driver da903x_battery_driver = {
|
||||
.name = "da903x-battery",
|
||||
},
|
||||
.probe = da9030_battery_probe,
|
||||
.remove_new = da9030_battery_remove,
|
||||
.remove = da9030_battery_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(da903x_battery_driver);
|
||||
|
@ -648,7 +648,7 @@ static void da9052_bat_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver da9052_bat_driver = {
|
||||
.probe = da9052_bat_probe,
|
||||
.remove_new = da9052_bat_remove,
|
||||
.remove = da9052_bat_remove,
|
||||
.driver = {
|
||||
.name = "da9052-bat",
|
||||
},
|
||||
|
@ -636,7 +636,7 @@ static struct platform_driver da9150_charger_driver = {
|
||||
.name = "da9150-charger",
|
||||
},
|
||||
.probe = da9150_charger_probe,
|
||||
.remove_new = da9150_charger_remove,
|
||||
.remove = da9150_charger_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(da9150_charger_driver);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Generic battery driver using IIO
|
||||
* Copyright (C) 2012, Anish Kumar <anish198519851985@gmail.com>
|
||||
* Copyright (C) 2012, Anish Kumar <yesanishhere@gmail.com>
|
||||
* Copyright (c) 2023, Sebastian Reichel <sre@kernel.org>
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
@ -295,6 +295,6 @@ static struct platform_driver gab_driver = {
|
||||
};
|
||||
module_platform_driver(gab_driver);
|
||||
|
||||
MODULE_AUTHOR("anish kumar <anish198519851985@gmail.com>");
|
||||
MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>");
|
||||
MODULE_DESCRIPTION("generic battery driver using IIO");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -302,7 +302,7 @@ static struct platform_driver micro_batt_device_driver = {
|
||||
.pm = µ_batt_dev_pm_ops,
|
||||
},
|
||||
.probe = micro_batt_probe,
|
||||
.remove_new = micro_batt_remove,
|
||||
.remove = micro_batt_remove,
|
||||
};
|
||||
module_platform_driver(micro_batt_device_driver);
|
||||
|
||||
|
@ -501,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_new = isp1704_charger_remove,
|
||||
.remove = isp1704_charger_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(isp1704_charger_driver);
|
||||
|
@ -368,11 +368,12 @@ static int yoga_c630_psy_register_bat_psy(struct yoga_c630_psy *ecbat)
|
||||
|
||||
bat_cfg.drv_data = ecbat;
|
||||
bat_cfg.fwnode = ecbat->fwnode;
|
||||
ecbat->bat_psy = power_supply_register_no_ws(ecbat->dev,
|
||||
ecbat->unit_mA ?
|
||||
&yoga_c630_psy_bat_psy_desc_mA :
|
||||
&yoga_c630_psy_bat_psy_desc_mWh,
|
||||
&bat_cfg);
|
||||
bat_cfg.no_wakeup_source = true;
|
||||
ecbat->bat_psy = power_supply_register(ecbat->dev,
|
||||
ecbat->unit_mA ?
|
||||
&yoga_c630_psy_bat_psy_desc_mA :
|
||||
&yoga_c630_psy_bat_psy_desc_mWh,
|
||||
&bat_cfg);
|
||||
if (IS_ERR(ecbat->bat_psy)) {
|
||||
dev_err(ecbat->dev, "failed to register battery supply\n");
|
||||
return PTR_ERR(ecbat->bat_psy);
|
||||
@ -442,7 +443,8 @@ static int yoga_c630_psy_probe(struct auxiliary_device *adev,
|
||||
adp_cfg.fwnode = ecbat->fwnode;
|
||||
adp_cfg.supplied_to = (char **)&yoga_c630_psy_bat_psy_desc_mA.name;
|
||||
adp_cfg.num_supplicants = 1;
|
||||
ecbat->adp_psy = devm_power_supply_register_no_ws(dev, &yoga_c630_psy_adpt_psy_desc, &adp_cfg);
|
||||
adp_cfg.no_wakeup_source = true;
|
||||
ecbat->adp_psy = devm_power_supply_register(dev, &yoga_c630_psy_adpt_psy_desc, &adp_cfg);
|
||||
if (IS_ERR(ecbat->adp_psy)) {
|
||||
dev_err(dev, "failed to register AC adapter supply\n");
|
||||
return PTR_ERR(ecbat->adp_psy);
|
||||
|
@ -716,7 +716,7 @@ static void lp8788_charger_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver lp8788_charger_driver = {
|
||||
.probe = lp8788_charger_probe,
|
||||
.remove_new = lp8788_charger_remove,
|
||||
.remove = lp8788_charger_remove,
|
||||
.driver = {
|
||||
.name = LP8788_DEV_CHARGER,
|
||||
},
|
||||
|
@ -634,7 +634,7 @@ static struct platform_driver max14577_charger_driver = {
|
||||
.of_match_table = of_max14577_charger_dt_match,
|
||||
},
|
||||
.probe = max14577_charger_probe,
|
||||
.remove_new = max14577_charger_remove,
|
||||
.remove = max14577_charger_remove,
|
||||
.id_table = max14577_charger_id,
|
||||
};
|
||||
module_platform_driver(max14577_charger_driver);
|
||||
|
@ -364,7 +364,7 @@ static struct platform_driver max77650_charger_driver = {
|
||||
.of_match_table = max77650_charger_of_match,
|
||||
},
|
||||
.probe = max77650_charger_probe,
|
||||
.remove_new = max77650_charger_remove,
|
||||
.remove = max77650_charger_remove,
|
||||
};
|
||||
module_platform_driver(max77650_charger_driver);
|
||||
|
||||
|
@ -798,7 +798,7 @@ static struct platform_driver max77693_charger_driver = {
|
||||
.name = "max77693-charger",
|
||||
},
|
||||
.probe = max77693_charger_probe,
|
||||
.remove_new = max77693_charger_remove,
|
||||
.remove = max77693_charger_remove,
|
||||
.id_table = max77693_charger_id,
|
||||
};
|
||||
module_platform_driver(max77693_charger_driver);
|
||||
|
@ -452,6 +452,7 @@ static int max77976_probe(struct i2c_client *client)
|
||||
|
||||
i2c_set_clientdata(client, chg);
|
||||
psy_cfg.drv_data = chg;
|
||||
psy_cfg.no_wakeup_source = true;
|
||||
chg->client = client;
|
||||
|
||||
chg->regmap = devm_regmap_init_i2c(client, &max77976_regmap_config);
|
||||
@ -475,7 +476,7 @@ static int max77976_probe(struct i2c_client *client)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
psy = devm_power_supply_register_no_ws(dev, &max77976_psy_desc, &psy_cfg);
|
||||
psy = devm_power_supply_register(dev, &max77976_psy_desc, &psy_cfg);
|
||||
if (IS_ERR(psy))
|
||||
return dev_err_probe(dev, PTR_ERR(psy), "cannot register\n");
|
||||
|
||||
|
@ -73,7 +73,7 @@ struct max8925_power_info {
|
||||
unsigned usb_online:1;
|
||||
unsigned bat_online:1;
|
||||
unsigned chg_mode:2;
|
||||
unsigned batt_detect:1; /* detecing MB by ID pin */
|
||||
unsigned batt_detect:1; /* detecting MB by ID pin */
|
||||
unsigned topoff_threshold:2;
|
||||
unsigned fast_charge:3;
|
||||
unsigned no_temp_support:1;
|
||||
@ -563,7 +563,7 @@ static void max8925_power_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver max8925_power_driver = {
|
||||
.probe = max8925_power_probe,
|
||||
.remove_new = max8925_power_remove,
|
||||
.remove = max8925_power_remove,
|
||||
.driver = {
|
||||
.name = "max8925-power",
|
||||
},
|
||||
|
@ -455,7 +455,7 @@ static struct platform_driver pcf50633_mbc_driver = {
|
||||
.name = "pcf50633-mbc",
|
||||
},
|
||||
.probe = pcf50633_mbc_probe,
|
||||
.remove_new = pcf50633_mbc_remove,
|
||||
.remove = pcf50633_mbc_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(pcf50633_mbc_driver);
|
||||
|
@ -170,6 +170,7 @@ static int __init pmu_bat_init(void)
|
||||
pbat->bat_desc.properties = pmu_bat_props;
|
||||
pbat->bat_desc.num_properties = ARRAY_SIZE(pmu_bat_props);
|
||||
pbat->bat_desc.get_property = pmu_bat_get_property;
|
||||
pbat->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
pbat->pbi = &pmu_batteries[i];
|
||||
psy_cfg.drv_data = pbat;
|
||||
|
||||
|
@ -13,9 +13,12 @@ struct device;
|
||||
struct device_type;
|
||||
struct power_supply;
|
||||
|
||||
extern int power_supply_property_is_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
extern void power_supply_init_attrs(void);
|
||||
extern void __init power_supply_init_attrs(void);
|
||||
extern int power_supply_uevent(const struct device *dev, struct kobj_uevent_env *env);
|
||||
extern const struct attribute_group *power_supply_attr_groups[];
|
||||
|
||||
@ -41,3 +44,20 @@ static inline int power_supply_create_triggers(struct power_supply *psy)
|
||||
static inline void power_supply_remove_triggers(struct power_supply *psy) {}
|
||||
|
||||
#endif /* CONFIG_LEDS_TRIGGERS */
|
||||
|
||||
#ifdef CONFIG_POWER_SUPPLY_HWMON
|
||||
|
||||
int power_supply_add_hwmon_sysfs(struct power_supply *psy);
|
||||
void power_supply_remove_hwmon_sysfs(struct power_supply *psy);
|
||||
|
||||
#else
|
||||
|
||||
static inline int power_supply_add_hwmon_sysfs(struct power_supply *psy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void power_supply_remove_hwmon_sysfs(struct power_supply *psy) {}
|
||||
|
||||
#endif /* CONFIG_POWER_SUPPLY_HWMON */
|
||||
|
@ -152,7 +152,7 @@ static void power_supply_deferred_register_work(struct work_struct *work)
|
||||
deferred_register_work.work);
|
||||
|
||||
if (psy->dev.parent) {
|
||||
while (!mutex_trylock(&psy->dev.parent->mutex)) {
|
||||
while (!device_trylock(psy->dev.parent)) {
|
||||
if (psy->removing)
|
||||
return;
|
||||
msleep(10);
|
||||
@ -162,7 +162,7 @@ static void power_supply_deferred_register_work(struct work_struct *work)
|
||||
power_supply_changed(psy);
|
||||
|
||||
if (psy->dev.parent)
|
||||
mutex_unlock(&psy->dev.parent->mutex);
|
||||
device_unlock(psy->dev.parent);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
@ -484,8 +484,6 @@ EXPORT_SYMBOL_GPL(power_supply_get_by_name);
|
||||
*/
|
||||
void power_supply_put(struct power_supply *psy)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
atomic_dec(&psy->use_cnt);
|
||||
put_device(&psy->dev);
|
||||
}
|
||||
@ -777,7 +775,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
|
||||
tab_len = size / (2 * sizeof(__be32));
|
||||
info->ocv_table_size[index] = tab_len;
|
||||
|
||||
table = info->ocv_table[index] =
|
||||
info->ocv_table[index] = table =
|
||||
devm_kcalloc(&psy->dev, tab_len, sizeof(*table), GFP_KERNEL);
|
||||
if (!info->ocv_table[index]) {
|
||||
power_supply_put_battery_info(psy, info);
|
||||
@ -798,7 +796,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
|
||||
goto out_ret_pointer;
|
||||
|
||||
info->resist_table_size = len / (2 * sizeof(__be32));
|
||||
resist_table = info->resist_table = devm_kcalloc(&psy->dev,
|
||||
info->resist_table = resist_table = devm_kcalloc(&psy->dev,
|
||||
info->resist_table_size,
|
||||
sizeof(*resist_table),
|
||||
GFP_KERNEL);
|
||||
@ -982,7 +980,7 @@ EXPORT_SYMBOL_GPL(power_supply_battery_info_get_prop);
|
||||
*
|
||||
* Return: the battery internal resistance percent
|
||||
*/
|
||||
int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table,
|
||||
int power_supply_temp2resist_simple(const struct power_supply_resistance_temp_table *table,
|
||||
int table_len, int temp)
|
||||
{
|
||||
int i, high, low;
|
||||
@ -1093,7 +1091,7 @@ EXPORT_SYMBOL_GPL(power_supply_get_maintenance_charging_setting);
|
||||
*
|
||||
* Return: the battery capacity.
|
||||
*/
|
||||
int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
|
||||
int power_supply_ocv2cap_simple(const struct power_supply_battery_ocv_table *table,
|
||||
int table_len, int ocv)
|
||||
{
|
||||
int i, high, low;
|
||||
@ -1118,7 +1116,7 @@ int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_ocv2cap_simple);
|
||||
|
||||
struct power_supply_battery_ocv_table *
|
||||
const struct power_supply_battery_ocv_table *
|
||||
power_supply_find_ocv2cap_table(struct power_supply_battery_info *info,
|
||||
int temp, int *table_len)
|
||||
{
|
||||
@ -1149,7 +1147,7 @@ EXPORT_SYMBOL_GPL(power_supply_find_ocv2cap_table);
|
||||
int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info,
|
||||
int ocv, int temp)
|
||||
{
|
||||
struct power_supply_battery_ocv_table *table;
|
||||
const struct power_supply_battery_ocv_table *table;
|
||||
int table_len;
|
||||
|
||||
table = power_supply_find_ocv2cap_table(info, temp, &table_len);
|
||||
@ -1233,7 +1231,6 @@ int power_supply_property_is_writeable(struct power_supply *psy,
|
||||
{
|
||||
return psy->desc->property_is_writeable && psy->desc->property_is_writeable(psy, psp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_property_is_writeable);
|
||||
|
||||
void power_supply_external_power_changed(struct power_supply *psy)
|
||||
{
|
||||
@ -1342,8 +1339,7 @@ static void psy_unregister_thermal(struct power_supply *psy)
|
||||
static struct power_supply *__must_check
|
||||
__power_supply_register(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg,
|
||||
bool ws)
|
||||
const struct power_supply_config *cfg)
|
||||
{
|
||||
struct device *dev;
|
||||
struct power_supply *psy;
|
||||
@ -1410,7 +1406,7 @@ __power_supply_register(struct device *parent,
|
||||
if (rc)
|
||||
goto device_add_failed;
|
||||
|
||||
rc = device_init_wakeup(dev, ws);
|
||||
rc = device_init_wakeup(dev, cfg ? !cfg->no_wakeup_source : true);
|
||||
if (rc)
|
||||
goto wakeup_init_failed;
|
||||
|
||||
@ -1476,33 +1472,10 @@ struct power_supply *__must_check power_supply_register(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg)
|
||||
{
|
||||
return __power_supply_register(parent, desc, cfg, true);
|
||||
return __power_supply_register(parent, desc, cfg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_register);
|
||||
|
||||
/**
|
||||
* power_supply_register_no_ws() - Register new non-waking-source power supply
|
||||
* @parent: Device to be a parent of power supply's device, usually
|
||||
* the device which probe function calls this
|
||||
* @desc: Description of power supply, must be valid through whole
|
||||
* lifetime of this power supply
|
||||
* @cfg: Run-time specific configuration accessed during registering,
|
||||
* may be NULL
|
||||
*
|
||||
* Return: A pointer to newly allocated power_supply on success
|
||||
* or ERR_PTR otherwise.
|
||||
* Use power_supply_unregister() on returned power_supply pointer to release
|
||||
* resources.
|
||||
*/
|
||||
struct power_supply *__must_check
|
||||
power_supply_register_no_ws(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg)
|
||||
{
|
||||
return __power_supply_register(parent, desc, cfg, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(power_supply_register_no_ws);
|
||||
|
||||
static void devm_power_supply_release(struct device *dev, void *res)
|
||||
{
|
||||
struct power_supply **psy = res;
|
||||
@ -1535,7 +1508,7 @@ devm_power_supply_register(struct device *parent,
|
||||
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
psy = __power_supply_register(parent, desc, cfg, true);
|
||||
psy = __power_supply_register(parent, desc, cfg);
|
||||
if (IS_ERR(psy)) {
|
||||
devres_free(ptr);
|
||||
} else {
|
||||
@ -1546,42 +1519,6 @@ devm_power_supply_register(struct device *parent,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_power_supply_register);
|
||||
|
||||
/**
|
||||
* devm_power_supply_register_no_ws() - Register managed non-waking-source power supply
|
||||
* @parent: Device to be a parent of power supply's device, usually
|
||||
* the device which probe function calls this
|
||||
* @desc: Description of power supply, must be valid through whole
|
||||
* lifetime of this power supply
|
||||
* @cfg: Run-time specific configuration accessed during registering,
|
||||
* may be NULL
|
||||
*
|
||||
* Return: A pointer to newly allocated power_supply on success
|
||||
* or ERR_PTR otherwise.
|
||||
* The returned power_supply pointer will be automatically unregistered
|
||||
* on driver detach.
|
||||
*/
|
||||
struct power_supply *__must_check
|
||||
devm_power_supply_register_no_ws(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg)
|
||||
{
|
||||
struct power_supply **ptr, *psy;
|
||||
|
||||
ptr = devres_alloc(devm_power_supply_release, sizeof(*ptr), GFP_KERNEL);
|
||||
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
psy = __power_supply_register(parent, desc, cfg, false);
|
||||
if (IS_ERR(psy)) {
|
||||
devres_free(ptr);
|
||||
} else {
|
||||
*ptr = psy;
|
||||
devres_add(parent, ptr);
|
||||
}
|
||||
return psy;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws);
|
||||
|
||||
/**
|
||||
* power_supply_unregister() - Remove this power supply from system
|
||||
* @psy: Pointer to power supply to unregister
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/slab.h>
|
||||
#include "power_supply.h"
|
||||
|
||||
struct power_supply_hwmon {
|
||||
struct power_supply *psy;
|
||||
|
@ -142,7 +142,7 @@ static const char * const POWER_SUPPLY_CHARGE_BEHAVIOUR_TEXT[] = {
|
||||
[POWER_SUPPLY_CHARGE_BEHAVIOUR_FORCE_DISCHARGE] = "force-discharge",
|
||||
};
|
||||
|
||||
static struct power_supply_attr power_supply_attrs[] = {
|
||||
static struct power_supply_attr power_supply_attrs[] __ro_after_init = {
|
||||
/* Properties of type `int' */
|
||||
POWER_SUPPLY_ENUM_ATTR(STATUS),
|
||||
POWER_SUPPLY_ENUM_ATTR(CHARGE_TYPE),
|
||||
@ -225,9 +225,9 @@ static struct power_supply_attr power_supply_attrs[] = {
|
||||
#define POWER_SUPPLY_ATTR_CNT ARRAY_SIZE(power_supply_attrs)
|
||||
|
||||
static struct attribute *
|
||||
__power_supply_attrs[POWER_SUPPLY_ATTR_CNT + 1];
|
||||
__power_supply_attrs[POWER_SUPPLY_ATTR_CNT + 1] __ro_after_init;
|
||||
|
||||
static struct power_supply_attr *to_ps_attr(struct device_attribute *attr)
|
||||
static const struct power_supply_attr *to_ps_attr(struct device_attribute *attr)
|
||||
{
|
||||
return container_of(attr, struct power_supply_attr, dev_attr);
|
||||
}
|
||||
@ -273,7 +273,7 @@ static ssize_t power_supply_show_property(struct device *dev,
|
||||
char *buf) {
|
||||
ssize_t ret;
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct power_supply_attr *ps_attr = to_ps_attr(attr);
|
||||
const struct power_supply_attr *ps_attr = to_ps_attr(attr);
|
||||
enum power_supply_property psp = dev_attr_psp(attr);
|
||||
union power_supply_propval value;
|
||||
|
||||
@ -326,7 +326,7 @@ static ssize_t power_supply_store_property(struct device *dev,
|
||||
const char *buf, size_t count) {
|
||||
ssize_t ret;
|
||||
struct power_supply *psy = dev_get_drvdata(dev);
|
||||
struct power_supply_attr *ps_attr = to_ps_attr(attr);
|
||||
const struct power_supply_attr *ps_attr = to_ps_attr(attr);
|
||||
enum power_supply_property psp = dev_attr_psp(attr);
|
||||
union power_supply_propval value;
|
||||
|
||||
@ -401,7 +401,7 @@ const struct attribute_group *power_supply_attr_groups[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
void power_supply_init_attrs(void)
|
||||
void __init power_supply_init_attrs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -151,7 +151,7 @@ struct qcom_battmgr_message {
|
||||
__le32 capacity_low;
|
||||
__le32 capacity_warning;
|
||||
__le32 cycle_count;
|
||||
/* thousandth of persent */
|
||||
/* thousandth of percent */
|
||||
__le32 accuracy;
|
||||
__le32 max_sample_time_ms;
|
||||
__le32 min_sample_time_ms;
|
||||
|
@ -832,7 +832,7 @@ static const struct smb2_register smb2_init_seq[] = {
|
||||
AUTO_RECHG_BIT | EN_ANALOG_DROP_IN_VBATT_BIT |
|
||||
CHARGER_INHIBIT_BIT,
|
||||
.val = CHARGER_INHIBIT_BIT },
|
||||
/* STAT pin software override, match downstream. Parallell charging? */
|
||||
/* STAT pin software override, match downstream. Parallel charging? */
|
||||
{ .addr = STAT_CFG,
|
||||
.mask = STAT_SW_OVERRIDE_CFG_BIT,
|
||||
.val = STAT_SW_OVERRIDE_CFG_BIT },
|
||||
|
@ -1017,10 +1017,10 @@ static const struct of_device_id smbb_charger_id_table[] = {
|
||||
MODULE_DEVICE_TABLE(of, smbb_charger_id_table);
|
||||
|
||||
static struct platform_driver smbb_charger_driver = {
|
||||
.probe = smbb_charger_probe,
|
||||
.remove_new = smbb_charger_remove,
|
||||
.driver = {
|
||||
.name = "qcom-smbb",
|
||||
.probe = smbb_charger_probe,
|
||||
.remove = smbb_charger_remove,
|
||||
.driver = {
|
||||
.name = "qcom-smbb",
|
||||
.of_match_table = smbb_charger_id_table,
|
||||
},
|
||||
};
|
||||
|
@ -240,9 +240,32 @@ static int rk817_record_battery_nvram_values(struct rk817_charger *charger)
|
||||
static int rk817_bat_calib_cap(struct rk817_charger *charger)
|
||||
{
|
||||
struct rk808 *rk808 = charger->rk808;
|
||||
int tmp, charge_now, charge_now_adc, volt_avg;
|
||||
int charge_now, charge_now_adc;
|
||||
u8 bulk_reg[4];
|
||||
|
||||
/* Don't do anything if there's no battery. */
|
||||
if (!charger->battery_present)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* When resuming from suspend, sometimes the voltage value would be
|
||||
* incorrect. BSP would simply wait two seconds and try reading the
|
||||
* values again. Do not do any sort of calibration activity when the
|
||||
* reported value is incorrect. The next scheduled update of battery
|
||||
* vaules should then return valid data and the driver can continue.
|
||||
* Use 2.7v as the sanity value because per the datasheet the PMIC
|
||||
* can in no way support a battery voltage lower than this. BSP only
|
||||
* checked for values too low, but I'm adding in a check for values
|
||||
* too high just in case; again the PMIC can in no way support
|
||||
* voltages above 4.45v, so this seems like a good value.
|
||||
*/
|
||||
if ((charger->volt_avg_uv < 2700000) || (charger->volt_avg_uv > 4450000)) {
|
||||
dev_dbg(charger->dev,
|
||||
"Battery voltage of %d is invalid, ignoring.\n",
|
||||
charger->volt_avg_uv);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Calibrate the soc and fcc on a fully charged battery */
|
||||
|
||||
if (charger->charge_status == CHARGE_FINISH && (!charger->soc_cal)) {
|
||||
@ -304,51 +327,6 @@ static int rk817_bat_calib_cap(struct rk817_charger *charger)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Calibrate the fully charged capacity when we previously had a full
|
||||
* battery (soc_cal = 1) and are now empty (at or below minimum design
|
||||
* voltage). If our columb counter is still positive, subtract that
|
||||
* from our fcc value to get a calibrated fcc, and if our columb
|
||||
* counter is negative add that to our fcc (but not to exceed our
|
||||
* design capacity).
|
||||
*/
|
||||
regmap_bulk_read(charger->rk808->regmap, RK817_GAS_GAUGE_BAT_VOL_H,
|
||||
bulk_reg, 2);
|
||||
tmp = get_unaligned_be16(bulk_reg);
|
||||
volt_avg = (charger->voltage_k * tmp) + 1000 * charger->voltage_b;
|
||||
if (volt_avg <= charger->bat_voltage_min_design_uv &&
|
||||
charger->soc_cal) {
|
||||
regmap_bulk_read(rk808->regmap, RK817_GAS_GAUGE_Q_PRES_H3,
|
||||
bulk_reg, 4);
|
||||
charge_now_adc = get_unaligned_be32(bulk_reg);
|
||||
charge_now = ADC_TO_CHARGE_UAH(charge_now_adc,
|
||||
charger->res_div);
|
||||
/*
|
||||
* Note, if charge_now is negative this will add it (what we
|
||||
* want) and if it's positive this will subtract (also what
|
||||
* we want).
|
||||
*/
|
||||
charger->fcc_mah = charger->fcc_mah - (charge_now / 1000);
|
||||
|
||||
dev_dbg(charger->dev,
|
||||
"Recalibrating full charge capacity to %d uah\n",
|
||||
charger->fcc_mah * 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the SOC to 0 if we are below the minimum system voltage.
|
||||
*/
|
||||
if (volt_avg <= charger->bat_voltage_min_design_uv) {
|
||||
charger->soc = 0;
|
||||
charge_now_adc = CHARGE_TO_ADC(0, charger->res_div);
|
||||
put_unaligned_be32(charge_now_adc, bulk_reg);
|
||||
regmap_bulk_write(rk808->regmap,
|
||||
RK817_GAS_GAUGE_Q_INIT_H3, bulk_reg, 4);
|
||||
dev_warn(charger->dev,
|
||||
"Battery voltage %d below minimum voltage %d\n",
|
||||
volt_avg, charger->bat_voltage_min_design_uv);
|
||||
}
|
||||
|
||||
rk817_record_battery_nvram_values(charger);
|
||||
|
||||
return 0;
|
||||
@ -648,6 +626,24 @@ static irqreturn_t rk817_plug_out_isr(int irq, void *cg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rk817_bat_set_prop(struct power_supply *ps,
|
||||
enum power_supply_property prop,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct rk817_charger *charger = power_supply_get_drvdata(ps);
|
||||
|
||||
switch (prop) {
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
||||
if ((val->intval < 500000) ||
|
||||
(val->intval > charger->bat_charge_full_design_uah))
|
||||
return -EINVAL;
|
||||
charger->fcc_mah = val->intval / 1000;
|
||||
return rk817_bat_calib_cap(charger);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static enum power_supply_property rk817_bat_props[] = {
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
@ -673,12 +669,25 @@ static enum power_supply_property rk817_chg_props[] = {
|
||||
POWER_SUPPLY_PROP_VOLTAGE_AVG,
|
||||
};
|
||||
|
||||
static int rk817_bat_prop_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CHARGE_FULL:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct power_supply_desc rk817_bat_desc = {
|
||||
.name = "rk817-battery",
|
||||
.type = POWER_SUPPLY_TYPE_BATTERY,
|
||||
.properties = rk817_bat_props,
|
||||
.property_is_writeable = rk817_bat_prop_writeable,
|
||||
.num_properties = ARRAY_SIZE(rk817_bat_props),
|
||||
.get_property = rk817_bat_get_prop,
|
||||
.set_property = rk817_bat_set_prop,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc rk817_chg_desc = {
|
||||
@ -1202,6 +1211,15 @@ static int rk817_charger_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rk817_suspend(struct device *dev)
|
||||
{
|
||||
struct rk817_charger *charger = dev_get_drvdata(dev);
|
||||
|
||||
cancel_delayed_work_sync(&charger->work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rk817_resume(struct device *dev)
|
||||
{
|
||||
|
||||
@ -1213,7 +1231,7 @@ static int __maybe_unused rk817_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rk817_charger_pm, NULL, rk817_resume);
|
||||
static SIMPLE_DEV_PM_OPS(rk817_charger_pm, rk817_suspend, rk817_resume);
|
||||
|
||||
static struct platform_driver rk817_charger_driver = {
|
||||
.probe = rk817_charger_probe,
|
||||
|
@ -139,6 +139,19 @@ enum {
|
||||
RT9471_PORTSTAT_DCP,
|
||||
};
|
||||
|
||||
enum {
|
||||
RT9471_ICSTAT_SLEEP = 0,
|
||||
RT9471_ICSTAT_VBUSRDY,
|
||||
RT9471_ICSTAT_TRICKLECHG,
|
||||
RT9471_ICSTAT_PRECHG,
|
||||
RT9471_ICSTAT_FASTCHG,
|
||||
RT9471_ICSTAT_IEOC,
|
||||
RT9471_ICSTAT_BGCHG,
|
||||
RT9471_ICSTAT_CHGDONE,
|
||||
RT9471_ICSTAT_CHGFAULT,
|
||||
RT9471_ICSTAT_OTG = 15,
|
||||
};
|
||||
|
||||
struct rt9471_chip {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
@ -153,8 +166,8 @@ struct rt9471_chip {
|
||||
};
|
||||
|
||||
static const struct reg_field rt9471_reg_fields[F_MAX_FIELDS] = {
|
||||
[F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 0),
|
||||
[F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 1, 1),
|
||||
[F_WDT] = REG_FIELD(RT9471_REG_TOP, 0, 1),
|
||||
[F_WDT_RST] = REG_FIELD(RT9471_REG_TOP, 2, 2),
|
||||
[F_CHG_EN] = REG_FIELD(RT9471_REG_FUNC, 0, 0),
|
||||
[F_HZ] = REG_FIELD(RT9471_REG_FUNC, 5, 5),
|
||||
[F_BATFET_DIS] = REG_FIELD(RT9471_REG_FUNC, 7, 7),
|
||||
@ -255,31 +268,32 @@ static int rt9471_get_ieoc(struct rt9471_chip *chip, int *microamp)
|
||||
|
||||
static int rt9471_get_status(struct rt9471_chip *chip, int *status)
|
||||
{
|
||||
unsigned int chg_ready, chg_done, fault_stat;
|
||||
unsigned int ic_stat;
|
||||
int ret;
|
||||
|
||||
ret = regmap_field_read(chip->rm_fields[F_ST_CHG_RDY], &chg_ready);
|
||||
ret = regmap_field_read(chip->rm_fields[F_IC_STAT], &ic_stat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_field_read(chip->rm_fields[F_ST_CHG_DONE], &chg_done);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(chip->regmap, RT9471_REG_STAT1, &fault_stat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fault_stat &= RT9471_CHGFAULT_MASK;
|
||||
|
||||
if (chg_ready && chg_done)
|
||||
*status = POWER_SUPPLY_STATUS_FULL;
|
||||
else if (chg_ready && fault_stat)
|
||||
switch (ic_stat) {
|
||||
case RT9471_ICSTAT_VBUSRDY:
|
||||
case RT9471_ICSTAT_CHGFAULT:
|
||||
*status = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
else if (chg_ready && !fault_stat)
|
||||
break;
|
||||
case RT9471_ICSTAT_TRICKLECHG ... RT9471_ICSTAT_BGCHG:
|
||||
*status = POWER_SUPPLY_STATUS_CHARGING;
|
||||
else
|
||||
break;
|
||||
case RT9471_ICSTAT_CHGDONE:
|
||||
*status = POWER_SUPPLY_STATUS_FULL;
|
||||
break;
|
||||
case RT9471_ICSTAT_SLEEP:
|
||||
case RT9471_ICSTAT_OTG:
|
||||
*status = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
break;
|
||||
default:
|
||||
*status = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -431,7 +431,7 @@ static const struct power_supply_vbat_ri_table samsung_vbat2res_charging_eb58515
|
||||
* temperature compensation tables so we just state 100% for every temperature.
|
||||
* If you have the datasheets, please provide these tables.
|
||||
*/
|
||||
static struct power_supply_resistance_temp_table samsung_temp2res[] = {
|
||||
static const struct power_supply_resistance_temp_table samsung_temp2res[] = {
|
||||
{ .temp = 50, .resistance = 100 },
|
||||
{ .temp = 40, .resistance = 100 },
|
||||
{ .temp = 30, .resistance = 100 },
|
||||
@ -447,7 +447,7 @@ static struct power_supply_resistance_temp_table samsung_temp2res[] = {
|
||||
* These must be sorted by falling OCV value.
|
||||
*/
|
||||
|
||||
static struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = {
|
||||
static const struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = {
|
||||
{ .ocv = 4330000, .capacity = 100},
|
||||
{ .ocv = 4320000, .capacity = 99},
|
||||
{ .ocv = 4283000, .capacity = 95},
|
||||
@ -499,7 +499,7 @@ static struct power_supply_battery_ocv_table samsung_ocv_cap_eb485159lu[] = {
|
||||
};
|
||||
|
||||
/* Same capacity table is used by eb-l1m7flu, eb425161la, eb425161lu */
|
||||
static struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = {
|
||||
static const struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = {
|
||||
{ .ocv = 4328000, .capacity = 100},
|
||||
{ .ocv = 4299000, .capacity = 99},
|
||||
{ .ocv = 4281000, .capacity = 98},
|
||||
@ -540,7 +540,7 @@ static struct power_supply_battery_ocv_table samsung_ocv_cap_1500mah[] = {
|
||||
{ .ocv = 3300000, .capacity = 0},
|
||||
};
|
||||
|
||||
static struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = {
|
||||
static const struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = {
|
||||
{ .ocv = 4178000, .capacity = 100},
|
||||
{ .ocv = 4148000, .capacity = 99},
|
||||
{ .ocv = 4105000, .capacity = 95},
|
||||
@ -572,7 +572,7 @@ static struct power_supply_battery_ocv_table samsung_ocv_cap_eb535151vu[] = {
|
||||
{ .ocv = 3300000, .capacity = 0},
|
||||
};
|
||||
|
||||
static struct power_supply_battery_ocv_table samsung_ocv_cap_eb585157lu[] = {
|
||||
static const struct power_supply_battery_ocv_table samsung_ocv_cap_eb585157lu[] = {
|
||||
{ .ocv = 4320000, .capacity = 100},
|
||||
{ .ocv = 4296000, .capacity = 99},
|
||||
{ .ocv = 4283000, .capacity = 98},
|
||||
|
@ -530,7 +530,7 @@ static struct platform_driver sc2731_charger_driver = {
|
||||
.of_match_table = sc2731_charger_of_match,
|
||||
},
|
||||
.probe = sc2731_charger_probe,
|
||||
.remove_new = sc2731_charger_remove,
|
||||
.remove = sc2731_charger_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(sc2731_charger_driver);
|
||||
|
@ -992,7 +992,7 @@ static int sc27xx_fgu_calibration(struct sc27xx_fgu_data *data)
|
||||
static int sc27xx_fgu_hw_init(struct sc27xx_fgu_data *data)
|
||||
{
|
||||
struct power_supply_battery_info *info;
|
||||
struct power_supply_battery_ocv_table *table;
|
||||
const struct power_supply_battery_ocv_table *table;
|
||||
int ret, delta_clbcnt, alarm_adc;
|
||||
|
||||
ret = power_supply_get_battery_info(data->battery, &info);
|
||||
@ -1183,10 +1183,14 @@ static int sc27xx_fgu_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(data->charge_chan);
|
||||
}
|
||||
|
||||
data->gpiod = devm_gpiod_get(dev, "bat-detect", GPIOD_IN);
|
||||
data->gpiod = devm_gpiod_get(dev, "battery-detect", GPIOD_IN);
|
||||
if (IS_ERR(data->gpiod)) {
|
||||
dev_err(dev, "failed to get battery detection GPIO\n");
|
||||
return PTR_ERR(data->gpiod);
|
||||
data->gpiod = devm_gpiod_get(dev, "bat-detect", GPIOD_IN);
|
||||
if (IS_ERR(data->gpiod)) {
|
||||
dev_err(dev, "failed to get battery detection GPIO\n");
|
||||
return PTR_ERR(data->gpiod);
|
||||
}
|
||||
dev_warn(dev, "bat-detect is deprecated, please use battery-detect\n");
|
||||
}
|
||||
|
||||
ret = gpiod_get_value_cansleep(data->gpiod);
|
||||
|
@ -343,7 +343,7 @@ static struct platform_driver tps65090_charger_driver = {
|
||||
.of_match_table = of_tps65090_charger_match,
|
||||
},
|
||||
.probe = tps65090_charger_probe,
|
||||
.remove_new = tps65090_charger_remove,
|
||||
.remove = tps65090_charger_remove,
|
||||
};
|
||||
module_platform_driver(tps65090_charger_driver);
|
||||
|
||||
|
@ -269,7 +269,7 @@ MODULE_DEVICE_TABLE(of, tps65217_charger_match_table);
|
||||
|
||||
static struct platform_driver tps65217_charger_driver = {
|
||||
.probe = tps65217_charger_probe,
|
||||
.remove_new = tps65217_charger_remove,
|
||||
.remove = tps65217_charger_remove,
|
||||
.driver = {
|
||||
.name = "tps65217-charger",
|
||||
.of_match_table = of_match_ptr(tps65217_charger_match_table),
|
||||
|
@ -1133,7 +1133,7 @@ MODULE_DEVICE_TABLE(of, twl_bci_of_match);
|
||||
|
||||
static struct platform_driver twl4030_bci_driver = {
|
||||
.probe = twl4030_bci_probe,
|
||||
.remove_new = twl4030_bci_remove,
|
||||
.remove = twl4030_bci_remove,
|
||||
.driver = {
|
||||
.name = "twl4030_bci",
|
||||
.of_match_table = of_match_ptr(twl_bci_of_match),
|
||||
|
581
drivers/power/supply/twl6030_charger.c
Normal file
581
drivers/power/supply/twl6030_charger.c
Normal file
@ -0,0 +1,581 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* TWL6030 charger
|
||||
*
|
||||
* Copyright (C) 2024 Andreas Kemnade <andreas@kemnade.info>
|
||||
*
|
||||
* based on older 6030 driver found in a v3.0 vendor kernel
|
||||
*
|
||||
* based on twl4030_bci_battery.c by TI
|
||||
* Copyright (C) 2008 Texas Instruments, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/twl.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
#include <linux/devm-helpers.h>
|
||||
|
||||
#define CONTROLLER_INT_MASK 0x00
|
||||
#define CONTROLLER_CTRL1 0x01
|
||||
#define CONTROLLER_WDG 0x02
|
||||
#define CONTROLLER_STAT1 0x03
|
||||
#define CHARGERUSB_INT_STATUS 0x04
|
||||
#define CHARGERUSB_INT_MASK 0x05
|
||||
#define CHARGERUSB_STATUS_INT1 0x06
|
||||
#define CHARGERUSB_STATUS_INT2 0x07
|
||||
#define CHARGERUSB_CTRL1 0x08
|
||||
#define CHARGERUSB_CTRL2 0x09
|
||||
#define CHARGERUSB_CTRL3 0x0A
|
||||
#define CHARGERUSB_STAT1 0x0B
|
||||
#define CHARGERUSB_VOREG 0x0C
|
||||
#define CHARGERUSB_VICHRG 0x0D
|
||||
#define CHARGERUSB_CINLIMIT 0x0E
|
||||
#define CHARGERUSB_CTRLLIMIT1 0x0F
|
||||
#define CHARGERUSB_CTRLLIMIT2 0x10
|
||||
#define ANTICOLLAPSE_CTRL1 0x11
|
||||
#define ANTICOLLAPSE_CTRL2 0x12
|
||||
|
||||
/* TWL6032 registers 0xDA to 0xDE - TWL6032_MODULE_CHARGER */
|
||||
#define CONTROLLER_CTRL2 0x00
|
||||
#define CONTROLLER_VSEL_COMP 0x01
|
||||
#define CHARGERUSB_VSYSREG 0x02
|
||||
#define CHARGERUSB_VICHRG_PC 0x03
|
||||
#define LINEAR_CHRG_STS 0x04
|
||||
|
||||
#define LINEAR_CHRG_STS_CRYSTL_OSC_OK 0x40
|
||||
#define LINEAR_CHRG_STS_END_OF_CHARGE 0x20
|
||||
#define LINEAR_CHRG_STS_VBATOV 0x10
|
||||
#define LINEAR_CHRG_STS_VSYSOV 0x08
|
||||
#define LINEAR_CHRG_STS_DPPM_STS 0x04
|
||||
#define LINEAR_CHRG_STS_CV_STS 0x02
|
||||
#define LINEAR_CHRG_STS_CC_STS 0x01
|
||||
|
||||
#define FG_REG_00 0x00
|
||||
#define FG_REG_01 0x01
|
||||
#define FG_REG_02 0x02
|
||||
#define FG_REG_03 0x03
|
||||
#define FG_REG_04 0x04
|
||||
#define FG_REG_05 0x05
|
||||
#define FG_REG_06 0x06
|
||||
#define FG_REG_07 0x07
|
||||
#define FG_REG_08 0x08
|
||||
#define FG_REG_09 0x09
|
||||
#define FG_REG_10 0x0A
|
||||
#define FG_REG_11 0x0B
|
||||
|
||||
/* CONTROLLER_INT_MASK */
|
||||
#define MVAC_FAULT BIT(7)
|
||||
#define MAC_EOC BIT(6)
|
||||
#define LINCH_GATED BIT(5)
|
||||
#define MBAT_REMOVED BIT(4)
|
||||
#define MFAULT_WDG BIT(3)
|
||||
#define MBAT_TEMP BIT(2)
|
||||
#define MVBUS_DET BIT(1)
|
||||
#define MVAC_DET BIT(0)
|
||||
|
||||
/* CONTROLLER_CTRL1 */
|
||||
#define CONTROLLER_CTRL1_EN_LINCH BIT(5)
|
||||
#define CONTROLLER_CTRL1_EN_CHARGER BIT(4)
|
||||
#define CONTROLLER_CTRL1_SEL_CHARGER BIT(3)
|
||||
|
||||
/* CONTROLLER_STAT1 */
|
||||
#define CONTROLLER_STAT1_EXTCHRG_STATZ BIT(7)
|
||||
#define CONTROLLER_STAT1_LINCH_GATED BIT(6)
|
||||
#define CONTROLLER_STAT1_CHRG_DET_N BIT(5)
|
||||
#define CONTROLLER_STAT1_FAULT_WDG BIT(4)
|
||||
#define CONTROLLER_STAT1_VAC_DET BIT(3)
|
||||
#define VAC_DET BIT(3)
|
||||
#define CONTROLLER_STAT1_VBUS_DET BIT(2)
|
||||
#define VBUS_DET BIT(2)
|
||||
#define CONTROLLER_STAT1_BAT_REMOVED BIT(1)
|
||||
#define CONTROLLER_STAT1_BAT_TEMP_OVRANGE BIT(0)
|
||||
|
||||
/* CHARGERUSB_INT_STATUS */
|
||||
#define EN_LINCH BIT(4)
|
||||
#define CURRENT_TERM_INT BIT(3)
|
||||
#define CHARGERUSB_STAT BIT(2)
|
||||
#define CHARGERUSB_THMREG BIT(1)
|
||||
#define CHARGERUSB_FAULT BIT(0)
|
||||
|
||||
/* CHARGERUSB_INT_MASK */
|
||||
#define MASK_MCURRENT_TERM BIT(3)
|
||||
#define MASK_MCHARGERUSB_STAT BIT(2)
|
||||
#define MASK_MCHARGERUSB_THMREG BIT(1)
|
||||
#define MASK_MCHARGERUSB_FAULT BIT(0)
|
||||
|
||||
/* CHARGERUSB_STATUS_INT1 */
|
||||
#define CHARGERUSB_STATUS_INT1_TMREG BIT(7)
|
||||
#define CHARGERUSB_STATUS_INT1_NO_BAT BIT(6)
|
||||
#define CHARGERUSB_STATUS_INT1_BST_OCP BIT(5)
|
||||
#define CHARGERUSB_STATUS_INT1_TH_SHUTD BIT(4)
|
||||
#define CHARGERUSB_STATUS_INT1_BAT_OVP BIT(3)
|
||||
#define CHARGERUSB_STATUS_INT1_POOR_SRC BIT(2)
|
||||
#define CHARGERUSB_STATUS_INT1_SLP_MODE BIT(1)
|
||||
#define CHARGERUSB_STATUS_INT1_VBUS_OVP BIT(0)
|
||||
|
||||
/* CHARGERUSB_STATUS_INT2 */
|
||||
#define ICCLOOP BIT(3)
|
||||
#define CURRENT_TERM BIT(2)
|
||||
#define CHARGE_DONE BIT(1)
|
||||
#define ANTICOLLAPSE BIT(0)
|
||||
|
||||
/* CHARGERUSB_CTRL1 */
|
||||
#define SUSPEND_BOOT BIT(7)
|
||||
#define OPA_MODE BIT(6)
|
||||
#define HZ_MODE BIT(5)
|
||||
#define TERM BIT(4)
|
||||
|
||||
/* CHARGERUSB_CTRL2 */
|
||||
#define UA_TO_VITERM(x) (((x) / 50000 - 1) << 5)
|
||||
|
||||
/* CHARGERUSB_CTRL3 */
|
||||
#define VBUSCHRG_LDO_OVRD BIT(7)
|
||||
#define CHARGE_ONCE BIT(6)
|
||||
#define BST_HW_PR_DIS BIT(5)
|
||||
#define AUTOSUPPLY BIT(3)
|
||||
#define BUCK_HSILIM BIT(0)
|
||||
|
||||
/* CHARGERUSB_VOREG */
|
||||
#define UV_TO_VOREG(x) (((x) - 3500000) / 20000)
|
||||
#define VOREG_TO_UV(x) (((x) & 0x3F) * 20000 + 3500000)
|
||||
#define CHARGERUSB_VOREG_3P52 0x01
|
||||
#define CHARGERUSB_VOREG_4P0 0x19
|
||||
#define CHARGERUSB_VOREG_4P2 0x23
|
||||
#define CHARGERUSB_VOREG_4P76 0x3F
|
||||
|
||||
/* CHARGERUSB_VICHRG */
|
||||
/*
|
||||
* might be inaccurate for < 500 mA, diffent scale might apply,
|
||||
* either starting from 100 mA or 300 mA
|
||||
*/
|
||||
#define UA_TO_VICHRG(x) (((x) / 100000) - 1)
|
||||
#define VICHRG_TO_UA(x) (((x) & 0xf) * 100000 + 100000)
|
||||
|
||||
/* CHARGERUSB_CINLIMIT */
|
||||
#define CHARGERUSB_CIN_LIMIT_100 0x1
|
||||
#define CHARGERUSB_CIN_LIMIT_300 0x5
|
||||
#define CHARGERUSB_CIN_LIMIT_500 0x9
|
||||
#define CHARGERUSB_CIN_LIMIT_NONE 0xF
|
||||
|
||||
/* CHARGERUSB_CTRLLIMIT2 */
|
||||
#define CHARGERUSB_CTRLLIMIT2_1500 0x0E
|
||||
#define LOCK_LIMIT BIT(4)
|
||||
|
||||
/* ANTICOLLAPSE_CTRL2 */
|
||||
#define BUCK_VTH_SHIFT 5
|
||||
|
||||
/* FG_REG_00 */
|
||||
#define CC_ACTIVE_MODE_SHIFT 6
|
||||
#define CC_AUTOCLEAR BIT(2)
|
||||
#define CC_CAL_EN BIT(1)
|
||||
#define CC_PAUSE BIT(0)
|
||||
|
||||
#define REG_TOGGLE1 0x90
|
||||
#define REG_PWDNSTATUS1 0x93
|
||||
#define FGDITHS BIT(7)
|
||||
#define FGDITHR BIT(6)
|
||||
#define FGS BIT(5)
|
||||
#define FGR BIT(4)
|
||||
#define BBSPOR_CFG 0xE6
|
||||
#define BB_CHG_EN BIT(3)
|
||||
|
||||
struct twl6030_charger_info {
|
||||
struct device *dev;
|
||||
struct power_supply *usb;
|
||||
struct power_supply_battery_info *binfo;
|
||||
struct work_struct work;
|
||||
int irq_chg;
|
||||
int input_current_limit;
|
||||
struct iio_channel *channel_vusb;
|
||||
struct delayed_work charger_monitor;
|
||||
bool extended_current_range;
|
||||
};
|
||||
|
||||
struct twl6030_charger_chip_data {
|
||||
bool extended_current_range;
|
||||
};
|
||||
|
||||
static int twl6030_charger_read(u8 reg, u8 *val)
|
||||
{
|
||||
return twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
|
||||
}
|
||||
|
||||
static int twl6030_charger_write(u8 reg, u8 val)
|
||||
{
|
||||
return twl_i2c_write_u8(TWL_MODULE_MAIN_CHARGE, val, reg);
|
||||
}
|
||||
|
||||
static int twl6030_config_cinlimit_reg(struct twl6030_charger_info *charger,
|
||||
unsigned int ua)
|
||||
{
|
||||
if (ua >= 50000 && ua <= 750000) {
|
||||
ua = (ua - 50000) / 50000;
|
||||
} else if ((ua > 750000) && (ua <= 1500000) && charger->extended_current_range) {
|
||||
ua = ((ua % 100000) ? 0x30 : 0x20) + ((ua - 100000) / 100000);
|
||||
} else {
|
||||
if (ua < 50000) {
|
||||
dev_err(charger->dev, "invalid input current limit\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* This is no current limit */
|
||||
ua = 0x0F;
|
||||
}
|
||||
|
||||
return twl6030_charger_write(CHARGERUSB_CINLIMIT, ua);
|
||||
}
|
||||
|
||||
/*
|
||||
* rewriting all stuff here, resets to extremely conservative defaults were
|
||||
* seen under some circumstances, like charge voltage to 3.5V
|
||||
*/
|
||||
static int twl6030_enable_usb(struct twl6030_charger_info *charger)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = twl6030_charger_write(CHARGERUSB_VICHRG,
|
||||
UA_TO_VICHRG(charger->binfo->constant_charge_current_max_ua));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = twl6030_charger_write(CONTROLLER_WDG, 0xff);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
charger->input_current_limit = 500000;
|
||||
ret = twl6030_config_cinlimit_reg(charger, charger->input_current_limit);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = twl6030_charger_write(CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_500);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = twl6030_charger_write(CHARGERUSB_VOREG,
|
||||
UV_TO_VOREG(charger->binfo->constant_charge_voltage_max_uv));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = twl6030_charger_write(CHARGERUSB_CTRL1, TERM);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (charger->binfo->charge_term_current_ua != -EINVAL) {
|
||||
ret = twl6030_charger_write(CHARGERUSB_CTRL2,
|
||||
UA_TO_VITERM(charger->binfo->charge_term_current_ua));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return twl6030_charger_write(CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER);
|
||||
}
|
||||
|
||||
static void twl6030_charger_wdg(struct work_struct *data)
|
||||
{
|
||||
struct twl6030_charger_info *charger =
|
||||
container_of(data, struct twl6030_charger_info,
|
||||
charger_monitor.work);
|
||||
|
||||
u8 val;
|
||||
u8 int_stat;
|
||||
u8 stat_int1;
|
||||
u8 stat_int2;
|
||||
|
||||
twl6030_charger_read(CONTROLLER_STAT1, &val);
|
||||
twl6030_charger_read(CHARGERUSB_INT_STATUS, &int_stat);
|
||||
twl6030_charger_read(CHARGERUSB_STATUS_INT1, &stat_int1);
|
||||
twl6030_charger_read(CHARGERUSB_STATUS_INT2, &stat_int2);
|
||||
dev_dbg(charger->dev,
|
||||
"wdg: stat1: %02x %s INT_STATUS %02x STATUS_INT1 %02x STATUS_INT2 %02x\n",
|
||||
val, (val & VBUS_DET) ? "usb online" : "usb offline",
|
||||
int_stat, stat_int1, stat_int2);
|
||||
|
||||
twl6030_charger_write(CONTROLLER_WDG, 0xff);
|
||||
schedule_delayed_work(&charger->charger_monitor,
|
||||
msecs_to_jiffies(10000));
|
||||
}
|
||||
|
||||
static irqreturn_t twl6030_charger_interrupt(int irq, void *arg)
|
||||
{
|
||||
struct twl6030_charger_info *charger = arg;
|
||||
u8 val;
|
||||
u8 int_stat;
|
||||
u8 stat_int1;
|
||||
u8 stat_int2;
|
||||
|
||||
if (twl6030_charger_read(CONTROLLER_STAT1, &val) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (twl6030_charger_read(CHARGERUSB_INT_STATUS, &int_stat) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (twl6030_charger_read(CHARGERUSB_STATUS_INT1, &stat_int1) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (twl6030_charger_read(CHARGERUSB_STATUS_INT2, &stat_int2) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
dev_dbg(charger->dev,
|
||||
"charger irq: stat1: %02x %s INT_STATUS %02x STATUS_INT1 %02x STATUS_INT2 %02x\n",
|
||||
val, (val & VBUS_DET) ? "usb online" : "usb offline",
|
||||
int_stat, stat_int1, stat_int2);
|
||||
power_supply_changed(charger->usb);
|
||||
|
||||
if (val & VBUS_DET) {
|
||||
if (twl6030_charger_read(CONTROLLER_CTRL1, &val) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (!(val & CONTROLLER_CTRL1_EN_CHARGER)) {
|
||||
if (twl6030_enable_usb(charger) < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
schedule_delayed_work(&charger->charger_monitor,
|
||||
msecs_to_jiffies(10000));
|
||||
}
|
||||
} else {
|
||||
cancel_delayed_work(&charger->charger_monitor);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int twl6030_charger_usb_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct twl6030_charger_info *charger = power_supply_get_drvdata(psy);
|
||||
int ret;
|
||||
u8 stat1;
|
||||
u8 intstat;
|
||||
|
||||
ret = twl6030_charger_read(CONTROLLER_STAT1, &stat1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
if (!(stat1 & VBUS_DET)) {
|
||||
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
break;
|
||||
}
|
||||
ret = twl6030_charger_read(CHARGERUSB_STATUS_INT2, &intstat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (intstat & CHARGE_DONE)
|
||||
val->intval = POWER_SUPPLY_STATUS_FULL;
|
||||
else if (intstat & CURRENT_TERM)
|
||||
val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
else
|
||||
val->intval = POWER_SUPPLY_STATUS_CHARGING;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
if (!charger->channel_vusb)
|
||||
return -ENODATA;
|
||||
|
||||
ret = iio_read_channel_processed_scale(charger->channel_vusb, &val->intval, 1000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = !!(stat1 & VBUS_DET);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
val->intval = charger->input_current_limit;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twl6030_charger_usb_set_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct twl6030_charger_info *charger = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
charger->input_current_limit = val->intval;
|
||||
return twl6030_config_cinlimit_reg(charger, charger->input_current_limit);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int twl6030_charger_usb_property_is_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp)
|
||||
{
|
||||
dev_info(&psy->dev, "is %d writeable?\n", (int)psp);
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static enum power_supply_property twl6030_charger_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc twl6030_charger_usb_desc = {
|
||||
.name = "twl6030_usb",
|
||||
.type = POWER_SUPPLY_TYPE_USB,
|
||||
.properties = twl6030_charger_props,
|
||||
.num_properties = ARRAY_SIZE(twl6030_charger_props),
|
||||
.get_property = twl6030_charger_usb_get_property,
|
||||
.set_property = twl6030_charger_usb_set_property,
|
||||
.property_is_writeable = twl6030_charger_usb_property_is_writeable,
|
||||
};
|
||||
|
||||
static int twl6030_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct twl6030_charger_info *charger;
|
||||
const struct twl6030_charger_chip_data *chip_data;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
int ret;
|
||||
u8 val;
|
||||
|
||||
charger = devm_kzalloc(&pdev->dev, sizeof(*charger), GFP_KERNEL);
|
||||
if (!charger)
|
||||
return -ENOMEM;
|
||||
|
||||
charger->dev = &pdev->dev;
|
||||
charger->irq_chg = platform_get_irq(pdev, 0);
|
||||
|
||||
chip_data = device_get_match_data(&pdev->dev);
|
||||
if (!chip_data)
|
||||
return dev_err_probe(&pdev->dev, -EINVAL, "missing chip data\n");
|
||||
|
||||
charger->extended_current_range = chip_data->extended_current_range;
|
||||
platform_set_drvdata(pdev, charger);
|
||||
psy_cfg.drv_data = charger;
|
||||
psy_cfg.fwnode = dev_fwnode(&pdev->dev);
|
||||
|
||||
charger->channel_vusb = devm_iio_channel_get(&pdev->dev, "vusb");
|
||||
if (IS_ERR(charger->channel_vusb)) {
|
||||
ret = PTR_ERR(charger->channel_vusb);
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret; /* iio not ready */
|
||||
dev_warn(&pdev->dev, "could not request vusb iio channel (%d)",
|
||||
ret);
|
||||
charger->channel_vusb = NULL;
|
||||
}
|
||||
|
||||
charger->usb = devm_power_supply_register(&pdev->dev,
|
||||
&twl6030_charger_usb_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(charger->usb))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(charger->usb),
|
||||
"Failed to register usb\n");
|
||||
|
||||
ret = power_supply_get_battery_info(charger->usb, &charger->binfo);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"Failed to get battery info\n");
|
||||
|
||||
dev_info(&pdev->dev, "battery with vmax %d imax: %d\n",
|
||||
charger->binfo->constant_charge_voltage_max_uv,
|
||||
charger->binfo->constant_charge_current_max_ua);
|
||||
|
||||
if (charger->binfo->constant_charge_voltage_max_uv == -EINVAL) {
|
||||
ret = twl6030_charger_read(CHARGERUSB_CTRLLIMIT1, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
charger->binfo->constant_charge_voltage_max_uv =
|
||||
VOREG_TO_UV(val);
|
||||
}
|
||||
|
||||
if (charger->binfo->constant_charge_voltage_max_uv > 4760000 ||
|
||||
charger->binfo->constant_charge_voltage_max_uv < 350000)
|
||||
return dev_err_probe(&pdev->dev, -EINVAL,
|
||||
"Invalid charge voltage\n");
|
||||
|
||||
if (charger->binfo->constant_charge_current_max_ua == -EINVAL) {
|
||||
ret = twl6030_charger_read(CHARGERUSB_CTRLLIMIT2, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
charger->binfo->constant_charge_current_max_ua = VICHRG_TO_UA(val);
|
||||
}
|
||||
|
||||
if (charger->binfo->constant_charge_current_max_ua < 100000 ||
|
||||
charger->binfo->constant_charge_current_max_ua > 1500000) {
|
||||
return dev_err_probe(&pdev->dev, -EINVAL,
|
||||
"Invalid charge current\n");
|
||||
}
|
||||
|
||||
if ((charger->binfo->charge_term_current_ua != -EINVAL) &&
|
||||
(charger->binfo->charge_term_current_ua > 400000 ||
|
||||
charger->binfo->charge_term_current_ua < 50000)) {
|
||||
return dev_err_probe(&pdev->dev, -EINVAL,
|
||||
"Invalid charge termination current\n");
|
||||
}
|
||||
|
||||
ret = devm_delayed_work_autocancel(&pdev->dev,
|
||||
&charger->charger_monitor,
|
||||
twl6030_charger_wdg);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"Failed to register delayed work\n");
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, charger->irq_chg, NULL,
|
||||
twl6030_charger_interrupt,
|
||||
IRQF_ONESHOT, pdev->name,
|
||||
charger);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"could not request irq %d\n",
|
||||
charger->irq_chg);
|
||||
|
||||
/* turing to charging to configure things */
|
||||
twl6030_charger_write(CONTROLLER_CTRL1, 0);
|
||||
twl6030_charger_interrupt(0, charger);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct twl6030_charger_chip_data twl6030_data = {
|
||||
.extended_current_range = false,
|
||||
};
|
||||
|
||||
static const struct twl6030_charger_chip_data twl6032_data = {
|
||||
.extended_current_range = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id twl_charger_of_match[] = {
|
||||
{.compatible = "ti,twl6030-charger", .data = &twl6030_data},
|
||||
{.compatible = "ti,twl6032-charger", .data = &twl6032_data},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, twl_charger_of_match);
|
||||
|
||||
static struct platform_driver twl6030_charger_driver = {
|
||||
.probe = twl6030_charger_probe,
|
||||
.driver = {
|
||||
.name = "twl6030_charger",
|
||||
.of_match_table = twl_charger_of_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(twl6030_charger_driver);
|
||||
|
||||
MODULE_DESCRIPTION("TWL6030 Battery Charger Interface driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -720,7 +720,7 @@ static void wm831x_power_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_power_driver = {
|
||||
.probe = wm831x_power_probe,
|
||||
.remove_new = wm831x_power_remove,
|
||||
.remove = wm831x_power_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-power",
|
||||
},
|
||||
|
@ -577,7 +577,7 @@ static void wm8350_power_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm8350_power_driver = {
|
||||
.probe = wm8350_power_probe,
|
||||
.remove_new = wm8350_power_remove,
|
||||
.remove = wm8350_power_remove,
|
||||
.driver = {
|
||||
.name = "wm8350-power",
|
||||
},
|
||||
|
@ -265,7 +265,7 @@ static struct platform_driver wm97xx_bat_driver = {
|
||||
#endif
|
||||
},
|
||||
.probe = wm97xx_bat_probe,
|
||||
.remove_new = wm97xx_bat_remove,
|
||||
.remove = wm97xx_bat_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(wm97xx_bat_driver);
|
||||
|
@ -236,6 +236,8 @@ struct power_supply_config {
|
||||
|
||||
char **supplied_to;
|
||||
size_t num_supplicants;
|
||||
|
||||
bool no_wakeup_source;
|
||||
};
|
||||
|
||||
/* Description of power supply */
|
||||
@ -750,9 +752,9 @@ struct power_supply_battery_info {
|
||||
int temp_alert_max;
|
||||
int temp_min;
|
||||
int temp_max;
|
||||
struct power_supply_battery_ocv_table *ocv_table[POWER_SUPPLY_OCV_TEMP_MAX];
|
||||
const struct power_supply_battery_ocv_table *ocv_table[POWER_SUPPLY_OCV_TEMP_MAX];
|
||||
int ocv_table_size[POWER_SUPPLY_OCV_TEMP_MAX];
|
||||
struct power_supply_resistance_temp_table *resist_table;
|
||||
const struct power_supply_resistance_temp_table *resist_table;
|
||||
int resist_table_size;
|
||||
const struct power_supply_vbat_ri_table *vbat2ri_discharging;
|
||||
int vbat2ri_discharging_size;
|
||||
@ -797,15 +799,15 @@ extern bool power_supply_battery_info_has_prop(struct power_supply_battery_info
|
||||
extern int power_supply_battery_info_get_prop(struct power_supply_battery_info *info,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val);
|
||||
extern int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
|
||||
extern int power_supply_ocv2cap_simple(const struct power_supply_battery_ocv_table *table,
|
||||
int table_len, int ocv);
|
||||
extern struct power_supply_battery_ocv_table *
|
||||
extern const struct power_supply_battery_ocv_table *
|
||||
power_supply_find_ocv2cap_table(struct power_supply_battery_info *info,
|
||||
int temp, int *table_len);
|
||||
extern int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info,
|
||||
int ocv, int temp);
|
||||
extern int
|
||||
power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table,
|
||||
power_supply_temp2resist_simple(const struct power_supply_resistance_temp_table *table,
|
||||
int table_len, int temp);
|
||||
extern int power_supply_vbat2ri(struct power_supply_battery_info *info,
|
||||
int vbat_uv, bool charging);
|
||||
@ -863,8 +865,6 @@ static inline int power_supply_set_property(struct power_supply *psy,
|
||||
const union power_supply_propval *val)
|
||||
{ return 0; }
|
||||
#endif
|
||||
extern int power_supply_property_is_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp);
|
||||
extern void power_supply_external_power_changed(struct power_supply *psy);
|
||||
|
||||
extern struct power_supply *__must_check
|
||||
@ -872,17 +872,9 @@ power_supply_register(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg);
|
||||
extern struct power_supply *__must_check
|
||||
power_supply_register_no_ws(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg);
|
||||
extern struct power_supply *__must_check
|
||||
devm_power_supply_register(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg);
|
||||
extern struct power_supply *__must_check
|
||||
devm_power_supply_register_no_ws(struct device *parent,
|
||||
const struct power_supply_desc *desc,
|
||||
const struct power_supply_config *cfg);
|
||||
extern void power_supply_unregister(struct power_supply *psy);
|
||||
extern int power_supply_powers(struct power_supply *psy, struct device *dev);
|
||||
|
||||
@ -945,19 +937,6 @@ static inline bool power_supply_is_watt_property(enum power_supply_property psp)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_POWER_SUPPLY_HWMON
|
||||
int power_supply_add_hwmon_sysfs(struct power_supply *psy);
|
||||
void power_supply_remove_hwmon_sysfs(struct power_supply *psy);
|
||||
#else
|
||||
static inline int power_supply_add_hwmon_sysfs(struct power_supply *psy)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void power_supply_remove_hwmon_sysfs(struct power_supply *psy) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
ssize_t power_supply_charge_behaviour_show(struct device *dev,
|
||||
unsigned int available_behaviours,
|
||||
|
Loading…
Reference in New Issue
Block a user