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/45eead3455f7
branches:  trunk
changeset: 828415:45eead3455f7
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 0dda38f61bbc -r 45eead3455f7 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 0dda38f61bbc -r 45eead3455f7 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