1 /* $NetBSD: nsclpcsio_isa.c,v 1.27 2008/04/04 13:10:41 xtraeme Exp $ */
5 * Matthias Drochner. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * National Semiconductor PC87366 LPC Super I/O driver.
31 * Supported logical devices: GPIO, TMS, VLM.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: nsclpcsio_isa.c,v 1.27 2008/04/04 13:10:41 xtraeme Exp $");
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/mutex.h>
44 /* Don't use gpio for now in the module */
49 #include <dev/isa/isareg.h>
50 #include <dev/isa/isavar.h>
56 #include <dev/gpio/gpiovar.h>
58 #include <dev/sysmon/sysmonvar.h>
60 #define SIO_REG_SID 0x20 /* Super I/O ID */
61 #define SIO_SID_PC87366 0xE9 /* PC87366 is identified by 0xE9.*/
63 #define SIO_REG_SRID 0x27 /* Super I/O Revision */
65 #define SIO_REG_LDN 0x07 /* Logical Device Number */
66 #define SIO_LDN_FDC 0x00 /* Floppy Disk Controller (FDC) */
67 #define SIO_LDN_PP 0x01 /* Parallel Port (PP) */
68 #define SIO_LDN_SP2 0x02 /* Serial Port 2 with IR (SP2) */
69 #define SIO_LDN_SP1 0x03 /* Serial Port 1 (SP1) */
70 #define SIO_LDN_SWC 0x04 /* System Wake-Up Control (SWC) */
71 #define SIO_LDN_KBCM 0x05 /* Mouse Controller (KBC) */
72 #define SIO_LDN_KBCK 0x06 /* Keyboard Controller (KBC) */
73 #define SIO_LDN_GPIO 0x07 /* General-Purpose I/O (GPIO) Ports */
74 #define SIO_LDN_ACB 0x08 /* ACCESS.bus Interface (ACB) */
75 #define SIO_LDN_FSCM 0x09 /* Fan Speed Control and Monitor (FSCM) */
76 #define SIO_LDN_WDT 0x0A /* WATCHDOG Timer (WDT) */
77 #define SIO_LDN_GMP 0x0B /* Game Port (GMP) */
78 #define SIO_LDN_MIDI 0x0C /* Musical Instrument Digital Interface */
79 #define SIO_LDN_VLM 0x0D /* Voltage Level Monitor (VLM) */
80 #define SIO_LDN_TMS 0x0E /* Temperature Sensor (TMS) */
82 #define SIO_REG_ACTIVE 0x30 /* Logical Device Activate Register */
83 #define SIO_ACTIVE_EN 0x01 /* enabled */
85 #define SIO_REG_IO_MSB 0x60 /* I/O Port Base, bits 15-8 */
86 #define SIO_REG_IO_LSB 0x61 /* I/O Port Base, bits 7-0 */
88 #define SIO_LDNUM 15 /* total number of logical devices */
90 /* Supported logical devices description */
96 { "GPIO", SIO_LDN_GPIO
, 16 },
97 { "VLM", SIO_LDN_VLM
, 16 },
98 { "TMS", SIO_LDN_TMS
, 16 }
102 #define SIO_GPIO_PINSEL 0xf0
103 #define SIO_GPIO_PINCFG 0xf1
104 #define SIO_GPIO_PINEV 0xf2
106 #define SIO_GPIO_CONF_OUTPUTEN (1 << 0)
107 #define SIO_GPIO_CONF_PUSHPULL (1 << 1)
108 #define SIO_GPIO_CONF_PULLUP (1 << 2)
110 #define SIO_GPDO0 0x00
111 #define SIO_GPDI0 0x01
112 #define SIO_GPEVEN0 0x02
113 #define SIO_GPEVST0 0x03
114 #define SIO_GPDO1 0x04
115 #define SIO_GPDI1 0x05
116 #define SIO_GPEVEN1 0x06
117 #define SIO_GPEVST1 0x07
118 #define SIO_GPDO2 0x08
119 #define SIO_GPDI2 0x09
120 #define SIO_GPDO3 0x0a
121 #define SIO_GPDI3 0x0b
123 #define SIO_GPIO_NPINS 29
126 #define SIO_TEVSTS 0x00 /* Temperature Event Status */
127 #define SIO_TEVSMI 0x02 /* Temperature Event to SMI */
128 #define SIO_TEVIRQ 0x04 /* Temperature Event to IRQ */
129 #define SIO_TMSCFG 0x08 /* TMS Configuration */
130 #define SIO_TMSBS 0x09 /* TMS Bank Select */
131 #define SIO_TCHCFST 0x0a /* Temperature Channel Config and Status */
132 #define SIO_RDCHT 0x0b /* Read Channel Temperature */
133 #define SIO_CHTH 0x0c /* Channel Temperature High Limit */
134 #define SIO_CHTL 0x0d /* Channel Temperature Low Limit */
135 #define SIO_CHOTL 0x0e /* Channel Overtemperature Limit */
138 #define SIO_VEVSTS0 0x00 /* Voltage Event Status 0 */
139 #define SIO_VEVSTS1 0x01 /* Voltage Event Status 1 */
140 #define SIO_VEVSMI0 0x02 /* Voltage Event to SMI 0 */
141 #define SIO_VEVSMI1 0x03 /* Voltage Event to SMI 1 */
142 #define SIO_VEVIRQ0 0x04 /* Voltage Event to IRQ 0 */
143 #define SIO_VEVIRQ1 0x05 /* Voltage Event to IRQ 1 */
144 #define SIO_VID 0x06 /* Voltage ID */
145 #define SIO_VCNVR 0x07 /* Voltage Conversion Rate */
146 #define SIO_VLMCFG 0x08 /* VLM Configuration */
147 #define SIO_VLMBS 0x09 /* VLM Bank Select */
148 #define SIO_VCHCFST 0x0a /* Voltage Channel Config and Status */
149 #define SIO_RDCHV 0x0b /* Read Channel Voltage */
150 #define SIO_CHVH 0x0c /* Channel Voltage High Limit */
151 #define SIO_CHVL 0x0d /* Channel Voltage Low Limit */
152 #define SIO_OTSL 0x0e /* Overtemperature Shutdown Limit */
154 #define SIO_REG_SIOCF1 0x21
155 #define SIO_REG_SIOCF2 0x22
156 #define SIO_REG_SIOCF3 0x23
157 #define SIO_REG_SIOCF4 0x24
158 #define SIO_REG_SIOCF5 0x25
159 #define SIO_REG_SIOCF8 0x28
160 #define SIO_REG_SIOCFA 0x2a
161 #define SIO_REG_SIOCFB 0x2b
162 #define SIO_REG_SIOCFC 0x2c
163 #define SIO_REG_SIOCFD 0x2d
165 #define SIO_VLM_OFF 3
166 #define SIO_NUM_SENSORS (SIO_VLM_OFF + 14)
167 #define SIO_VREF 1235 /* 1000.0 * VREF */
169 struct nsclpcsio_softc
{
172 bus_space_tag_t sc_iot
;
173 bus_space_handle_t sc_ioh
;
175 bus_space_handle_t sc_ld_ioh
[SIO_LDNUM
];
176 int sc_ld_en
[SIO_LDNUM
];
179 struct sysmon_envsys
*sc_sme
;
180 envsys_data_t sc_sensor
[SIO_NUM_SENSORS
];
185 struct gpio_chipset_tag sc_gpio_gc
;
186 struct gpio_pin sc_gpio_pins
[SIO_GPIO_NPINS
];
190 #define GPIO_READ(sc, reg) \
191 bus_space_read_1((sc)->sc_iot, \
192 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg))
193 #define GPIO_WRITE(sc, reg, val) \
194 bus_space_write_1((sc)->sc_iot, \
195 (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg), (val))
196 #define TMS_WRITE(sc, reg, val) \
197 bus_space_write_1((sc)->sc_iot, \
198 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg), (val))
199 #define TMS_READ(sc, reg) \
200 bus_space_read_1((sc)->sc_iot, \
201 (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg))
202 #define VLM_WRITE(sc, reg, val) \
203 bus_space_write_1((sc)->sc_iot, \
204 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg), (val))
205 #define VLM_READ(sc, reg) \
206 bus_space_read_1((sc)->sc_iot, \
207 (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg))
209 static int nsclpcsio_isa_match(device_t
, cfdata_t
, void *);
210 static void nsclpcsio_isa_attach(device_t
, device_t
, void *);
211 static int nsclpcsio_isa_detach(device_t
, int);
213 CFATTACH_DECL_NEW(nsclpcsio_isa
, sizeof(struct nsclpcsio_softc
),
214 nsclpcsio_isa_match
, nsclpcsio_isa_attach
, nsclpcsio_isa_detach
, NULL
);
216 static uint8_t nsread(bus_space_tag_t
, bus_space_handle_t
, int);
217 static void nswrite(bus_space_tag_t
, bus_space_handle_t
, int, uint8_t);
218 static int nscheck(bus_space_tag_t
, int);
220 static void nsclpcsio_tms_init(struct nsclpcsio_softc
*);
221 static void nsclpcsio_vlm_init(struct nsclpcsio_softc
*);
222 static void nsclpcsio_refresh(struct sysmon_envsys
*, envsys_data_t
*);
225 static void nsclpcsio_gpio_init(struct nsclpcsio_softc
*);
226 static void nsclpcsio_gpio_pin_select(struct nsclpcsio_softc
*, int);
227 static void nsclpcsio_gpio_pin_write(void *, int, int);
228 static int nsclpcsio_gpio_pin_read(void *, int);
229 static void nsclpcsio_gpio_pin_ctl(void *, int, int);
233 nsread(bus_space_tag_t iot
, bus_space_handle_t ioh
, int idx
)
235 bus_space_write_1(iot
, ioh
, 0, idx
);
236 return bus_space_read_1(iot
, ioh
, 1);
240 nswrite(bus_space_tag_t iot
, bus_space_handle_t ioh
, int idx
, uint8_t data
)
242 bus_space_write_1(iot
, ioh
, 0, idx
);
243 bus_space_write_1(iot
, ioh
, 1, data
);
247 nscheck(bus_space_tag_t iot
, int base
)
249 bus_space_handle_t ioh
;
252 if (bus_space_map(iot
, base
, 2, 0, &ioh
))
255 /* XXX this is for PC87366 only for now */
256 if (nsread(iot
, ioh
, SIO_REG_SID
) == SIO_SID_PC87366
)
259 bus_space_unmap(iot
, ioh
, 2);
264 nsclpcsio_isa_match(device_t parent
, cfdata_t match
, void *aux
)
266 struct isa_attach_args
*ia
= aux
;
269 if (ISA_DIRECT_CONFIG(ia
))
272 if (ia
->ia_nio
> 0 && ia
->ia_io
[0].ir_addr
!= ISA_UNKNOWN_PORT
) {
273 /* XXX check for legal iobase ??? */
274 if (nscheck(ia
->ia_iot
, ia
->ia_io
[0].ir_addr
)) {
275 iobase
= ia
->ia_io
[0].ir_addr
;
281 /* PC87366 has two possible locations depending on wiring */
282 if (nscheck(ia
->ia_iot
, 0x2e)) {
286 if (nscheck(ia
->ia_iot
, 0x4e)) {
295 ia
->ia_io
[0].ir_addr
= iobase
;
296 ia
->ia_io
[0].ir_size
= 2;
304 static struct sysmon_envsys
*
305 nsclpcsio_envsys_init(struct nsclpcsio_softc
*sc
)
308 struct sysmon_envsys
*sme
;
310 sme
= sysmon_envsys_create();
311 for (i
= 0; i
< SIO_NUM_SENSORS
; i
++) {
312 if (sysmon_envsys_sensor_attach(sme
, &sc
->sc_sensor
[i
]) != 0) {
313 aprint_error_dev(sc
->sc_dev
,
314 "could not attach sensor %d", i
);
320 * Hook into the System Monitor.
322 sme
->sme_name
= device_xname(sc
->sc_dev
);
323 sme
->sme_cookie
= sc
;
324 sme
->sme_refresh
= nsclpcsio_refresh
;
326 if ((i
= sysmon_envsys_register(sme
)) != 0) {
327 aprint_error_dev(sc
->sc_dev
,
328 "unable to register with sysmon (%d)\n", i
);
333 sysmon_envsys_destroy(sme
);
338 nsclpcsio_isa_attach(device_t parent
, device_t self
, void *aux
)
340 struct nsclpcsio_softc
*sc
= device_private(self
);
341 struct isa_attach_args
*ia
= aux
;
343 struct gpiobus_attach_args gba
;
347 mutex_init(&sc
->sc_lock
, MUTEX_DEFAULT
, IPL_NONE
);
350 sc
->sc_iot
= ia
->ia_iot
;
351 iobase
= ia
->ia_io
[0].ir_addr
;
353 if (bus_space_map(ia
->ia_iot
, iobase
, 2, 0, &sc
->sc_ioh
)) {
354 aprint_error(": can't map i/o space\n");
358 aprint_normal(": NSC PC87366 rev. 0x%d ",
359 nsread(sc
->sc_iot
, sc
->sc_ioh
, SIO_REG_SRID
));
361 /* Configure all supported logical devices */
362 for (i
= 0; i
< __arraycount(sio_ld
); i
++) {
363 sc
->sc_ld_en
[sio_ld
[i
].ld_num
] = 0;
365 /* Select the device and check if it's activated */
366 nswrite(sc
->sc_iot
, sc
->sc_ioh
, SIO_REG_LDN
, sio_ld
[i
].ld_num
);
367 if ((nsread(sc
->sc_iot
, sc
->sc_ioh
,
368 SIO_REG_ACTIVE
) & SIO_ACTIVE_EN
) == 0)
371 /* Map I/O space if necessary */
372 if (sio_ld
[i
].ld_iosize
!= 0) {
373 iobase
= (nsread(sc
->sc_iot
, sc
->sc_ioh
,
374 SIO_REG_IO_MSB
) << 8);
375 iobase
|= nsread(sc
->sc_iot
, sc
->sc_ioh
,
377 if (bus_space_map(sc
->sc_iot
, iobase
,
378 sio_ld
[i
].ld_iosize
, 0,
379 &sc
->sc_ld_ioh
[sio_ld
[i
].ld_num
]))
383 sc
->sc_ld_en
[sio_ld
[i
].ld_num
] = 1;
384 aprint_normal("%s ", sio_ld
[i
].ld_name
);
390 nsclpcsio_gpio_init(sc
);
392 nsclpcsio_tms_init(sc
);
393 nsclpcsio_vlm_init(sc
);
394 sc
->sc_sme
= nsclpcsio_envsys_init(sc
);
397 /* attach GPIO framework */
398 if (sc
->sc_ld_en
[SIO_LDN_GPIO
]) {
399 gba
.gba_gc
= &sc
->sc_gpio_gc
;
400 gba
.gba_pins
= sc
->sc_gpio_pins
;
401 gba
.gba_npins
= SIO_GPIO_NPINS
;
402 config_found_ia(self
, "gpiobus", &gba
, NULL
);
408 nsclpcsio_isa_detach(device_t self
, int flags
)
411 struct nsclpcsio_softc
*sc
= device_private(self
);
413 if ((rc
= config_detach_children(self
, flags
)) != 0)
416 if (sc
->sc_sme
!= NULL
)
417 sysmon_envsys_unregister(sc
->sc_sme
);
418 mutex_destroy(&sc
->sc_lock
);
420 for (i
= 0; i
< __arraycount(sio_ld
); i
++) {
421 if (sc
->sc_ld_en
[sio_ld
[i
].ld_num
] &&
422 sio_ld
[i
].ld_iosize
!= 0) {
423 bus_space_unmap(sc
->sc_iot
,
424 sc
->sc_ld_ioh
[sio_ld
[i
].ld_num
],
425 sio_ld
[i
].ld_iosize
);
429 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, 2);
435 nsclpcsio_tms_init(struct nsclpcsio_softc
*sc
)
439 /* Initialisation, PC87366.pdf, page 208 */
440 TMS_WRITE(sc
, 0x08, 0x00);
441 TMS_WRITE(sc
, 0x09, 0x0f);
442 TMS_WRITE(sc
, 0x0a, 0x08);
443 TMS_WRITE(sc
, 0x0b, 0x04);
444 TMS_WRITE(sc
, 0x0c, 0x35);
445 TMS_WRITE(sc
, 0x0d, 0x05);
446 TMS_WRITE(sc
, 0x0e, 0x05);
448 TMS_WRITE(sc
, SIO_TMSCFG
, 0x00);
450 for (i
= 0; i
< SIO_VLM_OFF
; i
++) {
451 TMS_WRITE(sc
, SIO_TMSBS
, i
);
452 TMS_WRITE(sc
, SIO_TCHCFST
, 0x01);
453 sc
->sc_sensor
[i
].units
= ENVSYS_STEMP
;
456 #define COPYDESCR(x, y) \
458 (void)strlcpy((x), (y), sizeof(x)); \
459 } while (/* CONSTCOND */ 0)
461 COPYDESCR(sc
->sc_sensor
[0].desc
, "TSENS1");
462 COPYDESCR(sc
->sc_sensor
[1].desc
, "TSENS2");
463 COPYDESCR(sc
->sc_sensor
[2].desc
, "TNSC");
467 nsclpcsio_vlm_init(struct nsclpcsio_softc
*sc
)
471 envsys_data_t
*sensor
= &sc
->sc_sensor
[SIO_VLM_OFF
];
473 for (i
= 0; i
< SIO_NUM_SENSORS
- SIO_VLM_OFF
; i
++) {
474 VLM_WRITE(sc
, SIO_VLMBS
, i
);
475 VLM_WRITE(sc
, SIO_VCHCFST
, 0x01);
476 sensor
[i
].units
= ENVSYS_SVOLTS_DC
;
479 for (i
= 0; i
< 7; i
++) {
480 (void)snprintf(tmp
, sizeof(tmp
), "VSENS%d", i
);
481 COPYDESCR(sensor
[i
].desc
, tmp
);
484 COPYDESCR(sensor
[7 ].desc
, "VSB");
485 COPYDESCR(sensor
[8 ].desc
, "VDD");
486 COPYDESCR(sensor
[9 ].desc
, "VBAT");
487 COPYDESCR(sensor
[10].desc
, "AVDD");
488 COPYDESCR(sensor
[11].desc
, "TS1");
489 COPYDESCR(sensor
[12].desc
, "TS2");
490 COPYDESCR(sensor
[13].desc
, "TS3");
495 nsclpcsio_refresh(struct sysmon_envsys
*sme
, envsys_data_t
*edata
)
497 struct nsclpcsio_softc
*sc
= sme
->sme_cookie
;
498 uint8_t status
, data
;
505 mutex_enter(&sc
->sc_lock
);
507 if (edata
->sensor
< SIO_VLM_OFF
&& sc
->sc_ld_en
[SIO_LDN_TMS
]) {
508 TMS_WRITE(sc
, SIO_TMSBS
, edata
->sensor
);
509 status
= TMS_READ(sc
, SIO_TCHCFST
);
510 if (!(status
& 0x01))
511 edata
->state
= ENVSYS_SINVALID
;
513 sdata
= TMS_READ(sc
, SIO_RDCHT
);
514 edata
->value_cur
= sdata
* 1000000 + 273150000;
515 edata
->state
= ENVSYS_SVALID
;
517 } else if (edata
->sensor
>= SIO_VLM_OFF
&&
518 edata
->sensor
< SIO_NUM_SENSORS
&&
519 sc
->sc_ld_en
[SIO_LDN_VLM
]) {
520 VLM_WRITE(sc
, SIO_VLMBS
, edata
->sensor
- SIO_VLM_OFF
);
521 status
= VLM_READ(sc
, SIO_VCHCFST
);
522 if (!(status
& 0x01)) {
523 edata
->state
= ENVSYS_SINVALID
;
525 data
= VLM_READ(sc
, SIO_RDCHV
);
527 switch (edata
->sensor
- SIO_VLM_OFF
) {
534 /* Vi = (2.45±0.05)*VREF *RDCHVi / 256 */
535 rfact
= 10 * scale
* ((245 * SIO_VREF
) >> 8);
536 edata
->value_cur
= data
* rfact
;
537 edata
->state
= ENVSYS_SVALID
;
540 mutex_exit(&sc
->sc_lock
);
545 nsclpcsio_gpio_pin_select(struct nsclpcsio_softc
*sc
, int pin
)
549 v
= ((pin
/ 8) << 4) | (pin
% 8);
551 nswrite(sc
->sc_iot
, sc
->sc_ioh
, SIO_REG_LDN
, SIO_LDN_GPIO
);
552 nswrite(sc
->sc_iot
, sc
->sc_ioh
, SIO_GPIO_PINSEL
, v
);
556 nsclpcsio_gpio_init(struct nsclpcsio_softc
*sc
)
560 for (i
= 0; i
< SIO_GPIO_NPINS
; i
++) {
561 sc
->sc_gpio_pins
[i
].pin_num
= i
;
562 sc
->sc_gpio_pins
[i
].pin_caps
= GPIO_PIN_INPUT
|
563 GPIO_PIN_OUTPUT
| GPIO_PIN_OPENDRAIN
|
564 GPIO_PIN_PUSHPULL
| GPIO_PIN_TRISTATE
|
567 sc
->sc_gpio_pins
[i
].pin_flags
= GPIO_PIN_TRISTATE
;
568 sc
->sc_gpio_pins
[i
].pin_state
= GPIO_PIN_LOW
;
569 nsclpcsio_gpio_pin_ctl(sc
, i
, sc
->sc_gpio_pins
[i
].pin_flags
);
570 nsclpcsio_gpio_pin_write(sc
, i
, sc
->sc_gpio_pins
[i
].pin_state
);
573 /* create controller tag */
574 sc
->sc_gpio_gc
.gp_cookie
= sc
;
575 sc
->sc_gpio_gc
.gp_pin_read
= nsclpcsio_gpio_pin_read
;
576 sc
->sc_gpio_gc
.gp_pin_write
= nsclpcsio_gpio_pin_write
;
577 sc
->sc_gpio_gc
.gp_pin_ctl
= nsclpcsio_gpio_pin_ctl
;
581 nsclpcsio_gpio_pin_read(void *aux
, int pin
)
583 struct nsclpcsio_softc
*sc
= (struct nsclpcsio_softc
*)aux
;
584 int port
, shift
, reg
;
608 v
= GPIO_READ(sc
, reg
);
610 return ((v
>> shift
) & 0x1);
614 nsclpcsio_gpio_pin_write(void *aux
, int pin
, int v
)
616 struct nsclpcsio_softc
*sc
= (struct nsclpcsio_softc
*)aux
;
617 int port
, shift
, reg
;
638 break; /* shouldn't happen */
641 d
= GPIO_READ(sc
, reg
);
646 GPIO_WRITE(sc
, reg
, d
);
650 nsclpcsio_gpio_pin_ctl(void *aux
, int pin
, int flags
)
652 struct nsclpcsio_softc
*sc
= (struct nsclpcsio_softc
*)aux
;
655 mutex_enter(&sc
->sc_lock
);
657 nswrite(sc
->sc_iot
, sc
->sc_ioh
, SIO_REG_LDN
, SIO_LDN_GPIO
);
658 nsclpcsio_gpio_pin_select(sc
, pin
);
659 conf
= nsread(sc
->sc_iot
, sc
->sc_ioh
, SIO_GPIO_PINCFG
);
661 conf
&= ~(SIO_GPIO_CONF_OUTPUTEN
| SIO_GPIO_CONF_PUSHPULL
|
662 SIO_GPIO_CONF_PULLUP
);
663 if ((flags
& GPIO_PIN_TRISTATE
) == 0)
664 conf
|= SIO_GPIO_CONF_OUTPUTEN
;
665 if (flags
& GPIO_PIN_PUSHPULL
)
666 conf
|= SIO_GPIO_CONF_PUSHPULL
;
667 if (flags
& GPIO_PIN_PULLUP
)
668 conf
|= SIO_GPIO_CONF_PULLUP
;
670 nswrite(sc
->sc_iot
, sc
->sc_ioh
, SIO_GPIO_PINCFG
, conf
);
672 mutex_exit(&sc
->sc_lock
);