]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
kernel: pse-pd: Fix missing regulator backport 21996/head
authorBevan Weiss <bevan.weiss@gmail.com>
Thu, 12 Feb 2026 06:05:12 +0000 (17:05 +1100)
committerRobert Marko <robimarko@gmail.com>
Fri, 13 Feb 2026 20:14:45 +0000 (21:14 +0100)
Fixes: 528c9259a70f Backport the PSE-PD...
When the original backport bring-in was done, the regulator power budget
portion was missed.  This results in kernel build errors when trying to
bring in PSE_CONTROLLER or PSE_REGULATOR configs.  Which are required to
bring in further PSE drivers.
Bring in the backport to fix that up.  Patch series naming is a bit wrong
here, but keeps patches together in ordering, whilst reducing files
touched in this commit.

Without this patch, when adding config of
CONFIG_PSE_CONTROLLER=y
CONFIG_PSE_REGULATOR=y
CONFIG_PSE_TPS23881=y
CONFIG_REGULATOR=y

The following errors occur:
drivers/net/pse-pd/pse_core.c:446:9:
  error: implicit declaration of function 'regulator_free_power_budget'

drivers/net/pse-pd/pse_core.c:559:16:
  error: implicit declaration of function 'regulator_request_power_budget'

Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/21996
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/generic/backport-6.12/626-16b-v6.17-regulator-Add-support-for-power-budget.patch [new file with mode: 0644]

diff --git a/target/linux/generic/backport-6.12/626-16b-v6.17-regulator-Add-support-for-power-budget.patch b/target/linux/generic/backport-6.12/626-16b-v6.17-regulator-Add-support-for-power-budget.patch
new file mode 100644 (file)
index 0000000..8f63044
--- /dev/null
@@ -0,0 +1,257 @@
+From 42d7c87b4e1251f36eceac987e74623e7cda8577 Mon Sep 17 00:00:00 2001
+From: Kory Maincent <kory.maincent@bootlin.com>
+Date: Wed, 15 Jan 2025 15:41:57 +0100
+Subject: [PATCH] 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 <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20250115-feature_regulator_pw_budget-v2-1-0a44b949e6bc@bootlin.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com>
+---
+ 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(+)
+
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -916,6 +916,26 @@ static ssize_t bypass_show(struct device
+ }
+ 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)                                           \
+@@ -1148,6 +1168,10 @@ static void print_constraints_debug(stru
+       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
+@@ -1631,6 +1655,9 @@ static int set_machine_constraints(struc
+               rdev->last_off = ktime_get();
+       }
++      if (!rdev->constraints->pw_budget_mW)
++              rdev->constraints->pw_budget_mW = INT_MAX;
++
+       print_constraints(rdev);
+       return 0;
+ }
+@@ -4646,6 +4673,87 @@ int regulator_get_current_limit(struct r
+ 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
+  * @mode: operating mode - one of the REGULATOR_MODE constants
+@@ -5283,6 +5391,8 @@ static struct attribute *regulator_dev_a
+       &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
+ };
+@@ -5364,6 +5474,10 @@ static umode_t regulator_attr_is_visible
+           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;
+ }
+--- a/drivers/regulator/of_regulator.c
++++ b/drivers/regulator/of_regulator.c
+@@ -125,6 +125,9 @@ static int of_get_regulation_constraints
+       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. */
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -235,6 +235,11 @@ int regulator_sync_voltage(struct regula
+ 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);
+@@ -534,6 +539,22 @@ static inline int regulator_get_current_
+       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)
+ {
+--- a/include/linux/regulator/driver.h
++++ b/include/linux/regulator/driver.h
+@@ -649,6 +649,8 @@ struct regulator_dev {
+       int cached_err;
+       bool use_cached_err;
+       spinlock_t err_lock;
++
++      int pw_requested_mW;
+ };
+ /*
+--- 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 */