Module Name:    src
Committed By:   jmcneill
Date:           Mon May 27 23:26:20 UTC 2019

Modified Files:
        src/sys/arch/arm/sunxi: sunxi_gpio.c

Log Message:
Fix support for Allwinner-specific pin bindings and add support for pink bank 
regulators


To generate a diff of this commit:
cvs rdiff -u -r1.23 -r1.24 src/sys/arch/arm/sunxi/sunxi_gpio.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/sunxi/sunxi_gpio.c
diff -u src/sys/arch/arm/sunxi/sunxi_gpio.c:1.23 src/sys/arch/arm/sunxi/sunxi_gpio.c:1.24
--- src/sys/arch/arm/sunxi/sunxi_gpio.c:1.23	Sat Jan 26 14:38:30 2019
+++ src/sys/arch/arm/sunxi/sunxi_gpio.c	Mon May 27 23:26:20 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_gpio.c,v 1.23 2019/01/26 14:38:30 thorpej Exp $ */
+/* $NetBSD: sunxi_gpio.c,v 1.24 2019/05/27 23:26:20 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -29,7 +29,7 @@
 #include "opt_soc.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.23 2019/01/26 14:38:30 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.24 2019/05/27 23:26:20 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,6 +50,8 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c
 #define	SUNXI_GPIO_MAX_EINT_BANK	5
 #define	SUNXI_GPIO_MAX_EINT		32
 
+#define	SUNXI_GPIO_MAX_BANK		26
+
 #define	SUNXI_GPIO_PORT(port)		(0x24 * (port))
 #define SUNXI_GPIO_CFG(port, pin)	(SUNXI_GPIO_PORT(port) + 0x00 + (0x4 * ((pin) / 8)))
 #define  SUNXI_GPIO_CFG_PINMASK(pin)	(0x7 << (((pin) % 8) * 4))
@@ -70,6 +72,8 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c
 #define	  SUNXI_GPIO_INT_MODE_DOUBLE_EDGE	0x4
 #define	SUNXI_GPIO_INT_CTL(bank)	(0x210 + 0x20 * (bank))
 #define	SUNXI_GPIO_INT_STATUS(bank)	(0x214 + 0x20 * (bank))
+#define	SUNXI_GPIO_GRP_CONFIG(bank)	(0x300 + 0x4 * (bank))
+#define	 SUNXI_GPIO_GRP_IO_BIAS_CONFIGMASK	0xf
 
 static const struct of_compat_data compat_data[] = {
 #ifdef SOC_SUN4I_A10
@@ -125,6 +129,7 @@ struct sunxi_gpio_softc {
 	device_t sc_dev;
 	bus_space_tag_t sc_bst;
 	bus_space_handle_t sc_bsh;
+	int sc_phandle;
 	const struct sunxi_gpio_padconf *sc_padconf;
 	kmutex_t sc_lock;
 
@@ -132,6 +137,8 @@ struct sunxi_gpio_softc {
 	gpio_pin_t *sc_pins;
 	device_t sc_gpiodev;
 
+	struct fdtbus_regulator *sc_pin_supply[SUNXI_GPIO_MAX_BANK];
+
 	u_int sc_eint_bank_max;
 
 	void *sc_ih;
@@ -602,7 +609,7 @@ sunxi_pinctrl_parse_pins(int phandle, in
 	len = OF_getproplen(phandle, "allwinner,pins");
 	if (len > 0) {
 		*pins_len = len;
-		return fdtbus_get_string(phandle, "allwinner,pins");
+		return fdtbus_get_prop(phandle, "allwinner,pins", pins_len);
 	}
 
 	return NULL;
@@ -650,6 +657,64 @@ sunxi_pinctrl_parse_drive_strength(int p
 	return -1;
 }
 
+static void
+sunxi_pinctrl_enable_regulator(struct sunxi_gpio_softc *sc,
+    const struct sunxi_gpio_pins *pin_def)
+{
+	char supply_prop[16];
+	uint32_t val;
+	u_int uvol;
+	int error;
+
+	const char c = tolower(pin_def->name[1]);
+	if (c < 'a' || c > 'z')
+		return;
+	const int index = c - 'a';
+
+	if (sc->sc_pin_supply[index] != NULL) {
+		/* Already enabled */
+		return;
+	}
+
+	snprintf(supply_prop, sizeof(supply_prop), "vcc-p%c-supply", c);
+	sc->sc_pin_supply[index] = fdtbus_regulator_acquire(sc->sc_phandle, supply_prop);
+	if (sc->sc_pin_supply[index] == NULL)
+		return;
+
+	aprint_debug_dev(sc->sc_dev, "enable \"%s\"\n", supply_prop);
+	error = fdtbus_regulator_enable(sc->sc_pin_supply[index]);
+	if (error != 0)
+		aprint_error_dev(sc->sc_dev, "failed to enable %s: %d\n", supply_prop, error);
+
+	if (sc->sc_padconf->has_io_bias_config) {
+		error = fdtbus_regulator_get_voltage(sc->sc_pin_supply[index], &uvol);
+		if (error != 0) {
+			aprint_error_dev(sc->sc_dev, "failed to get %s voltage: %d\n",
+			    supply_prop, error);
+			uvol = 0;
+		}
+		if (uvol != 0) {
+			if (uvol <= 1800000)
+				val = 0x0;	/* 1.8V */
+			else if (uvol <= 2500000)
+				val = 0x6;	/* 2.5V */
+			else if (uvol <= 2800000)
+				val = 0x9;	/* 2.8V */
+			else if (uvol <= 3000000)
+				val = 0xa;	/* 3.0V */
+			else
+				val = 0xd;	/* 3.3V */
+
+			aprint_debug_dev(sc->sc_dev, "set io bias config for port %d to 0x%x\n",
+			    pin_def->port, val);
+			val = GPIO_READ(sc, SUNXI_GPIO_GRP_CONFIG(pin_def->port));
+			val &= ~SUNXI_GPIO_GRP_IO_BIAS_CONFIGMASK;
+			val |= __SHIFTIN(val, SUNXI_GPIO_GRP_IO_BIAS_CONFIGMASK);
+			GPIO_WRITE(sc, SUNXI_GPIO_GRP_CONFIG(pin_def->port), val);
+		}
+	}
+}
+
 static int
 sunxi_pinctrl_set_config(device_t dev, const void *data, size_t len)
 {
@@ -694,6 +759,8 @@ sunxi_pinctrl_set_config(device_t dev, c
 
 		if (drive_strength != -1)
 			sunxi_gpio_setdrv(sc, pin_def, drive_strength);
+
+		sunxi_pinctrl_enable_regulator(sc, pin_def);
 	}
 
 	mutex_exit(&sc->sc_lock);
@@ -833,6 +900,7 @@ sunxi_gpio_attach(device_t parent, devic
 		}
 
 	sc->sc_dev = self;
+	sc->sc_phandle = phandle;
 	sc->sc_bst = faa->faa_bst;
 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
 		aprint_error(": couldn't map registers\n");
@@ -847,7 +915,10 @@ sunxi_gpio_attach(device_t parent, devic
 	fdtbus_register_gpio_controller(self, phandle, &sunxi_gpio_funcs);
 
 	for (child = OF_child(phandle); child; child = OF_peer(child)) {
-		if (!of_hasprop(child, "function") || !of_hasprop(child, "pins"))
+		bool is_valid =
+		    (of_hasprop(child, "function") && of_hasprop(child, "pins")) ||
+		    (of_hasprop(child, "allwinner,function") && of_hasprop(child, "allwinner,pins"));
+		if (!is_valid)
 			continue;
 		fdtbus_register_pinctrl_config(self, child, &sunxi_pinctrl_funcs);
 	}

Reply via email to