Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Dec 2017 20:51:08 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r326433 - head/sys/arm/allwinner
Message-ID:  <201712012051.vB1Kp8Gn049159@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Fri Dec  1 20:51:08 2017
New Revision: 326433
URL: https://svnweb.freebsd.org/changeset/base/326433

Log:
  a10_gpio: Add support for more modern pin configuration
  
  a10_gpio previously accepted only {allwinner,}drive and {allwinner,}pull for
  drive/bias setting, while newer DTS is using drive-strength and
  bias-{disable,pull-up,pull-down} properties. Accept these properties as
  well.
  
  Additionally make bias and drive strength optional rather than required; not
  setting them should just indicate that we do not need to configure these
  properties.
  
  Tested on:	BananaPi-M3 (a83t)
  Reviewed by:	manu
  Approved by:	emaste (implicit)
  Obtained from:	NetBSD (partially)
  Differential Revision:	https://reviews.freebsd.org/D13284

Modified:
  head/sys/arm/allwinner/a10_gpio.c

Modified: head/sys/arm/allwinner/a10_gpio.c
==============================================================================
--- head/sys/arm/allwinner/a10_gpio.c	Fri Dec  1 17:58:20 2017	(r326432)
+++ head/sys/arm/allwinner/a10_gpio.c	Fri Dec  1 20:51:08 2017	(r326433)
@@ -203,6 +203,11 @@ struct a10_gpio_softc {
 #define	A10_GPIO_GP_INT_STA		0x214
 #define	A10_GPIO_GP_INT_DEB		0x218
 
+static char *a10_gpio_parse_function(phandle_t node);
+static const char **a10_gpio_parse_pins(phandle_t node, int *pins_nb);
+static uint32_t a10_gpio_parse_bias(phandle_t node);
+static int a10_gpio_parse_drive_strength(phandle_t node, uint32_t *drive);
+
 static int a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value);
 static int a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
 static int a10_gpio_pin_get_locked(struct a10_gpio_softc *sc, uint32_t pin, unsigned int *value);
@@ -278,6 +283,9 @@ a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t p
 {
 	uint32_t bank, offset, val;
 
+	if (a10_gpio_get_pud(sc, pin) == state)
+		return;
+
 	/* Must be called with lock held. */
 	A10_GPIO_LOCK_ASSERT(sc);
 
@@ -313,6 +321,9 @@ a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t p
 {
 	uint32_t bank, offset, val;
 
+	if (a10_gpio_get_drv(sc, pin) == drive)
+		return;
+
 	/* Must be called with lock held. */
 	A10_GPIO_LOCK_ASSERT(sc);
 
@@ -541,7 +552,76 @@ a10_gpio_pin_get_locked(struct a10_gpio_softc *sc,uint
 	return (0);
 }
 
+static char *
+a10_gpio_parse_function(phandle_t node)
+{
+	char *function;
+
+	if (OF_getprop_alloc(node, "function", sizeof(*function),
+	    (void **)&function) != -1)
+		return (function);
+	if (OF_getprop_alloc(node, "allwinner,function", sizeof(*function),
+	    (void **)&function) != -1)
+		return (function);
+
+	return (NULL);
+}
+
+static const char **
+a10_gpio_parse_pins(phandle_t node, int *pins_nb)
+{
+	const char **pinlist;
+
+	*pins_nb = ofw_bus_string_list_to_array(node, "pins", &pinlist);
+	if (*pins_nb > 0)
+		return (pinlist);
+
+	*pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins",
+	    &pinlist);
+	if (*pins_nb > 0)
+		return (pinlist);
+
+	return (NULL);
+}
+
+static uint32_t
+a10_gpio_parse_bias(phandle_t node)
+{
+	uint32_t bias;
+
+	if (OF_getencprop(node, "pull", &bias, sizeof(bias)) != -1)
+		return (bias);
+	if (OF_getencprop(node, "allwinner,pull", &bias, sizeof(bias)) != -1)
+		return (bias);
+	if (OF_hasprop(node, "bias-disable"))
+		return (A10_GPIO_NONE);
+	if (OF_hasprop(node, "bias-pull-up"))
+		return (A10_GPIO_PULLUP);
+	if (OF_hasprop(node, "bias-pull-down"))
+		return (A10_GPIO_PULLDOWN);
+
+	return (A10_GPIO_NONE);
+}
+
 static int
+a10_gpio_parse_drive_strength(phandle_t node, uint32_t *drive)
+{
+	uint32_t drive_str;
+
+	if (OF_getencprop(node, "drive", drive, sizeof(*drive)) != -1)
+		return (0);
+	if (OF_getencprop(node, "allwinner,drive", drive, sizeof(*drive)) != -1)
+		return (0);
+	if (OF_getencprop(node, "drive-strength", &drive_str,
+	    sizeof(drive_str)) != -1) {
+		*drive = (drive_str / 10) - 1;
+		return (0);
+	}
+
+	return (1);
+}
+
+static int
 a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
 {
 	struct a10_gpio_softc *sc;
@@ -682,46 +762,29 @@ aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
 	char *pin_function = NULL;
 	uint32_t pin_drive, pin_pull;
 	int pins_nb, pin_num, pin_func, i, ret;
+	bool set_drive;
 
 	sc = device_get_softc(dev);
 	node = OF_node_from_xref(cfgxref);
 	ret = 0;
+	set_drive = false;
 
 	/* Getting all prop for configuring pins */
-	pins_nb = ofw_bus_string_list_to_array(node, "pins", &pinlist);
-	if (pins_nb <= 0) {
-		pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins",
-		    &pinlist);
-		if (pins_nb <= 0)
-			return (ENOENT);
+	pinlist = a10_gpio_parse_pins(node, &pins_nb);
+	if (pinlist == NULL)
+		return (ENOENT);
+
+	pin_function = a10_gpio_parse_function(node);
+	if (pin_function == NULL) {
+		ret = ENOENT;
+		goto out;
 	}
-	if (OF_getprop_alloc(node, "function",
-			     sizeof(*pin_function),
-			     (void **)&pin_function) == -1) {
-		if (OF_getprop_alloc(node, "allwinner,function",
-		    sizeof(*pin_function),
-		    (void **)&pin_function) == -1) {
-			ret = ENOENT;
-			goto out;
-		}
-	}
-	if (OF_getencprop(node, "drive",
-			  &pin_drive, sizeof(pin_drive)) == -1) {
-		if (OF_getencprop(node, "allwinner,drive",
-		    &pin_drive, sizeof(pin_drive)) == -1) {
-			ret = ENOENT;
-			goto out;
-		}
-	}
-	if (OF_getencprop(node, "pull",
-			  &pin_pull, sizeof(pin_pull)) == -1) {
-		if (OF_getencprop(node, "allwinner,pull",
-		    &pin_pull, sizeof(pin_pull)) == -1) {
-			ret = ENOENT;
-			goto out;
-		}
-	}
 
+	if (a10_gpio_parse_drive_strength(node, &pin_drive) == 0)
+		set_drive = true;
+
+	pin_pull = a10_gpio_parse_bias(node);
+
 	/* Configure each pin to the correct function, drive and pull */
 	for (i = 0; i < pins_nb; i++) {
 		pin_num = aw_find_pinnum_by_name(sc, pinlist[i]);
@@ -739,12 +802,11 @@ aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
 
 		if (a10_gpio_get_function(sc, pin_num) != pin_func)
 			a10_gpio_set_function(sc, pin_num, pin_func);
-		if (a10_gpio_get_drv(sc, pin_num) != pin_drive)
+		if (set_drive)
 			a10_gpio_set_drv(sc, pin_num, pin_drive);
-		if (a10_gpio_get_pud(sc, pin_num) != pin_pull &&
-			(pin_pull == A10_GPIO_PULLUP ||
-			    pin_pull == A10_GPIO_PULLDOWN))
+		if (pin_pull != A10_GPIO_NONE)
 			a10_gpio_set_pud(sc, pin_num, pin_pull);
+
 		A10_GPIO_UNLOCK(sc);
 	}
 



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