From 9d875d674ff830a6036153a4c390c75267e775b6 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Fri, 4 Jul 2025 15:50:21 -0600 Subject: power: Split *POWER_LEGACY portion of out to new header The commends in include/power/pmic.h say that once SPL_DM_PMIC exists we should update things. This has been true for some time, so let us update this to have the legacy portions in their own header, which should not be directly included. This cleans up the logic within the file too slightly. Signed-off-by: Tom Rini --- include/power/pmic.h | 89 ++---------------------------------------- include/power/pmic_legacy.h | 94 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 86 deletions(-) create mode 100644 include/power/pmic_legacy.h (limited to 'include/power') diff --git a/include/power/pmic.h b/include/power/pmic.h index 636221692d0..4aee07383a9 100644 --- a/include/power/pmic.h +++ b/include/power/pmic.h @@ -17,76 +17,9 @@ enum { PMIC_I2C, PMIC_SPI, PMIC_NONE}; -/* TODO: Change to !CONFIG_IS_ENABLED(DM_PMIC) when SPL_DM_PMIC exists */ #if CONFIG_IS_ENABLED(POWER_LEGACY) -enum { I2C_PMIC, I2C_NUM, }; -enum { PMIC_READ, PMIC_WRITE, }; -enum { PMIC_SENSOR_BYTE_ORDER_LITTLE, PMIC_SENSOR_BYTE_ORDER_BIG, }; - -enum { - PMIC_CHARGER_DISABLE, - PMIC_CHARGER_ENABLE, -}; - -struct p_i2c { - unsigned char addr; - unsigned char *buf; - unsigned char tx_num; -}; - -struct p_spi { - unsigned int cs; - unsigned int mode; - unsigned int bitlen; - unsigned int clk; - unsigned int flags; - u32 (*prepare_tx)(u32 reg, u32 *val, u32 write); -}; - -struct pmic; -struct power_fg { - int (*fg_battery_check) (struct pmic *p, struct pmic *bat); - int (*fg_battery_update) (struct pmic *p, struct pmic *bat); -}; - -struct power_chrg { - int (*chrg_type) (struct pmic *p); - int (*chrg_bat_present) (struct pmic *p); - int (*chrg_state) (struct pmic *p, int state, int current); -}; - -struct power_battery { - struct battery *bat; - int (*battery_init) (struct pmic *bat, struct pmic *p1, - struct pmic *p2, struct pmic *p3); - int (*battery_charge) (struct pmic *bat); - /* Keep info about power devices involved with battery operation */ - struct pmic *chrg, *fg, *muic; -}; - -struct pmic { - const char *name; - unsigned char bus; - unsigned char interface; - unsigned char sensor_byte_order; - unsigned int number_of_regs; - union hw { - struct p_i2c i2c; - struct p_spi spi; - } hw; - - void (*low_power_mode) (void); - struct power_battery *pbat; - struct power_chrg *chrg; - struct power_fg *fg; - - struct pmic *parent; - struct list_head list; -}; -#endif /* CONFIG_IS_ENABLED(POWER_LEGACY) */ - -/* TODO: Change to CONFIG_IS_ENABLED(DM_PMIC) when SPL_DM_PMIC exists */ -#if defined(CONFIG_DM_PMIC) || !CONFIG_IS_ENABLED(POWER_LEGACY) +#include +#else /** * U-Boot PMIC Framework * ===================== @@ -308,23 +241,7 @@ struct uc_pmic_priv { uint trans_len; }; -#endif /* DM_PMIC */ - -/* TODO: Change to CONFIG_IS_ENABLED(DM_PMIC) when SPL_DM_PMIC exists */ -#if CONFIG_IS_ENABLED(POWER_LEGACY) - -/* Legacy API, do not use */ -int pmic_init(unsigned char bus); -int power_init_board(void); -int pmic_dialog_init(unsigned char bus); -int check_reg(struct pmic *p, u32 reg); -struct pmic *pmic_alloc(void); -struct pmic *pmic_get(const char *s); -int pmic_probe(struct pmic *p); -int pmic_reg_read(struct pmic *p, u32 reg, u32 *val); -int pmic_reg_write(struct pmic *p, u32 reg, u32 val); -int pmic_set_output(struct pmic *p, u32 reg, int ldo, int on); -#endif /* CONFIG_IS_ENABLED(POWER_LEGACY) */ +#endif #define pmic_i2c_addr (p->hw.i2c.addr) #define pmic_i2c_tx_num (p->hw.i2c.tx_num) diff --git a/include/power/pmic_legacy.h b/include/power/pmic_legacy.h new file mode 100644 index 00000000000..7c244060b4a --- /dev/null +++ b/include/power/pmic_legacy.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2014-2015 Samsung Electronics + * Przemyslaw Marczak + * + * Copyright (C) 2011-2012 Samsung Electronics + * Lukasz Majewski + */ + +#ifndef __POWER_PMIC_LEGACY_H__ +#define __POWER_PMIC_LEGACY_H__ + +#ifndef __CORE_PMIC_H_ +#error "Do not include directly" +#endif + +enum { I2C_PMIC, I2C_NUM, }; +enum { PMIC_READ, PMIC_WRITE, }; +enum { PMIC_SENSOR_BYTE_ORDER_LITTLE, PMIC_SENSOR_BYTE_ORDER_BIG, }; + +enum { + PMIC_CHARGER_DISABLE, + PMIC_CHARGER_ENABLE, +}; + +struct p_i2c { + unsigned char addr; + unsigned char *buf; + unsigned char tx_num; +}; + +struct p_spi { + unsigned int cs; + unsigned int mode; + unsigned int bitlen; + unsigned int clk; + unsigned int flags; + u32 (*prepare_tx)(u32 reg, u32 *val, u32 write); +}; + +struct pmic; +struct power_fg { + int (*fg_battery_check) (struct pmic *p, struct pmic *bat); + int (*fg_battery_update) (struct pmic *p, struct pmic *bat); +}; + +struct power_chrg { + int (*chrg_type) (struct pmic *p); + int (*chrg_bat_present) (struct pmic *p); + int (*chrg_state) (struct pmic *p, int state, int current); +}; + +struct power_battery { + struct battery *bat; + int (*battery_init) (struct pmic *bat, struct pmic *p1, + struct pmic *p2, struct pmic *p3); + int (*battery_charge) (struct pmic *bat); + /* Keep info about power devices involved with battery operation */ + struct pmic *chrg, *fg, *muic; +}; + +struct pmic { + const char *name; + unsigned char bus; + unsigned char interface; + unsigned char sensor_byte_order; + unsigned int number_of_regs; + union hw { + struct p_i2c i2c; + struct p_spi spi; + } hw; + + void (*low_power_mode) (void); + struct power_battery *pbat; + struct power_chrg *chrg; + struct power_fg *fg; + + struct pmic *parent; + struct list_head list; +}; + +/* Legacy API, do not use */ +int pmic_init(unsigned char bus); +int power_init_board(void); +int pmic_dialog_init(unsigned char bus); +int check_reg(struct pmic *p, u32 reg); +struct pmic *pmic_alloc(void); +struct pmic *pmic_get(const char *s); +int pmic_probe(struct pmic *p); +int pmic_reg_read(struct pmic *p, u32 reg, u32 *val); +int pmic_reg_write(struct pmic *p, u32 reg, u32 val); +int pmic_set_output(struct pmic *p, u32 reg, int ldo, int on); + +#endif -- cgit v1.3.1 From 58b8ff0b663a7491c1964e1e3a8d1d88ef707077 Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Thu, 7 Aug 2025 17:35:22 +0100 Subject: power: regulator: tps65910: Cannot test unsigned for being negative The code in tps65910_regulator.c treats the field supply in struct tps65910_regulator_pdata as an int and even tests the value for being negative so change it from a u32 to int so that the code all works as expected. This issue was found by Smatch. Signed-off-by: Andrew Goodbody Signed-off-by: Peng Fan --- include/power/tps65910_pmic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/power') diff --git a/include/power/tps65910_pmic.h b/include/power/tps65910_pmic.h index 2026ec2f426..8fa02f33ab1 100644 --- a/include/power/tps65910_pmic.h +++ b/include/power/tps65910_pmic.h @@ -123,7 +123,7 @@ enum { /* platform data */ struct tps65910_regulator_pdata { - u32 supply; /* regulator supply voltage in uV */ + int supply; /* regulator supply voltage in uV */ uint unit; /* unit-address according to DT */ }; -- cgit v1.3.1 From 9065b87f35018a4e993e7dfb8a8ec29474785f76 Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Thu, 28 Aug 2025 13:24:04 +0200 Subject: power: pmic: pca9450: Add support for system reset The family of PCA9450 PMICs have the ability to perform system resets. Restarting via PMIC is preferred method of restarting the system as all the peripherals are brought to a know state after a power-cycle. The PCA9450 features a cold restart procedure which is initiated by an I2C command 0x14 to the SW_RST register. Support in Linux for restarting via PCA9450 PMIC has been added by Linux commit 6157e62b07d9 ("regulator: pca9450: Add restart handler"). Now add support for it also in the U-Boot via sysreset framework. Signed-off-by: Primoz Fiser Reviewed-by: Paul Geurts Signed-off-by: Peng Fan --- drivers/power/pmic/pca9450.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/power/pca9450.h | 2 ++ 2 files changed, 46 insertions(+) (limited to 'include/power') diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c index 0e3d14abf15..8b98c2239e1 100644 --- a/drivers/power/pmic/pca9450.c +++ b/drivers/power/pmic/pca9450.c @@ -6,13 +6,17 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -79,6 +83,15 @@ static int pca9450_bind(struct udevice *dev) static int pca9450_probe(struct udevice *dev) { unsigned int reset_ctrl; + int ret; + + if (CONFIG_IS_ENABLED(SYSRESET)) { + ret = device_bind_driver_to_node(dev, "pca9450_sysreset", + "pca9450_sysreset", + dev_ofnode(dev), NULL); + if (ret) + return ret; + } if (ofnode_read_bool(dev_ofnode(dev), "nxp,wdog_b-warm-reset")) reset_ctrl = PCA9450_PMIC_RESET_WDOG_B_CFG_WARM; @@ -112,3 +125,34 @@ U_BOOT_DRIVER(pmic_pca9450) = { .probe = pca9450_probe, .ops = &pca9450_ops, }; + +#ifdef CONFIG_SYSRESET +static int pca9450_sysreset_request(struct udevice *dev, enum sysreset_t type) +{ + u8 cmd = PCA9450_SW_RST_COLD_RST; + + if (type != SYSRESET_COLD) + return -EPROTONOSUPPORT; + + if (pmic_write(dev->parent, PCA9450_SW_RST, &cmd, 1)) { + dev_err(dev, "reset command failed\n"); + } else { + /* tRESTART is 250ms, delay 300ms just to be sure */ + mdelay(300); + /* Should not get here, warn if we do */ + dev_warn(dev, "didn't respond to reset command\n"); + } + + return -EINPROGRESS; +} + +static struct sysreset_ops pca9450_sysreset_ops = { + .request = pca9450_sysreset_request, +}; + +U_BOOT_DRIVER(pca9450_sysreset) = { + .name = "pca9450_sysreset", + .id = UCLASS_SYSRESET, + .ops = &pca9450_sysreset_ops, +}; +#endif /* CONFIG_SYSRESET */ diff --git a/include/power/pca9450.h b/include/power/pca9450.h index e5ab09fb8c8..9119ef793b1 100644 --- a/include/power/pca9450.h +++ b/include/power/pca9450.h @@ -75,4 +75,6 @@ enum { #define PCA9450_PMIC_RESET_WDOG_B_CFG_WARM 0x40 #define PCA9450_PMIC_RESET_WDOG_B_CFG_COLD_LDO12 0x80 +#define PCA9450_SW_RST_COLD_RST 0x14 + #endif -- cgit v1.3.1 From ad197b31b3f88d53c349995d8bbaeba4b18b8f2b Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Thu, 28 Aug 2025 13:24:05 +0200 Subject: power: pmic: pca9450: Add support for reset status PCA9450 PMIC supports reading the reset status from the PWRON_STAT register. Bits 7-4 give indication of the PMIC reset cause: - PWRON (BIT7) - Power ON triggered by PMIC_ON_REQ input line, - WDOGB (BIT6) - Boot after cold reset by WDOGB pin (watchdog reset), - SW_RST (BIT5) - Boot after cold reset initiated by the software, - PMIC_RST (BIT4) - Boot after PMIC_RST_B input line trigger. Add support for reading reset status via the sysreset framework in a convenient printable format. Signed-off-by: Primoz Fiser Reviewed-by: Paul Geurts Signed-off-by: Peng Fan --- drivers/power/pmic/pca9450.c | 38 ++++++++++++++++++++++++++++++++++++++ include/power/pca9450.h | 5 +++++ 2 files changed, 43 insertions(+) (limited to 'include/power') diff --git a/drivers/power/pmic/pca9450.c b/drivers/power/pmic/pca9450.c index 8b98c2239e1..e5c1f037b61 100644 --- a/drivers/power/pmic/pca9450.c +++ b/drivers/power/pmic/pca9450.c @@ -146,8 +146,46 @@ static int pca9450_sysreset_request(struct udevice *dev, enum sysreset_t type) return -EINPROGRESS; } +int pca9450_sysreset_get_status(struct udevice *dev, char *buf, int size) +{ + const char *reason; + int ret; + u8 reg; + + ret = pmic_read(dev->parent, PCA9450_PWRON_STAT, ®, 1); + if (ret) + return ret; + + switch (reg) { + case PCA9450_PWRON_STAT_PWRON_MASK: + reason = "PWRON"; + break; + case PCA9450_PWRON_STAT_WDOG_MASK: + reason = "WDOGB"; + break; + case PCA9450_PWRON_STAT_SW_RST_MASK: + reason = "SW_RST"; + break; + case PCA9450_PWRON_STAT_PMIC_RST_MASK: + reason = "PMIC_RST"; + break; + default: + reason = "UNKNOWN"; + break; + } + + ret = snprintf(buf, size, "Reset Status: %s\n", reason); + if (ret < 0) { + dev_err(dev, "Write reset status error (err = %d)\n", ret); + return -EIO; + } + + return 0; +} + static struct sysreset_ops pca9450_sysreset_ops = { .request = pca9450_sysreset_request, + .get_status = pca9450_sysreset_get_status, }; U_BOOT_DRIVER(pca9450_sysreset) = { diff --git a/include/power/pca9450.h b/include/power/pca9450.h index 9119ef793b1..41b7f95c034 100644 --- a/include/power/pca9450.h +++ b/include/power/pca9450.h @@ -75,6 +75,11 @@ enum { #define PCA9450_PMIC_RESET_WDOG_B_CFG_WARM 0x40 #define PCA9450_PMIC_RESET_WDOG_B_CFG_COLD_LDO12 0x80 +#define PCA9450_PWRON_STAT_PWRON_MASK 0x80 +#define PCA9450_PWRON_STAT_WDOG_MASK 0x40 +#define PCA9450_PWRON_STAT_SW_RST_MASK 0x20 +#define PCA9450_PWRON_STAT_PMIC_RST_MASK 0x10 + #define PCA9450_SW_RST_COLD_RST 0x14 #endif -- cgit v1.3.1