]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/powerpc/powerpc/openpic.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / powerpc / powerpc / openpic.c
1 /*-
2  * Copyright (C) 2002 Benno Rice.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
14  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * $FreeBSD$
26  */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/bus.h>
31 #include <sys/conf.h>
32 #include <sys/kernel.h>
33 #include <sys/rman.h>
34
35 #include <machine/bus.h>
36 #include <machine/intr.h>
37 #include <machine/intr_machdep.h>
38 #include <machine/md_var.h>
39 #include <machine/pio.h>
40 #include <machine/resource.h>
41
42 #include <vm/vm.h>
43 #include <vm/pmap.h>
44
45 #include <machine/openpicreg.h>
46 #include <machine/openpicvar.h>
47
48 #include "pic_if.h"
49
50 devclass_t openpic_devclass;
51
52 /*
53  * Local routines
54  */
55
56 static __inline uint32_t
57 openpic_read(struct openpic_softc *sc, u_int reg)
58 {
59         return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg));
60 }
61
62 static __inline void
63 openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val)
64 {
65         bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val);
66 }
67
68 static __inline void
69 openpic_set_priority(struct openpic_softc *sc, int cpu, int pri)
70 {
71         uint32_t x;
72
73         x = openpic_read(sc, OPENPIC_CPU_PRIORITY(cpu));
74         x &= ~OPENPIC_CPU_PRIORITY_MASK;
75         x |= pri;
76         openpic_write(sc, OPENPIC_CPU_PRIORITY(cpu), x);
77 }
78
79 int
80 openpic_attach(device_t dev)
81 {
82         struct openpic_softc *sc;
83         u_int     irq;
84         u_int32_t x;
85
86         sc = device_get_softc(dev);
87         sc->sc_dev = dev;
88
89         sc->sc_rid = 0;
90         sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
91             RF_ACTIVE);
92
93         if (sc->sc_memr == NULL) {
94                 device_printf(dev, "Could not alloc mem resource!\n");
95                 return (ENXIO);
96         }
97
98         sc->sc_bt = rman_get_bustag(sc->sc_memr);
99         sc->sc_bh = rman_get_bushandle(sc->sc_memr);
100
101         x = openpic_read(sc, OPENPIC_FEATURE);
102         switch (x & OPENPIC_FEATURE_VERSION_MASK) {
103         case 1:
104                 sc->sc_version = "1.0";
105                 break;
106         case 2:
107                 sc->sc_version = "1.2";
108                 break;
109         case 3:
110                 sc->sc_version = "1.3";
111                 break;
112         default:
113                 sc->sc_version = "unknown";
114                 break;
115         }
116
117         sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >>
118             OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1;
119         sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >>
120             OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1;
121
122         /*
123          * PSIM seems to report 1 too many IRQs
124          */
125         if (sc->sc_psim)
126                 sc->sc_nirq--;
127
128         if (bootverbose)
129                 device_printf(dev,
130                     "Version %s, supports %d CPUs and %d irqs\n",
131                     sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
132
133         /* disable all interrupts */
134         for (irq = 0; irq < sc->sc_nirq; irq++)
135                 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
136
137         openpic_set_priority(sc, 0, 15);
138
139         /* we don't need 8259 passthrough mode */
140         x = openpic_read(sc, OPENPIC_CONFIG);
141         x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
142         openpic_write(sc, OPENPIC_CONFIG, x);
143
144         /* send all interrupts to cpu 0 */
145         for (irq = 0; irq < sc->sc_nirq; irq++)
146                 openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
147
148         for (irq = 0; irq < sc->sc_nirq; irq++) {
149                 x = irq;                /* irq == vector. */
150                 x |= OPENPIC_IMASK;
151                 x |= OPENPIC_POLARITY_POSITIVE;
152                 x |= OPENPIC_SENSE_LEVEL;
153                 x |= 8 << OPENPIC_PRIORITY_SHIFT;
154                 openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
155         }
156
157         /* XXX IPI */
158         /* XXX set spurious intr vector */
159
160         openpic_set_priority(sc, 0, 0);
161
162         /* clear all pending interrupts */
163         for (irq = 0; irq < sc->sc_nirq; irq++) {
164                 (void)openpic_read(sc, OPENPIC_IACK(0));
165                 openpic_write(sc, OPENPIC_EOI(0), 0);
166         }
167
168         powerpc_register_pic(dev);
169
170         return (0);
171 }
172
173 /*
174  * PIC I/F methods
175  */
176
177 void
178 openpic_dispatch(device_t dev, struct trapframe *tf)
179 {
180         struct openpic_softc *sc;
181         u_int vector;
182
183         sc = device_get_softc(dev);
184         while (1) {
185                 vector = openpic_read(sc, OPENPIC_IACK(0));
186                 vector &= OPENPIC_VECTOR_MASK;
187                 if (vector == 255)
188                         break;
189                 powerpc_dispatch_intr(vector, tf);
190         }
191 }
192
193 void
194 openpic_enable(device_t dev, u_int irq, u_int vector)
195 {
196         struct openpic_softc *sc;
197         uint32_t x;
198
199         sc = device_get_softc(dev);
200         x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
201         x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
202         x |= vector;
203         openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
204 }
205
206 void
207 openpic_eoi(device_t dev, u_int irq __unused)
208 {
209         struct openpic_softc *sc;
210
211         sc = device_get_softc(dev);
212         openpic_write(sc, OPENPIC_EOI(0), 0);
213 }
214
215 void
216 openpic_mask(device_t dev, u_int irq)
217 {
218         struct openpic_softc *sc;
219         uint32_t x;
220
221         sc = device_get_softc(dev);
222         x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
223         x |= OPENPIC_IMASK;
224         openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
225         openpic_write(sc, OPENPIC_EOI(0), 0);
226 }
227
228 void
229 openpic_unmask(device_t dev, u_int irq)
230 {
231         struct openpic_softc *sc;
232         uint32_t x;
233
234         sc = device_get_softc(dev);
235         x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
236         x &= ~OPENPIC_IMASK;
237         openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
238 }