Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/isa Add wbsio(4) GPIO driver. Implemeted by s-yamagu...
details: https://anonhg.NetBSD.org/src/rev/096dc8f910da
branches: trunk
changeset: 358114:096dc8f910da
user: knakahara <knakahara%NetBSD.org@localhost>
date: Wed Dec 13 00:26:06 2017 +0000
description:
Add wbsio(4) GPIO driver. Implemeted by s-yamaguchi@IIJ, reviewed by msaitoh@n.o.
I just commit by proxy.
diffstat:
sys/dev/isa/files.isa | 4 +-
sys/dev/isa/wbsio.c | 409 ++++++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/isa/wbsioreg.h | 96 +++++++++++-
3 files changed, 505 insertions(+), 4 deletions(-)
diffs (truncated from 620 to 300 lines):
diff -r 9ccecd687e12 -r 096dc8f910da sys/dev/isa/files.isa
--- a/sys/dev/isa/files.isa Wed Dec 13 00:22:24 2017 +0000
+++ b/sys/dev/isa/files.isa Wed Dec 13 00:26:06 2017 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.isa,v 1.167 2016/12/09 04:32:39 christos Exp $
+# $NetBSD: files.isa,v 1.168 2017/12/13 00:26:06 knakahara Exp $
#
# Config file and device description for machine-independent ISA code.
# Included by ports that need it. Requires that the SCSI files be
@@ -454,7 +454,7 @@
file dev/isa/smsc.c smsc needs-flag
# Winbond LPC Super I/O
-device wbsio {}
+device wbsio { }: gpiobus
attach wbsio at isa
file dev/isa/wbsio.c wbsio
diff -r 9ccecd687e12 -r 096dc8f910da sys/dev/isa/wbsio.c
--- a/sys/dev/isa/wbsio.c Wed Dec 13 00:22:24 2017 +0000
+++ b/sys/dev/isa/wbsio.c Wed Dec 13 00:26:06 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wbsio.c,v 1.15 2017/08/18 04:07:51 msaitoh Exp $ */
+/* $NetBSD: wbsio.c,v 1.16 2017/12/13 00:26:06 knakahara Exp $ */
/* $OpenBSD: wbsio.c,v 1.10 2015/03/14 03:38:47 jsg Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis <kettenis%openbsd.org@localhost>
@@ -20,11 +20,14 @@
* Winbond LPC Super I/O driver.
*/
+#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/systm.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
#include <sys/bus.h>
@@ -32,15 +35,34 @@
#include <dev/isa/isavar.h>
#include <dev/isa/wbsioreg.h>
+/* Don't use gpio for now in the module */
+#ifndef _MODULE
+#include "gpio.h"
+#endif
+#if NGPIO > 0
+#include <dev/gpio/gpiovar.h>
+#endif
+
struct wbsio_softc {
device_t sc_dev;
device_t sc_lm_dev;
+#if NGPIO > 0
+ device_t sc_gpio_dev;
+#endif
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
struct isa_attach_args sc_ia;
struct isa_io sc_io;
+
+#if NGPIO > 0
+ bus_space_handle_t sc_gpio_ioh;
+ kmutex_t sc_gpio_lock;
+ struct gpio_chipset_tag sc_gpio_gc;
+ struct gpio_pin sc_gpio_pins[WBSIO_GPIO_NPINS];
+ bool sc_gpio_rt;
+#endif
};
static const struct wbsio_product {
@@ -79,6 +101,17 @@
static void wbsio_childdet(device_t, device_t);
static int wbsio_print(void *, const char *);
static int wbsio_search(device_t, cfdata_t, const int *, void *);
+#if NGPIO > 0
+static int wbsio_gpio_search(device_t, cfdata_t, const int *, void *);
+static int wbsio_gpio_rt_init(struct wbsio_softc *);
+static int wbsio_gpio_rt_read(struct wbsio_softc *, int, int);
+static void wbsio_gpio_rt_write(struct wbsio_softc *, int, int, int);
+static int wbsio_gpio_rt_pin_read(void *, int);
+static void wbsio_gpio_rt_pin_write(void *, int, int);
+static void wbsio_gpio_rt_pin_ctl(void *, int, int);
+static void wbsio_gpio_enable_nct6779d(device_t);
+static void wbsio_gpio_pinconfig_nct6779d(device_t);
+#endif
CFATTACH_DECL2_NEW(wbsio, sizeof(struct wbsio_softc),
wbsio_match, wbsio_attach, wbsio_detach, NULL,
@@ -229,6 +262,11 @@
if (!pmf_device_register(self, NULL, NULL))
aprint_error_dev(self, "couldn't establish power handler\n");
wbsio_rescan(self, "wbsio", NULL);
+
+#if NGPIO > 0
+
+ wbsio_rescan(self, "gpiobus", NULL);
+#endif
}
int
@@ -241,6 +279,17 @@
return rc;
bus_space_unmap(sc->sc_iot, sc->sc_ioh, WBSIO_IOSIZE);
pmf_device_deregister(self);
+
+#if NGPIO > 0
+ if (sc->sc_gpio_dev) {
+ bus_space_unmap(sc->sc_iot, sc->sc_gpio_ioh,
+ WBSIO_GPIO_IOSIZE);
+ }
+
+ if (sc->sc_gpio_rt) {
+ mutex_destroy(&sc->sc_gpio_lock);
+ }
+#endif
return 0;
}
@@ -248,6 +297,13 @@
wbsio_rescan(device_t self, const char *ifattr, const int *locators)
{
+#if NGPIO > 0
+ if (ifattr_match(ifattr, "gpiobus")) {
+ config_search_loc(wbsio_gpio_search, self,
+ ifattr, locators, NULL);
+ return 0;
+ }
+#endif
config_search_loc(wbsio_search, self, ifattr, locators, NULL);
return 0;
@@ -338,6 +394,357 @@
return (UNCONF);
}
+#if NGPIO > 0
+static int
+wbsio_gpio_search(device_t parent, cfdata_t cf, const int *slocs, void *aux)
+{
+ struct wbsio_softc *sc = device_private(parent);
+ const struct wbsio_product *product;
+ struct gpiobus_attach_args gba;
+ uint16_t devid;
+ uint8_t rev;
+ int i;
+
+ /* Enter configuration mode */
+ wbsio_conf_enable(sc->sc_iot, sc->sc_ioh);
+ /* Read device ID and revision */
+ devid = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID);
+ rev = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV);
+ /* Escape from configuration mode */
+ wbsio_conf_disable(sc->sc_iot, sc->sc_ioh);
+
+ if ((product = wbsio_lookup(devid, rev)) == NULL) {
+ aprint_error_dev(parent, "%s: Unknown device.\n", __func__);
+ return -1;
+ }
+
+ sc->sc_gpio_rt = false;
+
+ switch (product->id) {
+ case WBSIO_ID_NCT6779D:
+ wbsio_gpio_enable_nct6779d(parent);
+ sc->sc_gpio_rt = true;
+ break;
+ default:
+ aprint_error_dev(parent, "GPIO is not supported\n");
+ return -1;
+ }
+
+ if (sc->sc_gpio_rt) {
+ if (wbsio_gpio_rt_init(sc) != 0) {
+ sc->sc_gpio_rt = false;
+ return -1;
+ }
+ sc->sc_gpio_gc.gp_cookie = sc;
+ sc->sc_gpio_gc.gp_pin_read = wbsio_gpio_rt_pin_read;
+ sc->sc_gpio_gc.gp_pin_write = wbsio_gpio_rt_pin_write;
+ sc->sc_gpio_gc.gp_pin_ctl = wbsio_gpio_rt_pin_ctl;
+ } else {
+ aprint_error_dev(parent,
+ "GPIO indirect access is not supported\n");
+ return -1;
+ }
+
+ for (i = 0; i < WBSIO_GPIO_NPINS; i++) {
+ sc->sc_gpio_pins[i].pin_num = i;
+ sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
+ GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
+
+ /* safe defaults */
+ sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT;
+ sc->sc_gpio_pins[i].pin_state = GPIO_PIN_LOW;
+ sc->sc_gpio_gc.gp_pin_ctl(sc, i, sc->sc_gpio_pins[i].pin_flags);
+ sc->sc_gpio_gc.gp_pin_write(sc, i, sc->sc_gpio_pins[i].pin_state);
+ }
+
+ switch (product->id) {
+ case WBSIO_ID_NCT6779D:
+ wbsio_gpio_pinconfig_nct6779d(parent);
+ break;
+ }
+
+ gba.gba_gc = &sc->sc_gpio_gc;
+ gba.gba_pins = sc->sc_gpio_pins;
+ gba.gba_npins = WBSIO_GPIO_NPINS;
+
+ sc->sc_gpio_dev = config_attach(parent, cf, &gba, gpiobus_print);
+
+ return 0;
+}
+
+static int
+wbsio_gpio_rt_init(struct wbsio_softc *sc)
+{
+ uint16_t iobase;
+ uint8_t reg0, reg1;
+
+ /* Enter configuration mode */
+ wbsio_conf_enable(sc->sc_iot, sc->sc_ioh);
+
+ /* Get GPIO Register Table address */
+ wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_GPIO0);
+ reg0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_GPIO_ADDR_LSB);
+ reg1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_GPIO_ADDR_MSB);
+ iobase = (reg1 << 8) | (reg0 & ~0x7);
+
+ /* Escape from configuration mode */
+ wbsio_conf_disable(sc->sc_iot, sc->sc_ioh);
+
+ if (bus_space_map(sc->sc_iot, iobase, WBSIO_GPIO_IOSIZE,
+ 0, &sc->sc_gpio_ioh)) {
+ aprint_error_dev(sc->sc_dev,
+ "can't map gpio to i/o space\n");
+ return -1;
+ }
+
+ aprint_normal_dev(sc->sc_dev, "GPIO: port 0x%x-0x%x\n",
+ iobase, iobase + WBSIO_GPIO_IOSIZE);
+
+ mutex_init(&sc->sc_gpio_lock, MUTEX_DEFAULT, IPL_NONE);
+
+ return 0;
+}
+
+static int
+wbsio_gpio_rt_read(struct wbsio_softc *sc, int port, int reg)
+{
+ int v;
+
+ mutex_enter(&sc->sc_gpio_lock);
+
+ bus_space_write_1(sc->sc_iot, sc->sc_gpio_ioh,
+ WBSIO_GPIO_GSR, port);
+ v = bus_space_read_1(sc->sc_iot, sc->sc_gpio_ioh, reg);
+
+ mutex_exit(&sc->sc_gpio_lock);
+
+ return v;
+}
+
+static void
+wbsio_gpio_rt_write(struct wbsio_softc *sc, int port, int reg, int value)
+{
+
+ mutex_enter(&sc->sc_gpio_lock);
+
+ bus_space_write_1(sc->sc_iot, sc->sc_gpio_ioh,
+ WBSIO_GPIO_GSR, port);
+ bus_space_write_1(sc->sc_iot, sc->sc_gpio_ioh,
+ reg, value);
+
+ mutex_exit(&sc->sc_gpio_lock);
+}
+
+static int
+wbsio_gpio_rt_pin_read(void *aux, int pin)
+{
+ struct wbsio_softc *sc = (struct wbsio_softc *)aux;
+ int port, shift, data;
+
+ port = (pin >> 3) & 0x07;
+ shift = pin & 0x07;
+
+ data = wbsio_gpio_rt_read(sc, port, WBSIO_GPIO_DAT);
+
+ return ((data >> shift) & 0x01);
+}
+
+static void
+wbsio_gpio_rt_pin_write(void *aux, int pin, int v)
Home |
Main Index |
Thread Index |
Old Index