1 /* $NetBSD: gb225.c,v 1.5.32.1 2007/10/03 19:23:09 garbled Exp $ */
4 * Copyright (c) 2002, 2003 Genetec corp. All rights reserved.
5 * Written by Hiroyuki Bessho for Genetec corp.
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.
15 * 3. The name of Genetec corp. may not be used to endorse
16 * or promote products derived from this software without specific prior
19 * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP.
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 #include <sys/kernel.h>
37 #include <sys/reboot.h>
39 #include <machine/cpu.h>
40 #include <machine/bus.h>
41 #include <machine/intr.h>
42 #include <arm/cpufunc.h>
44 #include <arm/mainbus/mainbus.h>
45 #include <arm/xscale/pxa2x0reg.h>
46 #include <arm/xscale/pxa2x0var.h>
47 #include <arm/xscale/pxa2x0_gpio.h>
48 #include <arm/sa11x0/sa11x0_var.h>
49 #include <evbarm/g42xxeb/g42xxeb_reg.h>
50 #include <evbarm/g42xxeb/g42xxeb_var.h>
51 #include <evbarm/g42xxeb/gb225reg.h>
52 #include <evbarm/g42xxeb/gb225var.h>
56 #define OPIO_INTR G42XXEB_INT_EXT3
59 #define DEBOUNCE_COUNT 2
60 #define DEBOUNCE_TICKS (hz/20) /* 50ms */
63 static int opio_match(struct device
*, struct cfdata
*, void *);
64 static void opio_attach(struct device
*, struct device
*, void *);
65 static int opio_search(struct device
*, struct cfdata
*,
67 static int opio_print(void *, const char *);
69 static int opio_intr( void *arg
);
70 static void opio_debounce(void *arg
);
74 /* attach structures */
75 CFATTACH_DECL(opio
, sizeof(struct opio_softc
), opio_match
, opio_attach
,
79 * int opio_print(void *aux, const char *name)
80 * print configuration info for children
84 opio_print(void *aux
, const char *name
)
86 struct obio_attach_args
*oba
= (struct obio_attach_args
*)aux
;
88 if (oba
->oba_addr
!= OPIOCF_ADDR_DEFAULT
)
89 aprint_normal(" addr 0x%lx", oba
->oba_addr
);
94 opio_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
96 struct obio_softc
*psc
= (struct obio_softc
*)parent
;
99 optid
= bus_space_read_2(psc
->sc_iot
, psc
->sc_obioreg_ioh
,
102 return optid
== 0x01;
106 opio_attach(struct device
*parent
, struct device
*self
, void *aux
)
108 struct opio_softc
*sc
= (struct opio_softc
*)self
;
109 struct obio_softc
*bsc
= (struct obio_softc
*)parent
;
110 struct obio_attach_args
*oba
= aux
;
114 bus_space_handle_t memctl_ioh
= bsc
->sc_memctl_ioh
;
118 sc
->sc_memctl_ioh
= memctl_ioh
;
120 /* use 16bit access for CS4, 32bit for CS5 */
121 reg
= bus_space_read_4(iot
, memctl_ioh
, MEMCTL_MSC2
);
123 reg
&= ~(MSC_RBW
<<16);
124 /* XXX: set access timing */
125 bus_space_write_4(iot
, memctl_ioh
, MEMCTL_MSC2
, reg
);
127 /* Set alternative function for GPIO pings 48..57 on PXA2X0 */
129 reg
= bus_space_read_4(iot
, csc
->saip
.sc_gpioh
, GPIO_GPDR1
);
130 bus_space_write_4(iot
, csc
->saip
.sc_gpioh
, GPIO_GPDR1
,
131 (reg
& ~0x03ff0000) | 0x00ff0000);
132 reg
= bus_space_read_4(iot
, csc
->saip
.sc_gpioh
, GPIO_GAFR1_U
);
133 bus_space_write_4(iot
, csc
->saip
.sc_gpioh
, GPIO_GAFR1_U
,
134 (reg
& ~0x000fffff) | 0x0005aaaa );
136 for (i
=47; i
<= 55; ++i
)
137 pxa2x0_gpio_set_function(i
, GPIO_ALT_FN_2_OUT
);
138 pxa2x0_gpio_set_function(56, GPIO_ALT_FN_1_IN
);
139 pxa2x0_gpio_set_function(57, GPIO_ALT_FN_1_IN
);
142 /* Enable bus switch for option board */
143 reg
= bus_space_read_2(iot
, bsc
->sc_obioreg_ioh
, G42XXEB_EXTCTRL
);
144 bus_space_write_2(iot
, bsc
->sc_obioreg_ioh
, G42XXEB_EXTCTRL
, reg
| 3);
146 /* Map on-board FPGA registers */
147 if( bus_space_map( iot
, GB225_PLDREG_BASE
, GB225_PLDREG_SIZE
,
148 0, &(sc
->sc_ioh
) ) ){
149 aprint_error("%s: can't map FPGA registers\n", self
->dv_xname
);
154 callout_init(&sc
->sc_callout
, 0);
156 for (i
=0; i
< N_OPIO_INTR
; ++i
) {
157 sc
->sc_intr
[i
].func
= NULL
;
158 sc
->sc_intr
[i
].reported_state
= 0xff;
159 sc
->sc_intr
[i
].last_state
= 0xff;
163 sc
->sc_ih
= obio_intr_establish(bsc
, OPIO_INTR
, IPL_BIO
,
164 IST_EDGE_FALLING
, opio_intr
, sc
);
168 printf("%s: CF_DET=%x PCMCIA_DET=%x\n",
170 bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, GB225_CFDET
),
171 bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, GB225_PCMCIADET
));
175 * Attach each devices
177 config_search_ia(opio_search
, self
, "opio", NULL
);
181 opio_search(struct device
*parent
, struct cfdata
*cf
,
182 const int *ldesc
, void *aux
)
184 struct opio_softc
*sc
= (struct opio_softc
*)parent
;
185 struct obio_attach_args oba
;
188 oba
.oba_iot
= sc
->sc_iot
;
189 oba
.oba_addr
= cf
->cf_loc
[OPIOCF_ADDR
];
190 oba
.oba_intr
= cf
->cf_loc
[OPIOCF_INTR
];
192 if (config_match(parent
, cf
, &oba
) > 0)
193 config_attach(parent
, cf
, &oba
, opio_print
);
199 opio_intr_establish(struct opio_softc
*sc
, int intr
, int ipl
,
200 int (*func
)(void *, int), void *arg
)
202 sc
->sc_intr
[intr
].arg
= arg
;
203 sc
->sc_intr
[intr
].func
= func
;
205 return &sc
->sc_intr
[intr
];
211 * interrupt handler for option board. interrupt sources are:
212 * CF card insertion/removal.
213 * PCMCIA card insertion/removal.
215 * CF/PCMCIA power failure.
216 * We need to debounce for CF/PCMCIA card insertion/removal signal.
219 opio_intr( void *arg
)
221 struct opio_softc
*sc
= (struct opio_softc
*)arg
;
222 struct obio_softc
*bsc
=
223 (struct obio_softc
*)device_parent(&sc
->sc_dev
);
225 /* avoid further interrupts while debouncing */
226 obio_intr_mask(bsc
, sc
->sc_ih
);
230 if (sc
->sc_debounce
== ST_STABLE
) {
231 /* start debounce timer */
232 callout_reset(&sc
->sc_callout
, DEBOUNCE_TICKS
,
234 sc
->sc_debounce
= ST_BOUNCING
;
242 do_debounce(struct opio_softc
*sc
, int intr
, int val
, int count
)
247 struct opio_intr_handler
*p
= &sc
->sc_intr
[intr
];
249 if (p
->last_state
!= val
) {
250 p
->debounce_count
= 0;
254 else if (p
->debounce_count
++ < count
)
257 /* debounce done. if status has changed, report it */
258 if (p
->reported_state
!= val
) {
259 p
->reported_state
= val
;
261 s
= _splraise(p
->level
);
262 p
->func(p
->arg
, val
);
272 opio_debounce(void *arg
)
274 struct opio_softc
*sc
= arg
;
275 struct obio_softc
*osc
=
276 (struct obio_softc
*)device_parent(&sc
->sc_dev
);
277 bus_space_tag_t iot
= sc
->sc_iot
;
278 bus_space_handle_t ioh
= sc
->sc_ioh
;
282 reg
= bus_space_read_1(iot
, ioh
, GB225_CFDET
) & CARDDET_DET
;
283 flag
|= do_debounce(sc
, OPIO_INTR_CF_INSERT
, reg
, DEBOUNCE_COUNT
);
285 reg
= bus_space_read_1(iot
, ioh
, GB225_PCMCIADET
) & CARDDET_DET
;
286 flag
|= do_debounce(sc
, OPIO_INTR_PCMCIA_INSERT
, reg
, DEBOUNCE_COUNT
);
288 reg
= bus_space_read_1(iot
, ioh
, GB225_DEVERROR
);
290 flag
|= do_debounce(sc
, OPIO_INTR_USB_POWER
, reg
& DEVERROR_USB
, 1);
292 flag
|= do_debounce(sc
, OPIO_INTR_CARD_POWER
, reg
& DEVERROR_CARD
, 1);
296 /* start debounce timer */
297 callout_reset(&sc
->sc_callout
, DEBOUNCE_TICKS
,
301 sc
->sc_debounce
= ST_STABLE
;
302 obio_intr_unmask(osc
, sc
->sc_ih
);