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 {
1695d302545SFranç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
2075d302545SFrançois Tigeot int nsclpcsio_isa_probe(device_t);
2085d302545SFranç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
nsread(bus_space_tag_t iot,bus_space_handle_t ioh,int idx)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
nswrite(bus_space_tag_t iot,bus_space_handle_t ioh,int idx,u_int8_t data)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
nsclpcsio_isa_probe(device_t dev)2605d302545SFranç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
nsclpcsio_isa_attach(device_t dev)2875d302545SFranç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
nsclpcsio_refresh(void * arg)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
nsclpcsio_tms_init(struct nsclpcsio_softc * sc)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
nsclpcsio_tms_update(struct nsclpcsio_softc * sc)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
nsclpcsio_vlm_init(struct nsclpcsio_softc * sc)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
nsclpcsio_vlm_update(struct nsclpcsio_softc * sc)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
519*5c0a8865Szrj /* 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
nsclpcsio_gpio_pin_select(struct nsclpcsio_softc * sc,int pin)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
nsclpcsio_gpio_init(struct nsclpcsio_softc * sc)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
nsclpcsio_gpio_pin_read(void * arg,int pin)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
nsclpcsio_gpio_pin_write(void * arg,int pin,int value)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
nsclpcsio_gpio_pin_ctl(void * arg,int pin,int flags)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