Commit f7cdaeea authored by Linus Torvalds's avatar Linus Torvalds

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

Pull power supply and reset updates from Sebastian Reichel:
 "No core patches, only driver updates:

   - pwr-mlxbf: new reset driver for Mellanox BlueField

   - at91-reset: SAMA7G5 support

   - ab8500: continue refurbishing

   - misc minor fixes"

* tag 'for-v6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power-supply: (29 commits)
  power: supply: olpc_battery: Hold the reference returned by of_find_compatible_node
  power: supply: ab8500: add missing destroy_workqueue in ab8500_charger_bind
  power: supply: ab8500: Remove flush_scheduled_work() call.
  power: supply: ab8500_fg: drop duplicated 'is' in comment
  power: supply: ab8500: Drop external charger leftovers
  power: supply: ab8500: Add MAINTAINERS entry
  dt-bindings: power: reset: qcom,pshold: convert to dtschema
  power: supply: Fix typo in power_supply_check_supplies
  power: reset: pwr-mlxbf: change rst_pwr_hid and low_pwr_hid from global to local variables
  power: reset: pwr-mlxbf: add missing include
  power: reset: at91-reset: add support for SAMA7G5
  power: reset: at91-reset: add reset_controller_dev support
  power: reset: at91-reset: add at91_reset_data
  power: reset: at91-reset: document structures and enums
  dt-bindings: reset: add sama7g5 definitions
  dt-bindings: reset: atmel,at91sam9260-reset: add sama7g5 bindings
  dt-bindings: reset: convert Atmel/Microchip reset controller to YAML
  power: reset: pwr-mlxbf: add BlueField SoC power control driver
  power: supply: ab8500: Exit maintenance if too low voltage
  power: supply: ab8500: Respect charge_restart_voltage_uv
  ...
parents d16b418f c9d84681
......@@ -25,21 +25,6 @@ System Timer (ST) required properties:
Its subnodes can be:
- watchdog: compatible should be "atmel,at91rm9200-wdt"
RSTC Reset Controller required properties:
- compatible: Should be "atmel,<chip>-rstc".
<chip> can be "at91sam9260", "at91sam9g45", "sama5d3" or "samx7"
it also can be "microchip,sam9x60-rstc"
- reg: Should contain registers location and length
- clocks: phandle to input clock.
Example:
rstc@fffffd00 {
compatible = "atmel,at91sam9260-rstc";
reg = <0xfffffd00 0x10>;
clocks = <&clk32k>;
};
RAMC SDRAM/DDR Controller required properties:
- compatible: Should be "atmel,at91rm9200-sdramc", "syscon"
"atmel,at91sam9260-sdramc",
......
MSM Restart Driver
A power supply hold (ps-hold) bit is set to power the msm chipsets.
Clearing that bit allows us to restart/poweroff. The difference
between poweroff and restart is determined by unique power manager IC
settings.
Required Properties:
-compatible: "qcom,pshold"
-reg: Specifies the physical address of the ps-hold register
Example:
restart@fc4ab000 {
compatible = "qcom,pshold";
reg = <0xfc4ab000 0x4>;
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/reset/qcom,pshold.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SoC restart and power off
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description:
A power supply hold (ps-hold) bit is set to power the Qualcomm chipsets.
Clearing that bit allows us to restart/power off. The difference between
power off and restart is determined by unique power manager IC settings.
properties:
compatible:
const: qcom,pshold
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
reset-controller@fc4ab000 {
compatible = "qcom,pshold";
reg = <0xfc4ab000 0x4>;
};
......@@ -28,7 +28,7 @@ properties:
maxItems: 1
usb-otg-vbus:
type: object
$ref: /schemas/regulator/regulator.yaml#
description: |
Regulator that is used to control the VBUS voltage direction for
either USB host mode or for charging on the OTG port
......
......@@ -117,11 +117,18 @@ properties:
be done externally to fully comply with the JEITA safety guidelines if this flag
is set.
usb-charge-current-limit:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 100000
maximum: 2500000
description: |
Default USB charge current limit in uA.
usb-otg-in-supply:
description: Reference to the regulator supplying power to the USB_OTG_IN pin.
otg-vbus:
type: object
$ref: /schemas/regulator/regulator.yaml#
description: |
This node defines a regulator used to control the direction of VBUS voltage.
Specifically whether to supply voltage to VBUS for host mode operation of the OTG port,
......
......@@ -82,7 +82,7 @@ properties:
- 1 # SMB3XX_SYSOK_INOK_ACTIVE_HIGH
usb-vbus:
$ref: "../../regulator/regulator.yaml#"
$ref: /schemas/regulator/regulator.yaml#
type: object
properties:
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/reset/atmel,at91sam9260-reset.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Atmel/Microchip System Reset Controller
maintainers:
- Claudiu Beznea <claudiu.beznea@microchip.com>
description: |
The system reset controller can be used to reset the CPU. In case of
SAMA7G5 it can also reset some devices (e.g. USB PHYs).
properties:
compatible:
oneOf:
- items:
- enum:
- atmel,at91sam9260-rstc
- atmel,at91sam9g45-rstc
- atmel,sama5d3-rstc
- microchip,sam9x60-rstc
- microchip,sama7g5-rstc
- items:
- const: atmel,sama5d3-rstc
- const: atmel,at91sam9g45-rstc
reg:
minItems: 1
items:
- description: base registers for system reset control
- description: registers for device specific reset control
clocks:
maxItems: 1
"#reset-cells":
const: 1
required:
- compatible
- reg
- clocks
allOf:
- if:
properties:
compatible:
contains:
enum:
- microchip,sama7g5-rstc
then:
required:
- "#reset-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/at91.h>
reset-controller@fffffd00 {
compatible = "atmel,at91sam9260-rstc";
reg = <0xfffffd00 0x10>;
clocks = <&pmc PMC_TYPE_CORE PMC_SLOW>;
};
......@@ -264,6 +264,11 @@ W: http://www.adaptec.com/
F: Documentation/scsi/aacraid.rst
F: drivers/scsi/aacraid/
AB8500 BATTERY AND CHARGER DRIVERS
M: Linus Walleij <linus.walleij@linaro.org>
F: Documentation/devicetree/bindings/power/supply/*ab8500*
F: drivers/power/supply/*ab8500*
ABI/API
L: linux-api@vger.kernel.org
F: include/linux/syscalls.h
......
......@@ -297,4 +297,10 @@ config NVMEM_REBOOT_MODE
then the bootloader can read it and take different
action according to the mode.
config POWER_MLXBF
tristate "Mellanox BlueField power handling driver"
depends on (GPIO_MLXBF2 && ACPI)
help
This driver supports reset or low power mode handling for Mellanox BlueField.
endif
......@@ -35,3 +35,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
......@@ -17,10 +17,13 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/reset-controller.h>
#include <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.h>
#include <dt-bindings/reset/sama7g5-reset.h>
#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
......@@ -39,6 +42,17 @@
#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */
/**
* enum reset_type - reset types
* @RESET_TYPE_GENERAL: first power-up reset
* @RESET_TYPE_WAKEUP: return from backup mode
* @RESET_TYPE_WATCHDOG: watchdog fault
* @RESET_TYPE_SOFTWARE: processor reset required by software
* @RESET_TYPE_USER: NRST pin detected low
* @RESET_TYPE_CPU_FAIL: CPU clock failure detection
* @RESET_TYPE_XTAL_FAIL: 32KHz crystal failure dectection fault
* @RESET_TYPE_ULP2: ULP2 reset
*/
enum reset_type {
RESET_TYPE_GENERAL = 0,
RESET_TYPE_WAKEUP = 1,
......@@ -50,15 +64,48 @@ enum reset_type {
RESET_TYPE_ULP2 = 8,
};
/**
* struct at91_reset - AT91 reset specific data structure
* @rstc_base: base address for system reset
* @ramc_base: array with base addresses of RAM controllers
* @dev_base: base address for devices reset
* @sclk: slow clock
* @data: platform specific reset data
* @rcdev: reset controller device
* @lock: lock for devices reset register access
* @nb: reset notifier block
* @args: SoC specific system reset arguments
* @ramc_lpr: SDRAM Controller Low Power Register
*/
struct at91_reset {
void __iomem *rstc_base;
void __iomem *ramc_base[2];
void __iomem *dev_base;
struct clk *sclk;
const struct at91_reset_data *data;
struct reset_controller_dev rcdev;
spinlock_t lock;
struct notifier_block nb;
u32 args;
u32 ramc_lpr;
};
#define to_at91_reset(r) container_of(r, struct at91_reset, rcdev)
/**
* struct at91_reset_data - AT91 reset data
* @reset_args: SoC specific system reset arguments
* @n_device_reset: number of device resets
* @device_reset_min_id: min id for device reset
* @device_reset_max_id: max id for device reset
*/
struct at91_reset_data {
u32 reset_args;
u32 n_device_reset;
u8 device_reset_min_id;
u8 device_reset_max_id;
};
/*
* unless the SDRAM is cleanly shutdown before we hit the
* reset register it can be left driving the data bus and
......@@ -95,7 +142,7 @@ static int at91_reset(struct notifier_block *this, unsigned long mode,
"r" (reset->rstc_base),
"r" (1),
"r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN),
"r" (reset->args),
"r" (reset->data->reset_args),
"r" (reset->ramc_lpr)
: "r4");
......@@ -153,34 +200,133 @@ static const struct of_device_id at91_ramc_of_match[] = {
{ /* sentinel */ }
};
static const struct at91_reset_data sam9260 = {
.reset_args = AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST,
};
static const struct at91_reset_data samx7 = {
.reset_args = AT91_RSTC_KEY | AT91_RSTC_PROCRST,
};
static const struct at91_reset_data sama7g5 = {
.reset_args = AT91_RSTC_KEY | AT91_RSTC_PROCRST,
.n_device_reset = 3,
.device_reset_min_id = SAMA7G5_RESET_USB_PHY1,
.device_reset_max_id = SAMA7G5_RESET_USB_PHY3,
};
static const struct of_device_id at91_reset_of_match[] = {
{
.compatible = "atmel,at91sam9260-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST |
AT91_RSTC_PROCRST),
.data = &sam9260,
},
{
.compatible = "atmel,at91sam9g45-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST |
AT91_RSTC_PROCRST)
.data = &sam9260,
},
{
.compatible = "atmel,sama5d3-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST |
AT91_RSTC_PROCRST)
.data = &sam9260,
},
{
.compatible = "atmel,samx7-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST)
.data = &samx7,
},
{
.compatible = "microchip,sam9x60-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST)
.data = &samx7,
},
{
.compatible = "microchip,sama7g5-rstc",
.data = &sama7g5,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, at91_reset_of_match);
static int at91_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct at91_reset *reset = to_at91_reset(rcdev);
unsigned long flags;
u32 val;
spin_lock_irqsave(&reset->lock, flags);
val = readl_relaxed(reset->dev_base);
if (assert)
val |= BIT(id);
else
val &= ~BIT(id);
writel_relaxed(val, reset->dev_base);
spin_unlock_irqrestore(&reset->lock, flags);
return 0;
}
static int at91_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return at91_reset_update(rcdev, id, true);
}
static int at91_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return at91_reset_update(rcdev, id, false);
}
static int at91_reset_dev_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct at91_reset *reset = to_at91_reset(rcdev);
u32 val;
val = readl_relaxed(reset->dev_base);
return !!(val & BIT(id));
}
static const struct reset_control_ops at91_reset_ops = {
.assert = at91_reset_assert,
.deassert = at91_reset_deassert,
.status = at91_reset_dev_status,
};
static int at91_reset_of_xlate(struct reset_controller_dev *rcdev,
const struct of_phandle_args *reset_spec)
{
struct at91_reset *reset = to_at91_reset(rcdev);
if (!reset->data->n_device_reset ||
(reset_spec->args[0] < reset->data->device_reset_min_id ||
reset_spec->args[0] > reset->data->device_reset_max_id))
return -EINVAL;
return reset_spec->args[0];
}
static int at91_rcdev_init(struct at91_reset *reset,
struct platform_device *pdev)
{
if (!reset->data->n_device_reset)
return 0;
reset->dev_base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 1,
NULL);
if (IS_ERR(reset->dev_base))
return -ENODEV;
spin_lock_init(&reset->lock);
reset->rcdev.ops = &at91_reset_ops;
reset->rcdev.owner = THIS_MODULE;
reset->rcdev.of_node = pdev->dev.of_node;
reset->rcdev.nr_resets = reset->data->n_device_reset;
reset->rcdev.of_reset_n_cells = 1;
reset->rcdev.of_xlate = at91_reset_of_xlate;
return devm_reset_controller_register(&pdev->dev, &reset->rcdev);
}
static int __init at91_reset_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
......@@ -212,10 +358,12 @@ static int __init at91_reset_probe(struct platform_device *pdev)
}
}
match = of_match_node(at91_reset_of_match, pdev->dev.of_node);
reset->data = device_get_match_data(&pdev->dev);
if (!reset->data)
return -ENODEV;
reset->nb.notifier_call = at91_reset;
reset->nb.priority = 192;
reset->args = (u32)match->data;
reset->sclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(reset->sclk))
......@@ -229,6 +377,10 @@ static int __init at91_reset_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, reset);
ret = at91_rcdev_init(reset, pdev);
if (ret)
goto disable_clk;
if (of_device_is_compatible(pdev->dev.of_node, "microchip,sam9x60-rstc")) {
u32 val = readl(reset->rstc_base + AT91_RSTC_MR);
......@@ -237,14 +389,16 @@ static int __init at91_reset_probe(struct platform_device *pdev)
}
ret = register_restart_handler(&reset->nb);
if (ret) {
clk_disable_unprepare(reset->sclk);
return ret;
}
if (ret)
goto disable_clk;
at91_reset_status(pdev, reset->rstc_base);
return 0;
disable_clk:
clk_disable_unprepare(reset->sclk);
return ret;
}
static int __exit at91_reset_remove(struct platform_device *pdev)
......
// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause
/*
* Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES.
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/devm-helpers.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <linux/types.h>
struct pwr_mlxbf {
struct work_struct send_work;
const char *hid;
};
static void pwr_mlxbf_send_work(struct work_struct *work)
{
acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1);
}
static irqreturn_t pwr_mlxbf_irq(int irq, void *ptr)
{
const char *rst_pwr_hid = "MLNXBF24";
const char *low_pwr_hid = "MLNXBF29";
struct pwr_mlxbf *priv = ptr;
if (!strncmp(priv->hid, rst_pwr_hid, 8))
emergency_restart();
if (!strncmp(priv->hid, low_pwr_hid, 8))
schedule_work(&priv->send_work);
return IRQ_HANDLED;
}
static int pwr_mlxbf_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acpi_device *adev;
struct pwr_mlxbf *priv;
const char *hid;
int irq, err;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
adev = ACPI_COMPANION(dev);
if (!adev)
return -ENXIO;
hid = acpi_device_hid(adev);
priv->hid = hid;
irq = acpi_dev_gpio_irq_get(ACPI_COMPANION(dev), 0);
if (irq < 0)
return dev_err_probe(dev, irq, "Error getting %s irq.\n", priv->hid);
err = devm_work_autocancel(dev, &priv->send_work, pwr_mlxbf_send_work);
if (err)
return err;
err = devm_request_irq(dev, irq, pwr_mlxbf_irq, 0, hid, priv);
if (err)
dev_err(dev, "Failed request of %s irq\n", priv->hid);
return err;
}
static const struct acpi_device_id __maybe_unused pwr_mlxbf_acpi_match[] = {
{ "MLNXBF24", 0 },
{ "MLNXBF29", 0 },
{},
};
MODULE_DEVICE_TABLE(acpi, pwr_mlxbf_acpi_match);
static struct platform_driver pwr_mlxbf_driver = {
.driver = {
.name = "pwr_mlxbf",
.acpi_match_table = pwr_mlxbf_acpi_match,
},
.probe = pwr_mlxbf_probe,
};
module_platform_driver(pwr_mlxbf_driver);
MODULE_DESCRIPTION("Mellanox BlueField power driver");
MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
MODULE_LICENSE("Dual BSD/GPL");
......@@ -34,7 +34,6 @@ struct ux500_charger_ops {
* @max_out_volt_uv maximum output charger voltage in uV
* @max_out_curr_ua maximum output charger current in uA
* @enabled indicates if this charger is used or not
* @external external charger unit (pm2xxx)
*/
struct ux500_charger {
struct power_supply *psy;
......@@ -43,9 +42,6 @@ struct ux500_charger {
int max_out_curr_ua;
int wdt_refresh;
bool enabled;
bool external;
};
extern struct blocking_notifier_head charger_notifier_list;
#endif /* _AB8500_CHARGALG_H_ */
......@@ -697,7 +697,6 @@ static void ab8500_btemp_unbind(struct device *dev, struct device *master,
/* Delete the work queue */
destroy_workqueue(di->btemp_wq);
flush_scheduled_work();
}
static const struct component_ops ab8500_btemp_component_ops = {
......
......@@ -246,9 +246,6 @@ struct ab8500_chargalg {
struct kobject chargalg_kobject;
};
/*External charger prepare notifier*/
BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
/* Main battery properties */
static enum power_supply_property ab8500_chargalg_props[] = {
POWER_SUPPLY_PROP_STATUS,
......@@ -343,8 +340,7 @@ static int ab8500_chargalg_check_charger_enable(struct ab8500_chargalg *di)
return di->usb_chg->ops.check_enable(di->usb_chg,
bi->constant_charge_voltage_max_uv,
bi->constant_charge_current_max_ua);
} else if ((di->chg_info.charger_type & AC_CHG) &&
!(di->ac_chg->external)) {
} else if (di->chg_info.charger_type & AC_CHG) {
return di->ac_chg->ops.check_enable(di->ac_chg,
bi->constant_charge_voltage_max_uv,
bi->constant_charge_current_max_ua);
......@@ -473,15 +469,6 @@ static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di)
/* Check if charger exists and kick watchdog if charging */
if (di->ac_chg && di->ac_chg->ops.kick_wd &&
di->chg_info.online_chg & AC_CHG) {
/*
* If AB charger watchdog expired, pm2xxx charging
* gets disabled. To be safe, kick both AB charger watchdog
* and pm2xxx watchdog.
*/
if (di->ac_chg->external &&
di->usb_chg && di->usb_chg->ops.kick_wd)
di->usb_chg->ops.kick_wd(di->usb_chg);
return di->ac_chg->ops.kick_wd(di->ac_chg);
} else if (di->usb_chg && di->usb_chg->ops.kick_wd &&
di->chg_info.online_chg & USB_CHG)
......@@ -517,14 +504,6 @@ static int ab8500_chargalg_ac_en(struct ab8500_chargalg *di, int enable,
di->chg_info.ac_iset_ua = iset_ua;
di->chg_info.ac_vset_uv = vset_uv;
/* Enable external charger */
if (enable && di->ac_chg->external &&
!ab8500_chargalg_ex_ac_enable_toggle) {
blocking_notifier_call_chain(&charger_notifier_list,
0, di->dev);
ab8500_chargalg_ex_ac_enable_toggle++;
}
return di->ac_chg->ops.enable(di->ac_chg, enable, vset_uv, iset_ua);
}
......@@ -1216,6 +1195,34 @@ static void ab8500_chargalg_external_power_changed(struct power_supply *psy)
queue_work(di->chargalg_wq, &di->chargalg_work);
}
/**
* ab8500_chargalg_time_to_restart() - time to restart CC/CV charging?
* @di: charging algorithm state
*
* This checks if the voltage or capacity of the battery has fallen so
* low that we need to restart the CC/CV charge cycle.
*/
static bool ab8500_chargalg_time_to_restart(struct ab8500_chargalg *di)
{
struct power_supply_battery_info *bi = di->bm->bi;
/* Sanity check - these need to have some reasonable values */
if (!di->batt_data.volt_uv || !di->batt_data.percent)
return false;
/* Some batteries tell us at which voltage we should restart charging */
if (bi->charge_restart_voltage_uv > 0) {
if (di->batt_data.volt_uv <= bi->charge_restart_voltage_uv)
return true;
/* Else we restart as we reach a certain capacity */
} else {
if (di->batt_data.percent <= AB8500_RECHARGE_CAP)
return true;
}
return false;
}
/**
* ab8500_chargalg_algorithm() - Main function for the algorithm
* @di: pointer to the ab8500_chargalg structure
......@@ -1459,7 +1466,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
fallthrough;
case STATE_WAIT_FOR_RECHARGE:
if (di->batt_data.percent <= AB8500_RECHARGE_CAP)
if (ab8500_chargalg_time_to_restart(di))
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
break;
......@@ -1486,6 +1493,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
ab8500_chargalg_stop_maintenance_timer(di);
ab8500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT);
}
/*
* This happens if the voltage drops too quickly during
* maintenance charging, especially in older batteries.
*/
if (ab8500_chargalg_time_to_restart(di)) {
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
dev_info(di->dev, "restarted charging from maintenance state A - battery getting old?\n");
}
break;
case STATE_MAINTENANCE_B_INIT:
......@@ -1510,6 +1525,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
ab8500_chargalg_stop_maintenance_timer(di);
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
}
/*
* This happens if the voltage drops too quickly during
* maintenance charging, especially in older batteries.
*/
if (ab8500_chargalg_time_to_restart(di)) {
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
dev_info(di->dev, "restarted charging from maintenance state B - battery getting old?\n");
}
break;
case STATE_TEMP_LOWHIGH_INIT:
......@@ -1746,7 +1769,6 @@ static void ab8500_chargalg_unbind(struct device *dev, struct device *master,
/* Delete the work queue */
destroy_workqueue(di->chargalg_wq);
flush_scheduled_work();
}
static const struct component_ops ab8500_chargalg_component_ops = {
......
......@@ -1716,29 +1716,6 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
return ret;
}
static int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
unsigned long event, void *data)
{
int ret;
struct device *dev = data;
/*Toggle External charger control pin*/
ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
AB8500_SYS_CHARGER_CONTROL_REG,
EXTERNAL_CHARGER_DISABLE_REG_VAL);
if (ret < 0) {
dev_err(dev, "write reg failed %d\n", ret);
goto out;
}
ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
AB8500_SYS_CHARGER_CONTROL_REG,
EXTERNAL_CHARGER_ENABLE_REG_VAL);
if (ret < 0)
dev_err(dev, "Write reg failed %d\n", ret);
out:
return ret;
}
/**
* ab8500_charger_usb_check_enable() - enable usb charging
* @charger: pointer to the ux500_charger structure
......@@ -3316,10 +3293,6 @@ static int __maybe_unused ab8500_charger_suspend(struct device *dev)
return 0;
}
static struct notifier_block charger_nb = {
.notifier_call = ab8500_external_charger_prepare,
};
static char *supply_interface[] = {
"ab8500_chargalg",
"ab8500_fg",
......@@ -3378,6 +3351,7 @@ static int ab8500_charger_bind(struct device *dev)
ret = component_bind_all(dev, di);
if (ret) {
dev_err(dev, "can't bind component devices\n");
destroy_workqueue(di->charger_wq);
return ret;
}
......@@ -3404,8 +3378,6 @@ static void ab8500_charger_unbind(struct device *dev)
/* Delete the work queue */
destroy_workqueue(di->charger_wq);
flush_scheduled_work();
/* Unbind fg, btemp, algorithm */
component_unbind_all(dev, di);
}
......@@ -3540,7 +3512,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
*/
if (!is_ab8505(di->parent))
di->ac_chg.enabled = true;
di->ac_chg.external = false;
/* USB supply */
/* ux500_charger sub-class */
......@@ -3553,7 +3524,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
di->usb_chg.max_out_curr_ua =
ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
di->usb_chg.external = false;
di->usb_state.usb_current_ua = -1;
mutex_init(&di->charger_attached_mutex);
......@@ -3677,17 +3647,11 @@ static int ab8500_charger_probe(struct platform_device *pdev)
goto remove_ab8500_bm;
}
/* Notifier for external charger enabling */
if (!di->ac_chg.enabled)
blocking_notifier_chain_register(
&charger_notifier_list, &charger_nb);
di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(di->usb_phy)) {
dev_err(dev, "failed to get usb transceiver\n");
ret = -EINVAL;
goto out_charger_notifier;
goto remove_ab8500_bm;
}
di->nb.notifier_call = ab8500_charger_usb_notifier_call;
ret = usb_register_notifier(di->usb_phy, &di->nb);
......@@ -3696,7 +3660,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
goto put_usb_phy;
}
ret = component_master_add_with_match(&pdev->dev,
&ab8500_charger_comp_ops,
match);
......@@ -3711,10 +3674,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
usb_unregister_notifier(di->usb_phy, &di->nb);
put_usb_phy:
usb_put_phy(di->usb_phy);
out_charger_notifier:
if (!di->ac_chg.enabled)
blocking_notifier_chain_unregister(
&charger_notifier_list, &charger_nb);
remove_ab8500_bm:
ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
return ret;
......@@ -3729,9 +3688,6 @@ static int ab8500_charger_remove(struct platform_device *pdev)
usb_unregister_notifier(di->usb_phy, &di->nb);
ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
usb_put_phy(di->usb_phy);
if (!di->ac_chg.enabled)
blocking_notifier_chain_unregister(
&charger_notifier_list, &charger_nb);
return 0;
}
......
......@@ -412,7 +412,7 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
* ab8500_fg_clear_cap_samples() - Clear average filter
* @di: pointer to the ab8500_fg structure
*
* The capacity filter is is reset to zero.
* The capacity filter is reset to zero.
*/
static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
{
......@@ -3234,7 +3234,6 @@ static int ab8500_fg_remove(struct platform_device *pdev)
struct ab8500_fg *di = platform_get_drvdata(pdev);
destroy_workqueue(di->fg_wq);
flush_scheduled_work();
component_del(&pdev->dev, &ab8500_fg_component_ops);
list_del(&di->node);
ab8500_fg_sysfs_exit(di);
......
......@@ -287,7 +287,7 @@ static int bq24257_set_input_current_limit(struct bq24257_device *bq,
{
/*
* Address the case where the user manually sets an input current limit
* while the charger auto-detection mechanism is is active. In this
* while the charger auto-detection mechanism is active. In this
* case we want to abort and go straight to the user-specified value.
*/
if (bq->iilimit_autoset_enable)
......
......@@ -63,7 +63,7 @@ static int cros_pchg_ec_command(const struct charger_data *charger,
struct cros_ec_command *msg;
int ret;
msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
msg = kzalloc(struct_size(msg, data, max(outsize, insize)), GFP_KERNEL);
if (!msg)
return -ENOMEM;
......
......@@ -221,10 +221,8 @@ static int goldfish_battery_probe(struct platform_device *pdev)
}
data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
if (data->irq < 0)
return -ENODEV;
}
ret = devm_request_irq(&pdev->dev, data->irq,
goldfish_battery_interrupt,
......
......@@ -376,7 +376,7 @@ static int lp8788_update_charger_params(struct platform_device *pdev,
return 0;
}
/* settting charging parameters */
/* setting charging parameters */
for (i = 0; i < pdata->num_chg_params; i++) {
param = pdata->chg_params + i;
......
......@@ -3,7 +3,7 @@
* max77976_charger.c - Driver for the Maxim MAX77976 battery charger
*
* Copyright (C) 2021 Luca Ceresoli
* Author: Luca Ceresoli <luca@lucaceresoli.net>
* Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
*/
#include <linux/i2c.h>
......@@ -504,6 +504,6 @@ static struct i2c_driver max77976_driver = {
};
module_i2c_driver(max77976_driver);
MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
MODULE_DESCRIPTION("Maxim MAX77976 charger driver");
MODULE_LICENSE("GPL v2");
......@@ -635,6 +635,7 @@ static int olpc_battery_probe(struct platform_device *pdev)
struct power_supply_config bat_psy_cfg = {};
struct power_supply_config ac_psy_cfg = {};
struct olpc_battery_data *data;
struct device_node *np;
uint8_t status;
uint8_t ecver;
int ret;
......@@ -649,7 +650,9 @@ static int olpc_battery_probe(struct platform_device *pdev)
if (ret)
return ret;
if (of_find_compatible_node(NULL, NULL, "olpc,xo1.75-ec")) {
np = of_find_compatible_node(NULL, NULL, "olpc,xo1.75-ec");
if (np) {
of_node_put(np);
/* XO 1.75 */
data->new_proto = true;
data->little_endian = true;
......
This diff is collapsed.
......@@ -263,13 +263,13 @@ static int power_supply_check_supplies(struct power_supply *psy)
return 0;
/* All supplies found, allocate char ** array for filling */
psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(psy->supplied_from),
psy->supplied_from = devm_kzalloc(&psy->dev, sizeof(*psy->supplied_from),
GFP_KERNEL);
if (!psy->supplied_from)
return -ENOMEM;
*psy->supplied_from = devm_kcalloc(&psy->dev,
cnt - 1, sizeof(char *),
cnt - 1, sizeof(**psy->supplied_from),
GFP_KERNEL);
if (!*psy->supplied_from)
return -ENOMEM;
......
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
#ifndef __DT_BINDINGS_RESET_SAMA7G5_H
#define __DT_BINDINGS_RESET_SAMA7G5_H
#define SAMA7G5_RESET_USB_PHY1 4
#define SAMA7G5_RESET_USB_PHY2 5
#define SAMA7G5_RESET_USB_PHY3 6
#endif /* __DT_BINDINGS_RESET_SAMA7G5_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment