You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
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 ...
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
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>;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
# 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:
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# 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)
|
||||
|
||||
97
drivers/power/reset/pwr-mlxbf.c
Normal file
97
drivers/power/reset/pwr-mlxbf.c
Normal file
@@ -0,0 +1,97 @@
|
||||
// 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 @@ free_notifier:
|
||||
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,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user