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;