From 017b76fb8e5b6066f6791e7ad2387deb2c9c9a14 Mon Sep 17 00:00:00 2001 From: Joy Zou Date: Thu, 5 Dec 2024 11:51:12 -0500 Subject: regulator: pca9450: Add PMIC pca9452 support Add the PMIC pca9452 support, which add ldo3 compared with pca9451a. Signed-off-by: Joy Zou Signed-off-by: Frank Li Link: https://patch.msgid.link/20241205-pca9450-v1-4-aab448b74e78@nxp.com Signed-off-by: Mark Brown --- include/linux/regulator/pca9450.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux/regulator') diff --git a/include/linux/regulator/pca9450.h b/include/linux/regulator/pca9450.h index 243633c8dceb..b427b5873de1 100644 --- a/include/linux/regulator/pca9450.h +++ b/include/linux/regulator/pca9450.h @@ -10,6 +10,7 @@ enum pca9450_chip_type { PCA9450_TYPE_PCA9450A = 0, PCA9450_TYPE_PCA9450BC, PCA9450_TYPE_PCA9451A, + PCA9450_TYPE_PCA9452, PCA9450_TYPE_AMOUNT, }; -- cgit v1.2.3 From 1156b5e8be98c97087f8971609c852e418daf03b Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Sat, 4 Jan 2025 17:20:57 +0530 Subject: regulator: Guard of_regulator_bulk_get_all() with CONFIG_OF Since the definition is in drivers/regulator/of_regulator.c and compiled only if CONFIG_OF is enabled, building the consumer driver without CONFIG_OF and with CONFIG_REGULATOR will result in below build error: ERROR: modpost: "of_regulator_bulk_get_all" [drivers/pci/pwrctrl/pci-pwrctl-slot.ko] undefined! Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202412181640.12Iufkvd-lkp@intel.com/ Fixes: 27b9ecc7a9ba ("regulator: Add of_regulator_bulk_get_all") Signed-off-by: Manivannan Sadhasivam Reviewed-by: Bartosz Golaszewski Link: https://patch.msgid.link/20250104115058.19216-2-manivannan.sadhasivam@linaro.org Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'include/linux/regulator') diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 8c3c372ad735..85be83c8fa17 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -175,6 +175,8 @@ struct regulator *__must_check of_regulator_get_optional(struct device *dev, struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, struct device_node *node, const char *id); +int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers); #else static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev, struct device_node *node, @@ -189,6 +191,13 @@ static inline struct regulator *__must_check devm_of_regulator_get_optional(stru { return ERR_PTR(-ENODEV); } + +static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers) +{ + return 0; +} + #endif int regulator_register_supply_alias(struct device *dev, const char *id, @@ -223,8 +232,6 @@ int regulator_disable_deferred(struct regulator *regulator, int ms); int __must_check regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); -int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np, - struct regulator_bulk_data **consumers); int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers); void devm_regulator_bulk_put(struct regulator_bulk_data *consumers); @@ -483,12 +490,6 @@ static inline int devm_regulator_bulk_get(struct device *dev, int num_consumers, return 0; } -static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, - struct regulator_bulk_data **consumers) -{ - return 0; -} - static inline int devm_regulator_bulk_get_const( struct device *dev, int num_consumers, const struct regulator_bulk_data *in_consumers, -- cgit v1.2.3 From 907af7d6e0c8cf4086b1bc5218281b2ca09f130b Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Sat, 4 Jan 2025 17:20:58 +0530 Subject: regulator: Move OF_ API declarations/definitions outside CONFIG_REGULATOR Since these are hidden inside CONFIG_REGULATOR, building the consumer drivers without CONFIG_REGULATOR will result in the following build error: >> drivers/pci/pwrctrl/slot.c:39:15: error: implicit declaration of function 'of_regulator_bulk_get_all'; did you mean 'regulator_bulk_get'? [-Werror=implicit-function-declaration] 39 | ret = of_regulator_bulk_get_all(dev, dev_of_node(dev), | ^~~~~~~~~~~~~~~~~~~~~~~~~ | regulator_bulk_get cc1: some warnings being treated as errors This also removes the duplicated definitions that were possibly added to fix the build issues. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202501020407.HmQQQKa0-lkp@intel.com/ Fixes: 27b9ecc7a9ba ("regulator: Add of_regulator_bulk_get_all") Signed-off-by: Manivannan Sadhasivam Link: https://patch.msgid.link/20250104115058.19216-3-manivannan.sadhasivam@linaro.org Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 78 ++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 46 deletions(-) (limited to 'include/linux/regulator') diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 85be83c8fa17..bcba3935c6f9 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -168,38 +168,6 @@ int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id); void regulator_put(struct regulator *regulator); void devm_regulator_put(struct regulator *regulator); -#if IS_ENABLED(CONFIG_OF) -struct regulator *__must_check of_regulator_get_optional(struct device *dev, - struct device_node *node, - const char *id); -struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, - struct device_node *node, - const char *id); -int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np, - struct regulator_bulk_data **consumers); -#else -static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev, - struct device_node *node, - const char *id) -{ - return ERR_PTR(-ENODEV); -} - -static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, - struct device_node *node, - const char *id) -{ - return ERR_PTR(-ENODEV); -} - -static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, - struct regulator_bulk_data **consumers) -{ - return 0; -} - -#endif - int regulator_register_supply_alias(struct device *dev, const char *id, struct device *alias_dev, const char *alias_id); @@ -380,20 +348,6 @@ devm_regulator_get_optional(struct device *dev, const char *id) return ERR_PTR(-ENODEV); } -static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev, - struct device_node *node, - const char *id) -{ - return ERR_PTR(-ENODEV); -} - -static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, - struct device_node *node, - const char *id) -{ - return ERR_PTR(-ENODEV); -} - static inline void regulator_put(struct regulator *regulator) { } @@ -701,6 +655,38 @@ regulator_is_equal(struct regulator *reg1, struct regulator *reg2) } #endif +#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_REGULATOR) +struct regulator *__must_check of_regulator_get_optional(struct device *dev, + struct device_node *node, + const char *id); +struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, + struct device_node *node, + const char *id); +int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers); +#else +static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev, + struct device_node *node, + const char *id) +{ + return ERR_PTR(-ENODEV); +} + +static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev, + struct device_node *node, + const char *id) +{ + return ERR_PTR(-ENODEV); +} + +static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, + struct regulator_bulk_data **consumers) +{ + return 0; +} + +#endif + static inline int regulator_set_voltage_triplet(struct regulator *regulator, int min_uV, int target_uV, int max_uV) -- cgit v1.2.3 From 42d7c87b4e1251f36eceac987e74623e7cda8577 Mon Sep 17 00:00:00 2001 From: Kory Maincent Date: Wed, 15 Jan 2025 15:41:57 +0100 Subject: regulator: Add support for power budget Introduce power budget management for the regulator device. Enable tracking of available power capacity by providing helpers to request and release power budget allocations. Signed-off-by: Kory Maincent Link: https://patch.msgid.link/20250115-feature_regulator_pw_budget-v2-1-0a44b949e6bc@bootlin.com Signed-off-by: Mark Brown --- drivers/regulator/core.c | 114 +++++++++++++++++++++++++++++++++++++ drivers/regulator/of_regulator.c | 3 + include/linux/regulator/consumer.h | 21 +++++++ include/linux/regulator/driver.h | 2 + include/linux/regulator/machine.h | 2 + 5 files changed, 142 insertions(+) (limited to 'include/linux/regulator') diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c092b78c5f12..6c0ef1182248 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -917,6 +917,26 @@ static ssize_t bypass_show(struct device *dev, } static DEVICE_ATTR_RO(bypass); +static ssize_t power_budget_milliwatt_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", rdev->constraints->pw_budget_mW); +} +static DEVICE_ATTR_RO(power_budget_milliwatt); + +static ssize_t power_requested_milliwatt_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", rdev->pw_requested_mW); +} +static DEVICE_ATTR_RO(power_requested_milliwatt); + #define REGULATOR_ERROR_ATTR(name, bit) \ static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \ char *buf) \ @@ -1149,6 +1169,10 @@ static void print_constraints_debug(struct regulator_dev *rdev) if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) count += scnprintf(buf + count, len - count, "standby "); + if (constraints->pw_budget_mW) + count += scnprintf(buf + count, len - count, "%d mW budget", + constraints->pw_budget_mW); + if (!count) count = scnprintf(buf, len, "no parameters"); else @@ -1627,6 +1651,9 @@ static int set_machine_constraints(struct regulator_dev *rdev) rdev->last_off = ktime_get(); } + if (!rdev->constraints->pw_budget_mW) + rdev->constraints->pw_budget_mW = INT_MAX; + print_constraints(rdev); return 0; } @@ -4601,6 +4628,87 @@ int regulator_get_current_limit(struct regulator *regulator) } EXPORT_SYMBOL_GPL(regulator_get_current_limit); +/** + * regulator_get_unclaimed_power_budget - get regulator unclaimed power budget + * @regulator: regulator source + * + * Return: Unclaimed power budget of the regulator in mW. + */ +int regulator_get_unclaimed_power_budget(struct regulator *regulator) +{ + return regulator->rdev->constraints->pw_budget_mW - + regulator->rdev->pw_requested_mW; +} +EXPORT_SYMBOL_GPL(regulator_get_unclaimed_power_budget); + +/** + * regulator_request_power_budget - request power budget on a regulator + * @regulator: regulator source + * @pw_req: Power requested + * + * Return: 0 on success or a negative error number on failure. + */ +int regulator_request_power_budget(struct regulator *regulator, + unsigned int pw_req) +{ + struct regulator_dev *rdev = regulator->rdev; + int ret = 0, pw_tot_req; + + regulator_lock(rdev); + if (rdev->supply) { + ret = regulator_request_power_budget(rdev->supply, pw_req); + if (ret < 0) + goto out; + } + + pw_tot_req = rdev->pw_requested_mW + pw_req; + if (pw_tot_req > rdev->constraints->pw_budget_mW) { + rdev_warn(rdev, "power requested %d mW out of budget %d mW", + pw_req, + rdev->constraints->pw_budget_mW - rdev->pw_requested_mW); + regulator_notifier_call_chain(rdev, + REGULATOR_EVENT_OVER_CURRENT_WARN, + NULL); + ret = -ERANGE; + goto out; + } + + rdev->pw_requested_mW = pw_tot_req; +out: + regulator_unlock(rdev); + return ret; +} +EXPORT_SYMBOL_GPL(regulator_request_power_budget); + +/** + * regulator_free_power_budget - free power budget on a regulator + * @regulator: regulator source + * @pw: Power to be released. + * + * Return: Power budget of the regulator in mW. + */ +void regulator_free_power_budget(struct regulator *regulator, + unsigned int pw) +{ + struct regulator_dev *rdev = regulator->rdev; + int pw_tot_req; + + regulator_lock(rdev); + if (rdev->supply) + regulator_free_power_budget(rdev->supply, pw); + + pw_tot_req = rdev->pw_requested_mW - pw; + if (pw_tot_req >= 0) + rdev->pw_requested_mW = pw_tot_req; + else + rdev_warn(rdev, + "too much power freed %d mW (already requested %d mW)", + pw, rdev->pw_requested_mW); + + regulator_unlock(rdev); +} +EXPORT_SYMBOL_GPL(regulator_free_power_budget); + /** * regulator_set_mode - set regulator operating mode * @regulator: regulator source @@ -5239,6 +5347,8 @@ static struct attribute *regulator_dev_attrs[] = { &dev_attr_suspend_standby_mode.attr, &dev_attr_suspend_mem_mode.attr, &dev_attr_suspend_disk_mode.attr, + &dev_attr_power_budget_milliwatt.attr, + &dev_attr_power_requested_milliwatt.attr, NULL }; @@ -5320,6 +5430,10 @@ static umode_t regulator_attr_is_visible(struct kobject *kobj, attr == &dev_attr_suspend_disk_mode.attr) return ops->set_suspend_mode ? mode : 0; + if (attr == &dev_attr_power_budget_milliwatt.attr || + attr == &dev_attr_power_requested_milliwatt.attr) + return rdev->constraints->pw_budget_mW != INT_MAX ? mode : 0; + return mode; } diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 6acbd5f2e796..d8597215289f 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -125,6 +125,9 @@ static int of_get_regulation_constraints(struct device *dev, if (constraints->min_uA != constraints->max_uA) constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; + if (!of_property_read_u32(np, "regulator-power-budget-milliwatt", &pval)) + constraints->pw_budget_mW = pval; + constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); constraints->always_on = of_property_read_bool(np, "regulator-always-on"); if (!constraints->always_on) /* status change should be possible. */ diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 8c3c372ad735..8d1a6eca7eb9 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -258,6 +258,11 @@ int regulator_sync_voltage(struct regulator *regulator); int regulator_set_current_limit(struct regulator *regulator, int min_uA, int max_uA); int regulator_get_current_limit(struct regulator *regulator); +int regulator_get_unclaimed_power_budget(struct regulator *regulator); +int regulator_request_power_budget(struct regulator *regulator, + unsigned int pw_req); +void regulator_free_power_budget(struct regulator *regulator, + unsigned int pw); int regulator_set_mode(struct regulator *regulator, unsigned int mode); unsigned int regulator_get_mode(struct regulator *regulator); @@ -571,6 +576,22 @@ static inline int regulator_get_current_limit(struct regulator *regulator) return 0; } +static inline int regulator_get_unclaimed_power_budget(struct regulator *regulator) +{ + return INT_MAX; +} + +static inline int regulator_request_power_budget(struct regulator *regulator, + unsigned int pw_req) +{ + return -EOPNOTSUPP; +} + +static inline void regulator_free_power_budget(struct regulator *regulator, + unsigned int pw) +{ +} + static inline int regulator_set_mode(struct regulator *regulator, unsigned int mode) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 5b66caf1695d..4a216fdba354 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -656,6 +656,8 @@ struct regulator_dev { int cached_err; bool use_cached_err; spinlock_t err_lock; + + int pw_requested_mW; }; /* diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index b3db09a7429b..1fc440c5c4c7 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -113,6 +113,7 @@ struct notification_limit { * @min_uA: Smallest current consumers may set. * @max_uA: Largest current consumers may set. * @ilim_uA: Maximum input current. + * @pw_budget_mW: Power budget for the regulator in mW. * @system_load: Load that isn't captured by any consumer requests. * * @over_curr_limits: Limits for acting on over current. @@ -185,6 +186,7 @@ struct regulation_constraints { int max_uA; int ilim_uA; + int pw_budget_mW; int system_load; /* used for coupled regulators */ -- cgit v1.2.3