Module Name:    src
Committed By:   marty
Date:           Sat Dec 19 21:42:31 UTC 2015

Modified Files:
        src/sys/arch/arm/samsung: exynos_gpio.c exynos_var.h files.exynos
        src/sys/arch/evbarm/conf: EXYNOS
Added Files:
        src/sys/arch/arm/samsung: exynos_pinctrl.c

Log Message:
XU4 GPIO FDT broken snapshot

This is broken. exynos_gpio_bank_config and the call to it are wrong, and
the acquire function doesn't work.

But I'm in over my head and I need to discuss this:

There is a problem with the dtd: it doesn't have addresses for the individual
gpios.  Do I add the addresses to it, or go back to the old version where I
have them hard coded in the driver.

There is a problem with creating the gpio device entries:  I suspect I really
need to treat the pinctrl devices as busses and create the gpios as attached
to those busses, but I'm not familiar with how to do that in NetBSD. At the
minimum, a pointer to a similar situation would give me code to follow.
This is different than the usual bus attachment in that the gpios aren't
devices in the dtd (they don't have "compatible" properties) so they don't
get an attach routine called.  An alternative to generating the bus
attachments might be to add "compatible" properties to the GPIO entries
in the dtd. so that they do get attached in the normal way.

If I'm going to modify the DTD, then it should be checked in, so a decision
on where to check them in would be nice, even if it does mean spreading them
all over because of license issues.  (This DTD is GPL v2)


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/arm/samsung/exynos_gpio.c \
    src/sys/arch/arm/samsung/files.exynos
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/samsung/exynos_pinctrl.c
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/arm/samsung/exynos_var.h
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/conf/EXYNOS

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/samsung/exynos_gpio.c
diff -u src/sys/arch/arm/samsung/exynos_gpio.c:1.13 src/sys/arch/arm/samsung/exynos_gpio.c:1.14
--- src/sys/arch/arm/samsung/exynos_gpio.c:1.13	Fri Dec 11 04:03:44 2015
+++ src/sys/arch/arm/samsung/exynos_gpio.c	Sat Dec 19 21:42:31 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_gpio.c,v 1.13 2015/12/11 04:03:44 marty Exp $ */
+/*	$NetBSD: exynos_gpio.c,v 1.14 2015/12/19 21:42:31 marty Exp $ */
 
 /*-
 * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 #include "gpio.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.13 2015/12/11 04:03:44 marty Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.14 2015/12/19 21:42:31 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -49,6 +49,9 @@ __KERNEL_RCSID(1, "$NetBSD: exynos_gpio.
 #include <arm/samsung/exynos_reg.h>
 #include <arm/samsung/exynos_io.h>
 #include <arm/samsung/exynos_intr.h>
+#include <arm/samsung/exynos_pinctrl.h>
+
+#include <dev/fdt/fdtvar.h>
 
 struct exynos_gpio_pin_cfg {
 	uint32_t cfg;
@@ -62,9 +65,9 @@ struct exynos_gpio_softc;
 
 struct exynos_gpio_bank {
 	const char		bank_name[6];
-	struct exynos_gpio_softc *bank_sc;
 	device_t		bank_dev;
 	struct gpio_chipset_tag	bank_gc;
+	struct exynos_gpio_softc *bank_softc;
 	gpio_pin_t		bank_pins[8];
 
 	const bus_addr_t	bank_core_offset;
@@ -74,172 +77,42 @@ struct exynos_gpio_bank {
 	uint8_t			bank_pin_inuse_mask;
 	bus_space_handle_t	bank_bsh;
 	struct exynos_gpio_pin_cfg bank_cfg;
+	struct exynos_gpio_bank * bank_next;
 };
 
 struct exynos_gpio_softc {
 	device_t		sc_dev;
 	bus_space_tag_t		sc_bst;
 	bus_space_handle_t	sc_bsh;
-
-	struct exynos_gpio_bank *sc_banks;
 };
 
 struct exynos_gpio_pin {
 	struct exynos_gpio_softc *pin_sc;
-	const struct exynos_gpio_bank  *pin_bank;
 	int			  pin_no;
 	u_int			  pin_flags;
+	int			  pin_actlo;
+	const struct exynos_gpio_bank   *pin_bank;
 };
 
-#define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o))
-#define GPIO_GRP(v, s, o, n, b)	\
-	{ \
-		.bank_name = #n, \
-		.bank_core_offset = GPIO_REG(v,s,o), \
-		.bank_bits = b, \
-	}
-
-static struct exynos_gpio_bank exynos5_banks[] = {
-	GPIO_GRP(5, MUXA, 0x0000, gpy7, 8),
-	GPIO_GRP(5, MUXA, 0x0C00, gpx0, 8),
-	GPIO_GRP(5, MUXA, 0x0C20, gpx1, 8),
-	GPIO_GRP(5, MUXA, 0x0C40, gpx2, 8),
-	GPIO_GRP(5, MUXA, 0x0C60, gpx3, 8),
-
-	GPIO_GRP(5, MUXB, 0x0000, gpc0, 8),
-	GPIO_GRP(5, MUXB, 0x0020, gpc1, 8),
-	GPIO_GRP(5, MUXB, 0x0040, gpc2, 7),
-	GPIO_GRP(5, MUXB, 0x0060, gpc3, 4),
-	GPIO_GRP(5, MUXB, 0x0080, gpc4, 2),
-	GPIO_GRP(5, MUXB, 0x00A0, gpd1, 8),
-	GPIO_GRP(5, MUXB, 0x00C0, gpy0, 6),
-	GPIO_GRP(5, MUXB, 0x00E0, gpy1, 4),
-	GPIO_GRP(5, MUXB, 0x0100, gpy2, 6),
-	GPIO_GRP(5, MUXB, 0x0120, gpy3, 8),
-	GPIO_GRP(5, MUXB, 0x0140, gpy4, 8),
-	GPIO_GRP(5, MUXB, 0x0160, gpy5, 8),
-	GPIO_GRP(5, MUXB, 0x0180, gpy6, 8),
-
-	GPIO_GRP(5, MUXC, 0x0000, gpe0, 8),
-	GPIO_GRP(5, MUXC, 0x0020, gpe1, 2),
-	GPIO_GRP(5, MUXC, 0x0040, gpf0, 6),
-	GPIO_GRP(5, MUXC, 0x0060, gpf1, 8),
-	GPIO_GRP(5, MUXC, 0x0080, gpg0, 8),
-	GPIO_GRP(5, MUXC, 0x00A0, gpg1, 8),
-	GPIO_GRP(5, MUXC, 0x00C0, gpg2, 2),
-	GPIO_GRP(5, MUXC, 0x00E0, gpj4, 4),
-
-	GPIO_GRP(5, MUXD, 0x0000, gpa0, 8),
-	GPIO_GRP(5, MUXD, 0x0020, gpa1, 6),
-	GPIO_GRP(5, MUXD, 0x0040, gpa2, 8),
-	GPIO_GRP(5, MUXD, 0x0060, gpb0, 5),
-	GPIO_GRP(5, MUXD, 0x0080, gpb1, 5),
-	GPIO_GRP(5, MUXD, 0x00A0, gpb2, 4),
-	GPIO_GRP(5, MUXD, 0x00C0, gpb3, 8),
-	GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2),
-	GPIO_GRP(5, MUXD, 0x0100, gph0, 4),
+struct exynos_gpio_bank *exynos_gpio_banks;
 
-//	GPIO_GRP(5, MUXE, 0x0000, gpz0,  7),
+static void exynos_gpio_pin_ctl(void *cookie, int pin, int flags);
+static void *exynos_gpio_fdt_acquire(device_t, const void *,
+				     size_t, int);
+static void exynos_gpio_fdt_release(device_t, void *);
+
+static int exynos_gpio_fdt_read(device_t, void *);
+static void exynos_gpio_fdt_write(device_t, void *, int);
+//static int exynos_gpio_cfprint(void *, const char *);
+
+struct fdtbus_gpio_controller_func exynos_gpio_funcs = {
+	.acquire = exynos_gpio_fdt_acquire,
+	.release = exynos_gpio_fdt_release,
+	.read = exynos_gpio_fdt_read,
+	.write = exynos_gpio_fdt_write
 };
 
-static int exynos_gpio_match(device_t, cfdata_t, void *);
-static void exynos_gpio_attach(device_t, device_t, void *);
-
-static int exynos_gpio_pin_read(void *, int);
-static void exynos_gpio_pin_write(void *, int, int);
-static void exynos_gpio_pin_ctl(void *, int, int);
-static int exynos_gpio_cfprint(void *, const char *);
-struct exynos_gpio_pin *exynos_gpio_acquire(const char *pinname, u_int flags);
-
-/* force these structures in DATA segment */
-static struct exynos_gpio_bank *exynos_gpio_banks = NULL;
-static int exynos_n_gpio_banks = 0;
-
-static struct exynos_gpio_softc exynos_gpio_sc = {};
-
-CFATTACH_DECL_NEW(exynos_gpio, sizeof(struct exynos_gpio_softc),
-	exynos_gpio_match, exynos_gpio_attach, NULL, NULL);
-
-static int
-exynos_gpio_match(device_t parent, cfdata_t cf, void *aux)
-{
-#ifdef DIAGNOSTIC
-	struct exyo_attach_args * const exyoaa = aux;
-	struct exyo_locators *loc = &exyoaa->exyo_loc;
-#endif
-
-	/* no locators expected */
-	KASSERT(loc->loc_offset == 0);
-	KASSERT(loc->loc_size   == 0);
-	KASSERT(loc->loc_port   == EXYOCF_PORT_DEFAULT);
-
-	/* there can only be one */
-	if (exynos_gpio_sc.sc_dev != NULL)
-		return 0;
-	return 1;
-}
-
-
-#if NGPIO > 0
-static void
-exynos_gpio_attach_banks(device_t self)
-{
-	struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
-	struct exynos_gpio_bank *bank;
-	struct gpiobus_attach_args gba;
-	size_t pin_count = 0;
-	int i, bit, mask, pincaps, data;
-
-	if (exynos_n_gpio_banks == 0)
-		return;
-
-	/* find out how many pins we can offer */
-	pin_count = 0;
-	for (i = 0; i < exynos_n_gpio_banks; i++) {
-		pin_count += exynos_gpio_banks[i].bank_bits;
-	}
-
-	/* if no pins available, don't proceed */
-	if (pin_count == 0)
-		return;
-
-	/* allocate pin data */
-	sc->sc_banks = exynos_gpio_banks;
-	KASSERT(sc->sc_banks);
-
-	pincaps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
-		GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
-
-	for (i = 0; i < exynos_n_gpio_banks; i++) {
-		bank = &sc->sc_banks[i];
-		bank->bank_sc = sc;
-		bank->bank_gc.gp_cookie = bank;
-		bank->bank_gc.gp_pin_read = exynos_gpio_pin_read;
-		bank->bank_gc.gp_pin_write = exynos_gpio_pin_write;
-		bank->bank_gc.gp_pin_ctl = exynos_gpio_pin_ctl;
-		mask = bank->bank_pin_mask & ~bank->bank_pin_inuse_mask;
-		if (mask == 0)
-			continue;
-		data = bus_space_read_1(sc->sc_bst, bank->bank_bsh,
-				EXYNOS_GPIO_DAT);
-		for (bit = 0; mask != 0; mask >>= 1, data >>= 1, bit++) {
-			if (mask & 1) {
-				bank->bank_pins[bit].pin_num = bit + (i << 3);
-				bank->bank_pins[bit].pin_caps = pincaps;
-				bank->bank_pins[bit].pin_flags = pincaps;
-				bank->bank_pins[bit].pin_state = (data & 1) != 0;
-			}
-		}
-		memset(&gba, 0, sizeof(gba));
-		gba.gba_gc = &bank->bank_gc;
-		gba.gba_pins = bank->bank_pins;
-		gba.gba_npins = bit; /* MJF? */
-		bank->bank_dev = config_found_ia(self, "gpiobus", &gba,
-						 exynos_gpio_cfprint);
-	}
-}
-#endif
-
+#if 0
 static int
 exynos_gpio_cfprint(void *priv, const char *pnp)
 {
@@ -254,79 +127,7 @@ exynos_gpio_cfprint(void *priv, const ch
 
 	return UNCONF;
 }
-
-static void
-exynos_gpio_attach(device_t parent, device_t self, void *aux)
-{
-	struct exynos_gpio_softc * const sc = &exynos_gpio_sc;
-	struct exyo_attach_args * const exyoaa = aux;
-
-	sc->sc_dev = self;
-	sc->sc_bst = exyoaa->exyo_core_bst;
-	sc->sc_bsh = exyoaa->exyo_core_bsh;
-
-	exynos_gpio_bootstrap();
-	if (exynos_n_gpio_banks == 0) {
-		printf(": disabled, no pins defined\n");
-		return;
-	}
-
-	KASSERT(exynos_gpio_banks);
-	KASSERT(exynos_n_gpio_banks);
-
-	aprint_naive("\n");
-	aprint_normal("\n");
-
-#if NGPIO > 0
-	exynos_gpio_attach_banks(self);
 #endif
-}
-
-static void
-exynos_gpio_set_pin_func(struct exynos_gpio_pin_cfg *cfg,
-	int pin, int func)
-{
-	const u_int shift = (pin & 7) << 2;
-
-	cfg->cfg &= ~(0x0f << shift);
-	cfg->cfg |= func << shift;
-}
-
-
-static void
-exynos_gpio_set_pin_pull(struct exynos_gpio_pin_cfg *cfg, int pin, int pull)
-{
-	const u_int shift = (pin & 7) << 1;
-
-	cfg->pud &= ~(0x3 << shift);
-	cfg->pud |= pull << shift;
-}
-
-static int
-exynos_gpio_pin_read(void *cookie, int pin)
-{
-	struct exynos_gpio_bank * const bank = cookie;
-
-	KASSERT(pin < bank->bank_bits);
-	return (bus_space_read_1(exynos_gpio_sc.sc_bst, bank->bank_bsh,
-		EXYNOS_GPIO_DAT) >> pin) & 1;
-}
-
-static void
-exynos_gpio_pin_write(void *cookie, int pin, int value)
-{
-	struct exynos_gpio_bank * const bank = cookie;
-	int val;
-
-	KASSERT(pin < bank->bank_bits);
-	val = bus_space_read_1(exynos_gpio_sc.sc_bst, bank->bank_bsh,
-		EXYNOS_GPIO_DAT);
-	val &= ~__BIT(pin);
-	if (value)
-		val |= __BIT(pin);
-	bus_space_write_1(exynos_gpio_sc.sc_bst, bank->bank_bsh,
-		EXYNOS_GPIO_DAT, val);
-}
 
 static void
 exynos_gpio_update_cfg_regs(struct exynos_gpio_bank *bank,
@@ -371,6 +172,7 @@ exynos_gpio_pin_ctl(void *cookie, int pi
 {
 	struct exynos_gpio_bank * const bank = cookie;
 	struct exynos_gpio_pin_cfg ncfg = bank->bank_cfg;
+	u_int shift;
 	int pull;
 
 	/* honour pullup requests */
@@ -379,67 +181,74 @@ exynos_gpio_pin_ctl(void *cookie, int pi
 		pull = EXYNOS_GPIO_PIN_PULL_UP;
 	if (flags & GPIO_PIN_PULLDOWN)
 		pull = EXYNOS_GPIO_PIN_PULL_DOWN;
-	exynos_gpio_set_pin_pull(&ncfg, pin, pull);
+	shift = (pin & 7) << 1;
+	ncfg.pud &= ~(0x3 << shift);
+	ncfg.pud |= pull << shift;
 
 	/* honour i/o */
-	if (flags & GPIO_PIN_INPUT)
-		exynos_gpio_set_pin_func(&ncfg, pin, EXYNOS_GPIO_FUNC_INPUT);
-	if (flags & GPIO_PIN_OUTPUT)
-		exynos_gpio_set_pin_func(&ncfg, pin, EXYNOS_GPIO_FUNC_OUTPUT);
+	if (flags & GPIO_PIN_INPUT) {
+		ncfg.cfg &= ~(0x0f << shift);
+		ncfg.cfg |= EXYNOS_GPIO_FUNC_INPUT << shift;
+	} else if (flags & GPIO_PIN_OUTPUT) {
+		ncfg.cfg &= ~(0x0f << shift);
+		ncfg.cfg |= EXYNOS_GPIO_FUNC_OUTPUT << shift;
+	}
 
 	/* update any config registers that changed */
 	exynos_gpio_update_cfg_regs(bank, &ncfg);
 }
 
-/* bootstrapping */
 void
-exynos_gpio_bootstrap(void)
+exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent, int node)
 {
-	bus_space_tag_t bst = &exynos_bs_tag;
-	struct exynos_gpio_bank *bank;
-	struct gpio_chipset_tag *gc_tag;
-	int i;
-
-	/* determine what we're running on */
-	if (IS_EXYNOS5_P()) {
-		exynos_gpio_banks = exynos5_banks;
-		exynos_n_gpio_banks = __arraycount(exynos5_banks);
-	}
+//	bus_space_tag_t bst = &exynos_bs_tag; /* MJF: This is wrong */
+	struct exynos_gpio_bank *bank = kmem_zalloc(sizeof(*bank), KM_SLEEP);
+//	struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
+//	struct gpiobus_attach_args gba;
+	char result[64];
+//	int data;
+//	int error;
+
+	/*error =*/ OF_getprop(node, "name", result, sizeof(result));
+	printf(" GPIO %s\n", result);
+	if (exynos_gpio_banks)
+		bank->bank_next = exynos_gpio_banks;
+	exynos_gpio_banks = bank;
+	/* MJF: TODO: process all of the node properties */
+#if 0
+//	pincaps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
+//		GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN;
 
-	if (exynos_n_gpio_banks == 0)
-		return;
-
-	/* init banks */
-	for (i = 0; i < exynos_n_gpio_banks; i++) {
-		bank = &exynos_gpio_banks[i];
-		gc_tag = &bank->bank_gc;
-
-		bus_space_subregion(&exynos_bs_tag, exynos_core_bsh,
-			bank->bank_core_offset, EXYNOS_GPIO_GRP_SIZE,
-			&bank->bank_bsh);
-		KASSERT(&bank->bank_bsh);
-
-		bank->bank_pin_mask = __BIT(bank->bank_bits) - 1;
-		bank->bank_pin_inuse_mask = 0;
-
-		gc_tag->gp_cookie = bank;
-		gc_tag->gp_pin_read  = exynos_gpio_pin_read;
-		gc_tag->gp_pin_write = exynos_gpio_pin_write;
-		gc_tag->gp_pin_ctl   = exynos_gpio_pin_ctl;
-
-		/* read in our initial settings */
-		bank->bank_cfg.cfg = bus_space_read_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_CON);
-		bank->bank_cfg.pud = bus_space_read_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_PUD);
-		bank->bank_cfg.drv = bus_space_read_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_DRV);
-		bank->bank_cfg.conpwd = bus_space_read_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_CONPWD);
-		bank->bank_cfg.pudpwd = bus_space_read_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_PUDPWD);
-	}
+//	data = bus_space_read_1(sc->sc_bst, bank->bank_bsh,
+//				EXYNOS_GPIO_DAT);
 
+	sc->sc_dev = parent->sc_dev;
+	sc->sc_bst = parent->sc_bst;
+	
+	memset(&gba, 0, sizeof(gba));
+	gba.gba_gc = &bank->bank_gc;
+	gba.gba_pins = bank->bank_pins;
+//	gba.gba_npins = bit; /* MJF? */
+	bank->bank_dev = config_found_ia(parent->sc_dev, "gpiobus", &gba,
+					 exynos_gpio_cfprint);
+
+	bank->bank_pin_mask = __BIT(bank->bank_bits) - 1;
+	bank->bank_pin_inuse_mask = 0;
+
+
+	/* read in our initial settings */
+	bank->bank_cfg.cfg = bus_space_read_4(bst, bank->bank_bsh,
+					      EXYNOS_GPIO_CON);
+	bank->bank_cfg.pud = bus_space_read_4(bst, bank->bank_bsh,
+					      EXYNOS_GPIO_PUD);
+	bank->bank_cfg.drv = bus_space_read_4(bst, bank->bank_bsh,
+					      EXYNOS_GPIO_DRV);
+	bank->bank_cfg.conpwd = bus_space_read_4(bst, bank->bank_bsh,
+						 EXYNOS_GPIO_CONPWD);
+	bank->bank_cfg.pudpwd = bus_space_read_4(bst, bank->bank_bsh,
+						 EXYNOS_GPIO_PUDPWD);
+	/* MJF: TODO: Configure from the node data, if present */
+#endif
 }
 
 /*
@@ -453,8 +262,8 @@ static const struct exynos_gpio_bank *
 exynos_gpio_pin_lookup(const char *pinname, int *ppin)
 {
 	char bankname[5];
-	u_int n;
 	int pin;
+	struct exynos_gpio_bank *bank;
 
 	KASSERT(strlen(pinname) == 2 || strlen(pinname) == 3);
 
@@ -465,21 +274,21 @@ exynos_gpio_pin_lookup(const char *pinna
 	bankname[3] = pinname[3]; /*  D  */
 	pin = pinname[5] - '0';	  /* skip the '-' */
 
-	for (n = 0; n < __arraycount(exynos_gpio_banks); n++) {
-		const struct exynos_gpio_bank *pb =
-		    &exynos_gpio_banks[n];
-		if (strcmp(pb->bank_name, bankname) == 0) {
+	for (bank = exynos_gpio_banks; bank; bank = bank->bank_next)
+		if (strcmp(bank->bank_name, bankname) == 0) {
 			*ppin = pin;
-			return pb;
+			return bank;
 		}
-	}
 
 	return NULL;
 }
 
-struct exynos_gpio_pin *
-exynos_gpio_acquire(const char *pinname, u_int flags)
+static void *
+exynos_gpio_fdt_acquire(device_t dev, const void *data, size_t len, int flags)
 {
+	/* MJF:  This is wrong.  data is a u_int but I need a name */
+//	const u_int *gpio = data;
+	const char *pinname = data;
 	const struct exynos_gpio_bank *bank;
 	struct exynos_gpio_pin *gpin;
 	int pin;
@@ -489,12 +298,57 @@ exynos_gpio_acquire(const char *pinname,
 		return NULL;
 
 	gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
-	gpin->pin_sc = bank->bank_sc;
+	gpin->pin_sc = bank->bank_softc;
 	gpin->pin_bank = bank;
 	gpin->pin_no = pin;
 	gpin->pin_flags = flags;
+	gpin->pin_actlo = 0;
 
 	exynos_gpio_pin_ctl(&gpin->pin_bank, gpin->pin_no, gpin->pin_flags);
 
 	return gpin;
 }
+
+static void
+exynos_gpio_fdt_release(device_t dev, void *priv)
+{
+	struct exynos_gpio_pin *gpin = priv;
+
+	kmem_free(gpin, sizeof(*gpin));
+}
+
+static int
+exynos_gpio_fdt_read(device_t dev, void *priv)
+{
+	struct exynos_gpio_pin *gpin = priv;
+	int val;
+
+	val = (bus_space_read_1(gpin->pin_sc->sc_bst,
+				 gpin->pin_sc->sc_bsh,
+				 EXYNOS_GPIO_DAT) >> gpin->pin_no) & 1;
+
+	if (gpin->pin_actlo)
+		val = !val;
+
+	return val;
+}
+
+static void
+exynos_gpio_fdt_write(device_t dev, void *priv, int val)
+{
+	struct exynos_gpio_pin *gpin = priv;
+
+	if (gpin->pin_actlo)
+		val = !val;
+
+	val = bus_space_read_1(gpin->pin_sc->sc_bst,
+			       gpin->pin_sc->sc_bsh,
+			       EXYNOS_GPIO_DAT);
+	val &= ~__BIT(gpin->pin_no);
+	if (val)
+		val |= __BIT(gpin->pin_no);
+	bus_space_write_1(gpin->pin_sc->sc_bst,
+			  gpin->pin_sc->sc_bsh,
+			  EXYNOS_GPIO_DAT, val);
+
+}
Index: src/sys/arch/arm/samsung/files.exynos
diff -u src/sys/arch/arm/samsung/files.exynos:1.13 src/sys/arch/arm/samsung/files.exynos:1.14
--- src/sys/arch/arm/samsung/files.exynos:1.13	Thu Dec 17 22:39:37 2015
+++ src/sys/arch/arm/samsung/files.exynos	Sat Dec 19 21:42:31 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files.exynos,v 1.13 2015/12/17 22:39:37 marty Exp $
+#	$NetBSD: files.exynos,v 1.14 2015/12/19 21:42:31 marty Exp $
 #
 # Configuration info for Samsung Exynos SoC ARM Peripherals
 #
@@ -74,10 +74,16 @@ file	arch/arm/samsung/exynos_sscom.c	exy
 defflag opt_sscom.h     SSCOM0CONSOLE SSCOM1CONSOLE
 defparam opt_sscom.h    SSCOM_FREQ 
 
+# PINCTL
+device  exyopctl : gpiobus
+attach  exyopctl at fdt with exynos_pinctrl
+file	arch/arm/samsung/exynos_pinctrl.c	exynos_pinctl | exyo_io needs-flag
+file	arch/arm/samsung/exynos_gpio.c		exynos_pinctl | exyo_io needs-flag
+
 # GPIO
-device	exyogpio : gpiobus
-attach	exyogpio at exyo with exynos_gpio
-file	arch/arm/samsung/exynos_gpio.c		exynos_gpio | exyo_io needs-flag
+#device	exyogpio : gpiobus
+#attach	exyogpio at fdt with exynos_gpio
+#file	arch/arm/samsung/exynos_gpio.c		exynos_gpio | exyo_io needs-flag
 
 # USB2 Host Controller (EHCI/OHCI)
 device	exyousb { }

Index: src/sys/arch/arm/samsung/exynos_var.h
diff -u src/sys/arch/arm/samsung/exynos_var.h:1.20 src/sys/arch/arm/samsung/exynos_var.h:1.21
--- src/sys/arch/arm/samsung/exynos_var.h:1.20	Tue Dec 15 23:13:51 2015
+++ src/sys/arch/arm/samsung/exynos_var.h	Sat Dec 19 21:42:31 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_var.h,v 1.20 2015/12/15 23:13:51 marty Exp $	*/
+/*	$NetBSD: exynos_var.h,v 1.21 2015/12/19 21:42:31 marty Exp $	*/
 
 /*-
  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
@@ -125,7 +125,8 @@ extern bus_space_handle_t exynos_sysreg_
 
 extern void exynos_bootstrap(vaddr_t, vaddr_t);
 extern void exynos_dma_bootstrap(psize_t memsize);
-extern void exynos_gpio_bootstrap(void);
+struct exynos_pinctrl_softc;
+extern void exynos_gpio_bank_config(struct exynos_pinctrl_softc *, int);
 extern void exynos_wdt_reset(void);
 
 extern void exynos_init_clkout_for_usb(void);	// board specific

Index: src/sys/arch/evbarm/conf/EXYNOS
diff -u src/sys/arch/evbarm/conf/EXYNOS:1.2 src/sys/arch/evbarm/conf/EXYNOS:1.3
--- src/sys/arch/evbarm/conf/EXYNOS:1.2	Thu Dec 17 22:40:49 2015
+++ src/sys/arch/evbarm/conf/EXYNOS	Sat Dec 19 21:42:31 2015
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: EXYNOS,v 1.2 2015/12/17 22:40:49 marty Exp $
+#	$NetBSD: EXYNOS,v 1.3 2015/12/19 21:42:31 marty Exp $
 #
 #	ODROID-XU -- ODROID-XU4 Exynos5422 based kernel
 #
@@ -209,6 +209,9 @@ fdt*		at simplebus?
 
 fregulator*	at fdt?
 
+#interrupt controller
+gic*		at fdt?
+
 # Exynos SoC
 exyo0		at mainbus?
 
@@ -223,8 +226,12 @@ sscom*		at fdt?				# UART ?
 exyowdt0 	at fdt?				# watchdog
 
 # GPIO
-exyogpio0	at exyo0
-gpio*		at exyogpio?
+exyopctl0	at fdt?
+exyopctl1	at fdt?
+exyopctl2	at fdt?
+exyopctl3	at fdt?
+exyopctl4	at fdt?
+#gpio*		at exyogpio?
 
 # On-board USB
 exyousb*	at exyo0

Added files:

Index: src/sys/arch/arm/samsung/exynos_pinctrl.c
diff -u /dev/null src/sys/arch/arm/samsung/exynos_pinctrl.c:1.1
--- /dev/null	Sat Dec 19 21:42:31 2015
+++ src/sys/arch/arm/samsung/exynos_pinctrl.c	Sat Dec 19 21:42:31 2015
@@ -0,0 +1,110 @@
+/*	$NetBSD: exynos_pinctrl.c,v 1.1 2015/12/19 21:42:31 marty Exp $ */
+
+/*-
+* Copyright (c) 2015 The NetBSD Foundation, Inc.
+* All rights reserved.
+*
+* This code is derived from software contributed to The NetBSD Foundation
+* by Marty Fouts
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+* 1. Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "opt_exynos.h"
+#include "opt_arm_debug.h"
+#include "gpio.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.1 2015/12/19 21:42:31 marty Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+#include <sys/gpio.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#include <arm/samsung/exynos_reg.h>
+#include <arm/samsung/exynos_io.h>
+#include <arm/samsung/exynos_intr.h>
+#include <arm/samsung/exynos_pinctrl.h>
+
+#include <dev/fdt/fdtvar.h>
+
+static int exynos_pinctrl_match(device_t, cfdata_t, void *);
+static void exynos_pinctrl_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(exynos_pinctrl, sizeof(struct exynos_pinctrl_softc),
+	exynos_pinctrl_match, exynos_pinctrl_attach, NULL, NULL);
+
+static int
+exynos_pinctrl_match(device_t parent, cfdata_t cf, void *aux)
+{
+	const char * const compatible[] = { "samsung,exynos5422-pinctrl",
+					    NULL };
+	struct fdt_attach_args * const faa = aux;
+	return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+exynos_pinctrl_attach(device_t parent, device_t self, void *aux)
+{
+	struct exynos_pinctrl_softc * const sc
+		= kmem_zalloc(sizeof(*sc), KM_SLEEP);
+	struct fdt_attach_args * const faa = aux;
+	bus_addr_t addr;
+	bus_size_t size;
+	int error;
+	int child;
+
+	if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+		aprint_error(": couldn't get registers\n");
+		return;
+	}
+
+	printf(" pinctl @ 0x%08x\n", (uint)addr);
+	sc->sc_dev = self;
+	sc->sc_bst = faa->faa_bst;
+	error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
+	if (error) {
+		aprint_error(": couldn't map %#llx: %d",
+			     (uint64_t)addr, error);
+		return;
+	}
+
+	for (child = OF_child(faa->faa_phandle); child;
+	     child = OF_peer(child)) {
+		char result[64];
+		error = OF_getprop(child, "gpio-controller", result,
+				   sizeof(result));
+		if (error == -1)
+			continue;
+		exynos_gpio_bank_config(sc,child);
+	}
+
+	aprint_naive("\n");
+	aprint_normal("\n");
+
+}

Reply via email to