This commit is contained in:
Tom Rini 2023-07-04 11:22:57 -04:00
commit 45f77b807c
6 changed files with 107 additions and 59 deletions

View File

@ -101,7 +101,7 @@ struct fan53555_priv {
static int fan53555_regulator_of_to_plat(struct udevice *dev) 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 = struct dm_regulator_uclass_plat *uc_pdata =
dev_get_uclass_plat(dev); dev_get_uclass_plat(dev);
u32 sleep_vsel; u32 sleep_vsel;
@ -118,12 +118,12 @@ static int fan53555_regulator_of_to_plat(struct udevice *dev)
*/ */
switch (sleep_vsel) { switch (sleep_vsel) {
case FAN53555_VSEL0: case FAN53555_VSEL0:
dev_pdata->sleep_reg = FAN53555_VSEL0; plat->sleep_reg = FAN53555_VSEL0;
dev_pdata->vol_reg = FAN53555_VSEL1; plat->vol_reg = FAN53555_VSEL1;
break; break;
case FAN53555_VSEL1: case FAN53555_VSEL1:
dev_pdata->sleep_reg = FAN53555_VSEL1; plat->sleep_reg = FAN53555_VSEL1;
dev_pdata->vol_reg = FAN53555_VSEL0; plat->vol_reg = FAN53555_VSEL0;
break; break;
default: default:
pr_err("%s: invalid vsel id %d\n", dev->name, sleep_vsel); pr_err("%s: invalid vsel id %d\n", dev->name, sleep_vsel);

View File

@ -24,16 +24,16 @@ struct fixed_clock_regulator_plat {
static int fixed_regulator_of_to_plat(struct udevice *dev) static int fixed_regulator_of_to_plat(struct udevice *dev)
{ {
struct dm_regulator_uclass_plat *uc_pdata; 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); uc_pdata = dev_get_uclass_plat(dev);
if (!uc_pdata) if (!uc_pdata)
return -ENXIO; return -ENXIO;
uc_pdata->type = REGULATOR_TYPE_FIXED; 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) 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) static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
{ {
struct fixed_clock_regulator_plat *priv = dev_get_priv(dev); 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; int ret = 0;
if (enable) { if (enable) {
@ -101,11 +101,11 @@ static int fixed_clock_regulator_set_enable(struct udevice *dev, bool enable)
if (ret) if (ret)
return ret; return ret;
if (enable && dev_pdata->startup_delay_us) if (enable && plat->startup_delay_us)
udelay(dev_pdata->startup_delay_us); udelay(plat->startup_delay_us);
if (!enable && dev_pdata->off_on_delay_us) if (!enable && plat->off_on_delay_us)
udelay(dev_pdata->off_on_delay_us); udelay(plat->off_on_delay_us);
return ret; return ret;
} }

View File

@ -27,12 +27,12 @@ struct gpio_regulator_plat {
static int gpio_regulator_of_to_plat(struct udevice *dev) static int gpio_regulator_of_to_plat(struct udevice *dev)
{ {
struct dm_regulator_uclass_plat *uc_pdata; struct dm_regulator_uclass_plat *uc_pdata;
struct gpio_regulator_plat *dev_pdata; struct gpio_regulator_plat *plat;
struct gpio_desc *gpio; struct gpio_desc *gpio;
int ret, count, i, j; int ret, count, i, j;
u32 states_array[GPIO_REGULATOR_MAX_STATES * 2]; 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); uc_pdata = dev_get_uclass_plat(dev);
if (!uc_pdata) if (!uc_pdata)
return -ENXIO; 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 * per gpio-regulator. As of now no instance with multiple
* gpios is presnt * gpios is presnt
*/ */
gpio = &dev_pdata->gpio; gpio = &plat->gpio;
ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT); ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
if (ret) if (ret)
debug("regulator gpio - not found! Error: %d", 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; return ret;
for (i = 0, j = 0; i < count; i += 2) { for (i = 0, j = 0; i < count; i += 2) {
dev_pdata->voltages[j] = states_array[i]; plat->voltages[j] = states_array[i];
dev_pdata->states[j] = states_array[i + 1]; plat->states[j] = states_array[i + 1];
j++; 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) static int gpio_regulator_get_value(struct udevice *dev)
{ {
struct dm_regulator_uclass_plat *uc_pdata; 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; int enable;
if (!dev_pdata->gpio.dev) if (!plat->gpio.dev)
return -ENOSYS; return -ENOSYS;
uc_pdata = dev_get_uclass_plat(dev); uc_pdata = dev_get_uclass_plat(dev);
@ -91,30 +91,30 @@ static int gpio_regulator_get_value(struct udevice *dev)
return -EINVAL; return -EINVAL;
} }
enable = dm_gpio_get_value(&dev_pdata->gpio); enable = dm_gpio_get_value(&plat->gpio);
if (enable == dev_pdata->states[0]) if (enable == plat->states[0])
return dev_pdata->voltages[0]; return plat->voltages[0];
else else
return dev_pdata->voltages[1]; return plat->voltages[1];
} }
static int gpio_regulator_set_value(struct udevice *dev, int uV) 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; int ret;
bool enable; bool enable;
if (!dev_pdata->gpio.dev) if (!plat->gpio.dev)
return -ENOSYS; return -ENOSYS;
if (uV == dev_pdata->voltages[0]) if (uV == plat->voltages[0])
enable = dev_pdata->states[0]; enable = plat->states[0];
else if (uV == dev_pdata->voltages[1]) else if (uV == plat->voltages[1])
enable = dev_pdata->states[1]; enable = plat->states[1];
else else
return -EINVAL; return -EINVAL;
ret = dm_gpio_set_value(&dev_pdata->gpio, enable); ret = dm_gpio_set_value(&plat->gpio, enable);
if (ret) { if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name, pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
enable); 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) static int gpio_regulator_get_enable(struct udevice *dev)
{ {
struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev); struct gpio_regulator_plat *plat = dev_get_plat(dev);
return regulator_common_get_enable(dev, &dev_pdata->common); return regulator_common_get_enable(dev, &plat->common);
} }
static int gpio_regulator_set_enable(struct udevice *dev, bool enable) static int gpio_regulator_set_enable(struct udevice *dev, bool enable)
{ {
struct gpio_regulator_plat *dev_pdata = dev_get_plat(dev); struct gpio_regulator_plat *plat = dev_get_plat(dev);
return regulator_common_set_enable(dev, &dev_pdata->common, enable); return regulator_common_set_enable(dev, &plat->common, enable);
} }
static const struct dm_regulator_ops gpio_regulator_ops = { static const struct dm_regulator_ops gpio_regulator_ops = {

View File

@ -197,6 +197,12 @@ int regulator_set_enable_if_allowed(struct udevice *dev, bool enable)
ret = regulator_set_enable(dev, enable); ret = regulator_set_enable(dev, enable);
if (ret == -ENOSYS || ret == -EACCES) if (ret == -ENOSYS || ret == -EACCES)
return 0; 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; return ret;
} }

View File

@ -13,7 +13,7 @@
#include "regulator_common.h" #include "regulator_common.h"
int regulator_common_of_to_plat(struct udevice *dev, 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) const char *enable_gpio_name)
{ {
struct gpio_desc *gpio; struct gpio_desc *gpio;
@ -26,7 +26,7 @@ int regulator_common_of_to_plat(struct udevice *dev,
flags |= GPIOD_IS_OUT_ACTIVE; flags |= GPIOD_IS_OUT_ACTIVE;
/* Get optional enable GPIO desc */ /* Get optional enable GPIO desc */
gpio = &dev_pdata->gpio; gpio = &plat->gpio;
ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, flags); ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, flags);
if (ret) { if (ret) {
debug("Regulator '%s' optional enable GPIO - not found! Error: %d\n", 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 */ /* Get optional ramp up delay */
dev_pdata->startup_delay_us = dev_read_u32_default(dev, plat->startup_delay_us = dev_read_u32_default(dev,
"startup-delay-us", 0); "startup-delay-us", 0);
dev_pdata->off_on_delay_us = plat->off_on_delay_us = dev_read_u32_default(dev, "off-on-delay-us", 0);
dev_read_u32_default(dev, "off-on-delay-us", 0); if (!plat->off_on_delay_us) {
if (!dev_pdata->off_on_delay_us) { plat->off_on_delay_us =
dev_pdata->off_on_delay_us =
dev_read_u32_default(dev, "u-boot,off-on-delay-us", 0); 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, int regulator_common_get_enable(const struct udevice *dev,
struct regulator_common_plat *dev_pdata) struct regulator_common_plat *plat)
{ {
/* Enable GPIO is optional */ /* Enable GPIO is optional */
if (!dev_pdata->gpio.dev) if (!plat->gpio.dev)
return true; 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, 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; int ret;
debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__, debug("%s: dev='%s', enable=%d, delay=%d, has_gpio=%d\n", __func__,
dev->name, enable, dev_pdata->startup_delay_us, dev->name, enable, plat->startup_delay_us,
dm_gpio_is_valid(&dev_pdata->gpio)); dm_gpio_is_valid(&plat->gpio));
/* Enable GPIO is optional */ /* Enable GPIO is optional */
if (!dm_gpio_is_valid(&dev_pdata->gpio)) { if (!dm_gpio_is_valid(&plat->gpio)) {
if (!enable) if (!enable)
return -ENOSYS; return -ENOSYS;
return 0; 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) { if (ret) {
pr_err("Can't set regulator : %s gpio to: %d\n", dev->name, pr_err("Can't set regulator : %s gpio to: %d\n", dev->name,
enable); enable);
return ret; return ret;
} }
if (enable && dev_pdata->startup_delay_us) if (enable && plat->startup_delay_us)
udelay(dev_pdata->startup_delay_us); udelay(plat->startup_delay_us);
debug("%s: done\n", __func__); debug("%s: done\n", __func__);
if (!enable && dev_pdata->off_on_delay_us) if (!enable && plat->off_on_delay_us)
udelay(dev_pdata->off_on_delay_us); udelay(plat->off_on_delay_us);
if (enable)
plat->enable_count++;
else
plat->enable_count--;
return 0; return 0;
} }

View File

@ -13,14 +13,35 @@ struct regulator_common_plat {
struct gpio_desc gpio; /* GPIO for regulator enable control */ struct gpio_desc gpio; /* GPIO for regulator enable control */
unsigned int startup_delay_us; unsigned int startup_delay_us;
unsigned int off_on_delay_us; unsigned int off_on_delay_us;
unsigned int enable_count;
}; };
int regulator_common_of_to_plat(struct udevice *dev, 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); char *enable_gpio_name);
int regulator_common_get_enable(const struct udevice *dev, 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, 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 */ #endif /* _REGULATOR_COMMON_H */