Module Name:    src
Committed By:   jmcneill
Date:           Sun Jul  2 15:28:25 UTC 2017

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

Log Message:
Enable sunxi pinctrl support


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sun6i_a31_gpio.c \
    src/sys/arch/arm/sunxi/sunxi_gpio.c src/sys/arch/arm/sunxi/sunxi_gpio.h

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/sun6i_a31_gpio.c
diff -u src/sys/arch/arm/sunxi/sun6i_a31_gpio.c:1.1 src/sys/arch/arm/sunxi/sun6i_a31_gpio.c:1.2
--- src/sys/arch/arm/sunxi/sun6i_a31_gpio.c:1.1	Sun Jul  2 13:36:46 2017
+++ src/sys/arch/arm/sunxi/sun6i_a31_gpio.c	Sun Jul  2 15:28:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sun6i_a31_gpio.c,v 1.1 2017/07/02 13:36:46 jmcneill Exp $ */
+/* $NetBSD: sun6i_a31_gpio.c,v 1.2 2017/07/02 15:28:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2016 Emmanuel Vadot <m...@freebsd.org>
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sun6i_a31_gpio.c,v 1.1 2017/07/02 13:36:46 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sun6i_a31_gpio.c,v 1.2 2017/07/02 15:28:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -212,7 +212,33 @@ static const struct sunxi_gpio_pins a31_
 	{"PH30", 7, 30, {"gpio_in", "gpio_out", "nand1", NULL, NULL, NULL, NULL, NULL}},
 };
 
+static const struct sunxi_gpio_pins a31_r_pins[] = {
+	{"PL0",  0, 0,  {"gpio_in", "gpio_out", "s_twi", "s_p2wi", NULL, NULL, NULL, NULL}},
+	{"PL1",  0, 1,  {"gpio_in", "gpio_out", "s_twi", "s_p2wi", NULL, NULL, NULL, NULL}},
+	{"PL2",  0, 2,  {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, NULL, NULL}},
+	{"PL3",  0, 3,  {"gpio_in", "gpio_out", "s_uart", NULL, NULL, NULL, NULL, NULL}},
+	{"PL4",  0, 4,  {"gpio_in", "gpio_out", "s_ir", NULL, NULL, NULL, NULL, NULL}},
+	{"PL5",  0, 5,  {"gpio_in", "gpio_out", "pl_eint0", "s_jtag", NULL, NULL, NULL, NULL}, 2, 0},
+	{"PL6",  0, 6,  {"gpio_in", "gpio_out", "pl_eint1", "s_jtag", NULL, NULL, NULL, NULL}, 2, 1},
+	{"PL7",  0, 7,  {"gpio_in", "gpio_out", "pl_eint2", "s_jtag", NULL, NULL, NULL, NULL}, 2, 2},
+	{"PL8",  0, 8,  {"gpio_in", "gpio_out", "pl_eint3", "s_jtag", NULL, NULL, NULL, NULL}, 2, 3},
+
+	{"PM0",  1, 0,  {"gpio_in", "gpio_out", "pm_eint0", NULL, NULL, NULL, NULL, NULL}, 2, 0},
+	{"PM1",  1, 1,  {"gpio_in", "gpio_out", "pm_eint1", NULL, NULL, NULL, NULL, NULL}, 2, 1},
+	{"PM2",  1, 2,  {"gpio_in", "gpio_out", "pm_eint2", "1wire", NULL, NULL, NULL, NULL}, 2, 2},
+	{"PM3",  1, 3,  {"gpio_in", "gpio_out", "pm_eint3", NULL, NULL, NULL, NULL, NULL}, 2, 3},
+	{"PM4",  1, 4,  {"gpio_in", "gpio_out", "pm_eint4", NULL, NULL, NULL, NULL, NULL}, 2, 4},
+	{"PM5",  1, 5,  {"gpio_in", "gpio_out", "pm_eint5", NULL, NULL, NULL, NULL, NULL}, 2, 5},
+	{"PM6",  1, 6,  {"gpio_in", "gpio_out", "pm_eint6", NULL, NULL, NULL, NULL, NULL}, 2, 6},
+	{"PM7",  1, 7,  {"gpio_in", "gpio_out", "pm_eint7", "rtc", NULL, NULL, NULL, NULL}, 2, 7},
+};
+
 const struct sunxi_gpio_padconf sun6i_a31_padconf = {
 	.npins = __arraycount(a31_pins),
 	.pins = a31_pins,
 };
+
+const struct sunxi_gpio_padconf sun6i_a31_r_padconf = {
+	.npins = __arraycount(a31_r_pins),
+	.pins = a31_r_pins,
+};
Index: src/sys/arch/arm/sunxi/sunxi_gpio.c
diff -u src/sys/arch/arm/sunxi/sunxi_gpio.c:1.1 src/sys/arch/arm/sunxi/sunxi_gpio.c:1.2
--- src/sys/arch/arm/sunxi/sunxi_gpio.c:1.1	Sun Jul  2 13:36:46 2017
+++ src/sys/arch/arm/sunxi/sunxi_gpio.c	Sun Jul  2 15:28:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_gpio.c,v 1.1 2017/07/02 13:36:46 jmcneill Exp $ */
+/* $NetBSD: sunxi_gpio.c,v 1.2 2017/07/02 15:28:25 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.1 2017/07/02 13:36:46 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c,v 1.2 2017/07/02 15:28:25 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -49,11 +49,17 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_gpio.c
 #define  SUNXI_GPIO_CFG_PINMASK(pin)	(0x7 << (((pin) % 8) * 4))
 #define	SUNXI_GPIO_DATA(port)		(SUNXI_GPIO_PORT(port) + 0x10)
 #define	SUNXI_GPIO_DRV(port, pin)	(SUNXI_GPIO_PORT(port) + 0x14 + (0x4 * ((pin) / 16)))
+#define  SUNXI_GPIO_DRV_PINMASK(pin)	(0x3 << (((pin) % 16) * 4))
 #define	SUNXI_GPIO_PULL(port, pin)	(SUNXI_GPIO_PORT(port) + 0x1c + (0x4 * ((pin) / 16)))
+#define	 SUNXI_GPIO_PULL_DISABLE	0
+#define	 SUNXI_GPIO_PULL_UP		1
+#define	 SUNXI_GPIO_PULL_DOWN		2
+#define  SUNXI_GPIO_PULL_PINMASK(pin)	(0x3 << (((pin) % 16) * 4))
 
 static const struct of_compat_data compat_data[] = {
 #ifdef SOC_SUN6I_A31
 	{ "allwinner,sun6i-a31-pinctrl",	(uintptr_t)&sun6i_a31_padconf },
+	{ "allwinner,sun6i-a31-r-pinctrl",	(uintptr_t)&sun6i_a31_r_padconf },
 #endif
 #ifdef SOC_SUN8I_H3
 	{ "allwinner,sun8i-h3-pinctrl",		(uintptr_t)&sun8i_h3_padconf },
@@ -102,6 +108,21 @@ sunxi_gpio_lookup(struct sunxi_gpio_soft
 	return NULL;
 }
 
+static const struct sunxi_gpio_pins *
+sunxi_gpio_lookup_byname(struct sunxi_gpio_softc *sc, const char *name)
+{
+	const struct sunxi_gpio_pins *pin_def;
+	u_int n;
+
+	for (n = 0; n < sc->sc_padconf->npins; n++) {
+		pin_def = &sc->sc_padconf->pins[n];
+		if (strcmp(pin_def->name, name) == 0)
+			return pin_def;
+	}
+
+	return NULL;
+}
+
 static int
 sunxi_gpio_setfunc(struct sunxi_gpio_softc *sc,
     const struct sunxi_gpio_pins *pin_def, const char *func)
@@ -132,6 +153,48 @@ sunxi_gpio_setfunc(struct sunxi_gpio_sof
 }
 
 static int
+sunxi_gpio_setpull(struct sunxi_gpio_softc *sc,
+    const struct sunxi_gpio_pins *pin_def, int flags)
+{
+	uint32_t pull;
+
+	const bus_size_t pull_reg = SUNXI_GPIO_PULL(pin_def->port, pin_def->pin);
+	const uint32_t pull_mask = SUNXI_GPIO_PULL_PINMASK(pin_def->pin);
+
+	pull = GPIO_READ(sc, pull_reg);
+	pull &= ~pull_mask;
+	if (flags & GPIO_PIN_PULLUP)
+		pull |= __SHIFTIN(SUNXI_GPIO_PULL_UP, pull_mask);
+	else if (flags & GPIO_PIN_PULLDOWN)
+		pull |= __SHIFTIN(SUNXI_GPIO_PULL_DOWN, pull_mask);
+	else
+		pull |= __SHIFTIN(SUNXI_GPIO_PULL_DISABLE, pull_mask);
+	GPIO_WRITE(sc, pull_reg, pull);
+
+	return 0;
+}
+
+static int
+sunxi_gpio_setdrv(struct sunxi_gpio_softc *sc,
+    const struct sunxi_gpio_pins *pin_def, int drive_strength)
+{
+	uint32_t drv;
+
+	if (drive_strength < 10 || drive_strength > 40)
+		return EINVAL;
+
+	const bus_size_t drv_reg = SUNXI_GPIO_DRV(pin_def->port, pin_def->pin);
+	const uint32_t drv_mask = SUNXI_GPIO_DRV_PINMASK(pin_def->pin);
+
+	drv = GPIO_READ(sc, drv_reg);
+	drv &= ~drv_mask;
+	drv |= __SHIFTIN((drive_strength / 10) - 1, drv_mask);
+	GPIO_WRITE(sc, drv_reg, drv);
+
+	return 0;
+}
+
+static int
 sunxi_gpio_ctl(struct sunxi_gpio_softc *sc, const struct sunxi_gpio_pins *pin_def,
     int flags)
 {
@@ -256,6 +319,60 @@ static struct fdtbus_gpio_controller_fun
 };
 
 static int
+sunxi_pinctrl_set_config(device_t dev, const void *data, size_t len)
+{
+	struct sunxi_gpio_softc * const sc = device_private(dev);
+	const struct sunxi_gpio_pins *pin_def;
+	u_int drive_strength;
+
+	if (len != 4)
+		return -1;
+
+	const int phandle = fdtbus_get_phandle_from_native(be32dec(data));
+
+	/*
+	 * Required: pins, function
+	 * Optional: bias-disable, bias-pull-up, bias-pull-down, drive-strength
+	 */
+
+	const char *function = fdtbus_get_string(phandle, "function");
+	if (function == NULL)
+		return -1;
+	int pins_len = OF_getproplen(phandle, "pins");
+	if (pins_len <= 0)
+		return -1;
+	const char *pins = fdtbus_get_string(phandle, "pins");
+
+	for (pins = fdtbus_get_string(phandle, "pins");
+	     pins_len > 0;
+	     pins_len -= strlen(pins) + 1, pins += strlen(pins) + 1) {
+		pin_def = sunxi_gpio_lookup_byname(sc, pins);
+		if (pin_def == NULL) {
+			aprint_error_dev(dev, "unknown pin name '%s'\n", pins);
+			continue;
+		}
+		if (sunxi_gpio_setfunc(sc, pin_def, function) != 0)
+			continue;
+
+		if (of_hasprop(phandle, "bias-disable"))
+			sunxi_gpio_setpull(sc, pin_def, 0);
+		else if (of_hasprop(phandle, "bias-pull-up"))
+			sunxi_gpio_setpull(sc, pin_def, GPIO_PIN_PULLUP);
+		else if (of_hasprop(phandle, "bias-pull-down"))
+			sunxi_gpio_setpull(sc, pin_def, GPIO_PIN_PULLDOWN);
+
+		if (of_getprop_uint32(phandle, "drive-strength", &drive_strength) == 0)
+			sunxi_gpio_setdrv(sc, pin_def, drive_strength);
+	}
+
+	return 0;
+}
+
+static struct fdtbus_pinctrl_controller_func sunxi_pinctrl_funcs = {
+	.set_config = sunxi_pinctrl_set_config,
+};
+
+static int
 sunxi_gpio_match(device_t parent, cfdata_t cf, void *aux)
 {
 	struct fdt_attach_args * const faa = aux;
@@ -271,6 +388,7 @@ sunxi_gpio_attach(device_t parent, devic
 	const int phandle = faa->faa_phandle;
 	bus_addr_t addr;
 	bus_size_t size;
+	int child;
 
 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
 		aprint_error(": couldn't get registers\n");
@@ -289,4 +407,12 @@ sunxi_gpio_attach(device_t parent, devic
 	aprint_normal(": PIO\n");
 
 	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"))
+			continue;
+		fdtbus_register_pinctrl_config(self, child, &sunxi_pinctrl_funcs);
+	}
+
+	fdtbus_pinctrl_configure();
 }
Index: src/sys/arch/arm/sunxi/sunxi_gpio.h
diff -u src/sys/arch/arm/sunxi/sunxi_gpio.h:1.1 src/sys/arch/arm/sunxi/sunxi_gpio.h:1.2
--- src/sys/arch/arm/sunxi/sunxi_gpio.h:1.1	Sun Jul  2 13:36:46 2017
+++ src/sys/arch/arm/sunxi/sunxi_gpio.h	Sun Jul  2 15:28:25 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_gpio.h,v 1.1 2017/07/02 13:36:46 jmcneill Exp $ */
+/* $NetBSD: sunxi_gpio.h,v 1.2 2017/07/02 15:28:25 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca>
@@ -52,6 +52,7 @@ struct sunxi_gpio_padconf {
 
 #ifdef SOC_SUN6I_A31
 extern const struct sunxi_gpio_padconf sun6i_a31_padconf;
+extern const struct sunxi_gpio_padconf sun6i_a31_r_padconf;
 #endif
 
 #ifdef SOC_SUN8I_H3

Reply via email to