From: Svyatoslav Ryhel Date: Tue, 24 Oct 2023 07:49:08 +0000 (+0300) Subject: sysreset: implement PALMAS sysreset functions X-Git-Url: http://git.dujemihanovic.xyz/img/sics.gif?a=commitdiff_plain;h=4afdc7a3c63d99b53676d31cc38e18de15a036f5;p=u-boot.git sysreset: implement PALMAS sysreset functions PALMAS PMIC family has embedded poweroff function used by some device to initiane device power off. Implement it as sysreset driver. Signed-off-by: Svyatoslav Ryhel --- diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c index b2e8a2930c..32f2a938b2 100644 --- a/drivers/power/pmic/palmas.c +++ b/drivers/power/pmic/palmas.c @@ -8,13 +8,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include static const struct pmic_child_info pmic_children_info[] = { { .prefix = "ldo", .driver = PALMAS_LDO_DRIVER }, @@ -47,7 +47,16 @@ static int palmas_bind(struct udevice *dev) { ofnode pmic_node = ofnode_null(), regulators_node; ofnode subnode; - int children; + int children, ret; + + if (IS_ENABLED(CONFIG_SYSRESET_PALMAS)) { + ret = device_bind_driver(dev, PALMAS_RST_DRIVER, + "sysreset", NULL); + if (ret) { + log_err("cannot bind SYSRESET (ret = %d)\n", ret); + return ret; + } + } dev_for_each_subnode(subnode, dev) { const char *name; @@ -81,6 +90,24 @@ static int palmas_bind(struct udevice *dev) return 0; } +static int palmas_probe(struct udevice *dev) +{ + struct dm_i2c_chip *chip = dev_get_parent_plat(dev); + struct palmas_priv *priv = dev_get_priv(dev); + struct udevice *bus = dev_get_parent(dev); + u32 chip2_addr = chip->chip_addr + 1; + int ret; + + /* Palmas PMIC is multi chip and chips are located in a row */ + ret = i2c_get_chip(bus, chip2_addr, 1, &priv->chip2); + if (ret) { + log_err("cannot get second PMIC I2C chip (err %d)\n", ret); + return ret; + } + + return 0; +} + static struct dm_pmic_ops palmas_ops = { .read = palmas_read, .write = palmas_write, @@ -98,5 +125,7 @@ U_BOOT_DRIVER(pmic_palmas) = { .id = UCLASS_PMIC, .of_match = palmas_ids, .bind = palmas_bind, + .probe = palmas_probe, .ops = &palmas_ops, + .priv_auto = sizeof(struct palmas_priv), }; diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig index 659170d156..0e52f99628 100644 --- a/drivers/sysreset/Kconfig +++ b/drivers/sysreset/Kconfig @@ -109,6 +109,13 @@ config SYSRESET_SPL_AT91 This enables the system reset driver support for Microchip/Atmel SoCs in SPL. +config SYSRESET_PALMAS + bool "Enable support for PALMAS System Reset" + depends on PMIC_PALMAS + select SYSRESET_CMD_POWEROFF if CMD_POWEROFF + help + Enable system power management functions found in PLAMAS PMIC family. + config SYSRESET_PSCI bool "Enable support for PSCI System Reset" depends on ARM_PSCI_FW diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile index 0d96a204a9..c9f1c625ae 100644 --- a/drivers/sysreset/Makefile +++ b/drivers/sysreset/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_$(SPL_TPL_)SYSRESET_MAX77663) += sysreset_max77663.o obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o obj-$(CONFIG_SYSRESET_OCTEON) += sysreset_octeon.o +obj-$(CONFIG_$(SPL_TPL_)SYSRESET_PALMAS) += sysreset_palmas.o obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o obj-$(CONFIG_SYSRESET_SBI) += sysreset_sbi.o obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o diff --git a/drivers/sysreset/sysreset_palmas.c b/drivers/sysreset/sysreset_palmas.c new file mode 100644 index 0000000000..9e3aa40348 --- /dev/null +++ b/drivers/sysreset/sysreset_palmas.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright(C) 2023 Svyatoslav Ryhel + */ + +#include +#include +#include +#include +#include +#include + +static int palmas_sysreset_request(struct udevice *dev, + enum sysreset_t type) +{ + struct palmas_priv *priv = dev_get_priv(dev->parent); + int ret; + + /* + * Mask INT3 on second page which detects vbus + * or device will immediately turn on. + */ + ret = dm_i2c_reg_clrset(priv->chip2, PALMAS_INT3_MASK, + MASK_VBUS, MASK_VBUS); + if (ret < 0) + return ret; + + switch (type) { + case SYSRESET_POWER: + /* PALMAS: SW_RST > DEV_CTRL */ + pmic_reg_write(dev->parent, PALMAS_DEV_CTRL, SW_RST); + break; + case SYSRESET_POWER_OFF: + /* PALMAS: DEV_OFF > DEV_CTRL */ + pmic_reg_write(dev->parent, PALMAS_DEV_CTRL, DEV_OFF); + break; + default: + return -EPROTONOSUPPORT; + } + + return -EINPROGRESS; +} + +static struct sysreset_ops palmas_sysreset = { + .request = palmas_sysreset_request, +}; + +U_BOOT_DRIVER(sysreset_palmas) = { + .id = UCLASS_SYSRESET, + .name = PALMAS_RST_DRIVER, + .ops = &palmas_sysreset, +}; diff --git a/include/power/palmas.h b/include/power/palmas.h index df5f15c5bd..0a612052f0 100644 --- a/include/power/palmas.h +++ b/include/power/palmas.h @@ -2,6 +2,10 @@ #define TPS659038 0x1 #define TPS65917 0x2 +struct palmas_priv { + struct udevice *chip2; +}; + /* I2C device address for pmic palmas */ #define PALMAS_I2C_ADDR (0x12 >> 1) #define PALMAS_LDO_NUM 11 @@ -10,6 +14,7 @@ /* Drivers name */ #define PALMAS_LDO_DRIVER "palmas_ldo" #define PALMAS_SMPS_DRIVER "palmas_smps" +#define PALMAS_RST_DRIVER "palmas_rst" #define PALMAS_SMPS_VOLT_MASK 0x7F #define PALMAS_SMPS_RANGE_MASK 0x80 @@ -24,3 +29,9 @@ #define PALMAS_LDO_MODE_MASK 0x1 #define PALMAS_LDO_STATUS_MASK 0x10 #define PALMAS_LDO_BYPASS_EN 0x40 + +#define PALMAS_DEV_CTRL 0xA0 +#define SW_RST BIT(1) +#define DEV_OFF 0x00 +#define PALMAS_INT3_MASK 0x1B +#define MASK_VBUS BIT(7)