1 /* $NetBSD: vrc4172gpio.c,v 1.11 2006/03/29 04:16:45 thorpej Exp $ */
3 * Copyright (c) 2001 TAKEMRUA Shin. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: vrc4172gpio.c,v 1.11 2006/03/29 04:16:45 thorpej Exp $");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/malloc.h>
38 #include <sys/queue.h>
39 #include <sys/reboot.h>
40 #include <machine/bus.h>
41 #include <machine/platid.h>
42 #include <machine/platid_mask.h>
44 #include <dev/hpc/hpciovar.h>
46 #include <hpcmips/vr/vripif.h>
47 #include <hpcmips/vr/vripvar.h>
48 #include <hpcmips/vr/vrc4172gpioreg.h>
55 #define DBG_INTR (1<<1)
56 #define DBG_INFO (1<<2)
57 #ifndef VRC2GPIODEBUG_CONF
58 #define VRC2GPIODEBUG_CONF 0
59 #endif /* VRC2GPIODEBUG_CONF */
60 int vrc4172gpio_debug
= VRC2GPIODEBUG_CONF
;
61 #define DBG(flag) (vrc4172gpio_debug & (flag))
62 #define DPRINTF(flag, arg...) do { \
68 #define DPRINTF(flag, arg...) do {} while(0)
70 #define VPRINTF(arg...) do { \
75 #define CHECK_PORT(x) (0 <= (x) && (x) < VRC2_EXGP_NPORTS)
77 struct vrc4172gpio_intr_entry
{
81 TAILQ_ENTRY(vrc4172gpio_intr_entry
) ih_link
;
84 struct vrc4172gpio_softc
{
86 bus_space_tag_t sc_iot
;
87 bus_space_handle_t sc_ioh
;
88 struct hpcio_attach_args sc_args
;
89 struct hpcio_chip
*sc_hc
;
92 u_int32_t sc_intr_mask
;
94 u_int32_t sc_intr_mode
[VRC2_EXGP_NPORTS
];
95 TAILQ_HEAD(, vrc4172gpio_intr_entry
) sc_intr_head
[VRC2_EXGP_NPORTS
];
96 struct hpcio_chip sc_iochip
;
97 struct hpcio_attach_args sc_haa
;
100 int vrc4172gpio_match(struct device
*, struct cfdata
*, void*);
101 void vrc4172gpio_attach(struct device
*, struct device
*, void*);
102 void vrc4172gpio_callback(struct device
*self
);
103 int vrc4172gpio_intr(void*);
104 int vrc4172gpio_print(void*, const char*);
106 int vrc4172gpio_port_read(hpcio_chip_t
, int);
107 void vrc4172gpio_port_write(hpcio_chip_t
, int, int);
108 void *vrc4172gpio_intr_establish(hpcio_chip_t
, int, int, int (*)(void *), void*);
109 void vrc4172gpio_intr_disestablish(hpcio_chip_t
, void*);
110 void vrc4172gpio_intr_clear(hpcio_chip_t
, void*);
111 void vrc4172gpio_register_iochip(hpcio_chip_t
, hpcio_chip_t
);
112 void vrc4172gpio_update(hpcio_chip_t
);
113 void vrc4172gpio_dump(hpcio_chip_t
);
114 void vrc4172gpio_intr_dump(struct vrc4172gpio_softc
*, int);
115 hpcio_chip_t
vrc4172gpio_getchip(void*, int);
116 static void vrc4172gpio_diffport(struct vrc4172gpio_softc
*sc
);
118 static u_int16_t
read_2(struct vrc4172gpio_softc
*, bus_addr_t
);
119 static void write_2(struct vrc4172gpio_softc
*, bus_addr_t
, u_int16_t
);
120 static u_int32_t
read_4(struct vrc4172gpio_softc
*, bus_addr_t
);
121 static void write_4(struct vrc4172gpio_softc
*, bus_addr_t
, u_int32_t
);
122 static void dumpbits(u_int32_t
*, int, int, int, const char[2]);
124 static struct hpcio_chip vrc4172gpio_iochip
= {
125 .hc_portread
= vrc4172gpio_port_read
,
126 .hc_portwrite
= vrc4172gpio_port_write
,
127 .hc_intr_establish
= vrc4172gpio_intr_establish
,
128 .hc_intr_disestablish
= vrc4172gpio_intr_disestablish
,
129 .hc_intr_clear
= vrc4172gpio_intr_clear
,
130 .hc_register_iochip
= vrc4172gpio_register_iochip
,
131 .hc_update
= vrc4172gpio_update
,
132 .hc_dump
= vrc4172gpio_dump
,
135 static int intlv_regs
[] = {
141 CFATTACH_DECL(vrc4172gpio
, sizeof(struct vrc4172gpio_softc
),
142 vrc4172gpio_match
, vrc4172gpio_attach
, NULL
, NULL
);
145 * regster access method
147 static inline u_int16_t
148 read_2(struct vrc4172gpio_softc
*sc
, bus_addr_t off
)
150 return bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, off
);
154 write_2(struct vrc4172gpio_softc
*sc
, bus_addr_t off
, u_int16_t data
)
156 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, off
, data
);
160 read_4(struct vrc4172gpio_softc
*sc
, bus_addr_t off
)
162 u_int16_t reg0
, reg1
;
164 reg0
= read_2(sc
, off
);
165 reg1
= read_2(sc
, off
+ VRC2_EXGP_OFFSET
);
167 return (reg0
|(reg1
<<16));
171 write_4(struct vrc4172gpio_softc
*sc
, bus_addr_t off
, u_int32_t data
)
173 write_2(sc
, off
, data
& 0xffff);
174 write_2(sc
, off
+ VRC2_EXGP_OFFSET
, (data
>>16)&0xffff);
178 vrc4172gpio_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
180 struct hpcio_attach_args
*haa
= aux
;
183 if (strcmp(haa
->haa_busname
, HPCIO_BUSNAME
))
185 if (cf
->cf_loc
[HPCIOIFCF_PLATFORM
] == 0)
187 mask
= PLATID_DEREF(cf
->cf_loc
[HPCIOIFCF_PLATFORM
]);
189 return platid_match(&platid
, &mask
);
193 vrc4172gpio_attach(struct device
*parent
, struct device
*self
, void *aux
)
195 struct hpcio_attach_args
*args
= aux
;
196 struct vrc4172gpio_softc
*sc
= (void*)self
;
197 int i
, *loc
, port
, mode
;
198 u_int32_t regs
[6], t0
, t1
, t2
;
201 loc
= device_cfdata(&sc
->sc_dev
)->cf_loc
;
206 sc
->sc_iot
= args
->haa_iot
;
207 sc
->sc_hc
= (*args
->haa_getchip
)(args
->haa_sc
, loc
[HPCIOIFCF_IOCHIP
]);
208 sc
->sc_args
= *args
; /* structure copy */
209 bus_space_map(sc
->sc_iot
, loc
[HPCIOIFCF_ADDR
], loc
[HPCIOIFCF_SIZE
],
210 0 /* no cache */, &sc
->sc_ioh
);
211 if (sc
->sc_ioh
== 0) {
212 printf("%s: can't map bus space\n", sc
->sc_dev
.dv_xname
);
217 * dump Windows CE register setting
219 regs
[0] = read_4(sc
, VRC2_EXGPDATA
);
220 regs
[1] = read_4(sc
, VRC2_EXGPDIR
);
221 regs
[2] = read_4(sc
, VRC2_EXGPINTEN
);
222 regs
[3] = read_4(sc
, VRC2_EXGPINTTYP
);
223 t0
= read_2(sc
, VRC2_EXGPINTLV0L
);
224 t1
= read_2(sc
, VRC2_EXGPINTLV0H
);
225 t2
= read_2(sc
, VRC2_EXGPINTLV1L
);
226 regs
[4] = ((t2
&0xff00)<<8) | (t1
&0xff00) | ((t0
&0xff00)>>8);
227 regs
[5] = ((t2
&0xff)<<16) | ((t1
&0xff)<<8) | (t0
&0xff);
229 if (bootverbose
|| DBG(DBG_INFO
)) {
232 * i: input (no interrupt)
233 * H: level sense interrupt (active high)
234 * L: level sense interrupt (active low)
235 * B: both edge trigger interrupt
236 * P: positive edge trigger interrupt
237 * N: negative edge trigger interrupt
239 printf(" port#:321098765432109876543210\n");
240 printf(" EXGPDATA :");
241 dumpbits(®s
[0], 1, 23, 0, "10\n");
242 printf("WIN setting:");
243 dumpbits(®s
[1], 5, 23, 0,
244 "oooo" /* dir=1 en=1 typ=1 */
245 "oooo" /* dir=1 en=1 typ=0 */
246 "oooo" /* dir=1 en=0 typ=1 */
247 "oooo" /* dir=1 en=0 typ=0 */
248 "BBPN" /* dir=0 en=1 typ=1 */
249 "HLHL" /* dir=0 en=1 typ=0 */
250 "iiii" /* dir=0 en=0 typ=1 */
251 "iiii" /* dir=0 en=0 typ=0 */
257 printf(" EXGPDIR :");
258 dumpbits(®s
[1], 1, 23, 0, "oi\n");
260 printf(" EXGPINTEN :");
261 dumpbits(®s
[2], 1, 23, 0, "I-\n");
263 printf(" EXGPINTTYP:");
264 dumpbits(®s
[3], 1, 23, 0, "EL\n");
267 dumpbits(®s
[4], 1, 23, 0, "10\n");
270 dumpbits(®s
[5], 1, 23, 0, "10\n");
272 printf(" EXGPINTLV :%04x %04x %04x\n", t2
, t1
, t0
);
274 #endif /* VRC2GPIODEBUG */
277 * initialize register and internal data
279 sc
->sc_intr_mask
= 0;
280 write_2(sc
, VRC2_EXGPINTEN
, sc
->sc_intr_mask
);
281 for (i
= 0; i
< VRC2_EXGP_NPORTS
; i
++)
282 TAILQ_INIT(&sc
->sc_intr_head
[i
]);
283 sc
->sc_data
= read_4(sc
, VRC2_EXGPDATA
);
284 if (bootverbose
|| DBG(DBG_INFO
)) {
287 sc
->sc_intr_mask
= (~read_4(sc
, VRC2_EXGPDIR
) & 0xffffff);
288 write_4(sc
, VRC2_EXGPINTTYP
, 0); /* level sence interrupt */
289 data
= ~read_4(sc
, VRC2_EXGPDATA
);
290 write_2(sc
, VRC2_EXGPINTLV0L
, (data
>> 0) & 0xff);
291 write_2(sc
, VRC2_EXGPINTLV0H
, (data
>> 8) & 0xff);
292 write_2(sc
, VRC2_EXGPINTLV1L
, (data
>> 16) & 0xff);
296 * install interrupt handler
298 port
= loc
[HPCIOIFCF_PORT
];
299 mode
= HPCIO_INTR_LEVEL
| HPCIO_INTR_HIGH
;
301 hpcio_intr_establish(sc
->sc_hc
, port
, mode
, vrc4172gpio_intr
, sc
);
302 if (sc
->sc_intr_handle
== NULL
) {
303 printf("%s: can't establish interrupt\n", sc
->sc_dev
.dv_xname
);
308 * fill hpcio_chip structure
310 sc
->sc_iochip
= vrc4172gpio_iochip
; /* structure copy */
311 sc
->sc_iochip
.hc_chipid
= VRIP_IOCHIP_VRC4172GPIO
;
312 sc
->sc_iochip
.hc_name
= sc
->sc_dev
.dv_xname
;
313 sc
->sc_iochip
.hc_sc
= sc
;
314 /* Register functions to upper interface */
315 hpcio_register_iochip(sc
->sc_hc
, &sc
->sc_iochip
);
320 sc
->sc_haa
.haa_busname
= HPCIO_BUSNAME
;
321 sc
->sc_haa
.haa_sc
= sc
;
322 sc
->sc_haa
.haa_getchip
= vrc4172gpio_getchip
;
323 sc
->sc_haa
.haa_iot
= sc
->sc_iot
;
324 while (config_found(self
, &sc
->sc_haa
, vrc4172gpio_print
)) ;
328 #if 1 /* XXX Sometimes mounting root device failed. Why? XXX*/
329 config_defer(self
, vrc4172gpio_callback
);
331 vrc4172gpio_callback(self
);
336 vrc4172gpio_callback(struct device
*self
)
338 struct vrc4172gpio_softc
*sc
= (void*)self
;
340 sc
->sc_haa
.haa_busname
= "vrisab";
341 config_found(self
, &sc
->sc_haa
, vrc4172gpio_print
);
345 vrc4172gpio_print(void *aux
, const char *pnp
)
356 vrc4172gpio_port_read(hpcio_chip_t hc
, int port
)
358 struct vrc4172gpio_softc
*sc
= hc
->hc_sc
;
361 if (!CHECK_PORT(port
))
362 panic("%s: illegal gpio port", __func__
);
364 on
= (read_4(sc
, VRC2_EXGPDATA
) & (1 << port
));
370 vrc4172gpio_port_write(hpcio_chip_t hc
, int port
, int onoff
)
372 struct vrc4172gpio_softc
*sc
= hc
->hc_sc
;
375 if (!CHECK_PORT(port
))
376 panic("%s: illegal gpio port", __func__
);
377 data
= read_4(sc
, VRC2_EXGPDATA
);
382 write_4(sc
, VRC2_EXGPDATA
, data
);
386 vrc4172gpio_update(hpcio_chip_t hc
)
391 vrc4172gpio_intr_dump(struct vrc4172gpio_softc
*sc
, int port
)
393 u_int32_t mask
, mask2
;
397 mask2
= (1 << (port
% 8));
398 intlv_reg
= intlv_regs
[port
/8];
400 if (read_4(sc
, VRC2_EXGPDIR
) & mask
) {
406 if (read_4(sc
, VRC2_EXGPINTTYP
) & mask
) {
407 if (read_4(sc
, intlv_reg
) & (mask2
<< 8)) {
408 printf(", both edge");
410 if (read_4(sc
, intlv_reg
) & mask2
)
411 printf(", positive edge");
413 printf(", negative edge");
416 if (read_4(sc
, intlv_reg
) & mask2
)
417 printf(", high level");
419 printf(", low level");
424 vrc4172gpio_diffport(struct vrc4172gpio_softc
*sc
)
427 data
= read_4(sc
, VRC2_EXGPDATA
);
428 if (sc
->sc_data
!= data
) {
429 printf(" port# 321098765432109876543210\n");
430 printf("vrc4172data:");
431 dumpbits(&data
, 1, 23, 0, "10\n");
432 /* bits which changed */
433 data
= (data
& ~sc
->sc_data
)|(~data
& sc
->sc_data
);
435 dumpbits(&data
, 1, 23, 0, "^ \n");
441 dumpbits(u_int32_t
*data
, int ndata
, int start
, int end
, const char *sym
)
446 panic("%s(%d): %s", __FILE__
, __LINE__
, __func__
);
448 for (i
= start
; end
<= i
; i
--) {
450 for (j
= 0; j
< ndata
; j
++)
451 d
= (d
<< 1) | ((data
[j
] & (1 << i
)) ? 1 : 0);
452 printf("%c", sym
[(1 << ndata
) - d
- 1]);
456 printf("%c", sym
[1<<ndata
]);
460 vrc4172gpio_dump(hpcio_chip_t hc
)
465 vrc4172gpio_getchip(void* scx
, int chipid
)
467 struct vrc4172gpio_softc
*sc
= scx
;
469 return (&sc
->sc_iochip
);
476 vrc4172gpio_intr_establish(
478 int port
, /* GPIO pin # */
479 int mode
, /* GIU trigger setting */
480 int (*ih_fun
)(void*),
483 struct vrc4172gpio_softc
*sc
= hc
->hc_sc
;
485 u_int32_t reg
, mask
, mask2
;
486 struct vrc4172gpio_intr_entry
*ih
;
491 if (!CHECK_PORT(port
))
492 panic ("%s: bogus interrupt line", __func__
);
493 if (sc
->sc_intr_mode
[port
] && mode
!= sc
->sc_intr_mode
[port
])
494 panic ("%s: bogus interrupt type", __func__
);
496 sc
->sc_intr_mode
[port
] = mode
;
499 mask2
= (1 << (port
% 8));
500 intlv_reg
= intlv_regs
[port
/8];
502 ih
= malloc(sizeof(struct vrc4172gpio_intr_entry
), M_DEVBUF
, M_NOWAIT
);
504 panic("%s: no memory", __func__
);
509 TAILQ_INSERT_TAIL(&sc
->sc_intr_head
[port
], ih
, ih_link
);
513 printf("port %2d:", port
);
514 vrc4172gpio_intr_dump(sc
, port
);
523 reg
= read_4(sc
, VRC2_EXGPDIR
);
525 write_4(sc
, VRC2_EXGPDIR
, reg
);
527 /* interrupt triger (level/edge) */
528 reg
= read_4(sc
, VRC2_EXGPINTTYP
);
529 if (mode
& HPCIO_INTR_EDGE
)
530 reg
|= mask
; /* edge */
532 reg
&= ~mask
; /* level */
533 write_4(sc
, VRC2_EXGPINTTYP
, reg
);
535 /* interrupt trigger option */
536 reg
= read_4(sc
, intlv_reg
);
537 if (mode
& HPCIO_INTR_EDGE
) {
538 switch (mode
& (HPCIO_INTR_POSEDGE
| HPCIO_INTR_NEGEDGE
)) {
539 case HPCIO_INTR_POSEDGE
:
540 reg
&= ~(mask2
<< 8);
543 case HPCIO_INTR_NEGEDGE
:
544 reg
&= ~(mask2
<< 8);
547 case HPCIO_INTR_POSEDGE
| HPCIO_INTR_NEGEDGE
:
553 if (mode
& HPCIO_INTR_HIGH
)
554 reg
|= mask2
; /* high */
556 reg
&= ~mask2
; /* low */
558 write_4(sc
, intlv_reg
, reg
);
562 vrc4172gpio_intr_dump(sc
, port
);
567 /* XXX, Vrc4172 doesn't have register to set hold or through */
570 * clear interrupt status and enable interrupt
572 vrc4172gpio_intr_clear(&sc
->sc_iochip
, ih
);
573 sc
->sc_intr_mask
|= mask
;
574 write_4(sc
, VRC2_EXGPINTEN
, sc
->sc_intr_mask
);
578 DPRINTF(DBG_INFO
, "\n");
584 vrc4172gpio_intr_disestablish(hpcio_chip_t hc
, void *arg
)
586 struct vrc4172gpio_intr_entry
*ihe
= arg
;
587 struct vrc4172gpio_softc
*sc
= hc
->hc_sc
;
588 int port
= ihe
->ih_port
;
589 struct vrc4172gpio_intr_entry
*ih
;
593 TAILQ_FOREACH(ih
, &sc
->sc_intr_head
[port
], ih_link
) {
595 TAILQ_REMOVE(&sc
->sc_intr_head
[port
], ih
, ih_link
);
597 if (TAILQ_EMPTY(&sc
->sc_intr_head
[port
])) {
598 /* disable interrupt */
599 sc
->sc_intr_mask
&= ~(1<<port
);
600 write_4(sc
, VRC2_EXGPINTEN
,
607 panic("%s: no such a handle.", __func__
);
611 /* Clear interrupt */
613 vrc4172gpio_intr_clear(hpcio_chip_t hc
, void *arg
)
615 struct vrc4172gpio_softc
*sc
= hc
->hc_sc
;
616 struct vrc4172gpio_intr_entry
*ihe
= arg
;
618 write_4(sc
, VRC2_EXGPINTST
, 1 << ihe
->ih_port
);
619 write_4(sc
, VRC2_EXGPINTST
, 0);
623 vrc4172gpio_register_iochip(hpcio_chip_t hc
, hpcio_chip_t iochip
)
625 struct vrc4172gpio_softc
*sc
= hc
->hc_sc
;
627 hpcio_register_iochip(sc
->sc_hc
, iochip
);
630 /* interrupt handler */
632 vrc4172gpio_intr(void *arg
)
634 struct vrc4172gpio_softc
*sc
= arg
;
638 /* dispatch handler */
639 reg
= read_4(sc
, VRC2_EXGPINTST
);
640 DPRINTF(DBG_INTR
, "%s: EXGPINTST=%06x\n", __func__
, reg
);
641 for (i
= 0; i
< VRC2_EXGP_NPORTS
; i
++) {
642 if (reg
& (1 << i
)) {
643 register struct vrc4172gpio_intr_entry
*ih
;
646 * call interrupt handler
648 TAILQ_FOREACH(ih
, &sc
->sc_intr_head
[i
], ih_link
) {
649 ih
->ih_fun(ih
->ih_arg
);
653 * disable interrupt if no handler is installed
655 if (TAILQ_EMPTY(&sc
->sc_intr_head
[i
])) {
656 sc
->sc_intr_mask
&= ~(1 << i
);
657 write_2(sc
, VRC2_EXGPINTEN
, sc
->sc_intr_mask
);
659 /* dump EXGPDATA bits which changed */
660 if (bootverbose
|| DBG(DBG_INFO
))
661 vrc4172gpio_diffport(sc
);