Module Name:    src
Committed By:   marty
Date:           Tue Dec 22 03:36:01 UTC 2015

Modified Files:
        src/sys/arch/arm/samsung: exynos_gpio.c exynos_pinctrl.c
            exynos_pinctrl.h

Log Message:
XU4 GPIO Driver

This is a moderately tested working gpio driver for the Exynos based ODROID
XU4.  To use this you have to edit the dtd file exynos54422-pinctrl.dtsi
and change the two occurances of 'gpz' to 'gpz0'.  Otherewise it will crash
on a lookup failure.

It certainly could use a code review.


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/arm/samsung/exynos_gpio.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/samsung/exynos_pinctrl.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/samsung/exynos_pinctrl.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/samsung/exynos_gpio.c
diff -u src/sys/arch/arm/samsung/exynos_gpio.c:1.15 src/sys/arch/arm/samsung/exynos_gpio.c:1.16
--- src/sys/arch/arm/samsung/exynos_gpio.c:1.15	Mon Dec 21 04:58:50 2015
+++ src/sys/arch/arm/samsung/exynos_gpio.c	Tue Dec 22 03:36:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_gpio.c,v 1.15 2015/12/21 04:58:50 marty Exp $ */
+/*	$NetBSD: exynos_gpio.c,v 1.16 2015/12/22 03:36:01 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.15 2015/12/21 04:58:50 marty Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.16 2015/12/22 03:36:01 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -67,7 +67,7 @@ struct exynos_gpio_bank {
 	const char		bank_name[6];
 	device_t		bank_dev;
 	struct gpio_chipset_tag	bank_gc;
-	struct exynos_gpio_softc *bank_softc;
+	struct exynos_gpio_softc *bank_sc;
 	gpio_pin_t		bank_pins[8];
 
 	const bus_addr_t	bank_core_offset;
@@ -94,16 +94,74 @@ struct exynos_gpio_pin {
 	const struct exynos_gpio_bank   *pin_bank;
 };
 
-struct exynos_gpio_bank *exynos_gpio_banks;
 
-static void exynos_gpio_pin_ctl(void *cookie, int pin, int flags);
+//#define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o))
+#define GPIO_REG(v,s,o) ((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),
+
+	GPIO_GRP(5, MUXE, 0x0000, gpz0, 7),
+
+};
+
+struct exynos_gpio_bank *exynos_gpio_banks = exynos5_banks;
+
+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 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 *);
+static struct exynos_gpio_bank *
+exynos_gpio_pin_lookup(const char *pinname, int *ppin);
+static int exynos_gpio_cfprint(void *, const char *);
 
 struct fdtbus_gpio_controller_func exynos_gpio_funcs = {
 	.acquire = exynos_gpio_fdt_acquire,
@@ -111,8 +169,15 @@ struct fdtbus_gpio_controller_func exyno
 	.read = exynos_gpio_fdt_read,
 	.write = exynos_gpio_fdt_write
 };
+#define GPIO_WRITE(bank, reg, val) \
+	bus_space_write_4((bank)->bank_sc->sc_bst, \
+	    (bank)->bank_sc->sc_bsh, \
+	    (bank)->bank_core_offset + (reg), (val))
+#define GPIO_READ(bank, reg) \
+	bus_space_read_4((bank)->bank_sc->sc_bst, \
+	    (bank)->bank_sc->sc_bsh, \
+	    (bank)->bank_core_offset + (reg))
 
-#if 0
 static int
 exynos_gpio_cfprint(void *priv, const char *pnp)
 {
@@ -127,45 +192,62 @@ exynos_gpio_cfprint(void *priv, const ch
 
 	return UNCONF;
 }
-#endif
 
 static void
 exynos_gpio_update_cfg_regs(struct exynos_gpio_bank *bank,
 	const struct exynos_gpio_pin_cfg *ncfg)
 {
-	bus_space_tag_t bst = &armv7_generic_bs_tag;
-
 	if (bank->bank_cfg.cfg != ncfg->cfg) {
-		bus_space_write_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_CON, ncfg->cfg);
+		GPIO_WRITE(bank, EXYNOS_GPIO_CON, ncfg->cfg);
 		bank->bank_cfg.cfg = ncfg->cfg;
 	}
 	if (bank->bank_cfg.pud != ncfg->pud) {
-		bus_space_write_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_PUD, ncfg->pud);
+		GPIO_WRITE(bank, EXYNOS_GPIO_PUD, ncfg->pud);
 		bank->bank_cfg.pud = ncfg->pud;
 	}
 
-	/* the following attributes are not yet setable */
-#if 0
 	if (bank->bank_cfg.drv != ncfg->drv) {
-		bus_space_write_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_DRV, ncfg->drv);
+		GPIO_WRITE(bank, EXYNOS_GPIO_DRV, ncfg->drv);
 		bank->bank_cfg.drv = ncfg->drv;
 	}
 	if (bank->bank_cfg.conpwd != ncfg->conpwd) {
-		bus_space_write_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_CONPWD, ncfg->conpwd);
+		GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, ncfg->conpwd);
 		bank->bank_cfg.conpwd = ncfg->conpwd;
 	}
 	if (bank->bank_cfg.pudpwd != ncfg->pudpwd) {
-		bus_space_write_4(bst, bank->bank_bsh,
-			EXYNOS_GPIO_PUDPWD, ncfg->pudpwd);
+		GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, ncfg->pudpwd);
 		bank->bank_cfg.pudpwd = ncfg->pudpwd;
 	}
-#endif
 }
 
+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(bank->bank_sc->sc_bst,
+				 bank->bank_sc->sc_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(bank->bank_sc->sc_bst,
+			       bank->bank_sc->sc_bsh,
+			       EXYNOS_GPIO_DAT);
+	val &= ~__BIT(pin);
+	if (value)
+		val |= __BIT(pin);
+	bus_space_write_1(bank->bank_sc->sc_bst,
+			  bank->bank_sc->sc_bsh,
+		EXYNOS_GPIO_DAT, val);
+}
 
 static void
 exynos_gpio_pin_ctl(void *cookie, int pin, int flags)
@@ -201,34 +283,30 @@ exynos_gpio_pin_ctl(void *cookie, int pi
 void
 exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent, int node)
 {
-//	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;
+	struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
+	struct gpiobus_attach_args gba;
+	struct gpio_chipset_tag *gc_tag;
 	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;
-
-//	data = bus_space_read_1(sc->sc_bst, bank->bank_bsh,
-//				EXYNOS_GPIO_DAT);
 
+	OF_getprop(node, "name", result, sizeof(result));
+	bank = exynos_gpio_pin_lookup(result, 0);
+	KASSERT(bank);
+	
 	sc->sc_dev = parent->sc_dev;
-	sc->sc_bst = parent->sc_bst;
+	sc->sc_bst = &armv7_generic_bs_tag;
+	sc->sc_bsh = parent->sc_bsh;
 	
+	gc_tag = &bank->bank_gc;
+	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;
 	memset(&gba, 0, sizeof(gba));
 	gba.gba_gc = &bank->bank_gc;
 	gba.gba_pins = bank->bank_pins;
-//	gba.gba_npins = bit; /* MJF? */
+	gba.gba_npins = bank->bank_bits;
+	bank->bank_sc = sc;
 	bank->bank_dev = config_found_ia(parent->sc_dev, "gpiobus", &gba,
 					 exynos_gpio_cfprint);
 
@@ -237,18 +315,11 @@ exynos_gpio_bank_config(struct exynos_pi
 
 
 	/* 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
+	bank->bank_cfg.cfg = GPIO_READ(bank, EXYNOS_GPIO_CON);
+	bank->bank_cfg.pud = GPIO_READ(bank, EXYNOS_GPIO_PUD);
+	bank->bank_cfg.drv = GPIO_READ(bank, EXYNOS_GPIO_DRV);
+	bank->bank_cfg.conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD);
+	bank->bank_cfg.pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD);
 }
 
 /*
@@ -258,27 +329,31 @@ exynos_gpio_bank_config(struct exynos_pi
  *     N = '0' - '8'    ===== pin number
  */
 
-static const struct exynos_gpio_bank *
+static struct exynos_gpio_bank *
 exynos_gpio_pin_lookup(const char *pinname, int *ppin)
 {
 	char bankname[5];
 	int pin;
+	int n;
 	struct exynos_gpio_bank *bank;
 
-	KASSERT(strlen(pinname) == 2 || strlen(pinname) == 3);
-
 	memset(bankname, 0, sizeof(bankname));
 	bankname[0] = pinname[0]; /* 'g' */
 	bankname[1] = pinname[1]; /* 'p' */
 	bankname[2] = pinname[2]; /*  L  */
 	bankname[3] = pinname[3]; /*  D  */
-	pin = pinname[5] - '0';	  /* skip the '-' */
+	bankname[4] = 0;
+	if (ppin)
+		pin = pinname[5] - '0';	  /* skip the '-' */
 
-	for (bank = exynos_gpio_banks; bank; bank = bank->bank_next)
+	for (n = 0; n < __arraycount(exynos5_banks); n++) {
+		bank = &exynos_gpio_banks[n];
 		if (strcmp(bank->bank_name, bankname) == 0) {
-			*ppin = pin;
+			if (ppin)
+				*ppin = pin;
 			return bank;
 		}
+	}
 
 	return NULL;
 }
@@ -298,7 +373,7 @@ exynos_gpio_fdt_acquire(device_t dev, co
 		return NULL;
 
 	gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
-	gpin->pin_sc = bank->bank_softc;
+	gpin->pin_sc = bank->bank_sc;
 	gpin->pin_bank = bank;
 	gpin->pin_no = pin;
 	gpin->pin_flags = flags;

Index: src/sys/arch/arm/samsung/exynos_pinctrl.c
diff -u src/sys/arch/arm/samsung/exynos_pinctrl.c:1.3 src/sys/arch/arm/samsung/exynos_pinctrl.c:1.4
--- src/sys/arch/arm/samsung/exynos_pinctrl.c:1.3	Mon Dec 21 04:58:50 2015
+++ src/sys/arch/arm/samsung/exynos_pinctrl.c	Tue Dec 22 03:36:01 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: exynos_pinctrl.c,v 1.3 2015/12/21 04:58:50 marty Exp $ */
+/*	$NetBSD: exynos_pinctrl.c,v 1.4 2015/12/22 03:36:01 marty Exp $ */
 
 /*-
 * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 #include "gpio.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.3 2015/12/21 04:58:50 marty Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_pinctrl.c,v 1.4 2015/12/22 03:36:01 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -84,7 +84,7 @@ exynos_pinctrl_attach(device_t parent, d
 		return;
 	}
 
-	aprint_normal(" pinctl @ 0x%08x", (uint)addr);
+	aprint_normal(" pinctl @ 0x%08x ", (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);
@@ -104,6 +104,9 @@ exynos_pinctrl_attach(device_t parent, d
 		exynos_gpio_bank_config(sc,child);
 	}
 
+	fdtbus_register_gpio_controller(self, faa->faa_phandle,
+	    &exynos_gpio_funcs);
+
 	aprint_naive("\n");
 	aprint_normal("\n");
 

Index: src/sys/arch/arm/samsung/exynos_pinctrl.h
diff -u src/sys/arch/arm/samsung/exynos_pinctrl.h:1.1 src/sys/arch/arm/samsung/exynos_pinctrl.h:1.2
--- src/sys/arch/arm/samsung/exynos_pinctrl.h:1.1	Sat Dec 19 21:43:36 2015
+++ src/sys/arch/arm/samsung/exynos_pinctrl.h	Tue Dec 22 03:36:01 2015
@@ -1,3 +1,5 @@
+extern struct fdtbus_gpio_controller_func exynos_gpio_funcs;
+
 struct exynos_pinctrl_softc {
 	device_t		sc_dev;
 	bus_space_tag_t		sc_bst;

Reply via email to