aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2019-10-16 14:42:49 +0000
committerAndriy Gapon <avg@FreeBSD.org>2019-10-16 14:42:49 +0000
commite3df342a32debf2cc8bdc20582afd8adeec35775 (patch)
tree9a8cb93054d9b24cc04a995d41a61c2772a70e0b
parent3635891a92ce6fcadca6381eb83d83623236092c (diff)
downloadsrc-e3df342a32debf2cc8bdc20582afd8adeec35775.tar.gz
src-e3df342a32debf2cc8bdc20582afd8adeec35775.zip
move nctgpio to superio(4) bus
This is where it logically belongs. The change allows to drop a bunch of low lewel code. Reviewed by: gonzo MFC after: 19 days Differential Revision: https://reviews.freebsd.org/D21980
Notes
Notes: svn path=/head/; revision=353643
-rw-r--r--sys/dev/nctgpio/nctgpio.c275
1 files changed, 57 insertions, 218 deletions
diff --git a/sys/dev/nctgpio/nctgpio.c b/sys/dev/nctgpio/nctgpio.c
index eb86b0a9e5eb..e6edcedfd2a7 100644
--- a/sys/dev/nctgpio/nctgpio.c
+++ b/sys/dev/nctgpio/nctgpio.c
@@ -42,34 +42,20 @@
#include <sys/lock.h>
#include <sys/module.h>
-#include <sys/rman.h>
#include <sys/gpio.h>
-#include <isa/isavar.h>
-
#include <machine/bus.h>
-#include <machine/resource.h>
#include <dev/gpio/gpiobusvar.h>
+#include <dev/superio/superio.h>
#include "gpio_if.h"
-/*
- * Global configuration registers (CR).
- */
-#define NCT_CR_LDN 0x07 /* Logical Device Number */
-#define NCT_CR_CHIP_ID 0x20 /* Chip ID */
-#define NCT_CR_CHIP_ID_H 0x20 /* Chip ID (high byte) */
-#define NCT_CR_CHIP_ID_L 0x21 /* Chip ID (low byte) */
-#define NCT_CR_OPT_1 0x26 /* Global Options (1) */
-
/* Logical Device Numbers. */
#define NCT_LDN_GPIO 0x07
-#define NCT_LDN_GPIO_CFG 0x08
#define NCT_LDN_GPIO_MODE 0x0f
/* Logical Device 7 */
-#define NCT_LD7_GPIO_ENABLE 0x30
#define NCT_LD7_GPIO0_IOR 0xe0
#define NCT_LD7_GPIO0_DAT 0xe1
#define NCT_LD7_GPIO0_INV 0xe2
@@ -83,8 +69,6 @@
#define NCT_LDF_GPIO0_OUTCFG 0xe0
#define NCT_LDF_GPIO1_OUTCFG 0xe1
-#define NCT_EXTFUNC_ENTER 0x87
-#define NCT_EXTFUNC_EXIT 0xaa
#define NCT_MAX_PIN 15
#define NCT_IS_VALID_PIN(_p) ((_p) >= 0 && (_p) <= NCT_MAX_PIN)
@@ -97,10 +81,9 @@
struct nct_softc {
device_t dev;
+ device_t dev_f;
device_t busdev;
struct mtx mtx;
- struct resource *portres;
- int rid;
struct gpio_pin pins[NCT_MAX_PIN + 1];
};
@@ -112,22 +95,6 @@ struct nct_softc {
#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED)
-#define NCT_BARRIER_WRITE(_sc) \
- bus_barrier((_sc)->portres, 0, 2, BUS_SPACE_BARRIER_WRITE)
-
-#define NCT_BARRIER_READ_WRITE(_sc) \
- bus_barrier((_sc)->portres, 0, 2, \
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
-
-static void ext_cfg_enter(struct nct_softc *);
-static void ext_cfg_exit(struct nct_softc *);
-
-/*
- * Potential Extended Function Enable Register addresses.
- * Same address as EFIR.
- */
-uint8_t probe_addrs[] = {0x2e, 0x4e};
-
struct nuvoton_vendor_device_id {
uint16_t chip_id;
const char * descr;
@@ -146,76 +113,6 @@ struct nuvoton_vendor_device_id {
},
};
-static void
-write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value)
-{
- GPIO_ASSERT_LOCKED(sc);
- bus_write_1(sc->portres, 0, reg);
- NCT_BARRIER_WRITE(sc);
- bus_write_1(sc->portres, 1, value);
- NCT_BARRIER_WRITE(sc);
-}
-
-static uint8_t
-read_cfg_reg_1(struct nct_softc *sc, uint8_t reg)
-{
- uint8_t value;
-
- GPIO_ASSERT_LOCKED(sc);
- bus_write_1(sc->portres, 0, reg);
- NCT_BARRIER_READ_WRITE(sc);
- value = bus_read_1(sc->portres, 1);
- NCT_BARRIER_READ_WRITE(sc);
-
- return (value);
-}
-
-static uint16_t
-read_cfg_reg_2(struct nct_softc *sc, uint8_t reg)
-{
- uint16_t value;
-
- value = read_cfg_reg_1(sc, reg) << 8;
- value |= read_cfg_reg_1(sc, reg + 1);
-
- return (value);
-}
-
-/*
- * Enable extended function mode.
- *
- */
-static void
-ext_cfg_enter(struct nct_softc *sc)
-{
- GPIO_ASSERT_LOCKED(sc);
- bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
- NCT_BARRIER_WRITE(sc);
- bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
- NCT_BARRIER_WRITE(sc);
-}
-
-/*
- * Disable extended function mode.
- *
- */
-static void
-ext_cfg_exit(struct nct_softc *sc)
-{
- GPIO_ASSERT_LOCKED(sc);
- bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT);
- NCT_BARRIER_WRITE(sc);
-}
-
-/*
- * Select a Logical Device.
- */
-static void
-select_ldn(struct nct_softc *sc, uint8_t ldn)
-{
- write_cfg_reg_1(sc, NCT_CR_LDN, ldn);
-}
-
/*
* Get the GPIO Input/Output register address
* for a pin.
@@ -289,10 +186,9 @@ nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num)
uint8_t ior;
reg = nct_ior_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- ior = read_cfg_reg_1(sc, reg);
+ ior = superio_read(sc->dev, reg);
ior &= ~(NCT_PIN_BIT(pin_num));
- write_cfg_reg_1(sc, reg, ior);
+ superio_write(sc->dev, reg, ior);
}
/*
@@ -305,10 +201,9 @@ nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
uint8_t ior;
reg = nct_ior_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- ior = read_cfg_reg_1(sc, reg);
+ ior = superio_read(sc->dev, reg);
ior |= NCT_PIN_BIT(pin_num);
- write_cfg_reg_1(sc, reg, ior);
+ superio_write(sc->dev, reg, ior);
}
/*
@@ -321,8 +216,7 @@ nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
uint8_t ior;
reg = nct_ior_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- ior = read_cfg_reg_1(sc, reg);
+ ior = superio_read(sc->dev, reg);
return (ior & NCT_PIN_BIT(pin_num));
}
@@ -337,14 +231,13 @@ nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data)
uint8_t value;
reg = nct_dat_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- value = read_cfg_reg_1(sc, reg);
+ value = superio_read(sc->dev, reg);
if (data)
value |= NCT_PIN_BIT(pin_num);
else
value &= ~(NCT_PIN_BIT(pin_num));
- write_cfg_reg_1(sc, reg, value);
+ superio_write(sc->dev, reg, value);
}
static bool
@@ -353,9 +246,8 @@ nct_read_pin(struct nct_softc *sc, uint32_t pin_num)
uint8_t reg;
reg = nct_dat_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- return (read_cfg_reg_1(sc, reg) & NCT_PIN_BIT(pin_num));
+ return (superio_read(sc->dev, reg) & NCT_PIN_BIT(pin_num));
}
static void
@@ -365,10 +257,9 @@ nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
uint8_t inv;
reg = nct_inv_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- inv = read_cfg_reg_1(sc, reg);
+ inv = superio_read(sc->dev, reg);
inv |= (NCT_PIN_BIT(pin_num));
- write_cfg_reg_1(sc, reg, inv);
+ superio_write(sc->dev, reg, inv);
}
static void
@@ -378,10 +269,9 @@ nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num)
uint8_t inv;
reg = nct_inv_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- inv = read_cfg_reg_1(sc, reg);
+ inv = superio_read(sc->dev, reg);
inv &= ~(NCT_PIN_BIT(pin_num));
- write_cfg_reg_1(sc, reg, inv);
+ superio_write(sc->dev, reg, inv);
}
static bool
@@ -391,8 +281,7 @@ nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
uint8_t inv;
reg = nct_inv_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO);
- inv = read_cfg_reg_1(sc, reg);
+ inv = superio_read(sc->dev, reg);
return (inv & NCT_PIN_BIT(pin_num));
}
@@ -404,10 +293,9 @@ nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num)
uint8_t outcfg;
reg = nct_outcfg_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO_MODE);
- outcfg = read_cfg_reg_1(sc, reg);
- outcfg |= (NCT_PIN_BIT(pin_num));
- write_cfg_reg_1(sc, reg, outcfg);
+ outcfg = superio_read(sc->dev_f, reg);
+ outcfg |= NCT_PIN_BIT(pin_num);
+ superio_write(sc->dev_f, reg, outcfg);
}
static void
@@ -417,10 +305,9 @@ nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num)
uint8_t outcfg;
reg = nct_outcfg_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO_MODE);
- outcfg = read_cfg_reg_1(sc, reg);
- outcfg &= ~(NCT_PIN_BIT(pin_num));
- write_cfg_reg_1(sc, reg, outcfg);
+ outcfg = superio_read(sc->dev_f, reg);
+ outcfg &= ~NCT_PIN_BIT(pin_num);
+ superio_write(sc->dev_f, reg, outcfg);
}
static bool
@@ -430,66 +317,33 @@ nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num)
uint8_t outcfg;
reg = nct_outcfg_addr(pin_num);
- select_ldn(sc, NCT_LDN_GPIO_MODE);
- outcfg = read_cfg_reg_1(sc, reg);
-
+ outcfg = superio_read(sc->dev_f, reg);
return (outcfg & NCT_PIN_BIT(pin_num));
}
-static void
-nct_identify(driver_t *driver, device_t parent)
-{
- if (device_find_child(parent, driver->name, 0) != NULL)
- return;
-
- BUS_ADD_CHILD(parent, 0, driver->name, 0);
-}
-
static int
nct_probe(device_t dev)
{
- int i, j;
- int rc;
- struct nct_softc *sc;
+ int j;
uint16_t chipid;
- /* Make sure we do not claim some ISA PNP device. */
- if (isa_get_logicalid(dev) != 0)
+ if (superio_vendor(dev) != SUPERIO_VENDOR_NUVOTON)
+ return (ENXIO);
+ if (superio_get_type(dev) != SUPERIO_DEV_GPIO)
return (ENXIO);
- sc = device_get_softc(dev);
-
- for (i = 0; i < nitems(probe_addrs); i++) {
- sc->rid = 0;
- sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
- probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE);
- if (sc->portres == NULL)
- continue;
-
- GPIO_LOCK_INIT(sc);
-
- GPIO_ASSERT_UNLOCKED(sc);
- GPIO_LOCK(sc);
- ext_cfg_enter(sc);
- chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID);
- ext_cfg_exit(sc);
- GPIO_UNLOCK(sc);
-
- GPIO_LOCK_DESTROY(sc);
+ /*
+ * There are several GPIO devices, we attach only to one of them
+ * and use the rest without attaching.
+ */
+ if (superio_get_ldn(dev) != NCT_LDN_GPIO)
+ return (ENXIO);
- bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
- bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid);
-
- for (j = 0; j < nitems(nct_devs); j++) {
- if (chipid == nct_devs[j].chip_id) {
- rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2);
- if (rc != 0) {
- device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]);
- continue;
- }
- device_set_desc(dev, nct_devs[j].descr);
- return (BUS_PROBE_DEFAULT);
- }
+ chipid = superio_devid(dev);
+ for (j = 0; j < nitems(nct_devs); j++) {
+ if (chipid == nct_devs[j].chip_id) {
+ device_set_desc(dev, "Nuvoton GPIO controller");
+ return (BUS_PROBE_DEFAULT);
}
}
return (ENXIO);
@@ -502,24 +356,19 @@ nct_attach(device_t dev)
int i;
sc = device_get_softc(dev);
-
- sc->rid = 0;
- sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
- 0ul, ~0ul, 2, RF_ACTIVE);
- if (sc->portres == NULL) {
- device_printf(dev, "cannot allocate ioport\n");
+ sc->dev = dev;
+ sc->dev_f = superio_find_dev(device_get_parent(dev), SUPERIO_DEV_GPIO,
+ NCT_LDN_GPIO_MODE);
+ if (sc->dev_f == NULL) {
+ device_printf(dev, "failed to find LDN F\n");
return (ENXIO);
}
- GPIO_LOCK_INIT(sc);
+ /* Enable gpio0 and gpio1. */
+ superio_dev_enable(dev, 0x03);
- GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK_INIT(sc);
GPIO_LOCK(sc);
- ext_cfg_enter(sc);
- select_ldn(sc, NCT_LDN_GPIO);
- /* Enable gpio0 and gpio1. */
- write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE,
- read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x03);
for (i = 0; i <= NCT_MAX_PIN; i++) {
struct gpio_pin *pin;
@@ -550,12 +399,7 @@ nct_attach(device_t dev)
sc->busdev = gpiobus_attach_bus(dev);
if (sc->busdev == NULL) {
GPIO_ASSERT_UNLOCKED(sc);
- GPIO_LOCK(sc);
- ext_cfg_exit(sc);
- GPIO_UNLOCK(sc);
- bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
GPIO_LOCK_DESTROY(sc);
-
return (ENXIO);
}
@@ -571,13 +415,6 @@ nct_detach(device_t dev)
gpiobus_detach_bus(dev);
GPIO_ASSERT_UNLOCKED(sc);
- GPIO_LOCK(sc);
- ext_cfg_exit(sc);
- GPIO_UNLOCK(sc);
-
- /* Cleanup resources. */
- bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
-
GPIO_LOCK_DESTROY(sc);
return (0);
@@ -775,26 +612,25 @@ nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
static device_method_t nct_methods[] = {
/* Device interface */
- DEVMETHOD(device_identify, nct_identify),
DEVMETHOD(device_probe, nct_probe),
DEVMETHOD(device_attach, nct_attach),
DEVMETHOD(device_detach, nct_detach),
/* GPIO */
- DEVMETHOD(gpio_get_bus, nct_gpio_get_bus),
- DEVMETHOD(gpio_pin_max, nct_gpio_pin_max),
- DEVMETHOD(gpio_pin_get, nct_gpio_pin_get),
- DEVMETHOD(gpio_pin_set, nct_gpio_pin_set),
- DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle),
- DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname),
- DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps),
+ DEVMETHOD(gpio_get_bus, nct_gpio_get_bus),
+ DEVMETHOD(gpio_pin_max, nct_gpio_pin_max),
+ DEVMETHOD(gpio_pin_get, nct_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, nct_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle),
+ DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags),
DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags),
DEVMETHOD_END
};
-static driver_t nct_isa_driver = {
+static driver_t nct_driver = {
"gpio",
nct_methods,
sizeof(struct nct_softc)
@@ -802,5 +638,8 @@ static driver_t nct_isa_driver = {
static devclass_t nct_devclass;
-DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL);
+DRIVER_MODULE(nctgpio, superio, nct_driver, nct_devclass, NULL, NULL);
MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1);
+MODULE_DEPEND(nctgpio, superio, 1, 1, 1);
+MODULE_VERSION(nctgpio, 1);
+