xref: /netbsd-src/sys/arch/hpcmips/vr/vrecu.c (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
1 /* $NetBSD: vrecu.c,v 1.6 2005/12/11 12:17:34 christos Exp $ */
2 
3 /*
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Naoto Shimazaki of YOKOGAWA Electric Corporation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: vrecu.c,v 1.6 2005/12/11 12:17:34 christos Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/device.h>
44 #include <sys/malloc.h>
45 #include <sys/queue.h>
46 #include <sys/systm.h>
47 
48 #include <machine/bus.h>
49 #include <machine/intr.h>
50 
51 #include <hpcmips/vr/vrcpudef.h>
52 #include <hpcmips/vr/vripif.h>
53 #include <hpcmips/vr/vr4181ecureg.h>
54 
55 #include <dev/isa/isareg.h>
56 #include <dev/isa/isavar.h>
57 #include <dev/pcmcia/pcmciareg.h>
58 #include <dev/pcmcia/pcmciavar.h>
59 #include <dev/pcmcia/pcmciachip.h>
60 
61 #include <dev/ic/i82365reg.h>
62 #include <dev/ic/i82365var.h>
63 #include <dev/isa/i82365_isavar.h>
64 
65 static int pcic_vrip_match(struct device *, struct cfdata *, void *);
66 static void pcic_vrip_attach(struct device *, struct device *, void *);
67 static void *pcic_vrip_chip_intr_establish(pcmcia_chipset_handle_t,
68 					   struct pcmcia_function *, int,
69 					   int (*)(void *), void *);
70 static void pcic_vrip_chip_intr_disestablish(pcmcia_chipset_handle_t, void *);
71 static int pcic_vrip_intr(void *);
72 
73 struct pcic_vrip_softc {
74 	struct pcic_softc	sc_pcic;	/* real pcic softc */
75 	u_int16_t		sc_intr_mask;
76 	u_int16_t		sc_intr_valid;
77 	struct intrhand {
78 		int	(*ih_fun)(void *);
79 		void	*ih_arg;
80 	} 			sc_intrhand[ECU_MAX_INTR];
81 };
82 
83 CFATTACH_DECL(pcic_vrip, sizeof(struct pcic_vrip_softc),
84 	      pcic_vrip_match, pcic_vrip_attach, NULL, NULL);
85 
86 static struct pcmcia_chip_functions pcic_vrip_functions = {
87 	.mem_alloc		= pcic_chip_mem_alloc,
88 	.mem_free		= pcic_chip_mem_free,
89 	.mem_map		= pcic_chip_mem_map,
90 	.mem_unmap		= pcic_chip_mem_unmap,
91 
92 	.io_alloc		= pcic_chip_io_alloc,
93 	.io_free		= pcic_chip_io_free,
94 	.io_map			= pcic_chip_io_map,
95 	.io_unmap		= pcic_chip_io_unmap,
96 
97 	.intr_establish		= pcic_vrip_chip_intr_establish,
98 	.intr_disestablish	= pcic_vrip_chip_intr_disestablish,
99 
100 	.socket_enable		= pcic_chip_socket_enable,
101 	.socket_disable		= pcic_chip_socket_disable,
102 	.socket_settype		= pcic_chip_socket_settype,
103 };
104 
105 
106 static int
107 pcic_vrip_match(struct device *parent, struct cfdata *match, void *aux)
108 {
109 	return 1;
110 }
111 
112 static void
113 pcic_vrip_attach(struct device *parent, struct device *self, void *aux)
114 {
115 	struct pcic_softc	*sc = (void *) self;
116 	struct pcic_vrip_softc	*vsc = (void *) self;
117 	struct vrip_attach_args	*va = aux;
118 	bus_space_handle_t	ioh;
119 	bus_space_handle_t	memh;
120 	int			i;
121 
122 	vsc->sc_intr_valid = PCIC_INTR_IRQ_VALIDMASK;
123 	vsc->sc_intr_mask = 0xffff;
124 	for (i = 0; i < ECU_MAX_INTR; i++)
125 		vsc->sc_intrhand[i].ih_fun = NULL;
126 
127 	if ((sc->ih = vrip_intr_establish(va->va_vc, va->va_unit, 0,
128 					  IPL_NET, pcic_vrip_intr, sc))
129 	    == NULL) {
130 		printf("%s: can't establish interrupt", sc->dev.dv_xname);
131 	}
132 
133         /* Map i/o space. */
134         if (bus_space_map(va->va_iot, va->va_addr, ECU_SIZE, 0, &ioh)) {
135                 printf(": can't map pcic register space\n");
136                 return;
137         }
138 
139 	/* init CFG_REG_1 */
140 	bus_space_write_2(va->va_iot, ioh, ECU_CFG_REG_1_W, 0x0001);
141 
142 	/* mask all interrupt */
143 	bus_space_write_2(va->va_iot, ioh, ECU_INTMSK_REG_W,
144 			  vsc->sc_intr_mask);
145 
146 	/* Map mem space. */
147 #if 1
148 	if (bus_space_map(va->va_iot, VR_ISA_MEM_BASE, 0x4000, 0, &memh))
149 		panic("pcic_pci_attach: can't map mem space");
150 
151 	sc->membase = VR_ISA_MEM_BASE;
152 	sc->subregionmask = (1 << (0x4000 / PCIC_MEM_PAGESIZE)) - 1;
153 
154 	sc->iobase = VR_ISA_PORT_BASE + 0x400;
155 	sc->iosize = 0xbff;
156 #else
157 	if (bus_space_map(va->va_iot, VR_ISA_MEM_BASE, 0x70000, 0, &memh))
158 		panic("pcic_pci_attach: can't map mem space");
159 
160 	sc->membase = VR_ISA_MEM_BASE;
161 	sc->subregionmask = (1 << (0x70000 / PCIC_MEM_PAGESIZE)) - 1;
162 
163 	sc->iobase = VR_ISA_PORT_BASE;
164 	sc->iosize = 0x10000;
165 #endif
166 
167 	sc->pct = &pcic_vrip_functions;
168 
169 	sc->iot = va->va_iot;
170 	sc->ioh = ioh;
171 	sc->memt = va->va_iot;
172 	sc->memh = memh;
173 
174 	printf("\n");
175 
176 	sc->irq = -1;
177 
178 	pcic_attach(sc);
179 	pcic_attach_sockets(sc);
180         pcic_attach_sockets_finish(sc);
181 }
182 
183 static void *
184 pcic_vrip_chip_intr_establish(pcmcia_chipset_handle_t pch,
185 			      struct pcmcia_function *pf,
186 			      int ipl,
187 			      int (*ih_fun)(void *),
188 			      void *ih_arg)
189 {
190 	struct pcic_handle	*h;
191 	struct pcic_softc	*sc;
192 	struct pcic_vrip_softc	*vsc;
193 	struct intrhand		*ih;
194 
195 	int	irq;
196 	int	r;
197 
198 
199 	/*
200 	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX
201 	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX
202 	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX
203 	 */
204 	irq = 11;
205 	/*
206 	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX
207 	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX
208 	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX
209 	 */
210 
211 
212 	h = (struct pcic_handle *) pch;
213 	sc = (struct pcic_softc *) h->ph_parent;
214 	vsc = (struct pcic_vrip_softc *) h->ph_parent;
215 
216 
217 	ih = &vsc->sc_intrhand[irq];
218 	if (ih->ih_fun) /* cannot share ecu interrupt */
219 		return NULL;
220 	ih->ih_fun = ih_fun;
221 	ih->ih_arg = ih_arg;
222 
223 	h->ih_irq = irq;
224 	if (h->flags & PCIC_FLAG_ENABLED) {
225 		r = pcic_read(h, PCIC_INTR);
226 		r &= ~PCIC_INTR_IRQ_MASK;
227 		pcic_write(h, PCIC_INTR, r | irq);
228         }
229 
230 	vsc->sc_intr_mask &= ~(1 << irq);
231 	bus_space_write_2(sc->iot, sc->ioh, ECU_INTMSK_REG_W,
232 			  vsc->sc_intr_mask);
233 
234 	return ih;
235 }
236 
237 static void
238 pcic_vrip_chip_intr_disestablish(pcmcia_chipset_handle_t pch, void *arg)
239 {
240 	struct pcic_handle	*h;
241 	struct pcic_softc	*sc;
242 	struct pcic_vrip_softc	*vsc;
243 	struct intrhand		*ih = arg;
244 
245 	int	s;
246 	int	r;
247 
248 	h = (struct pcic_handle *) pch;
249 	sc = (struct pcic_softc *) h->ph_parent;
250 	vsc = (struct pcic_vrip_softc *) h->ph_parent;
251 
252 	if (ih != &vsc->sc_intrhand[h->ih_irq])
253 		panic("pcic_vrip_chip_intr_disestablish: bad handler");
254 
255 	s = splhigh();
256 
257 	vsc->sc_intr_mask |= 1 << h->ih_irq;
258 	bus_space_write_2(sc->iot, sc->ioh, ECU_INTMSK_REG_W,
259 			  vsc->sc_intr_mask);
260 
261 	h->ih_irq = 0;
262 	if (h->flags & PCIC_FLAG_ENABLED) {
263 		r = pcic_read(h, PCIC_INTR);
264 		r &= ~(PCIC_INTR_IRQ_MASK | PCIC_INTR_ENABLE);
265 		pcic_write(h, PCIC_INTR, r);
266         }
267 
268 	ih->ih_fun = NULL;
269 	ih->ih_arg = NULL;
270 
271 	splx(s);
272 }
273 
274 /*
275  * interrupt handler
276  */
277 static int
278 pcic_vrip_intr(void *arg)
279 {
280 	struct pcic_softc	*sc = arg;
281 	struct pcic_vrip_softc	*vsc = arg;
282 	int			i;
283 	u_int16_t		r;
284 
285 	r = bus_space_read_2(sc->iot, sc->ioh, ECU_INTSTAT_REG_W)
286 		& ~vsc->sc_intr_mask;
287 
288 	for (i = 0; i < ECU_MAX_INTR; i++) {
289 		struct intrhand	*ih = &vsc->sc_intrhand[i];
290 		if (ih->ih_fun && (r & (1 << i)))
291 			ih->ih_fun(ih->ih_arg);
292 	}
293 	return 1;
294 }
295