svn commit: r337705 - stable/11/sys/dev/extres/regulator
Michal Meloun
mmel at FreeBSD.org
Mon Aug 13 08:47:55 UTC 2018
Author: mmel
Date: Mon Aug 13 08:47:54 2018
New Revision: 337705
URL: https://svnweb.freebsd.org/changeset/base/337705
Log:
MFC r335249:
Fix handling of enable counter for shared GPIO line in fixed regulator.
Modified:
stable/11/sys/dev/extres/regulator/regnode_if.m
stable/11/sys/dev/extres/regulator/regulator.c
stable/11/sys/dev/extres/regulator/regulator_fixed.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/dev/extres/regulator/regnode_if.m
==============================================================================
--- stable/11/sys/dev/extres/regulator/regnode_if.m Mon Aug 13 07:28:25 2018 (r337704)
+++ stable/11/sys/dev/extres/regulator/regnode_if.m Mon Aug 13 08:47:54 2018 (r337705)
@@ -31,6 +31,15 @@ HEADER {
struct regnode;
}
+CODE {
+ static int
+ regnode_default_stop(struct regnode *regnode, int *udelay)
+ {
+
+ return(REGNODE_ENABLE(regnode, false, udelay));
+ }
+}
+
#
# Initialize regulator
# Returns 0 on success or a standard errno value.
@@ -80,3 +89,12 @@ METHOD int get_voltage {
struct regnode *regnode;
int *uvolt;
};
+
+#
+# Stop (shutdown) regulator
+# Returns 0 on success or a standard errno value.
+#
+METHOD int stop {
+ struct regnode *regnode;
+ int *udelay;
+} DEFAULT regnode_default_stop;
Modified: stable/11/sys/dev/extres/regulator/regulator.c
==============================================================================
--- stable/11/sys/dev/extres/regulator/regulator.c Mon Aug 13 07:28:25 2018 (r337704)
+++ stable/11/sys/dev/extres/regulator/regulator.c Mon Aug 13 08:47:54 2018 (r337705)
@@ -515,7 +515,7 @@ regnode_stop(struct regnode *regnode, int depth)
/* Disable regulator for each node in chain, starting from consumer */
if ((regnode->enable_cnt == 0) &&
((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) {
- rv = REGNODE_ENABLE(regnode, false, &udelay);
+ rv = REGNODE_STOP(regnode, &udelay);
if (rv != 0) {
REGNODE_UNLOCK(regnode);
return (rv);
@@ -527,7 +527,7 @@ regnode_stop(struct regnode *regnode, int depth)
rv = regnode_resolve_parent(regnode);
if (rv != 0)
return (rv);
- if (regnode->parent != NULL)
+ if (regnode->parent != NULL && regnode->parent->enable_cnt == 0)
rv = regnode_stop(regnode->parent, depth + 1);
return (rv);
}
Modified: stable/11/sys/dev/extres/regulator/regulator_fixed.c
==============================================================================
--- stable/11/sys/dev/extres/regulator/regulator_fixed.c Mon Aug 13 07:28:25 2018 (r337704)
+++ stable/11/sys/dev/extres/regulator/regulator_fixed.c Mon Aug 13 08:47:54 2018 (r337705)
@@ -56,6 +56,7 @@ struct gpio_entry {
struct gpiobus_pin gpio_pin;
int use_cnt;
int enable_cnt;
+ bool always_on;
};
static gpio_list_t gpio_list = TAILQ_HEAD_INITIALIZER(gpio_list);
static struct mtx gpio_list_mtx;
@@ -71,12 +72,14 @@ static int regnode_fixed_init(struct regnode *regnode)
static int regnode_fixed_enable(struct regnode *regnode, bool enable,
int *udelay);
static int regnode_fixed_status(struct regnode *regnode, int *status);
+static int regnode_fixed_stop(struct regnode *regnode, int *udelay);
static regnode_method_t regnode_fixed_methods[] = {
/* Regulator interface */
REGNODEMETHOD(regnode_init, regnode_fixed_init),
REGNODEMETHOD(regnode_enable, regnode_fixed_enable),
REGNODEMETHOD(regnode_status, regnode_fixed_status),
+ REGNODEMETHOD(regnode_stop, regnode_fixed_stop),
REGNODEMETHOD_END
};
DEFINE_CLASS_1(regnode_fixed, regnode_fixed_class, regnode_fixed_methods,
@@ -188,8 +191,6 @@ regnode_fixed_enable(struct regnode *regnode, bool ena
dev = regnode_get_device(regnode);
*udelay = 0;
- if (sc->param->always_on && !enable)
- return (0);
if (sc->gpio_entry == NULL)
return (0);
pin = &sc->gpio_entry->gpio_pin;
@@ -204,6 +205,8 @@ regnode_fixed_enable(struct regnode *regnode, bool ena
if (sc->gpio_entry->enable_cnt >= 1)
return (0);
}
+ if (sc->gpio_entry->always_on && !enable)
+ return (0);
if (!sc->param->enable_active_high)
enable = !enable;
rv = GPIO_PIN_SET(pin->dev, pin->pin, enable);
@@ -215,7 +218,43 @@ regnode_fixed_enable(struct regnode *regnode, bool ena
return (0);
}
+/*
+ * Stop (physicaly shutdown) regulator.
+ * Take shared GPIO pins in account
+ */
static int
+regnode_fixed_stop(struct regnode *regnode, int *udelay)
+{
+ device_t dev;
+ struct regnode_fixed_sc *sc;
+ struct gpiobus_pin *pin;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ dev = regnode_get_device(regnode);
+
+ *udelay = 0;
+ if (sc->gpio_entry == NULL)
+ return (0);
+ if (sc->gpio_entry->always_on)
+ return (0);
+ pin = &sc->gpio_entry->gpio_pin;
+ if (sc->gpio_entry->enable_cnt > 0) {
+ /* Other regulator(s) are enabled. */
+ /* XXXX Any diagnostic message? Or error? */
+ return (0);
+ }
+ rv = GPIO_PIN_SET(pin->dev, pin->pin,
+ sc->param->enable_active_high ? false: true);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+ *udelay = sc->param->enable_delay;
+ return (0);
+}
+
+static int
regnode_fixed_status(struct regnode *regnode, int *status)
{
struct regnode_fixed_sc *sc;
@@ -264,6 +303,10 @@ regnode_fixed_register(device_t dev, struct regnode_fi
device_printf(dev, "Cannot register regulator.\n");
return(ENXIO);
}
+
+ if (sc->gpio_entry != NULL)
+ sc->gpio_entry->always_on |= sc->param->always_on;
+
return (0);
}
More information about the svn-src-stable
mailing list