1ab6df5bcSAlex Hornung /* $OpenBSD: blambert $ */ 2ab6df5bcSAlex Hornung /* $NetBSD: nsclpcsio_isa.c,v 1.5 2002/10/22 16:18:26 drochner Exp $ */ 3ab6df5bcSAlex Hornung 4ab6df5bcSAlex Hornung /* 5ab6df5bcSAlex Hornung * Copyright (c) 2002 Matthias Drochner. All rights reserved. 6ab6df5bcSAlex Hornung * Copyright (c) 2004 Markus Friedl. All rights reserved. 7ab6df5bcSAlex Hornung * Copyright (c) 2004 Alexander Yurchenko. All rights reserved. 8ab6df5bcSAlex Hornung * 9ab6df5bcSAlex Hornung * Redistribution and use in source and binary forms, with or without 10ab6df5bcSAlex Hornung * modification, are permitted provided that the following conditions 11ab6df5bcSAlex Hornung * are met: 12ab6df5bcSAlex Hornung * 1. Redistributions of source code must retain the above copyright 13ab6df5bcSAlex Hornung * notice, this list of conditions, and the following disclaimer. 14ab6df5bcSAlex Hornung * 2. Redistributions in binary form must reproduce the above copyright 15ab6df5bcSAlex Hornung * notice, this list of conditions and the following disclaimer in the 16ab6df5bcSAlex Hornung * documentation and/or other materials provided with the distribution. 17ab6df5bcSAlex Hornung * 18ab6df5bcSAlex Hornung * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19ab6df5bcSAlex Hornung * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20ab6df5bcSAlex Hornung * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21ab6df5bcSAlex Hornung * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22ab6df5bcSAlex Hornung * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23ab6df5bcSAlex Hornung * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24ab6df5bcSAlex Hornung * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25ab6df5bcSAlex Hornung * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26ab6df5bcSAlex Hornung * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27ab6df5bcSAlex Hornung * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28ab6df5bcSAlex Hornung * SUCH DAMAGE. 29ab6df5bcSAlex Hornung */ 30ab6df5bcSAlex Hornung 31ab6df5bcSAlex Hornung /* 32ab6df5bcSAlex Hornung * National Semiconductor PC87366 LPC Super I/O. 33ab6df5bcSAlex Hornung * Supported logical devices: GPIO, TMS, VLM. 34ab6df5bcSAlex Hornung */ 35ab6df5bcSAlex Hornung 36c8cb1400SAlex Hornung #include "use_gpio.h" 37c8cb1400SAlex Hornung 38ab6df5bcSAlex Hornung #include <sys/param.h> 39ab6df5bcSAlex Hornung #include <sys/systm.h> 40ab6df5bcSAlex Hornung #include <sys/device.h> 41ab6df5bcSAlex Hornung #include <sys/kernel.h> 42ab6df5bcSAlex Hornung #include <sys/sensors.h> 43c8cb1400SAlex Hornung #include <sys/module.h> 44c8cb1400SAlex Hornung #include <sys/rman.h> 45ab6df5bcSAlex Hornung 46c8cb1400SAlex Hornung #include <sys/bus.h> 47ab6df5bcSAlex Hornung 48c8cb1400SAlex Hornung #include <bus/isa/isareg.h> 49c8cb1400SAlex Hornung #include <bus/isa/isavar.h> 50ab6df5bcSAlex Hornung 51c8cb1400SAlex Hornung #include <dev/misc/gpio/gpio.h> 52ab6df5bcSAlex Hornung 53ab6df5bcSAlex Hornung #if defined(NSC_LPC_SIO_DEBUG) 54c8cb1400SAlex Hornung #define DPRINTF(x) do { kprintf x; } while (0) 55ab6df5bcSAlex Hornung #else 56ab6df5bcSAlex Hornung #define DPRINTF(x) 57ab6df5bcSAlex Hornung #endif 58ab6df5bcSAlex Hornung 59ab6df5bcSAlex Hornung #define SIO_REG_SID 0x20 /* Super I/O ID */ 60ab6df5bcSAlex Hornung #define SIO_SID_PC87366 0xE9 /* PC87366 is identified by 0xE9.*/ 61ab6df5bcSAlex Hornung 62ab6df5bcSAlex Hornung #define SIO_REG_SRID 0x27 /* Super I/O Revision */ 63ab6df5bcSAlex Hornung 64ab6df5bcSAlex Hornung #define SIO_REG_LDN 0x07 /* Logical Device Number */ 65ab6df5bcSAlex Hornung #define SIO_LDN_FDC 0x00 /* Floppy Disk Controller (FDC) */ 66ab6df5bcSAlex Hornung #define SIO_LDN_PP 0x01 /* Parallel Port (PP) */ 67ab6df5bcSAlex Hornung #define SIO_LDN_SP2 0x02 /* Serial Port 2 with IR (SP2) */ 68ab6df5bcSAlex Hornung #define SIO_LDN_SP1 0x03 /* Serial Port 1 (SP1) */ 69ab6df5bcSAlex Hornung #define SIO_LDN_SWC 0x04 /* System Wake-Up Control (SWC) */ 70ab6df5bcSAlex Hornung #define SIO_LDN_KBCM 0x05 /* Mouse Controller (KBC) */ 71ab6df5bcSAlex Hornung #define SIO_LDN_KBCK 0x06 /* Keyboard Controller (KBC) */ 72ab6df5bcSAlex Hornung #define SIO_LDN_GPIO 0x07 /* General-Purpose I/O (GPIO) Ports */ 73ab6df5bcSAlex Hornung #define SIO_LDN_ACB 0x08 /* ACCESS.bus Interface (ACB) */ 74ab6df5bcSAlex Hornung #define SIO_LDN_FSCM 0x09 /* Fan Speed Control and Monitor (FSCM) */ 75ab6df5bcSAlex Hornung #define SIO_LDN_WDT 0x0A /* WATCHDOG Timer (WDT) */ 76ab6df5bcSAlex Hornung #define SIO_LDN_GMP 0x0B /* Game Port (GMP) */ 77ab6df5bcSAlex Hornung #define SIO_LDN_MIDI 0x0C /* Musical Instrument Digital Interface */ 78ab6df5bcSAlex Hornung #define SIO_LDN_VLM 0x0D /* Voltage Level Monitor (VLM) */ 79ab6df5bcSAlex Hornung #define SIO_LDN_TMS 0x0E /* Temperature Sensor (TMS) */ 80ab6df5bcSAlex Hornung 81ab6df5bcSAlex Hornung #define SIO_REG_ACTIVE 0x30 /* Logical Device Activate Register */ 82ab6df5bcSAlex Hornung #define SIO_ACTIVE_EN 0x01 /* enabled */ 83ab6df5bcSAlex Hornung 84ab6df5bcSAlex Hornung #define SIO_REG_IO_MSB 0x60 /* I/O Port Base, bits 15-8 */ 85ab6df5bcSAlex Hornung #define SIO_REG_IO_LSB 0x61 /* I/O Port Base, bits 7-0 */ 86ab6df5bcSAlex Hornung 87ab6df5bcSAlex Hornung #define SIO_LDNUM 15 /* total number of logical devices */ 88ab6df5bcSAlex Hornung 89ab6df5bcSAlex Hornung /* Supported logical devices description */ 90ab6df5bcSAlex Hornung static const struct { 91ab6df5bcSAlex Hornung const char *ld_name; 92ab6df5bcSAlex Hornung int ld_num; 93ab6df5bcSAlex Hornung int ld_iosize; 94ab6df5bcSAlex Hornung } sio_ld[] = { 95ab6df5bcSAlex Hornung { "GPIO", SIO_LDN_GPIO, 16 }, 96ab6df5bcSAlex Hornung { "VLM", SIO_LDN_VLM, 16 }, 97ab6df5bcSAlex Hornung { "TMS", SIO_LDN_TMS, 16 }, 98ab6df5bcSAlex Hornung }; 99ab6df5bcSAlex Hornung 100ab6df5bcSAlex Hornung /* GPIO */ 101ab6df5bcSAlex Hornung #define SIO_GPIO_PINSEL 0xf0 102ab6df5bcSAlex Hornung #define SIO_GPIO_PINCFG 0xf1 103ab6df5bcSAlex Hornung #define SIO_GPIO_PINEV 0xf2 104ab6df5bcSAlex Hornung 105ab6df5bcSAlex Hornung #define SIO_GPIO_CONF_OUTPUTEN (1 << 0) 106ab6df5bcSAlex Hornung #define SIO_GPIO_CONF_PUSHPULL (1 << 1) 107ab6df5bcSAlex Hornung #define SIO_GPIO_CONF_PULLUP (1 << 2) 108ab6df5bcSAlex Hornung 109ab6df5bcSAlex Hornung #define SIO_GPDO0 0x00 110ab6df5bcSAlex Hornung #define SIO_GPDI0 0x01 111ab6df5bcSAlex Hornung #define SIO_GPEVEN0 0x02 112ab6df5bcSAlex Hornung #define SIO_GPEVST0 0x03 113ab6df5bcSAlex Hornung #define SIO_GPDO1 0x04 114ab6df5bcSAlex Hornung #define SIO_GPDI1 0x05 115ab6df5bcSAlex Hornung #define SIO_GPEVEN1 0x06 116ab6df5bcSAlex Hornung #define SIO_GPEVST1 0x07 117ab6df5bcSAlex Hornung #define SIO_GPDO2 0x08 118ab6df5bcSAlex Hornung #define SIO_GPDI2 0x09 119ab6df5bcSAlex Hornung #define SIO_GPDO3 0x0a 120ab6df5bcSAlex Hornung #define SIO_GPDI3 0x0b 121ab6df5bcSAlex Hornung 122ab6df5bcSAlex Hornung #define SIO_GPIO_NPINS 29 123ab6df5bcSAlex Hornung 124ab6df5bcSAlex Hornung /* TMS */ 125ab6df5bcSAlex Hornung #define SIO_TEVSTS 0x00 /* Temperature Event Status */ 126ab6df5bcSAlex Hornung #define SIO_TEVSMI 0x02 /* Temperature Event to SMI */ 127ab6df5bcSAlex Hornung #define SIO_TEVIRQ 0x04 /* Temperature Event to IRQ */ 128ab6df5bcSAlex Hornung #define SIO_TMSCFG 0x08 /* TMS Configuration */ 129ab6df5bcSAlex Hornung #define SIO_TMSBS 0x09 /* TMS Bank Select */ 130ab6df5bcSAlex Hornung #define SIO_TCHCFST 0x0A /* Temperature Channel Config and Status */ 131ab6df5bcSAlex Hornung #define SIO_RDCHT 0x0B /* Read Channel Temperature */ 132ab6df5bcSAlex Hornung #define SIO_CHTH 0x0C /* Channel Temperature High Limit */ 133ab6df5bcSAlex Hornung #define SIO_CHTL 0x0D /* Channel Temperature Low Limit */ 134ab6df5bcSAlex Hornung #define SIO_CHOTL 0x0E /* Channel Overtemperature Limit */ 135ab6df5bcSAlex Hornung 136ab6df5bcSAlex Hornung /* VLM */ 137ab6df5bcSAlex Hornung #define SIO_VEVSTS0 0x00 /* Voltage Event Status 0 */ 138ab6df5bcSAlex Hornung #define SIO_VEVSTS1 0x01 /* Voltage Event Status 1 */ 139ab6df5bcSAlex Hornung #define SIO_VEVSMI0 0x02 /* Voltage Event to SMI 0 */ 140ab6df5bcSAlex Hornung #define SIO_VEVSMI1 0x03 /* Voltage Event to SMI 1 */ 141ab6df5bcSAlex Hornung #define SIO_VEVIRQ0 0x04 /* Voltage Event to IRQ 0 */ 142ab6df5bcSAlex Hornung #define SIO_VEVIRQ1 0x05 /* Voltage Event to IRQ 1 */ 143ab6df5bcSAlex Hornung #define SIO_VID 0x06 /* Voltage ID */ 144ab6df5bcSAlex Hornung #define SIO_VCNVR 0x07 /* Voltage Conversion Rate */ 145ab6df5bcSAlex Hornung #define SIO_VLMCFG 0x08 /* VLM Configuration */ 146ab6df5bcSAlex Hornung #define SIO_VLMBS 0x09 /* VLM Bank Select */ 147ab6df5bcSAlex Hornung #define SIO_VCHCFST 0x0A /* Voltage Channel Config and Status */ 148ab6df5bcSAlex Hornung #define SIO_RDCHV 0x0B /* Read Channel Voltage */ 149ab6df5bcSAlex Hornung #define SIO_CHVH 0x0C /* Channel Voltage High Limit */ 150ab6df5bcSAlex Hornung #define SIO_CHVL 0x0D /* Channel Voltage Low Limit */ 151ab6df5bcSAlex Hornung #define SIO_OTSL 0x0E /* Overtemperature Shutdown Limit */ 152ab6df5bcSAlex Hornung 153ab6df5bcSAlex Hornung #define SIO_REG_SIOCF1 0x21 154ab6df5bcSAlex Hornung #define SIO_REG_SIOCF2 0x22 155ab6df5bcSAlex Hornung #define SIO_REG_SIOCF3 0x23 156ab6df5bcSAlex Hornung #define SIO_REG_SIOCF4 0x24 157ab6df5bcSAlex Hornung #define SIO_REG_SIOCF5 0x25 158ab6df5bcSAlex Hornung #define SIO_REG_SIOCF8 0x28 159ab6df5bcSAlex Hornung #define SIO_REG_SIOCFA 0x2A 160ab6df5bcSAlex Hornung #define SIO_REG_SIOCFB 0x2B 161ab6df5bcSAlex Hornung #define SIO_REG_SIOCFC 0x2C 162ab6df5bcSAlex Hornung #define SIO_REG_SIOCFD 0x2D 163ab6df5bcSAlex Hornung 164ab6df5bcSAlex Hornung #define SIO_NUM_SENSORS (3+14) 165ab6df5bcSAlex Hornung #define SIO_VLM_OFF 3 166ab6df5bcSAlex Hornung #define SIO_VREF 1235 /* 1000.0 * VREF */ 167ab6df5bcSAlex Hornung 168ab6df5bcSAlex Hornung struct nsclpcsio_softc { 169*5d302545SFrançois Tigeot device_t sc_dev; 170c8cb1400SAlex Hornung struct resource *sc_iores; 171c8cb1400SAlex Hornung int sc_iorid; 172ab6df5bcSAlex Hornung bus_space_tag_t sc_iot; 173ab6df5bcSAlex Hornung bus_space_handle_t sc_ioh; 174ab6df5bcSAlex Hornung 175ab6df5bcSAlex Hornung bus_space_handle_t sc_ld_ioh[SIO_LDNUM]; 176ab6df5bcSAlex Hornung int sc_ld_en[SIO_LDNUM]; 177c8cb1400SAlex Hornung #if NGPIO > 0 178ab6df5bcSAlex Hornung /* GPIO */ 179c8cb1400SAlex Hornung struct gpio sc_gpio_gc; 180ab6df5bcSAlex Hornung struct gpio_pin sc_gpio_pins[SIO_GPIO_NPINS]; 181c8cb1400SAlex Hornung #endif 182ab6df5bcSAlex Hornung 183ab6df5bcSAlex Hornung /* TMS and VLM */ 184ab6df5bcSAlex Hornung struct ksensor sensors[SIO_NUM_SENSORS]; 185ab6df5bcSAlex Hornung struct ksensordev sensordev; 186ab6df5bcSAlex Hornung }; 187ab6df5bcSAlex Hornung 188ab6df5bcSAlex Hornung #define GPIO_READ(sc, reg) \ 189ab6df5bcSAlex Hornung bus_space_read_1((sc)->sc_iot, \ 190ab6df5bcSAlex Hornung (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg)) 191ab6df5bcSAlex Hornung #define GPIO_WRITE(sc, reg, val) \ 192ab6df5bcSAlex Hornung bus_space_write_1((sc)->sc_iot, \ 193ab6df5bcSAlex Hornung (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg), (val)) 194ab6df5bcSAlex Hornung #define TMS_WRITE(sc, reg, val) \ 195ab6df5bcSAlex Hornung bus_space_write_1((sc)->sc_iot, \ 196ab6df5bcSAlex Hornung (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg), (val)) 197ab6df5bcSAlex Hornung #define TMS_READ(sc, reg) \ 198ab6df5bcSAlex Hornung bus_space_read_1((sc)->sc_iot, \ 199ab6df5bcSAlex Hornung (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg)) 200ab6df5bcSAlex Hornung #define VLM_WRITE(sc, reg, val) \ 201ab6df5bcSAlex Hornung bus_space_write_1((sc)->sc_iot, \ 202ab6df5bcSAlex Hornung (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg), (val)) 203ab6df5bcSAlex Hornung #define VLM_READ(sc, reg) \ 204ab6df5bcSAlex Hornung bus_space_read_1((sc)->sc_iot, \ 205ab6df5bcSAlex Hornung (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg)) 206ab6df5bcSAlex Hornung 207*5d302545SFrançois Tigeot int nsclpcsio_isa_probe(device_t); 208*5d302545SFrançois Tigeot int nsclpcsio_isa_attach(device_t); 209ab6df5bcSAlex Hornung 210c8cb1400SAlex Hornung 211c8cb1400SAlex Hornung static device_method_t nsclpcsio_isa_methods[] = { 212c8cb1400SAlex Hornung DEVMETHOD(device_probe, nsclpcsio_isa_probe), 213c8cb1400SAlex Hornung DEVMETHOD(device_attach, nsclpcsio_isa_attach), 214d3c9c58eSSascha Wildner DEVMETHOD_END 215ab6df5bcSAlex Hornung }; 216ab6df5bcSAlex Hornung 217c8cb1400SAlex Hornung static driver_t nsclpcsio_isa_driver = { 218c8cb1400SAlex Hornung "nsclpcsio", 219c8cb1400SAlex Hornung nsclpcsio_isa_methods, 220c8cb1400SAlex Hornung sizeof (struct nsclpcsio_softc) 221ab6df5bcSAlex Hornung }; 222ab6df5bcSAlex Hornung 223c8cb1400SAlex Hornung static devclass_t nsclpcsio_devclass; 224c8cb1400SAlex Hornung 225c8cb1400SAlex Hornung DRIVER_MODULE(nsclpcsio_isa, isa, nsclpcsio_isa_driver, nsclpcsio_devclass, NULL, NULL); 226c8cb1400SAlex Hornung 227c8cb1400SAlex Hornung 228ab6df5bcSAlex Hornung 229ab6df5bcSAlex Hornung static u_int8_t nsread(bus_space_tag_t, bus_space_handle_t, int); 230ab6df5bcSAlex Hornung static void nswrite(bus_space_tag_t, bus_space_handle_t, int, u_int8_t); 231ab6df5bcSAlex Hornung 232c8cb1400SAlex Hornung #if NGPIO > 0 233ab6df5bcSAlex Hornung void nsclpcsio_gpio_init(struct nsclpcsio_softc *); 234ab6df5bcSAlex Hornung int nsclpcsio_gpio_pin_read(void *, int); 235ab6df5bcSAlex Hornung void nsclpcsio_gpio_pin_write(void *, int, int); 236ab6df5bcSAlex Hornung void nsclpcsio_gpio_pin_ctl(void *, int, int); 237c8cb1400SAlex Hornung #endif 238ab6df5bcSAlex Hornung 239ab6df5bcSAlex Hornung void nsclpcsio_tms_init(struct nsclpcsio_softc *); 240ab6df5bcSAlex Hornung void nsclpcsio_vlm_init(struct nsclpcsio_softc *); 241ab6df5bcSAlex Hornung void nsclpcsio_tms_update(struct nsclpcsio_softc *); 242ab6df5bcSAlex Hornung void nsclpcsio_vlm_update(struct nsclpcsio_softc *); 243ab6df5bcSAlex Hornung void nsclpcsio_refresh(void *); 244ab6df5bcSAlex Hornung 245ab6df5bcSAlex Hornung static u_int8_t 246ab6df5bcSAlex Hornung nsread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx) 247ab6df5bcSAlex Hornung { 248ab6df5bcSAlex Hornung bus_space_write_1(iot, ioh, 0, idx); 249ab6df5bcSAlex Hornung return (bus_space_read_1(iot, ioh, 1)); 250ab6df5bcSAlex Hornung } 251ab6df5bcSAlex Hornung 252ab6df5bcSAlex Hornung static void 253ab6df5bcSAlex Hornung nswrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data) 254ab6df5bcSAlex Hornung { 255ab6df5bcSAlex Hornung bus_space_write_1(iot, ioh, 0, idx); 256ab6df5bcSAlex Hornung bus_space_write_1(iot, ioh, 1, data); 257ab6df5bcSAlex Hornung } 258ab6df5bcSAlex Hornung 259ab6df5bcSAlex Hornung int 260*5d302545SFrançois Tigeot nsclpcsio_isa_probe(device_t dev) 261ab6df5bcSAlex Hornung { 262c8cb1400SAlex Hornung struct resource *iores; 263c8cb1400SAlex Hornung int iorid = 0; 264ab6df5bcSAlex Hornung bus_space_tag_t iot; 265ab6df5bcSAlex Hornung bus_space_handle_t ioh; 266ab6df5bcSAlex Hornung int rv = 0; 267ab6df5bcSAlex Hornung 268c8cb1400SAlex Hornung iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid, 0ul, ~0ul, 8, RF_ACTIVE); 269c8cb1400SAlex Hornung if (iores == NULL) { 270c8cb1400SAlex Hornung return 1; 271c8cb1400SAlex Hornung } 272c8cb1400SAlex Hornung iot = rman_get_bustag(iores); 273c8cb1400SAlex Hornung ioh = rman_get_bushandle(iores); 274ab6df5bcSAlex Hornung 275ab6df5bcSAlex Hornung if (nsread(iot, ioh, SIO_REG_SID) == SIO_SID_PC87366) 276ab6df5bcSAlex Hornung rv = 1; 277ab6df5bcSAlex Hornung 278c8cb1400SAlex Hornung bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores); 279ab6df5bcSAlex Hornung if (rv) { 280c8cb1400SAlex Hornung return 0; 281ab6df5bcSAlex Hornung } 282ab6df5bcSAlex Hornung 283c8cb1400SAlex Hornung return 1; 284ab6df5bcSAlex Hornung } 285ab6df5bcSAlex Hornung 286c8cb1400SAlex Hornung int 287*5d302545SFrançois Tigeot nsclpcsio_isa_attach(device_t dev) 288ab6df5bcSAlex Hornung { 289ab6df5bcSAlex Hornung int iobase; 290c8cb1400SAlex Hornung struct nsclpcsio_softc *sc = device_get_softc(dev); 291ab6df5bcSAlex Hornung int i; 292ab6df5bcSAlex Hornung 293c8cb1400SAlex Hornung sc->sc_dev = dev; 294c8cb1400SAlex Hornung sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid, 0ul, ~0ul, 8, RF_ACTIVE); 295c8cb1400SAlex Hornung if (sc->sc_iores == NULL) { 296c8cb1400SAlex Hornung return 1; 297ab6df5bcSAlex Hornung } 298c8cb1400SAlex Hornung sc->sc_iot = rman_get_bustag(sc->sc_iores); 299c8cb1400SAlex Hornung sc->sc_ioh = rman_get_bushandle(sc->sc_iores); 300c8cb1400SAlex Hornung 301c8cb1400SAlex Hornung kprintf("%s: NSC PC87366 rev %d:", device_get_nameunit(sc->sc_dev), 302ab6df5bcSAlex Hornung nsread(sc->sc_iot, sc->sc_ioh, SIO_REG_SRID)); 303ab6df5bcSAlex Hornung 304ab6df5bcSAlex Hornung /* Configure all supported logical devices */ 305c157ff7aSSascha Wildner for (i = 0; i < NELEM(sio_ld); i++) { 306ab6df5bcSAlex Hornung sc->sc_ld_en[sio_ld[i].ld_num] = 0; 307ab6df5bcSAlex Hornung 308ab6df5bcSAlex Hornung /* Select the device and check if it's activated */ 309ab6df5bcSAlex Hornung nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, sio_ld[i].ld_num); 310ab6df5bcSAlex Hornung if ((nsread(sc->sc_iot, sc->sc_ioh, 311ab6df5bcSAlex Hornung SIO_REG_ACTIVE) & SIO_ACTIVE_EN) == 0) 312ab6df5bcSAlex Hornung continue; 313ab6df5bcSAlex Hornung 314ab6df5bcSAlex Hornung /* Map I/O space if necessary */ 315ab6df5bcSAlex Hornung if (sio_ld[i].ld_iosize != 0) { 316c8cb1400SAlex Hornung 317ab6df5bcSAlex Hornung iobase = (nsread(sc->sc_iot, sc->sc_ioh, 318ab6df5bcSAlex Hornung SIO_REG_IO_MSB) << 8); 319c8cb1400SAlex Hornung 320ab6df5bcSAlex Hornung iobase |= nsread(sc->sc_iot, sc->sc_ioh, 321ab6df5bcSAlex Hornung SIO_REG_IO_LSB); 322c8cb1400SAlex Hornung #if 0 323c8cb1400SAlex Hornung /* XXX: Not elegant without alloc_resource, but works */ 324c8cb1400SAlex Hornung kprintf("debugging: iobase = %x\n", iobase); 325c8cb1400SAlex Hornung iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid, 326c8cb1400SAlex Hornung iobase, sio_ld[i].ld_iosize, sio_ld[i].ld_iosize, RF_ACTIVE); 327c8cb1400SAlex Hornung if (iores == NULL) { 328c8cb1400SAlex Hornung kprintf("messed up alloc3\n"); 329ab6df5bcSAlex Hornung continue; 330ab6df5bcSAlex Hornung } 331c8cb1400SAlex Hornung /* XXX: if implemented, also use the rman get handle stuff */ 332c8cb1400SAlex Hornung #endif 333c8cb1400SAlex Hornung sc->sc_ld_ioh[sio_ld[i].ld_num] = iobase; 334c8cb1400SAlex Hornung } 335ab6df5bcSAlex Hornung 336ab6df5bcSAlex Hornung sc->sc_ld_en[sio_ld[i].ld_num] = 1; 337c8cb1400SAlex Hornung kprintf(" %s", sio_ld[i].ld_name); 338ab6df5bcSAlex Hornung } 339ab6df5bcSAlex Hornung 340c8cb1400SAlex Hornung kprintf("\n"); 341c8cb1400SAlex Hornung #if NGPIO > 0 342ab6df5bcSAlex Hornung nsclpcsio_gpio_init(sc); 343c8cb1400SAlex Hornung #endif 344ab6df5bcSAlex Hornung nsclpcsio_tms_init(sc); 345ab6df5bcSAlex Hornung nsclpcsio_vlm_init(sc); 346ab6df5bcSAlex Hornung 347ab6df5bcSAlex Hornung /* Hook into hw.sensors sysctl */ 348c8cb1400SAlex Hornung strlcpy(sc->sensordev.xname, device_get_nameunit(sc->sc_dev), 349ab6df5bcSAlex Hornung sizeof(sc->sensordev.xname)); 350ab6df5bcSAlex Hornung for (i = 0; i < SIO_NUM_SENSORS; i++) { 351ab6df5bcSAlex Hornung if (i < SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_TMS]) 352ab6df5bcSAlex Hornung continue; 353ab6df5bcSAlex Hornung if (i >= SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_VLM]) 354ab6df5bcSAlex Hornung continue; 355ab6df5bcSAlex Hornung sensor_attach(&sc->sensordev, &sc->sensors[i]); 356ab6df5bcSAlex Hornung } 357ab6df5bcSAlex Hornung sensordev_install(&sc->sensordev); 358ab6df5bcSAlex Hornung if (sc->sc_ld_en[SIO_LDN_TMS] || sc->sc_ld_en[SIO_LDN_VLM]) { 359c8cb1400SAlex Hornung sensor_task_register(sc, nsclpcsio_refresh, 2); 360ab6df5bcSAlex Hornung } 361ab6df5bcSAlex Hornung 362c8cb1400SAlex Hornung #if NGPIO > 0 363ab6df5bcSAlex Hornung /* Attach GPIO framework */ 364ab6df5bcSAlex Hornung if (sc->sc_ld_en[SIO_LDN_GPIO]) { 365c8cb1400SAlex Hornung sc->sc_gpio_gc.driver_name = "pc83766"; 366c8cb1400SAlex Hornung sc->sc_gpio_gc.arg = sc; 367c8cb1400SAlex Hornung sc->sc_gpio_gc.pin_read = nsclpcsio_gpio_pin_read; 368c8cb1400SAlex Hornung sc->sc_gpio_gc.pin_write = nsclpcsio_gpio_pin_write; 369c8cb1400SAlex Hornung sc->sc_gpio_gc.pin_ctl = nsclpcsio_gpio_pin_ctl; 370c8cb1400SAlex Hornung sc->sc_gpio_gc.pins = sc->sc_gpio_pins; 371c8cb1400SAlex Hornung sc->sc_gpio_gc.npins = SIO_GPIO_NPINS; 372c8cb1400SAlex Hornung gpio_register(&sc->sc_gpio_gc); 373ab6df5bcSAlex Hornung } 374c8cb1400SAlex Hornung #endif 375c8cb1400SAlex Hornung 376c8cb1400SAlex Hornung return 0; 377ab6df5bcSAlex Hornung } 378ab6df5bcSAlex Hornung 379ab6df5bcSAlex Hornung void 380ab6df5bcSAlex Hornung nsclpcsio_refresh(void *arg) 381ab6df5bcSAlex Hornung { 382ab6df5bcSAlex Hornung struct nsclpcsio_softc *sc = (struct nsclpcsio_softc *)arg; 383ab6df5bcSAlex Hornung 384ab6df5bcSAlex Hornung if (sc->sc_ld_en[SIO_LDN_TMS]) 385ab6df5bcSAlex Hornung nsclpcsio_tms_update(sc); 386ab6df5bcSAlex Hornung if (sc->sc_ld_en[SIO_LDN_VLM]) 387ab6df5bcSAlex Hornung nsclpcsio_vlm_update(sc); 388ab6df5bcSAlex Hornung } 389ab6df5bcSAlex Hornung 390ab6df5bcSAlex Hornung void 391ab6df5bcSAlex Hornung nsclpcsio_tms_init(struct nsclpcsio_softc *sc) 392ab6df5bcSAlex Hornung { 393ab6df5bcSAlex Hornung int i; 394ab6df5bcSAlex Hornung 395ab6df5bcSAlex Hornung /* Initialisation, PC87366.pdf, page 208 */ 396ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x08, 0x00); 397ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x09, 0x0f); 398ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x0a, 0x08); 399ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x0b, 0x04); 400ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x0c, 0x35); 401ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x0d, 0x05); 402ab6df5bcSAlex Hornung TMS_WRITE(sc, 0x0e, 0x05); 403ab6df5bcSAlex Hornung 404ab6df5bcSAlex Hornung TMS_WRITE(sc, SIO_TMSCFG, 0x00); 405ab6df5bcSAlex Hornung 406ab6df5bcSAlex Hornung /* Enable the sensors */ 407ab6df5bcSAlex Hornung for (i = 0; i < 3; i++) { 408ab6df5bcSAlex Hornung TMS_WRITE(sc, SIO_TMSBS, i); 409ab6df5bcSAlex Hornung TMS_WRITE(sc, SIO_TCHCFST, 0x01); 410ab6df5bcSAlex Hornung 411ab6df5bcSAlex Hornung sc->sensors[i].type = SENSOR_TEMP; 412ab6df5bcSAlex Hornung } 413ab6df5bcSAlex Hornung 414ab6df5bcSAlex Hornung strlcpy(sc->sensors[0].desc, "Remote", sizeof(sc->sensors[0].desc)); 415ab6df5bcSAlex Hornung strlcpy(sc->sensors[1].desc, "Remote", sizeof(sc->sensors[1].desc)); 416ab6df5bcSAlex Hornung strlcpy(sc->sensors[2].desc, "Local", sizeof(sc->sensors[2].desc)); 417ab6df5bcSAlex Hornung 418ab6df5bcSAlex Hornung nsclpcsio_tms_update(sc); 419ab6df5bcSAlex Hornung } 420ab6df5bcSAlex Hornung 421ab6df5bcSAlex Hornung void 422ab6df5bcSAlex Hornung nsclpcsio_tms_update(struct nsclpcsio_softc *sc) 423ab6df5bcSAlex Hornung { 424ab6df5bcSAlex Hornung u_int8_t status; 425ab6df5bcSAlex Hornung int8_t sdata; 426ab6df5bcSAlex Hornung int i; 427ab6df5bcSAlex Hornung 428ab6df5bcSAlex Hornung for (i = 0; i < 3; i++) { 429ab6df5bcSAlex Hornung TMS_WRITE(sc, SIO_TMSBS, i); 430ab6df5bcSAlex Hornung status = TMS_READ(sc, SIO_TCHCFST); 431ab6df5bcSAlex Hornung if (!(status & 0x01)) { 432ab6df5bcSAlex Hornung DPRINTF(("%s: status %d: disabled\n", 433ab6df5bcSAlex Hornung sc->sensors[i].desc, status)); 434ab6df5bcSAlex Hornung sc->sensors[i].value = 0; 435ab6df5bcSAlex Hornung continue; 436ab6df5bcSAlex Hornung } 437ab6df5bcSAlex Hornung sdata = TMS_READ(sc, SIO_RDCHT); 438ab6df5bcSAlex Hornung DPRINTF(("%s: status %d C %d\n", sc->sensors[i].desc, 439ab6df5bcSAlex Hornung status, sdata)); 440ab6df5bcSAlex Hornung sc->sensors[i].value = sdata * 1000000 + 273150000; 441ab6df5bcSAlex Hornung } 442ab6df5bcSAlex Hornung } 443ab6df5bcSAlex Hornung 444ab6df5bcSAlex Hornung void 445ab6df5bcSAlex Hornung nsclpcsio_vlm_init(struct nsclpcsio_softc *sc) 446ab6df5bcSAlex Hornung { 447ab6df5bcSAlex Hornung int i; 448ab6df5bcSAlex Hornung char *desc = NULL; 449ab6df5bcSAlex Hornung 450ab6df5bcSAlex Hornung VLM_WRITE(sc, SIO_VLMCFG, 0x00); 451ab6df5bcSAlex Hornung 452ab6df5bcSAlex Hornung /* Enable the sensors */ 453ab6df5bcSAlex Hornung for (i = 0; i < 14; i++) { 454ab6df5bcSAlex Hornung VLM_WRITE(sc, SIO_VLMBS, i); 455ab6df5bcSAlex Hornung VLM_WRITE(sc, SIO_VCHCFST, 0x01); 456ab6df5bcSAlex Hornung 457ab6df5bcSAlex Hornung desc = NULL; 458ab6df5bcSAlex Hornung switch (i) { 459ab6df5bcSAlex Hornung case 7: 460ab6df5bcSAlex Hornung desc = "VSB"; 461ab6df5bcSAlex Hornung break; 462ab6df5bcSAlex Hornung case 8: 463ab6df5bcSAlex Hornung desc = "VDD"; 464ab6df5bcSAlex Hornung break; 465ab6df5bcSAlex Hornung case 9: 466ab6df5bcSAlex Hornung desc = "VBAT"; 467ab6df5bcSAlex Hornung break; 468ab6df5bcSAlex Hornung case 10: 469ab6df5bcSAlex Hornung desc = "AVDD"; 470ab6df5bcSAlex Hornung break; 471ab6df5bcSAlex Hornung case 11: 472ab6df5bcSAlex Hornung desc = "TS1"; 473ab6df5bcSAlex Hornung break; 474ab6df5bcSAlex Hornung case 12: 475ab6df5bcSAlex Hornung desc = "TS2"; 476ab6df5bcSAlex Hornung break; 477ab6df5bcSAlex Hornung case 13: 478ab6df5bcSAlex Hornung desc = "TS3"; 479ab6df5bcSAlex Hornung break; 480ab6df5bcSAlex Hornung } 481ab6df5bcSAlex Hornung /* only init .desc if we have something meaningful to say */ 482ab6df5bcSAlex Hornung if (desc != NULL) 483ab6df5bcSAlex Hornung strlcpy(sc->sensors[SIO_VLM_OFF + i].desc, desc, 484ab6df5bcSAlex Hornung sizeof(sc->sensors[SIO_VLM_OFF + i].desc)); 485ab6df5bcSAlex Hornung sc->sensors[SIO_VLM_OFF + i].type = SENSOR_VOLTS_DC; 486ab6df5bcSAlex Hornung 487ab6df5bcSAlex Hornung } 488ab6df5bcSAlex Hornung nsclpcsio_vlm_update(sc); 489ab6df5bcSAlex Hornung } 490ab6df5bcSAlex Hornung 491ab6df5bcSAlex Hornung void 492ab6df5bcSAlex Hornung nsclpcsio_vlm_update(struct nsclpcsio_softc *sc) 493ab6df5bcSAlex Hornung { 494ab6df5bcSAlex Hornung u_int8_t status; 495ab6df5bcSAlex Hornung u_int8_t data; 496ab6df5bcSAlex Hornung int scale, rfact, i; 497ab6df5bcSAlex Hornung 498ab6df5bcSAlex Hornung for (i = 0; i < 14; i++) { 499ab6df5bcSAlex Hornung VLM_WRITE(sc, SIO_VLMBS, i); 500ab6df5bcSAlex Hornung status = VLM_READ(sc, SIO_VCHCFST); 501ab6df5bcSAlex Hornung if (!(status & 0x01)) { 502ab6df5bcSAlex Hornung DPRINTF(("%s: status %d: disabled\n", 503ab6df5bcSAlex Hornung sc->sensors[SIO_VLM_OFF + i].desc, status)); 504ab6df5bcSAlex Hornung sc->sensors[SIO_VLM_OFF + i].value = 0; 505ab6df5bcSAlex Hornung continue; 506ab6df5bcSAlex Hornung } 507ab6df5bcSAlex Hornung data = VLM_READ(sc, SIO_RDCHV); 508ab6df5bcSAlex Hornung DPRINTF(("%s: status %d V %d\n", 509ab6df5bcSAlex Hornung sc->sensors[SIO_VLM_OFF + i].desc, status, data)); 510ab6df5bcSAlex Hornung 511ab6df5bcSAlex Hornung scale = 1; 512ab6df5bcSAlex Hornung switch (i) { 513ab6df5bcSAlex Hornung case 7: 514ab6df5bcSAlex Hornung case 8: 515ab6df5bcSAlex Hornung case 10: 516ab6df5bcSAlex Hornung scale = 2; 517ab6df5bcSAlex Hornung } 518ab6df5bcSAlex Hornung 519ab6df5bcSAlex Hornung /* Vi = (2.45�0.05)*VREF *RDCHVi / 256 */ 520ab6df5bcSAlex Hornung rfact = 10 * scale * ((245 * SIO_VREF) >> 8); 521ab6df5bcSAlex Hornung sc->sensors[SIO_VLM_OFF + i].value = data * rfact; 522ab6df5bcSAlex Hornung } 523ab6df5bcSAlex Hornung } 524ab6df5bcSAlex Hornung 525c8cb1400SAlex Hornung #if NGPIO > 0 526ab6df5bcSAlex Hornung static __inline void 527ab6df5bcSAlex Hornung nsclpcsio_gpio_pin_select(struct nsclpcsio_softc *sc, int pin) 528ab6df5bcSAlex Hornung { 529ab6df5bcSAlex Hornung int port, shift; 530ab6df5bcSAlex Hornung u_int8_t data; 531ab6df5bcSAlex Hornung 532ab6df5bcSAlex Hornung port = pin / 8; 533ab6df5bcSAlex Hornung shift = pin % 8; 534ab6df5bcSAlex Hornung data = (port << 4) | shift; 535ab6df5bcSAlex Hornung 536ab6df5bcSAlex Hornung nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 537ab6df5bcSAlex Hornung nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINSEL, data); 538ab6df5bcSAlex Hornung } 539ab6df5bcSAlex Hornung 540ab6df5bcSAlex Hornung void 541ab6df5bcSAlex Hornung nsclpcsio_gpio_init(struct nsclpcsio_softc *sc) 542ab6df5bcSAlex Hornung { 543ab6df5bcSAlex Hornung int i; 544ab6df5bcSAlex Hornung 545ab6df5bcSAlex Hornung for (i = 0; i < SIO_GPIO_NPINS; i++) { 546ab6df5bcSAlex Hornung sc->sc_gpio_pins[i].pin_num = i; 547ab6df5bcSAlex Hornung sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | 548ab6df5bcSAlex Hornung GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | 549ab6df5bcSAlex Hornung GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | 550ab6df5bcSAlex Hornung GPIO_PIN_PULLUP; 551ab6df5bcSAlex Hornung 552ab6df5bcSAlex Hornung /* Read initial state */ 553ab6df5bcSAlex Hornung sc->sc_gpio_pins[i].pin_state = nsclpcsio_gpio_pin_read(sc, 554ab6df5bcSAlex Hornung i) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; 555ab6df5bcSAlex Hornung } 556ab6df5bcSAlex Hornung } 557ab6df5bcSAlex Hornung 558ab6df5bcSAlex Hornung int 559ab6df5bcSAlex Hornung nsclpcsio_gpio_pin_read(void *arg, int pin) 560ab6df5bcSAlex Hornung { 561ab6df5bcSAlex Hornung struct nsclpcsio_softc *sc = arg; 562ab6df5bcSAlex Hornung int port, shift, reg; 563ab6df5bcSAlex Hornung u_int8_t data; 564ab6df5bcSAlex Hornung 565ab6df5bcSAlex Hornung port = pin / 8; 566ab6df5bcSAlex Hornung shift = pin % 8; 567ab6df5bcSAlex Hornung 568ab6df5bcSAlex Hornung switch (port) { 569ab6df5bcSAlex Hornung case 0: 570ab6df5bcSAlex Hornung reg = SIO_GPDI0; 571ab6df5bcSAlex Hornung break; 572ab6df5bcSAlex Hornung case 1: 573ab6df5bcSAlex Hornung reg = SIO_GPDI1; 574ab6df5bcSAlex Hornung break; 575ab6df5bcSAlex Hornung case 2: 576ab6df5bcSAlex Hornung reg = SIO_GPDI2; 577ab6df5bcSAlex Hornung break; 578ab6df5bcSAlex Hornung case 3: 579ab6df5bcSAlex Hornung reg = SIO_GPDI3; 580ab6df5bcSAlex Hornung break; 581c8cb1400SAlex Hornung default: 582c8cb1400SAlex Hornung return 0; 583ab6df5bcSAlex Hornung } 584ab6df5bcSAlex Hornung 585ab6df5bcSAlex Hornung data = GPIO_READ(sc, reg); 586ab6df5bcSAlex Hornung 587ab6df5bcSAlex Hornung return ((data >> shift) & 0x1); 588ab6df5bcSAlex Hornung } 589ab6df5bcSAlex Hornung 590ab6df5bcSAlex Hornung void 591ab6df5bcSAlex Hornung nsclpcsio_gpio_pin_write(void *arg, int pin, int value) 592ab6df5bcSAlex Hornung { 593ab6df5bcSAlex Hornung struct nsclpcsio_softc *sc = arg; 594ab6df5bcSAlex Hornung int port, shift, reg; 595ab6df5bcSAlex Hornung u_int8_t data; 596ab6df5bcSAlex Hornung 597ab6df5bcSAlex Hornung port = pin / 8; 598ab6df5bcSAlex Hornung shift = pin % 8; 599ab6df5bcSAlex Hornung 600ab6df5bcSAlex Hornung switch (port) { 601ab6df5bcSAlex Hornung case 0: 602ab6df5bcSAlex Hornung reg = SIO_GPDO0; 603ab6df5bcSAlex Hornung break; 604ab6df5bcSAlex Hornung case 1: 605ab6df5bcSAlex Hornung reg = SIO_GPDO1; 606ab6df5bcSAlex Hornung break; 607ab6df5bcSAlex Hornung case 2: 608ab6df5bcSAlex Hornung reg = SIO_GPDO2; 609ab6df5bcSAlex Hornung break; 610ab6df5bcSAlex Hornung case 3: 611ab6df5bcSAlex Hornung reg = SIO_GPDO3; 612ab6df5bcSAlex Hornung break; 613c8cb1400SAlex Hornung default: 614c8cb1400SAlex Hornung return; 615ab6df5bcSAlex Hornung } 616ab6df5bcSAlex Hornung 617ab6df5bcSAlex Hornung data = GPIO_READ(sc, reg); 618ab6df5bcSAlex Hornung if (value == 0) 619ab6df5bcSAlex Hornung data &= ~(1 << shift); 620ab6df5bcSAlex Hornung else if (value == 1) 621ab6df5bcSAlex Hornung data |= (1 << shift); 622ab6df5bcSAlex Hornung 623ab6df5bcSAlex Hornung GPIO_WRITE(sc, reg, data); 624ab6df5bcSAlex Hornung } 625ab6df5bcSAlex Hornung 626ab6df5bcSAlex Hornung void 627ab6df5bcSAlex Hornung nsclpcsio_gpio_pin_ctl(void *arg, int pin, int flags) 628ab6df5bcSAlex Hornung { 629ab6df5bcSAlex Hornung struct nsclpcsio_softc *sc = arg; 630ab6df5bcSAlex Hornung u_int8_t conf = 1; 631ab6df5bcSAlex Hornung 632ab6df5bcSAlex Hornung nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO); 633ab6df5bcSAlex Hornung nsclpcsio_gpio_pin_select(sc, pin); 634ab6df5bcSAlex Hornung conf = nsread(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG); 635ab6df5bcSAlex Hornung 636ab6df5bcSAlex Hornung conf &= ~(SIO_GPIO_CONF_OUTPUTEN | SIO_GPIO_CONF_PUSHPULL | 637ab6df5bcSAlex Hornung SIO_GPIO_CONF_PULLUP); 638ab6df5bcSAlex Hornung if ((flags & GPIO_PIN_TRISTATE) == 0) 639ab6df5bcSAlex Hornung conf |= SIO_GPIO_CONF_OUTPUTEN; 640ab6df5bcSAlex Hornung if (flags & GPIO_PIN_PUSHPULL) 641ab6df5bcSAlex Hornung conf |= SIO_GPIO_CONF_PUSHPULL; 642ab6df5bcSAlex Hornung if (flags & GPIO_PIN_PULLUP) 643ab6df5bcSAlex Hornung conf |= SIO_GPIO_CONF_PULLUP; 644ab6df5bcSAlex Hornung 645ab6df5bcSAlex Hornung nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG, conf); 646ab6df5bcSAlex Hornung } 647c8cb1400SAlex Hornung #endif /* NGPIO */ 648