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: ...@@ -25,21 +25,6 @@ System Timer (ST) required properties:
Its subnodes can be: Its subnodes can be:
- watchdog: compatible should be "atmel,at91rm9200-wdt" - 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: RAMC SDRAM/DDR Controller required properties:
- compatible: Should be "atmel,at91rm9200-sdramc", "syscon" - compatible: Should be "atmel,at91rm9200-sdramc", "syscon"
"atmel,at91sam9260-sdramc", "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: ...@@ -28,7 +28,7 @@ properties:
maxItems: 1 maxItems: 1
usb-otg-vbus: usb-otg-vbus:
type: object $ref: /schemas/regulator/regulator.yaml#
description: | description: |
Regulator that is used to control the VBUS voltage direction for Regulator that is used to control the VBUS voltage direction for
either USB host mode or for charging on the OTG port either USB host mode or for charging on the OTG port
......
...@@ -117,11 +117,18 @@ properties: ...@@ -117,11 +117,18 @@ properties:
be done externally to fully comply with the JEITA safety guidelines if this flag be done externally to fully comply with the JEITA safety guidelines if this flag
is set. 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: usb-otg-in-supply:
description: Reference to the regulator supplying power to the USB_OTG_IN pin. description: Reference to the regulator supplying power to the USB_OTG_IN pin.
otg-vbus: otg-vbus:
type: object $ref: /schemas/regulator/regulator.yaml#
description: | description: |
This node defines a regulator used to control the direction of VBUS voltage. 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, Specifically whether to supply voltage to VBUS for host mode operation of the OTG port,
......
...@@ -82,7 +82,7 @@ properties: ...@@ -82,7 +82,7 @@ properties:
- 1 # SMB3XX_SYSOK_INOK_ACTIVE_HIGH - 1 # SMB3XX_SYSOK_INOK_ACTIVE_HIGH
usb-vbus: usb-vbus:
$ref: "../../regulator/regulator.yaml#" $ref: /schemas/regulator/regulator.yaml#
type: object type: object
properties: 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/ ...@@ -264,6 +264,11 @@ W: http://www.adaptec.com/
F: Documentation/scsi/aacraid.rst F: Documentation/scsi/aacraid.rst
F: drivers/scsi/aacraid/ 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 ABI/API
L: linux-api@vger.kernel.org L: linux-api@vger.kernel.org
F: include/linux/syscalls.h F: include/linux/syscalls.h
......
...@@ -297,4 +297,10 @@ config NVMEM_REBOOT_MODE ...@@ -297,4 +297,10 @@ config NVMEM_REBOOT_MODE
then the bootloader can read it and take different then the bootloader can read it and take different
action according to the mode. 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 endif
...@@ -35,3 +35,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o ...@@ -35,3 +35,4 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
...@@ -17,10 +17,13 @@ ...@@ -17,10 +17,13 @@
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/reset-controller.h>
#include <soc/at91/at91sam9_ddrsdr.h> #include <soc/at91/at91sam9_ddrsdr.h>
#include <soc/at91/at91sam9_sdramc.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_CR 0x00 /* Reset Controller Control Register */
#define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */ #define AT91_RSTC_PROCRST BIT(0) /* Processor Reset */
#define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */ #define AT91_RSTC_PERRST BIT(2) /* Peripheral Reset */
...@@ -39,6 +42,17 @@ ...@@ -39,6 +42,17 @@
#define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */ #define AT91_RSTC_URSTIEN BIT(4) /* User Reset Interrupt Enable */
#define AT91_RSTC_ERSTL GENMASK(11, 8) /* External Reset Length */ #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 { enum reset_type {
RESET_TYPE_GENERAL = 0, RESET_TYPE_GENERAL = 0,
RESET_TYPE_WAKEUP = 1, RESET_TYPE_WAKEUP = 1,
...@@ -50,15 +64,48 @@ enum reset_type { ...@@ -50,15 +64,48 @@ enum reset_type {
RESET_TYPE_ULP2 = 8, 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 { struct at91_reset {
void __iomem *rstc_base; void __iomem *rstc_base;
void __iomem *ramc_base[2]; void __iomem *ramc_base[2];
void __iomem *dev_base;
struct clk *sclk; struct clk *sclk;
const struct at91_reset_data *data;
struct reset_controller_dev rcdev;
spinlock_t lock;
struct notifier_block nb; struct notifier_block nb;
u32 args; u32 args;
u32 ramc_lpr; 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 * unless the SDRAM is cleanly shutdown before we hit the
* reset register it can be left driving the data bus and * 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, ...@@ -95,7 +142,7 @@ static int at91_reset(struct notifier_block *this, unsigned long mode,
"r" (reset->rstc_base), "r" (reset->rstc_base),
"r" (1), "r" (1),
"r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN), "r" cpu_to_le32(AT91_DDRSDRC_LPCB_POWER_DOWN),
"r" (reset->args), "r" (reset->data->reset_args),
"r" (reset->ramc_lpr) "r" (reset->ramc_lpr)
: "r4"); : "r4");
...@@ -153,34 +200,133 @@ static const struct of_device_id at91_ramc_of_match[] = { ...@@ -153,34 +200,133 @@ static const struct of_device_id at91_ramc_of_match[] = {
{ /* sentinel */ } { /* 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[] = { static const struct of_device_id at91_reset_of_match[] = {
{ {
.compatible = "atmel,at91sam9260-rstc", .compatible = "atmel,at91sam9260-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | .data = &sam9260,
AT91_RSTC_PROCRST),
}, },
{ {
.compatible = "atmel,at91sam9g45-rstc", .compatible = "atmel,at91sam9g45-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | .data = &sam9260,
AT91_RSTC_PROCRST)
}, },
{ {
.compatible = "atmel,sama5d3-rstc", .compatible = "atmel,sama5d3-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PERRST | .data = &sam9260,
AT91_RSTC_PROCRST)
}, },
{ {
.compatible = "atmel,samx7-rstc", .compatible = "atmel,samx7-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST) .data = &samx7,
}, },
{ {
.compatible = "microchip,sam9x60-rstc", .compatible = "microchip,sam9x60-rstc",
.data = (void *)(AT91_RSTC_KEY | AT91_RSTC_PROCRST) .data = &samx7,
},
{
.compatible = "microchip,sama7g5-rstc",
.data = &sama7g5,
}, },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, at91_reset_of_match); 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) static int __init at91_reset_probe(struct platform_device *pdev)
{ {
const struct of_device_id *match; const struct of_device_id *match;
...@@ -212,10 +358,12 @@ static int __init at91_reset_probe(struct platform_device *pdev) ...@@ -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.notifier_call = at91_reset;
reset->nb.priority = 192; reset->nb.priority = 192;
reset->args = (u32)match->data;
reset->sclk = devm_clk_get(&pdev->dev, NULL); reset->sclk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(reset->sclk)) if (IS_ERR(reset->sclk))
...@@ -229,6 +377,10 @@ static int __init at91_reset_probe(struct platform_device *pdev) ...@@ -229,6 +377,10 @@ static int __init at91_reset_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, reset); 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")) { if (of_device_is_compatible(pdev->dev.of_node, "microchip,sam9x60-rstc")) {
u32 val = readl(reset->rstc_base + AT91_RSTC_MR); u32 val = readl(reset->rstc_base + AT91_RSTC_MR);
...@@ -237,14 +389,16 @@ static int __init at91_reset_probe(struct platform_device *pdev) ...@@ -237,14 +389,16 @@ static int __init at91_reset_probe(struct platform_device *pdev)
} }
ret = register_restart_handler(&reset->nb); ret = register_restart_handler(&reset->nb);
if (ret) { if (ret)
clk_disable_unprepare(reset->sclk); goto disable_clk;
return ret;
}
at91_reset_status(pdev, reset->rstc_base); at91_reset_status(pdev, reset->rstc_base);
return 0; return 0;
disable_clk:
clk_disable_unprepare(reset->sclk);
return ret;
} }
static int __exit at91_reset_remove(struct platform_device *pdev) 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 { ...@@ -34,7 +34,6 @@ struct ux500_charger_ops {
* @max_out_volt_uv maximum output charger voltage in uV * @max_out_volt_uv maximum output charger voltage in uV
* @max_out_curr_ua maximum output charger current in uA * @max_out_curr_ua maximum output charger current in uA
* @enabled indicates if this charger is used or not * @enabled indicates if this charger is used or not
* @external external charger unit (pm2xxx)
*/ */
struct ux500_charger { struct ux500_charger {
struct power_supply *psy; struct power_supply *psy;
...@@ -43,9 +42,6 @@ struct ux500_charger { ...@@ -43,9 +42,6 @@ struct ux500_charger {
int max_out_curr_ua; int max_out_curr_ua;
int wdt_refresh; int wdt_refresh;
bool enabled; bool enabled;
bool external;
}; };
extern struct blocking_notifier_head charger_notifier_list;
#endif /* _AB8500_CHARGALG_H_ */ #endif /* _AB8500_CHARGALG_H_ */
...@@ -697,7 +697,6 @@ static void ab8500_btemp_unbind(struct device *dev, struct device *master, ...@@ -697,7 +697,6 @@ static void ab8500_btemp_unbind(struct device *dev, struct device *master,
/* Delete the work queue */ /* Delete the work queue */
destroy_workqueue(di->btemp_wq); destroy_workqueue(di->btemp_wq);
flush_scheduled_work();
} }
static const struct component_ops ab8500_btemp_component_ops = { static const struct component_ops ab8500_btemp_component_ops = {
......
...@@ -246,9 +246,6 @@ struct ab8500_chargalg { ...@@ -246,9 +246,6 @@ struct ab8500_chargalg {
struct kobject chargalg_kobject; struct kobject chargalg_kobject;
}; };
/*External charger prepare notifier*/
BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
/* Main battery properties */ /* Main battery properties */
static enum power_supply_property ab8500_chargalg_props[] = { static enum power_supply_property ab8500_chargalg_props[] = {
POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_STATUS,
...@@ -343,8 +340,7 @@ static int ab8500_chargalg_check_charger_enable(struct ab8500_chargalg *di) ...@@ -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, return di->usb_chg->ops.check_enable(di->usb_chg,
bi->constant_charge_voltage_max_uv, bi->constant_charge_voltage_max_uv,
bi->constant_charge_current_max_ua); bi->constant_charge_current_max_ua);
} else if ((di->chg_info.charger_type & AC_CHG) && } else if (di->chg_info.charger_type & AC_CHG) {
!(di->ac_chg->external)) {
return di->ac_chg->ops.check_enable(di->ac_chg, return di->ac_chg->ops.check_enable(di->ac_chg,
bi->constant_charge_voltage_max_uv, bi->constant_charge_voltage_max_uv,
bi->constant_charge_current_max_ua); bi->constant_charge_current_max_ua);
...@@ -473,15 +469,6 @@ static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di) ...@@ -473,15 +469,6 @@ static int ab8500_chargalg_kick_watchdog(struct ab8500_chargalg *di)
/* Check if charger exists and kick watchdog if charging */ /* Check if charger exists and kick watchdog if charging */
if (di->ac_chg && di->ac_chg->ops.kick_wd && if (di->ac_chg && di->ac_chg->ops.kick_wd &&
di->chg_info.online_chg & AC_CHG) { 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); return di->ac_chg->ops.kick_wd(di->ac_chg);
} else if (di->usb_chg && di->usb_chg->ops.kick_wd && } else if (di->usb_chg && di->usb_chg->ops.kick_wd &&
di->chg_info.online_chg & USB_CHG) di->chg_info.online_chg & USB_CHG)
...@@ -517,14 +504,6 @@ static int ab8500_chargalg_ac_en(struct ab8500_chargalg *di, int enable, ...@@ -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_iset_ua = iset_ua;
di->chg_info.ac_vset_uv = vset_uv; 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); 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) ...@@ -1216,6 +1195,34 @@ static void ab8500_chargalg_external_power_changed(struct power_supply *psy)
queue_work(di->chargalg_wq, &di->chargalg_work); 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 * ab8500_chargalg_algorithm() - Main function for the algorithm
* @di: pointer to the ab8500_chargalg structure * @di: pointer to the ab8500_chargalg structure
...@@ -1459,7 +1466,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) ...@@ -1459,7 +1466,7 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
fallthrough; fallthrough;
case STATE_WAIT_FOR_RECHARGE: 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); ab8500_chargalg_state_to(di, STATE_NORMAL_INIT);
break; break;
...@@ -1486,6 +1493,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) ...@@ -1486,6 +1493,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
ab8500_chargalg_stop_maintenance_timer(di); ab8500_chargalg_stop_maintenance_timer(di);
ab8500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT); 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; break;
case STATE_MAINTENANCE_B_INIT: case STATE_MAINTENANCE_B_INIT:
...@@ -1510,6 +1525,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di) ...@@ -1510,6 +1525,14 @@ static void ab8500_chargalg_algorithm(struct ab8500_chargalg *di)
ab8500_chargalg_stop_maintenance_timer(di); ab8500_chargalg_stop_maintenance_timer(di);
ab8500_chargalg_state_to(di, STATE_NORMAL_INIT); 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; break;
case STATE_TEMP_LOWHIGH_INIT: case STATE_TEMP_LOWHIGH_INIT:
...@@ -1746,7 +1769,6 @@ static void ab8500_chargalg_unbind(struct device *dev, struct device *master, ...@@ -1746,7 +1769,6 @@ static void ab8500_chargalg_unbind(struct device *dev, struct device *master,
/* Delete the work queue */ /* Delete the work queue */
destroy_workqueue(di->chargalg_wq); destroy_workqueue(di->chargalg_wq);
flush_scheduled_work();
} }
static const struct component_ops ab8500_chargalg_component_ops = { static const struct component_ops ab8500_chargalg_component_ops = {
......
...@@ -1716,29 +1716,6 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, ...@@ -1716,29 +1716,6 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
return ret; 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 * ab8500_charger_usb_check_enable() - enable usb charging
* @charger: pointer to the ux500_charger structure * @charger: pointer to the ux500_charger structure
...@@ -3316,10 +3293,6 @@ static int __maybe_unused ab8500_charger_suspend(struct device *dev) ...@@ -3316,10 +3293,6 @@ static int __maybe_unused ab8500_charger_suspend(struct device *dev)
return 0; return 0;
} }
static struct notifier_block charger_nb = {
.notifier_call = ab8500_external_charger_prepare,
};
static char *supply_interface[] = { static char *supply_interface[] = {
"ab8500_chargalg", "ab8500_chargalg",
"ab8500_fg", "ab8500_fg",
...@@ -3378,6 +3351,7 @@ static int ab8500_charger_bind(struct device *dev) ...@@ -3378,6 +3351,7 @@ static int ab8500_charger_bind(struct device *dev)
ret = component_bind_all(dev, di); ret = component_bind_all(dev, di);
if (ret) { if (ret) {
dev_err(dev, "can't bind component devices\n"); dev_err(dev, "can't bind component devices\n");
destroy_workqueue(di->charger_wq);
return ret; return ret;
} }
...@@ -3404,8 +3378,6 @@ static void ab8500_charger_unbind(struct device *dev) ...@@ -3404,8 +3378,6 @@ static void ab8500_charger_unbind(struct device *dev)
/* Delete the work queue */ /* Delete the work queue */
destroy_workqueue(di->charger_wq); destroy_workqueue(di->charger_wq);
flush_scheduled_work();
/* Unbind fg, btemp, algorithm */ /* Unbind fg, btemp, algorithm */
component_unbind_all(dev, di); component_unbind_all(dev, di);
} }
...@@ -3540,7 +3512,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) ...@@ -3540,7 +3512,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
*/ */
if (!is_ab8505(di->parent)) if (!is_ab8505(di->parent))
di->ac_chg.enabled = true; di->ac_chg.enabled = true;
di->ac_chg.external = false;
/* USB supply */ /* USB supply */
/* ux500_charger sub-class */ /* ux500_charger sub-class */
...@@ -3553,7 +3524,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) ...@@ -3553,7 +3524,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
di->usb_chg.max_out_curr_ua = di->usb_chg.max_out_curr_ua =
ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1]; ab8500_charge_output_curr_map[ARRAY_SIZE(ab8500_charge_output_curr_map) - 1];
di->usb_chg.wdt_refresh = CHG_WD_INTERVAL; di->usb_chg.wdt_refresh = CHG_WD_INTERVAL;
di->usb_chg.external = false;
di->usb_state.usb_current_ua = -1; di->usb_state.usb_current_ua = -1;
mutex_init(&di->charger_attached_mutex); mutex_init(&di->charger_attached_mutex);
...@@ -3677,17 +3647,11 @@ static int ab8500_charger_probe(struct platform_device *pdev) ...@@ -3677,17 +3647,11 @@ static int ab8500_charger_probe(struct platform_device *pdev)
goto remove_ab8500_bm; 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); di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(di->usb_phy)) { if (IS_ERR_OR_NULL(di->usb_phy)) {
dev_err(dev, "failed to get usb transceiver\n"); dev_err(dev, "failed to get usb transceiver\n");
ret = -EINVAL; ret = -EINVAL;
goto out_charger_notifier; goto remove_ab8500_bm;
} }
di->nb.notifier_call = ab8500_charger_usb_notifier_call; di->nb.notifier_call = ab8500_charger_usb_notifier_call;
ret = usb_register_notifier(di->usb_phy, &di->nb); ret = usb_register_notifier(di->usb_phy, &di->nb);
...@@ -3696,7 +3660,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) ...@@ -3696,7 +3660,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
goto put_usb_phy; goto put_usb_phy;
} }
ret = component_master_add_with_match(&pdev->dev, ret = component_master_add_with_match(&pdev->dev,
&ab8500_charger_comp_ops, &ab8500_charger_comp_ops,
match); match);
...@@ -3711,10 +3674,6 @@ static int ab8500_charger_probe(struct platform_device *pdev) ...@@ -3711,10 +3674,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
usb_unregister_notifier(di->usb_phy, &di->nb); usb_unregister_notifier(di->usb_phy, &di->nb);
put_usb_phy: put_usb_phy:
usb_put_phy(di->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: remove_ab8500_bm:
ab8500_bm_of_remove(di->usb_chg.psy, di->bm); ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
return ret; return ret;
...@@ -3729,9 +3688,6 @@ static int ab8500_charger_remove(struct platform_device *pdev) ...@@ -3729,9 +3688,6 @@ static int ab8500_charger_remove(struct platform_device *pdev)
usb_unregister_notifier(di->usb_phy, &di->nb); usb_unregister_notifier(di->usb_phy, &di->nb);
ab8500_bm_of_remove(di->usb_chg.psy, di->bm); ab8500_bm_of_remove(di->usb_chg.psy, di->bm);
usb_put_phy(di->usb_phy); usb_put_phy(di->usb_phy);
if (!di->ac_chg.enabled)
blocking_notifier_chain_unregister(
&charger_notifier_list, &charger_nb);
return 0; return 0;
} }
......
...@@ -412,7 +412,7 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample) ...@@ -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 * ab8500_fg_clear_cap_samples() - Clear average filter
* @di: pointer to the ab8500_fg structure * @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) static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
{ {
...@@ -3234,7 +3234,6 @@ static int ab8500_fg_remove(struct platform_device *pdev) ...@@ -3234,7 +3234,6 @@ static int ab8500_fg_remove(struct platform_device *pdev)
struct ab8500_fg *di = platform_get_drvdata(pdev); struct ab8500_fg *di = platform_get_drvdata(pdev);
destroy_workqueue(di->fg_wq); destroy_workqueue(di->fg_wq);
flush_scheduled_work();
component_del(&pdev->dev, &ab8500_fg_component_ops); component_del(&pdev->dev, &ab8500_fg_component_ops);
list_del(&di->node); list_del(&di->node);
ab8500_fg_sysfs_exit(di); ab8500_fg_sysfs_exit(di);
......
...@@ -287,7 +287,7 @@ static int bq24257_set_input_current_limit(struct bq24257_device *bq, ...@@ -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 * 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. * case we want to abort and go straight to the user-specified value.
*/ */
if (bq->iilimit_autoset_enable) if (bq->iilimit_autoset_enable)
......
...@@ -63,7 +63,7 @@ static int cros_pchg_ec_command(const struct charger_data *charger, ...@@ -63,7 +63,7 @@ static int cros_pchg_ec_command(const struct charger_data *charger,
struct cros_ec_command *msg; struct cros_ec_command *msg;
int ret; int ret;
msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL); msg = kzalloc(struct_size(msg, data, max(outsize, insize)), GFP_KERNEL);
if (!msg) if (!msg)
return -ENOMEM; return -ENOMEM;
......
...@@ -221,10 +221,8 @@ static int goldfish_battery_probe(struct platform_device *pdev) ...@@ -221,10 +221,8 @@ static int goldfish_battery_probe(struct platform_device *pdev)
} }
data->irq = platform_get_irq(pdev, 0); data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0) { if (data->irq < 0)
dev_err(&pdev->dev, "platform_get_irq failed\n");
return -ENODEV; return -ENODEV;
}
ret = devm_request_irq(&pdev->dev, data->irq, ret = devm_request_irq(&pdev->dev, data->irq,
goldfish_battery_interrupt, goldfish_battery_interrupt,
......
...@@ -376,7 +376,7 @@ static int lp8788_update_charger_params(struct platform_device *pdev, ...@@ -376,7 +376,7 @@ static int lp8788_update_charger_params(struct platform_device *pdev,
return 0; return 0;
} }
/* settting charging parameters */ /* setting charging parameters */
for (i = 0; i < pdata->num_chg_params; i++) { for (i = 0; i < pdata->num_chg_params; i++) {
param = pdata->chg_params + i; param = pdata->chg_params + i;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* max77976_charger.c - Driver for the Maxim MAX77976 battery charger * max77976_charger.c - Driver for the Maxim MAX77976 battery charger
* *
* Copyright (C) 2021 Luca Ceresoli * Copyright (C) 2021 Luca Ceresoli
* Author: Luca Ceresoli <luca@lucaceresoli.net> * Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
*/ */
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -504,6 +504,6 @@ static struct i2c_driver max77976_driver = { ...@@ -504,6 +504,6 @@ static struct i2c_driver max77976_driver = {
}; };
module_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_DESCRIPTION("Maxim MAX77976 charger driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -635,6 +635,7 @@ static int olpc_battery_probe(struct platform_device *pdev) ...@@ -635,6 +635,7 @@ static int olpc_battery_probe(struct platform_device *pdev)
struct power_supply_config bat_psy_cfg = {}; struct power_supply_config bat_psy_cfg = {};
struct power_supply_config ac_psy_cfg = {}; struct power_supply_config ac_psy_cfg = {};
struct olpc_battery_data *data; struct olpc_battery_data *data;
struct device_node *np;
uint8_t status; uint8_t status;
uint8_t ecver; uint8_t ecver;
int ret; int ret;
...@@ -649,7 +650,9 @@ static int olpc_battery_probe(struct platform_device *pdev) ...@@ -649,7 +650,9 @@ static int olpc_battery_probe(struct platform_device *pdev)
if (ret) if (ret)
return 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 */ /* XO 1.75 */
data->new_proto = true; data->new_proto = true;
data->little_endian = true; data->little_endian = true;
......
This diff is collapsed.
...@@ -263,13 +263,13 @@ static int power_supply_check_supplies(struct power_supply *psy) ...@@ -263,13 +263,13 @@ static int power_supply_check_supplies(struct power_supply *psy)
return 0; return 0;
/* All supplies found, allocate char ** array for filling */ /* 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); GFP_KERNEL);
if (!psy->supplied_from) if (!psy->supplied_from)
return -ENOMEM; return -ENOMEM;
*psy->supplied_from = devm_kcalloc(&psy->dev, *psy->supplied_from = devm_kcalloc(&psy->dev,
cnt - 1, sizeof(char *), cnt - 1, sizeof(**psy->supplied_from),
GFP_KERNEL); GFP_KERNEL);
if (!*psy->supplied_from) if (!*psy->supplied_from)
return -ENOMEM; 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