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