Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Aug 2018 08:47:54 +0000 (UTC)
From:      Michal Meloun <mmel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r337705 - stable/11/sys/dev/extres/regulator
Message-ID:  <201808130847.w7D8lshj070000@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808130847.w7D8lshj070000>