Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/samsung XU4 GPIO Driver
details: https://anonhg.NetBSD.org/src/rev/0287393a8ef1
branches: trunk
changeset: 812577:0287393a8ef1
user: marty <marty%NetBSD.org@localhost>
date: Tue Dec 22 03:36:01 2015 +0000
description:
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.
diffstat:
sys/arch/arm/samsung/exynos_gpio.c | 199 +++++++++++++++++++++++----------
sys/arch/arm/samsung/exynos_pinctrl.c | 9 +-
sys/arch/arm/samsung/exynos_pinctrl.h | 2 +
3 files changed, 145 insertions(+), 65 deletions(-)
diffs (truncated from 369 to 300 lines):
diff -r a61114bc6710 -r 0287393a8ef1 sys/arch/arm/samsung/exynos_gpio.c
--- a/sys/arch/arm/samsung/exynos_gpio.c Tue Dec 22 02:17:21 2015 +0000
+++ b/sys/arch/arm/samsung/exynos_gpio.c Tue Dec 22 03:36:01 2015 +0000
@@ -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 @@
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 @@
const struct exynos_gpio_bank *pin_bank;
};
-struct exynos_gpio_bank *exynos_gpio_banks;
+
+//#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),
-static void exynos_gpio_pin_ctl(void *cookie, int pin, int flags);
+ 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 @@
.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 @@
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 @@
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 @@
/* 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 @@
* 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 '-' */
Home |
Main Index |
Thread Index |
Old Index