aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-07-04 11:22:57 -0400
committerTom Rini <trini@konsulko.com>2023-07-04 11:22:57 -0400
commit45f77b807c2f6b8da88ae897b7eb2238e25df36b (patch)
tree744bd9cc4265fb5ad94e82a9e7ff25df44950c4e
parent67d8b46e6efa306403e45f4c76f24b86a5e63b75 (diff)
parent8202bc29454cfdd5839058e4b79c36a3fbb221cf (diff)
downloadu-boot-WIP/04Jul2023-next.zip
u-boot-WIP/04Jul2023-next.tar.gz
u-boot-WIP/04Jul2023-next.tar.bz2
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-pmic into nextWIP/04Jul2023-next
-rw-r--r--drivers/power/regulator/fan53555.c10
-rw-r--r--drivers/power/regulator/fixed.c16
-rw-r--r--drivers/power/regulator/gpio-regulator.c46
-rw-r--r--drivers/power/regulator/regulator-uclass.c6
-rw-r--r--drivers/power/regulator/regulator_common.c61
-rw-r--r--drivers/power/regulator/regulator_common.h27
6 files changed, 107 insertions, 59 deletions
diff --git a/drivers/power/regulator/fan53555.c b/drivers/power/regulator/fan53555.c
index 5681206..815f96b 100644
--- a/drivers/power/regulator/fan53555.c
+++ b/drivers/power/regulator/fan53555.c
@@ -101,7 +101,7 @@ struct fan53555_priv {
static int fan53555_regulator_of_to_plat(struct udevice *dev)
{
- struct fan53555_plat *dev_pdata = dev_get_plat(dev);
+ struct fan53555_plat *plat = dev_get_plat(dev);
struct dm_regulator_uclass_plat *uc_pdata =
dev_get_uclass_plat(dev);
u32 sleep_vsel;
@@ -118,12 +118,12 @@ static int fan53555_regulator_of_to_plat(struct udevice *dev)
*/
switch (sleep_vsel) {
case FAN53555_VSEL0:
- dev_pdata->sleep_reg = FAN53555_VSEL0;
- dev_pdata->vol_reg = FAN53555_VSEL1;
+ plat->sleep_reg = FAN53555_VSEL0;
+ plat->vol_reg = FAN53555_VSEL1;
break;
case FAN53555_VSEL1:
- dev_pdata->sleep_reg = FAN53555_VSEL1;
- dev_pdata->vol_reg = FAN53555_VSEL0;
+ plat->sleep_reg = FAN53555_VSEL1;
+ plat->vol_reg = FAN53555_VSEL0;
break;
default:
pr_err("%s: invalid vsel id %d\n", dev->name, sleep_vsel);
diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index 90004d1..ad3b4b9 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -24,16 +24,16 @@ struct fixed_clock_regulator_plat {
static int fixed_regulator_of_to_plat(struct udevice *dev)
{
struct dm_regulator_uclass_plat *uc_pdata;
- struct regulator_common_plat *dev_pdata;
+ struct regulator_common_plat *plat;
- dev_pdata = dev_get_plat(dev);
+ plat = dev_get_plat(dev);
uc_pdata = dev_get_uclass_plat(dev);
if (!uc_pdata)
return -ENXIO;
uc_pdata->type = REGULATOR_TYPE_FIXED;
- return regulator_common_of_to_plat(dev, dev_pdata, "gpio");
+ return regulator_common_of_to_plat(dev, plat, "gpio");
}
static int fixed_regulator_get_value(struct udevice *dev)
@@ -88,7 +88,7 @@ static int fixed_clock_regulator_get_enable(struct udevice *dev)
static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
{
struct fixed_clock_regulator_plat *priv = dev_get_priv(dev);
- struct regulator_common_plat *dev_pdata = dev_get_plat(dev);
+ struct regulator_common_plat *plat = dev_get_plat(dev);
int ret = 0;
if (enable) {
@@ -101,11 +101,11 @@ static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
if (ret)
return ret;
- if (enable && dev_pdata->startup_delay_us)
- udelay(dev_pdata->startup_delay_us);
+ if (enable && plat->startup_delay_us)
+ udelay(plat->startup_delay_us);
- if (!enable && dev_pdata->off_on_delay_us)
- udelay(dev_pdata->off_on_delay_us);
+ if (!enable && plat->off_on_delay_us)
+ udelay(plat->off_on_delay_us);
return ret;
}
diff --git a/drivers/power/regulator/gpio-regulator.c b/drivers/power/regulator/gpio-regulator.c
index 9c0a68a..ded7be0 100644
--- a/drivers/power/regulator/gpio-regulator.c
+++ b/drivers/power/regulator/gpio-regulator.c
@@ -27,12 +27,12 @@ struct gpio_regulator_plat {
static int gpio_regulator_of_to_plat(struct udevice *dev)
{
struct dm_regulator_uclass_plat *uc_pdata;
- struct gpio_regulator_plat *dev_pdata;
+ struct gpio_regulator_plat *plat;
struct gpio_desc *gpio;
int ret, count, i, j;
u32 states_array[GPIO_REGULATOR_MAX_STATES * 2];
- dev_pdata = dev_get_plat(dev);
+ plat = dev_get_plat(dev);
uc_pdata = dev_get_uclass_plat(dev);
if (!uc_pdata)
return -ENXIO;
@@ -47,7 +47,7 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
* per gpio-regulator. As of now no instance with multiple
* gpios is presnt
*/
- gpio = &dev_pdata->gpio;
+ gpio = &plat->gpio;
ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
if (ret)
debug("regulator gpio - not found! Error: %d", ret);
@@ -68,21 +68,21 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
return ret;
for (i = 0, j = 0; i < count; i += 2) {
- dev_pdata->voltages[j] = states_array[i];
- dev_pdata->states[j] = states_array[i + 1];
+ plat->voltages[j] = states_array[i];
+ plat->states[j] = states_array[i + 1];
j++;
}
- return regulator_common_of_to_plat(dev, &dev_pdata->common, "enable-gpios");
+ return regulator_common_of_to_plat(dev, &plat->common, "enable-gpios");
}
static int gpio_regulator_get_value(struct udevice *dev)
{
struct dm_regulator_uclass_plat *uc_pdata;
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
int enable;
- if (!dev_pdata->gpio.dev)
+ if (!plat->gpio.dev)
return -ENOSYS;
uc_pdata = dev_get_uclass_plat(dev);
@@ -91,30 +91,30 @@ static int gpio_regulator_get_value(struct udevice *dev)
return -EINVAL;
}
- enable = dm_gpio_get_value(&dev_pdata->gpio);
- if (enable == dev_pdata->states[0])
- return dev_pdata->voltages[0];
+ enable = dm_gpio_get_value(&plat->gpio);
+ if (enable == plat->states[0])
+ return plat->voltages[0];
else
- return dev_pdata->voltages[1];
+ return plat->voltages[1];
}
static int gpio_regulator_set_value(struct udevice *dev, int uV)
{
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
int ret;
bool enable;
- if (!dev_pdata->gpio.dev)
+ if (!plat->gpio.dev)
return -ENOSYS;
- if (uV == dev_pdata->voltages[0])
- enable = dev_pdata->states[0];
- else if (uV == dev_pdata->voltages[1])
- enable = dev_pdata->states[1];
+ if (uV == plat->voltages[0])
+ enable = plat->states[0];
+ else if (uV == plat->voltages[1])
+ enable = plat->states[1];
else
return -EINVAL;
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
+ ret = dm_gpio_set_value(&plat->gpio, enable);
if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
@@ -126,14 +126,14 @@ static int gpio_regulator_set_value(struct udevice *dev, int uV)
static int gpio_regulator_get_enable(struct udevice *dev)
{
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
- return regulator_common_get_enable(dev, &dev_pdata->common);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
+ return regulator_common_get_enable(dev, &plat->common);
}
static int gpio_regulator_set_enable(struct udevice *dev, bool enable)
{
- struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev);
- return regulator_common_set_enable(dev, &dev_pdata->common, enable);
+ struct gpio_regulator_plat *plat = dev_get_plat(dev);
+ return regulator_common_set_enable(dev, &plat->common, enable);
}
static const struct dm_regulator_ops gpio_regulator_ops = {
diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index d608f7c..3a6ba69 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -197,6 +197,12 @@ int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
ret = regulator_set_enable(dev, enable);
if (ret == -ENOSYS || ret == -EACCES)
return 0;
+ /* if we want to disable but it's in use by someone else */
+ if (!enable && ret == -EBUSY)
+ return 0;
+ /* if it's already enabled/disabled */
+ if (ret == -EALREADY)
+ return 0;
return ret;
}
diff --git a/drivers/power/regulator/regulator_common.c b/drivers/power/regulator/regulator_common.c
index 93d8196..e26f5eb 100644
--- a/drivers/power/regulator/regulator_common.c
+++ b/drivers/power/regulator/regulator_common.c
@@ -13,7 +13,7 @@
#include "regulator_common.h"
int regulator_common_of_to_plat(struct udevice *dev,
- struct regulator_common_plat *dev_pdata,
+ struct regulator_common_plat *plat,
const char *enable_gpio_name)
{
struct gpio_desc *gpio;
@@ -26,7 +26,7 @@ int regulator_common_of_to_plat(struct udevice *dev,
flags |= GPIOD_IS_OUT_ACTIVE;
/* Get optional enable GPIO desc */
- gpio = &dev_pdata->gpio;
+ gpio = &plat->gpio;
ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, flags);
if (ret) {
debug("Regulator '%s' optional enable GPIO - not found! Error: %d\n",
@@ -36,12 +36,11 @@ int regulator_common_of_to_plat(struct udevice *dev,
}
/* Get optional ramp up delay */
- dev_pdata->startup_delay_us = dev_read_u32_default(dev,
- "startup-delay-us", 0);
- dev_pdata->off_on_delay_us =
- dev_read_u32_default(dev, "off-on-delay-us", 0);
- if (!dev_pdata->off_on_delay_us) {
- dev_pdata->off_on_delay_us =
+ plat->startup_delay_us = dev_read_u32_default(dev,
+ "startup-delay-us", 0);
+ plat->off_on_delay_us = dev_read_u32_default(dev, "off-on-delay-us", 0);
+ if (!plat->off_on_delay_us) {
+ plat->off_on_delay_us =
dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0);
}
@@ -49,43 +48,65 @@ int regulator_common_of_to_plat(struct udevice *dev,
}
int regulator_common_get_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata)
+ struct regulator_common_plat *plat)
{
/* Enable GPIO is optional */
- if (!dev_pdata->gpio.dev)
+ if (!plat->gpio.dev)
return true;
- return dm_gpio_get_value(&dev_pdata->gpio);
+ return dm_gpio_get_value(&plat->gpio);
}
int regulator_common_set_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata, bool enable)
+ struct regulator_common_plat *plat, bool enable)
{
int ret;
debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
- dev->name, enable, dev_pdata->startup_delay_us,
- dm_gpio_is_valid(&dev_pdata->gpio));
+ dev->name, enable, plat->startup_delay_us,
+ dm_gpio_is_valid(&plat->gpio));
/* Enable GPIO is optional */
- if (!dm_gpio_is_valid(&dev_pdata->gpio)) {
+ if (!dm_gpio_is_valid(&plat->gpio)) {
if (!enable)
return -ENOSYS;
return 0;
}
- ret = dm_gpio_set_value(&dev_pdata->gpio, enable);
+ /* If previously enabled, increase count */
+ if (enable && plat->enable_count > 0) {
+ plat->enable_count++;
+ return -EALREADY;
+ }
+
+ if (!enable) {
+ if (plat->enable_count > 1) {
+ /* If enabled multiple times, decrease count */
+ plat->enable_count--;
+ return -EBUSY;
+ } else if (!plat->enable_count) {
+ /* If already disabled, do nothing */
+ return -EALREADY;
+ }
+ }
+
+ ret = dm_gpio_set_value(&plat->gpio, enable);
if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
enable);
return ret;
}
- if (enable && dev_pdata->startup_delay_us)
- udelay(dev_pdata->startup_delay_us);
+ if (enable && plat->startup_delay_us)
+ udelay(plat->startup_delay_us);
debug("%s: done\n", __func__);
- if (!enable && dev_pdata->off_on_delay_us)
- udelay(dev_pdata->off_on_delay_us);
+ if (!enable && plat->off_on_delay_us)
+ udelay(plat->off_on_delay_us);
+
+ if (enable)
+ plat->enable_count++;
+ else
+ plat->enable_count--;
return 0;
}
diff --git a/drivers/power/regulator/regulator_common.h b/drivers/power/regulator/regulator_common.h
index c10492f..d496289 100644
--- a/drivers/power/regulator/regulator_common.h
+++ b/drivers/power/regulator/regulator_common.h
@@ -13,14 +13,35 @@ struct regulator_common_plat {
struct gpio_desc gpio; /* GPIO for regulator enable control */
unsigned int startup_delay_us;
unsigned int off_on_delay_us;
+ unsigned int enable_count;
};
int regulator_common_of_to_plat(struct udevice *dev,
- struct regulator_common_plat *dev_pdata, const
+ struct regulator_common_plat *plat, const
char *enable_gpio_name);
int regulator_common_get_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata);
+ struct regulator_common_plat *plat);
+/*
+ * Enable or Disable a regulator
+ *
+ * This is a reentrant function and subsequent calls that enable will
+ * increase an internal counter, and disable calls will decrease the counter.
+ * The actual resource will be enabled when the counter gets to 1 coming from 0,
+ * and disabled when it reaches 0 coming from 1.
+ *
+ * @dev: regulator device
+ * @plat: Platform data
+ * @enable: bool indicating whether to enable or disable the regulator
+ * @return:
+ * 0 on Success
+ * -EBUSY if the regulator cannot be disabled because it's requested by
+ * another device
+ * -EALREADY if the regulator has already been enabled or has already been
+ * disabled
+ * -EACCES if there is no possibility to enable/disable the regulator
+ * -ve on different error situation
+ */
int regulator_common_set_enable(const struct udevice *dev,
- struct regulator_common_plat *dev_pdata, bool enable);
+ struct regulator_common_plat *plat, bool enable);
#endif /* _REGULATOR_COMMON_H */