plumicu.c revision 1.3.6.2 1 1.3.6.2 bouyer /* $NetBSD: plumicu.c,v 1.3.6.2 2000/11/20 20:46:07 bouyer Exp $ */
2 1.3.6.2 bouyer
3 1.3.6.2 bouyer /*
4 1.3.6.2 bouyer * Copyright (c) 1999, 2000 by UCHIYAMA Yasushi
5 1.3.6.2 bouyer * All rights reserved.
6 1.3.6.2 bouyer *
7 1.3.6.2 bouyer * Redistribution and use in source and binary forms, with or without
8 1.3.6.2 bouyer * modification, are permitted provided that the following conditions
9 1.3.6.2 bouyer * are met:
10 1.3.6.2 bouyer * 1. Redistributions of source code must retain the above copyright
11 1.3.6.2 bouyer * notice, this list of conditions and the following disclaimer.
12 1.3.6.2 bouyer * 2. The name of the developer may NOT be used to endorse or promote products
13 1.3.6.2 bouyer * derived from this software without specific prior written permission.
14 1.3.6.2 bouyer *
15 1.3.6.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 1.3.6.2 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 1.3.6.2 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 1.3.6.2 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.3.6.2 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.3.6.2 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 1.3.6.2 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.3.6.2 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.3.6.2 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.3.6.2 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.3.6.2 bouyer * SUCH DAMAGE.
26 1.3.6.2 bouyer *
27 1.3.6.2 bouyer */
28 1.3.6.2 bouyer
29 1.3.6.2 bouyer #include "opt_tx39_debug.h"
30 1.3.6.2 bouyer
31 1.3.6.2 bouyer #include <sys/param.h>
32 1.3.6.2 bouyer #include <sys/systm.h>
33 1.3.6.2 bouyer #include <sys/device.h>
34 1.3.6.2 bouyer
35 1.3.6.2 bouyer #include <machine/bus.h>
36 1.3.6.2 bouyer #include <machine/intr.h>
37 1.3.6.2 bouyer
38 1.3.6.2 bouyer #include <hpcmips/tx/tx39var.h>
39 1.3.6.2 bouyer #include <hpcmips/dev/plumvar.h>
40 1.3.6.2 bouyer #include <hpcmips/dev/plumicuvar.h>
41 1.3.6.2 bouyer #include <hpcmips/dev/plumicureg.h>
42 1.3.6.2 bouyer
43 1.3.6.2 bouyer #ifdef PLUMICUDEBUG
44 1.3.6.2 bouyer #define DPRINTF(arg) printf arg
45 1.3.6.2 bouyer #else
46 1.3.6.2 bouyer #define DPRINTF(arg)
47 1.3.6.2 bouyer #endif
48 1.3.6.2 bouyer
49 1.3.6.2 bouyer int plumicu_match __P((struct device*, struct cfdata*, void*));
50 1.3.6.2 bouyer void plumicu_attach __P((struct device*, struct device*, void*));
51 1.3.6.2 bouyer int plumicu_intr __P((void*));
52 1.3.6.2 bouyer
53 1.3.6.2 bouyer __inline__ void plum_di __P((plum_chipset_tag_t));
54 1.3.6.2 bouyer __inline__ void plum_ei __P((plum_chipset_tag_t));
55 1.3.6.2 bouyer
56 1.3.6.2 bouyer const struct plum_intr_ctrl {
57 1.3.6.2 bouyer plumreg_t ic_ackpat1;
58 1.3.6.2 bouyer plumreg_t ic_ackpat2; int ic_ackreg2;
59 1.3.6.2 bouyer plumreg_t ic_ienpat; int ic_ienreg;
60 1.3.6.2 bouyer plumreg_t ic_senpat; int ic_senreg;
61 1.3.6.2 bouyer } pi_ctrl[PLUM_INTR_MAX] = {
62 1.3.6.2 bouyer [PLUM_INT_C1IO] = {PLUM_INT_INTSTA_PCCINT,
63 1.3.6.2 bouyer PLUM_INT_PCCINTS_C1IO, PLUM_INT_PCCINTS_REG,
64 1.3.6.2 bouyer PLUM_INT_PCCIEN_IENC1IO, PLUM_INT_PCCIEN_REG,
65 1.3.6.2 bouyer PLUM_INT_PCCIEN_SENC1IO, PLUM_INT_PCCIEN_REG
66 1.3.6.2 bouyer },
67 1.3.6.2 bouyer [PLUM_INT_C1RI] = {PLUM_INT_INTSTA_PCCINT,
68 1.3.6.2 bouyer PLUM_INT_PCCINTS_C1RI, PLUM_INT_PCCINTS_REG,
69 1.3.6.2 bouyer PLUM_INT_PCCIEN_IENC1RI, PLUM_INT_PCCIEN_REG,
70 1.3.6.2 bouyer PLUM_INT_PCCIEN_SENC1RI, PLUM_INT_PCCIEN_REG
71 1.3.6.2 bouyer },
72 1.3.6.2 bouyer [PLUM_INT_C1SC] = {PLUM_INT_INTSTA_C1SCINT, 0, 0, 0, 0, 0, 0},
73 1.3.6.2 bouyer [PLUM_INT_C2IO] = {PLUM_INT_INTSTA_PCCINT,
74 1.3.6.2 bouyer PLUM_INT_PCCINTS_C2IO, PLUM_INT_PCCINTS_REG,
75 1.3.6.2 bouyer PLUM_INT_PCCIEN_IENC2IO, PLUM_INT_PCCIEN_REG,
76 1.3.6.2 bouyer PLUM_INT_PCCIEN_SENC2IO, PLUM_INT_PCCIEN_REG
77 1.3.6.2 bouyer },
78 1.3.6.2 bouyer [PLUM_INT_C2RI] = {PLUM_INT_INTSTA_PCCINT,
79 1.3.6.2 bouyer PLUM_INT_PCCINTS_C2RI, PLUM_INT_PCCINTS_REG,
80 1.3.6.2 bouyer PLUM_INT_PCCIEN_IENC2RI, PLUM_INT_PCCIEN_REG,
81 1.3.6.2 bouyer PLUM_INT_PCCIEN_SENC2RI, PLUM_INT_PCCIEN_REG
82 1.3.6.2 bouyer },
83 1.3.6.2 bouyer [PLUM_INT_C2SC] = {PLUM_INT_INTSTA_C2SCINT, 0, 0, 0, 0, 0, 0},
84 1.3.6.2 bouyer [PLUM_INT_DISP] = {PLUM_INT_INTSTA_DISPINT, 0, 0, 0, 0, 0, 0},
85 1.3.6.2 bouyer [PLUM_INT_USB] = {PLUM_INT_INTSTA_USBINT,
86 1.3.6.2 bouyer 0, 0,
87 1.3.6.2 bouyer PLUM_INT_USBINTEN_IEN, PLUM_INT_USBINTEN_REG,
88 1.3.6.2 bouyer 0, 0
89 1.3.6.2 bouyer },
90 1.3.6.2 bouyer [PLUM_INT_USBWAKE] = {PLUM_INT_INTSTA_USBWAKE,
91 1.3.6.2 bouyer 0, 0,
92 1.3.6.2 bouyer PLUM_INT_USBINTEN_WIEN, PLUM_INT_USBINTEN_REG,
93 1.3.6.2 bouyer 0, 0
94 1.3.6.2 bouyer },
95 1.3.6.2 bouyer [PLUM_INT_SM] = {PLUM_INT_INTSTA_SMINT,
96 1.3.6.2 bouyer 0, 0,
97 1.3.6.2 bouyer PLUM_INT_SMIEN, PLUM_INT_SMIEN_REG,
98 1.3.6.2 bouyer 0, 0
99 1.3.6.2 bouyer },
100 1.3.6.2 bouyer [PLUM_INT_EXT5IO0] = {PLUM_INT_INTSTA_EXTINT,
101 1.3.6.2 bouyer PLUM_INT_EXTINTS_IO5INT0, PLUM_INT_EXTINTS_REG,
102 1.3.6.2 bouyer PLUM_INT_EXTIEN_IENIO5INT0, PLUM_INT_EXTIEN_REG,
103 1.3.6.2 bouyer PLUM_INT_EXTIEN_SENIO5INT0, PLUM_INT_EXTIEN_REG,
104 1.3.6.2 bouyer },
105 1.3.6.2 bouyer [PLUM_INT_EXT5IO1] = {PLUM_INT_INTSTA_EXTINT,
106 1.3.6.2 bouyer PLUM_INT_EXTINTS_IO5INT1, PLUM_INT_EXTINTS_REG,
107 1.3.6.2 bouyer PLUM_INT_EXTIEN_IENIO5INT1, PLUM_INT_EXTIEN_REG,
108 1.3.6.2 bouyer PLUM_INT_EXTIEN_SENIO5INT1, PLUM_INT_EXTIEN_REG,
109 1.3.6.2 bouyer },
110 1.3.6.2 bouyer [PLUM_INT_EXT5IO2] = {PLUM_INT_INTSTA_EXTINT,
111 1.3.6.2 bouyer PLUM_INT_EXTINTS_IO5INT2, PLUM_INT_EXTINTS_REG,
112 1.3.6.2 bouyer PLUM_INT_EXTIEN_IENIO5INT2, PLUM_INT_EXTIEN_REG,
113 1.3.6.2 bouyer PLUM_INT_EXTIEN_SENIO5INT2, PLUM_INT_EXTIEN_REG,
114 1.3.6.2 bouyer },
115 1.3.6.2 bouyer [PLUM_INT_EXT5IO3] = {PLUM_INT_INTSTA_EXTINT,
116 1.3.6.2 bouyer PLUM_INT_EXTINTS_IO5INT3, PLUM_INT_EXTINTS_REG,
117 1.3.6.2 bouyer PLUM_INT_EXTIEN_IENIO5INT0, PLUM_INT_EXTIEN_REG,
118 1.3.6.2 bouyer PLUM_INT_EXTIEN_SENIO5INT0, PLUM_INT_EXTIEN_REG,
119 1.3.6.2 bouyer },
120 1.3.6.2 bouyer [PLUM_INT_EXT3IO0] = {PLUM_INT_INTSTA_EXTINT,
121 1.3.6.2 bouyer PLUM_INT_EXTINTS_IO3INT0, PLUM_INT_EXTINTS_REG,
122 1.3.6.2 bouyer PLUM_INT_EXTIEN_IENIO3INT0, PLUM_INT_EXTIEN_REG,
123 1.3.6.2 bouyer PLUM_INT_EXTIEN_SENIO3INT0, PLUM_INT_EXTIEN_REG,
124 1.3.6.2 bouyer },
125 1.3.6.2 bouyer [PLUM_INT_EXT3IO1] = {PLUM_INT_INTSTA_EXTINT,
126 1.3.6.2 bouyer PLUM_INT_EXTINTS_IO3INT1, PLUM_INT_EXTINTS_REG,
127 1.3.6.2 bouyer PLUM_INT_EXTIEN_IENIO3INT1, PLUM_INT_EXTIEN_REG,
128 1.3.6.2 bouyer PLUM_INT_EXTIEN_SENIO3INT1, PLUM_INT_EXTIEN_REG,
129 1.3.6.2 bouyer }
130 1.3.6.2 bouyer };
131 1.3.6.2 bouyer
132 1.3.6.2 bouyer struct plum_intr_entry {
133 1.3.6.2 bouyer int pi_enabled;
134 1.3.6.2 bouyer int pi_line;
135 1.3.6.2 bouyer int (*pi_fun) __P((void*));
136 1.3.6.2 bouyer void *pi_arg;
137 1.3.6.2 bouyer const struct plum_intr_ctrl *pi_ctrl;
138 1.3.6.2 bouyer };
139 1.3.6.2 bouyer
140 1.3.6.2 bouyer struct plumicu_softc {
141 1.3.6.2 bouyer struct device sc_dev;
142 1.3.6.2 bouyer plum_chipset_tag_t sc_pc;
143 1.3.6.2 bouyer bus_space_tag_t sc_regt;
144 1.3.6.2 bouyer bus_space_handle_t sc_regh;
145 1.3.6.2 bouyer void *sc_ih;
146 1.3.6.2 bouyer int sc_enable_count;
147 1.3.6.2 bouyer struct plum_intr_entry sc_intr[PLUM_INTR_MAX];
148 1.3.6.2 bouyer };
149 1.3.6.2 bouyer
150 1.3.6.2 bouyer struct cfattach plumicu_ca = {
151 1.3.6.2 bouyer sizeof(struct plumicu_softc), plumicu_match, plumicu_attach
152 1.3.6.2 bouyer };
153 1.3.6.2 bouyer
154 1.3.6.2 bouyer #ifdef PLUMICUDEBUG
155 1.3.6.2 bouyer void plumicu_dump __P((struct plumicu_softc*));
156 1.3.6.2 bouyer #endif
157 1.3.6.2 bouyer
158 1.3.6.2 bouyer int
159 1.3.6.2 bouyer plumicu_match(parent, cf, aux)
160 1.3.6.2 bouyer struct device *parent;
161 1.3.6.2 bouyer struct cfdata *cf;
162 1.3.6.2 bouyer void *aux;
163 1.3.6.2 bouyer {
164 1.3.6.2 bouyer return (2); /* 1st attach group */
165 1.3.6.2 bouyer }
166 1.3.6.2 bouyer
167 1.3.6.2 bouyer void
168 1.3.6.2 bouyer plumicu_attach(parent, self, aux)
169 1.3.6.2 bouyer struct device *parent;
170 1.3.6.2 bouyer struct device *self;
171 1.3.6.2 bouyer void *aux;
172 1.3.6.2 bouyer {
173 1.3.6.2 bouyer struct plum_attach_args *pa = aux;
174 1.3.6.2 bouyer struct plumicu_softc *sc = (void*)self;
175 1.3.6.2 bouyer const struct plum_intr_ctrl *pic;
176 1.3.6.2 bouyer bus_space_tag_t regt;
177 1.3.6.2 bouyer bus_space_handle_t regh;
178 1.3.6.2 bouyer plumreg_t reg;
179 1.3.6.2 bouyer int i;
180 1.3.6.2 bouyer
181 1.3.6.2 bouyer sc->sc_pc = pa->pa_pc;
182 1.3.6.2 bouyer sc->sc_regt = pa->pa_regt;
183 1.3.6.2 bouyer
184 1.3.6.2 bouyer /* map plum2 interrupt controller register space */
185 1.3.6.2 bouyer if (bus_space_map(sc->sc_regt, PLUM_INT_REGBASE,
186 1.3.6.2 bouyer PLUM_INT_REGSIZE, 0, &sc->sc_regh)) {
187 1.3.6.2 bouyer printf(":interrupt register map failed\n");
188 1.3.6.2 bouyer return;
189 1.3.6.2 bouyer }
190 1.3.6.2 bouyer #ifdef PLUMICUDEBUG
191 1.3.6.2 bouyer plumicu_dump(sc);
192 1.3.6.2 bouyer #endif
193 1.3.6.2 bouyer /* disable all interrupt */
194 1.3.6.2 bouyer regt = sc->sc_regt;
195 1.3.6.2 bouyer regh = sc->sc_regh;
196 1.3.6.2 bouyer for (i = 0; i < PLUM_INTR_MAX; i++) {
197 1.3.6.2 bouyer pic = &pi_ctrl[i];
198 1.3.6.2 bouyer if (pic->ic_ienreg) {
199 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, pic->ic_ienreg);
200 1.3.6.2 bouyer reg &= ~pic->ic_ienpat;
201 1.3.6.2 bouyer plum_conf_write(regt, regh, pic->ic_ienreg, reg);
202 1.3.6.2 bouyer }
203 1.3.6.2 bouyer if (pic->ic_senreg) {
204 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, pic->ic_senreg);
205 1.3.6.2 bouyer reg &= ~pic->ic_senpat;
206 1.3.6.2 bouyer plum_conf_write(regt, regh, pic->ic_senreg, reg);
207 1.3.6.2 bouyer }
208 1.3.6.2 bouyer }
209 1.3.6.2 bouyer
210 1.3.6.2 bouyer /* register handle to plum_chipset_tag */
211 1.3.6.2 bouyer plum_conf_register_intr(sc->sc_pc, (void*)sc);
212 1.3.6.2 bouyer
213 1.3.6.2 bouyer /* disable interrupt redirect to TX39 core */
214 1.3.6.2 bouyer plum_di(sc->sc_pc);
215 1.3.6.2 bouyer
216 1.3.6.2 bouyer if (!(sc->sc_ih = tx_intr_establish(sc->sc_pc->pc_tc, pa->pa_irq,
217 1.3.6.2 bouyer IST_EDGE, IPL_BIO,
218 1.3.6.2 bouyer plumicu_intr, sc))) {
219 1.3.6.2 bouyer printf(": can't establish interrupt\n");
220 1.3.6.2 bouyer }
221 1.3.6.2 bouyer printf("\n");
222 1.3.6.2 bouyer }
223 1.3.6.2 bouyer
224 1.3.6.2 bouyer __inline__ void
225 1.3.6.2 bouyer plum_di(pc)
226 1.3.6.2 bouyer plum_chipset_tag_t pc;
227 1.3.6.2 bouyer {
228 1.3.6.2 bouyer struct plumicu_softc *sc = pc->pc_intrt;
229 1.3.6.2 bouyer
230 1.3.6.2 bouyer plum_conf_write(sc->sc_regt, sc->sc_regh, PLUM_INT_INTIEN_REG, 0);
231 1.3.6.2 bouyer }
232 1.3.6.2 bouyer
233 1.3.6.2 bouyer __inline__ void
234 1.3.6.2 bouyer plum_ei(pc)
235 1.3.6.2 bouyer plum_chipset_tag_t pc;
236 1.3.6.2 bouyer {
237 1.3.6.2 bouyer struct plumicu_softc *sc = pc->pc_intrt;
238 1.3.6.2 bouyer
239 1.3.6.2 bouyer plum_conf_write(sc->sc_regt, sc->sc_regh, PLUM_INT_INTIEN_REG,
240 1.3.6.2 bouyer PLUM_INT_INTIEN);
241 1.3.6.2 bouyer }
242 1.3.6.2 bouyer
243 1.3.6.2 bouyer void*
244 1.3.6.2 bouyer plum_intr_establish(pc, line, mode, level, ih_fun, ih_arg)
245 1.3.6.2 bouyer plum_chipset_tag_t pc;
246 1.3.6.2 bouyer int line;
247 1.3.6.2 bouyer int mode; /* no meaning */
248 1.3.6.2 bouyer int level; /* XXX not yet */
249 1.3.6.2 bouyer int (*ih_fun) __P((void*));
250 1.3.6.2 bouyer void *ih_arg;
251 1.3.6.2 bouyer {
252 1.3.6.2 bouyer struct plumicu_softc *sc = pc->pc_intrt;
253 1.3.6.2 bouyer bus_space_tag_t regt = sc->sc_regt;
254 1.3.6.2 bouyer bus_space_handle_t regh = sc->sc_regh;
255 1.3.6.2 bouyer plumreg_t reg;
256 1.3.6.2 bouyer struct plum_intr_entry *pi;
257 1.3.6.2 bouyer
258 1.3.6.2 bouyer if (!LEGAL_PRUM_INTR(line)) {
259 1.3.6.2 bouyer panic("plum_intr_establish: bogus interrupt line");
260 1.3.6.2 bouyer }
261 1.3.6.2 bouyer
262 1.3.6.2 bouyer pi = &sc->sc_intr[line];
263 1.3.6.2 bouyer pi->pi_line = line;
264 1.3.6.2 bouyer pi->pi_fun = ih_fun;
265 1.3.6.2 bouyer pi->pi_arg = ih_arg;
266 1.3.6.2 bouyer pi->pi_ctrl = &pi_ctrl[line];
267 1.3.6.2 bouyer
268 1.3.6.2 bouyer /* Enable interrupt */
269 1.3.6.2 bouyer
270 1.3.6.2 bouyer /* status enable */
271 1.3.6.2 bouyer if (pi->pi_ctrl->ic_senreg) {
272 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, pi->pi_ctrl->ic_senreg);
273 1.3.6.2 bouyer reg |= pi->pi_ctrl->ic_senpat;
274 1.3.6.2 bouyer plum_conf_write(regt, regh, pi->pi_ctrl->ic_senreg, reg);
275 1.3.6.2 bouyer }
276 1.3.6.2 bouyer /* interrupt enable */
277 1.3.6.2 bouyer if (pi->pi_ctrl->ic_ienreg) {
278 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, pi->pi_ctrl->ic_ienreg);
279 1.3.6.2 bouyer reg |= pi->pi_ctrl->ic_ienpat;
280 1.3.6.2 bouyer plum_conf_write(regt, regh, pi->pi_ctrl->ic_ienreg, reg);
281 1.3.6.2 bouyer }
282 1.3.6.2 bouyer
283 1.3.6.2 bouyer /* Enable redirect to TX39 core */
284 1.3.6.2 bouyer DPRINTF(("plum_intr_establish: %d (count=%d)\n", line,
285 1.3.6.2 bouyer sc->sc_enable_count));
286 1.3.6.2 bouyer
287 1.3.6.2 bouyer if (sc->sc_enable_count++ == 0)
288 1.3.6.2 bouyer plum_ei(pc);
289 1.3.6.2 bouyer
290 1.3.6.2 bouyer pi->pi_enabled = 1;
291 1.3.6.2 bouyer
292 1.3.6.2 bouyer return (ih_fun);
293 1.3.6.2 bouyer }
294 1.3.6.2 bouyer
295 1.3.6.2 bouyer void
296 1.3.6.2 bouyer plum_intr_disestablish(pc, arg)
297 1.3.6.2 bouyer plum_chipset_tag_t pc;
298 1.3.6.2 bouyer void *arg;
299 1.3.6.2 bouyer {
300 1.3.6.2 bouyer struct plumicu_softc *sc = pc->pc_intrt;
301 1.3.6.2 bouyer bus_space_tag_t regt = sc->sc_regt;
302 1.3.6.2 bouyer bus_space_handle_t regh = sc->sc_regh;
303 1.3.6.2 bouyer plumreg_t reg;
304 1.3.6.2 bouyer struct plum_intr_entry *pi;
305 1.3.6.2 bouyer int i;
306 1.3.6.2 bouyer
307 1.3.6.2 bouyer sc = pc->pc_intrt;
308 1.3.6.2 bouyer
309 1.3.6.2 bouyer for (i = 0; i < PLUM_INTR_MAX; i++) {
310 1.3.6.2 bouyer pi = &sc->sc_intr[i];
311 1.3.6.2 bouyer if (pi->pi_fun != arg)
312 1.3.6.2 bouyer continue;
313 1.3.6.2 bouyer DPRINTF(("plum_intr_disestablish: %d (count=%d)\n",
314 1.3.6.2 bouyer pi->pi_line, sc->sc_enable_count - 1));
315 1.3.6.2 bouyer goto found;
316 1.3.6.2 bouyer }
317 1.3.6.2 bouyer panic("plum_intr_disestablish: can't find entry.");
318 1.3.6.2 bouyer /* NOTREACHED */
319 1.3.6.2 bouyer found:
320 1.3.6.2 bouyer pi->pi_enabled = 0;
321 1.3.6.2 bouyer /* Disable interrupt */
322 1.3.6.2 bouyer if (pi->pi_ctrl->ic_ienreg) {
323 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, pi->pi_ctrl->ic_ienreg);
324 1.3.6.2 bouyer reg &= ~(pi->pi_ctrl->ic_ienpat);
325 1.3.6.2 bouyer plum_conf_write(regt, regh, pi->pi_ctrl->ic_ienreg, reg);
326 1.3.6.2 bouyer }
327 1.3.6.2 bouyer if (pi->pi_ctrl->ic_senreg) {
328 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, pi->pi_ctrl->ic_senreg);
329 1.3.6.2 bouyer reg &= ~(pi->pi_ctrl->ic_senpat);
330 1.3.6.2 bouyer plum_conf_write(regt, regh, pi->pi_ctrl->ic_senreg, reg);
331 1.3.6.2 bouyer }
332 1.3.6.2 bouyer
333 1.3.6.2 bouyer /* Disable/Enable interrupt redirect to TX39 core */
334 1.3.6.2 bouyer if (--sc->sc_enable_count == 0)
335 1.3.6.2 bouyer plum_di(pc);
336 1.3.6.2 bouyer }
337 1.3.6.2 bouyer
338 1.3.6.2 bouyer int
339 1.3.6.2 bouyer plumicu_intr(arg)
340 1.3.6.2 bouyer void *arg;
341 1.3.6.2 bouyer {
342 1.3.6.2 bouyer struct plumicu_softc *sc = arg;
343 1.3.6.2 bouyer bus_space_tag_t regt = sc->sc_regt;
344 1.3.6.2 bouyer bus_space_handle_t regh = sc->sc_regh;
345 1.3.6.2 bouyer plumreg_t reg1, reg2, reg_ext, reg_pccard;
346 1.3.6.2 bouyer int i;
347 1.3.6.2 bouyer
348 1.3.6.2 bouyer plum_di(sc->sc_pc);
349 1.3.6.2 bouyer /* read level 1 status */
350 1.3.6.2 bouyer reg1 = plum_conf_read(regt, regh, PLUM_INT_INTSTA_REG);
351 1.3.6.2 bouyer
352 1.3.6.2 bouyer /* read level 2 status and acknowledge */
353 1.3.6.2 bouyer reg_ext = plum_conf_read(regt, regh, PLUM_INT_EXTINTS_REG);
354 1.3.6.2 bouyer plum_conf_write(regt, regh, PLUM_INT_EXTINTS_REG, reg_ext);
355 1.3.6.2 bouyer
356 1.3.6.2 bouyer reg_pccard = plum_conf_read(regt, regh, PLUM_INT_PCCINTS_REG);
357 1.3.6.2 bouyer plum_conf_write(regt, regh, PLUM_INT_PCCINTS_REG, reg_pccard);
358 1.3.6.2 bouyer
359 1.3.6.2 bouyer for (i = 0; i < PLUM_INTR_MAX; i++) {
360 1.3.6.2 bouyer register struct plum_intr_entry *pi;
361 1.3.6.2 bouyer register const struct plum_intr_ctrl *pic = &pi_ctrl[i];
362 1.3.6.2 bouyer
363 1.3.6.2 bouyer if (!(pic->ic_ackpat1 & reg1))
364 1.3.6.2 bouyer continue;
365 1.3.6.2 bouyer
366 1.3.6.2 bouyer pi = &sc->sc_intr[i];
367 1.3.6.2 bouyer if (!pi->pi_enabled)
368 1.3.6.2 bouyer continue;
369 1.3.6.2 bouyer
370 1.3.6.2 bouyer if (pic->ic_ackreg2 == 0) {
371 1.3.6.2 bouyer (*pi->pi_fun)(pi->pi_arg);
372 1.3.6.2 bouyer continue;
373 1.3.6.2 bouyer }
374 1.3.6.2 bouyer
375 1.3.6.2 bouyer reg2 = pic->ic_ackreg2 == PLUM_INT_PCCINTS_REG
376 1.3.6.2 bouyer ? reg_pccard : reg_ext;
377 1.3.6.2 bouyer
378 1.3.6.2 bouyer if (pic->ic_ackpat2 & reg2)
379 1.3.6.2 bouyer (*pi->pi_fun)(pi->pi_arg);
380 1.3.6.2 bouyer }
381 1.3.6.2 bouyer plum_ei(sc->sc_pc);
382 1.3.6.2 bouyer
383 1.3.6.2 bouyer return (0);
384 1.3.6.2 bouyer }
385 1.3.6.2 bouyer
386 1.3.6.2 bouyer #ifdef PLUMICUDEBUG
387 1.3.6.2 bouyer void
388 1.3.6.2 bouyer plumicu_dump(sc)
389 1.3.6.2 bouyer struct plumicu_softc *sc;
390 1.3.6.2 bouyer {
391 1.3.6.2 bouyer bus_space_tag_t regt = sc->sc_regt;
392 1.3.6.2 bouyer bus_space_handle_t regh = sc->sc_regh;
393 1.3.6.2 bouyer plumreg_t reg;
394 1.3.6.2 bouyer
395 1.3.6.2 bouyer printf("status:");
396 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, PLUM_INT_INTSTA_REG);
397 1.3.6.2 bouyer bitdisp(reg);
398 1.3.6.2 bouyer printf("ExtIO\n");
399 1.3.6.2 bouyer printf("status:");
400 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, PLUM_INT_EXTINTS_REG);
401 1.3.6.2 bouyer bitdisp(reg);
402 1.3.6.2 bouyer printf("enable:");
403 1.3.6.2 bouyer reg = plum_conf_read(regt, regh, PLUM_INT_EXTIEN_REG);
404 1.3.6.2 bouyer bitdisp(reg);
405 1.3.6.2 bouyer
406 1.3.6.2 bouyer }
407 1.3.6.2 bouyer #endif /* PLUMICUDEBUG */
408