power: pmic: axp: Implement poweroff via sysreset
The AXP PMICs have the ability to power off the system. The existing code for this is duplicated for each PMIC variant, and uses the legacy non-DM "pmic_bus" interface. When SYSRESET is enabled, this can all be replaced with a sysreset device using the DM_PMIC interface. Since the trigger bit is the same on all PMIC variants, use the register definitions from the oldest supported PMIC. Signed-off-by: Samuel Holland <samuel@sholland.org> Reviewed-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
parent
830e161eb4
commit
95d9ffd7b6
@ -66,6 +66,8 @@ config PMIC_ACT8846
|
|||||||
config PMIC_AXP
|
config PMIC_AXP
|
||||||
bool "Enable Driver Model for X-Powers AXP PMICs"
|
bool "Enable Driver Model for X-Powers AXP PMICs"
|
||||||
depends on DM_I2C
|
depends on DM_I2C
|
||||||
|
select SYSRESET_CMD_POWEROFF if SYSRESET && CMD_POWEROFF
|
||||||
|
imply CMD_POWEROFF if SYSRESET
|
||||||
help
|
help
|
||||||
This config enables driver-model PMIC uclass features for
|
This config enables driver-model PMIC uclass features for
|
||||||
X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
|
X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
|
||||||
|
@ -1,8 +1,37 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0+
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
|
||||||
|
#include <axp_pmic.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dm/lists.h>
|
||||||
#include <i2c.h>
|
#include <i2c.h>
|
||||||
#include <power/pmic.h>
|
#include <power/pmic.h>
|
||||||
|
#include <sysreset.h>
|
||||||
|
|
||||||
|
#if CONFIG_IS_ENABLED(SYSRESET)
|
||||||
|
static int axp_sysreset_request(struct udevice *dev, enum sysreset_t type)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (type != SYSRESET_POWER_OFF)
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
ret = pmic_clrsetbits(dev->parent, AXP152_SHUTDOWN, 0, AXP152_POWEROFF);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sysreset_ops axp_sysreset_ops = {
|
||||||
|
.request = axp_sysreset_request,
|
||||||
|
};
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(axp_sysreset) = {
|
||||||
|
.name = "axp_sysreset",
|
||||||
|
.id = UCLASS_SYSRESET,
|
||||||
|
.ops = &axp_sysreset_ops,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static int axp_pmic_reg_count(struct udevice *dev)
|
static int axp_pmic_reg_count(struct udevice *dev)
|
||||||
{
|
{
|
||||||
@ -16,6 +45,24 @@ static struct dm_pmic_ops axp_pmic_ops = {
|
|||||||
.write = dm_i2c_write,
|
.write = dm_i2c_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int axp_pmic_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = dm_scan_fdt_dev(dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (CONFIG_IS_ENABLED(SYSRESET)) {
|
||||||
|
ret = device_bind_driver_to_node(dev, "axp_sysreset", "axp_sysreset",
|
||||||
|
dev_ofnode(dev), NULL);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct udevice_id axp_pmic_ids[] = {
|
static const struct udevice_id axp_pmic_ids[] = {
|
||||||
{ .compatible = "x-powers,axp152" },
|
{ .compatible = "x-powers,axp152" },
|
||||||
{ .compatible = "x-powers,axp202" },
|
{ .compatible = "x-powers,axp202" },
|
||||||
@ -33,6 +80,6 @@ U_BOOT_DRIVER(axp_pmic) = {
|
|||||||
.name = "axp_pmic",
|
.name = "axp_pmic",
|
||||||
.id = UCLASS_PMIC,
|
.id = UCLASS_PMIC,
|
||||||
.of_match = axp_pmic_ids,
|
.of_match = axp_pmic_ids,
|
||||||
.bind = dm_scan_fdt_dev,
|
.bind = axp_pmic_bind,
|
||||||
.ops = &axp_pmic_ops,
|
.ops = &axp_pmic_ops,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user