1 /* $NetBSD: i80321_mainbus.c,v 1.13 2003/12/17 22:03:24 abs Exp $ */
2
3 /*-
4 * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * IQ80321 front-end for the i80321 I/O Processor. We take care
40 * of setting up the i80321 memory map, PCI interrupt routing, etc.,
41 * which are all specific to the board the i80321 is wired up to.
42 */
43
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD: releng/9.2/sys/arm/xscale/i80321/iq80321.c 218909 2011-02-21 09:01:34Z brucec $");
46
47 #define _ARM32_BUS_DMA_PRIVATE
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/bus.h>
51 #include <sys/kernel.h>
52 #include <sys/module.h>
53 #include <sys/malloc.h>
54 #include <sys/rman.h>
55 #include <machine/bus.h>
56 #include <machine/intr.h>
57
58 #include <arm/xscale/i80321/i80321reg.h>
59 #include <arm/xscale/i80321/i80321var.h>
60 #include <arm/xscale/i80321/iq80321reg.h>
61 #include <arm/xscale/i80321/iq80321var.h>
62 #include <arm/xscale/i80321/i80321_intr.h>
63
64 #include <dev/pci/pcireg.h>
65
66
67 int iq80321_probe(device_t);
68 void iq80321_identify(driver_t *, device_t);
69 int iq80321_attach(device_t);
70
71 int
72 iq80321_probe(device_t dev)
73 {
74 device_set_desc(dev, "Intel 80321");
75 return (0);
76 }
77
78 void
79 iq80321_identify(driver_t *driver, device_t parent)
80 {
81
82 BUS_ADD_CHILD(parent, 0, "iq", 0);
83 }
84
85 static struct arm32_dma_range i80321_dr;
86 static int dma_range_init = 0;
87
88 struct arm32_dma_range *
89 bus_dma_get_range(void)
90 {
91 if (dma_range_init == 0)
92 return (NULL);
93 return (&i80321_dr);
94 }
95
96 int
97 bus_dma_get_range_nb(void)
98 {
99 if (dma_range_init == 0)
100 return (0);
101 return (1);
102 }
103
104 #define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
105 #define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
106
107 int
108 iq80321_attach(device_t dev)
109 {
110 struct i80321_softc *sc = device_get_softc(dev);
111 int b0u, b0l, b1u, b1l;
112 vm_paddr_t memstart = 0;
113 vm_size_t memsize = 0;
114 int busno;
115
116 /*
117 * Fill in the space tag for the i80321's own devices,
118 * and hand-craft the space handle for it (the device
119 * was mapped during early bootstrap).
120 */
121 i80321_bs_init(&i80321_bs_tag, sc);
122 sc->sc_st = &i80321_bs_tag;
123 sc->sc_sh = IQ80321_80321_VBASE;
124 sc->dev = dev;
125 sc->sc_is_host = 1;
126
127 /*
128 * Slice off a subregion for the Memory Controller -- we need it
129 * here in order read the memory size.
130 */
131 if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
132 VERDE_MCU_SIZE, &sc->sc_mcu_sh))
133 panic("%s: unable to subregion MCU registers",
134 device_get_name(dev));
135
136 if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
137 VERDE_ATU_SIZE, &sc->sc_atu_sh))
138 panic("%s: unable to subregion ATU registers",
139 device_get_name(dev));
140
141 /*
142 * We have mapped the PCI I/O windows in the early
143 * bootstrap phase.
144 */
145 sc->sc_iow_vaddr = IQ80321_IOW_VBASE;
146
147 /*
148 * Check the configuration of the ATU to see if another BIOS
149 * has configured us. If a PC BIOS didn't configure us, then:
150 * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
151 * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
152 * If a BIOS has configured us, at least one of those should be
153 * different. This is pretty fragile, but it's not clear what
154 * would work better.
155 */
156 b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
157 b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
158 b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
159 b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);
160
161 #ifdef VERBOSE_INIT_ARM
162 printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
163 b0l,b0u, b1l, b1u );
164 #endif
165
166 #define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
167 b0l &= PCI_MAPREG_MEM_ADDR_MASK;
168 b0u &= PCI_MAPREG_MEM_ADDR_MASK;
169 b1l &= PCI_MAPREG_MEM_ADDR_MASK;
170 b1u &= PCI_MAPREG_MEM_ADDR_MASK;
171
172 #ifdef VERBOSE_INIT_ARM
173 printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
174 b0l,b0u, b1l, b1u );
175 #endif
176
177 if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
178 sc->sc_is_host = 0;
179 else
180 sc->sc_is_host = 1;
181
182 /* FIXME: i force it's */
183
184 #ifdef CPU_XSCALE_80219
185 sc->sc_is_host = 1;
186 #endif
187
188 i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
189 /*
190 * We set up the Inbound Windows as follows:
191 *
192 * 0 Access to i80321 PMMRs
193 *
194 * 1 Reserve space for private devices
195 *
196 * 2 RAM access
197 *
198 * 3 Unused.
199 *
200 * This chunk needs to be customized for each IOP321 application.
201 */
202 #if 0
203 sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
204 sc->sc_iwin[0].iwin_base_hi = 0;
205 sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
206 sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
207 #endif
208 if (sc->sc_is_host) {
209
210 /* Map PCI:Local 1:1. */
211 sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
212 PCI_MAPREG_MEM_PREFETCHABLE_MASK |
213 PCI_MAPREG_MEM_TYPE_64BIT;
214 sc->sc_iwin[1].iwin_base_hi = 0;
215 } else {
216
217 sc->sc_iwin[1].iwin_base_lo = 0;
218 sc->sc_iwin[1].iwin_base_hi = 0;
219 }
220 sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
221 sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
222
223 if (sc->sc_is_host) {
224 sc->sc_iwin[2].iwin_base_lo = memstart |
225 PCI_MAPREG_MEM_PREFETCHABLE_MASK |
226 PCI_MAPREG_MEM_TYPE_64BIT;
227 sc->sc_iwin[2].iwin_base_hi = 0;
228 } else {
229 sc->sc_iwin[2].iwin_base_lo = 0;
230 sc->sc_iwin[2].iwin_base_hi = 0;
231 }
232 sc->sc_iwin[2].iwin_xlate = memstart;
233 sc->sc_iwin[2].iwin_size = memsize;
234
235 if (sc->sc_is_host) {
236 sc->sc_iwin[3].iwin_base_lo = 0 |
237 PCI_MAPREG_MEM_PREFETCHABLE_MASK |
238 PCI_MAPREG_MEM_TYPE_64BIT;
239 } else {
240 sc->sc_iwin[3].iwin_base_lo = 0;
241 }
242 sc->sc_iwin[3].iwin_base_hi = 0;
243 sc->sc_iwin[3].iwin_xlate = 0;
244 sc->sc_iwin[3].iwin_size = 0;
245
246 #ifdef VERBOSE_INIT_ARM
247 printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
248 sc->sc_iwin[1].iwin_base_hi,
249 sc->sc_iwin[1].iwin_base_lo,
250 sc->sc_iwin[1].iwin_xlate,
251 sc->sc_iwin[1].iwin_size
252 );
253 printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
254 sc->sc_iwin[2].iwin_base_hi,
255 sc->sc_iwin[2].iwin_base_lo,
256 sc->sc_iwin[2].iwin_xlate,
257 sc->sc_iwin[2].iwin_size
258 );
259 #endif
260
261 /*
262 * We set up the Outbound Windows as follows:
263 *
264 * 0 Access to private PCI space.
265 *
266 * 1 Unused.
267 */
268 #define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
269 sc->sc_owin[0].owin_xlate_lo =
270 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
271 sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
272 /*
273 * Set the Secondary Outbound I/O window to map
274 * to PCI address 0 for all 64K of the I/O space.
275 */
276 sc->sc_ioout_xlate = 0;
277 i80321_attach(sc);
278 i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
279 i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
280 i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
281 dma_range_init = 1;
282 busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
283 busno = PCIXSR_BUSNO(busno);
284 if (busno == 0xff)
285 busno = 0;
286 sc->sc_irq_rman.rm_type = RMAN_ARRAY;
287 sc->sc_irq_rman.rm_descr = "i80321 IRQs";
288 if (rman_init(&sc->sc_irq_rman) != 0 ||
289 rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
290 panic("i80321_attach: failed to set up IRQ rman");
291
292 device_add_child(dev, "obio", 0);
293 device_add_child(dev, "itimer", 0);
294 device_add_child(dev, "iopwdog", 0);
295 #ifndef CPU_XSCALE_80219
296 device_add_child(dev, "iqseg", 0);
297 #endif
298 device_add_child(dev, "pcib", busno);
299 device_add_child(dev, "i80321_dma", 0);
300 device_add_child(dev, "i80321_dma", 1);
301 #ifndef CPU_XSCALE_80219
302 device_add_child(dev, "i80321_aau", 0);
303 #endif
304 bus_generic_probe(dev);
305 bus_generic_attach(dev);
306
307 return (0);
308 }
309
310 void
311 arm_mask_irq(uintptr_t nb)
312 {
313 intr_enabled &= ~(1 << nb);
314 i80321_set_intrmask();
315 }
316
317 void
318 arm_unmask_irq(uintptr_t nb)
319 {
320 intr_enabled |= (1 << nb);
321 i80321_set_intrmask();
322 }
323
324
325 void
326 cpu_reset()
327 {
328 (void) disable_interrupts(I32_bit|F32_bit);
329 *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE +
330 ATU_PCSR) = PCSR_RIB | PCSR_RPB;
331 printf("Reset failed!\n");
332 for(;;);
333 }
334
335 static struct resource *
336 iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid,
337 u_long start, u_long end, u_long count, u_int flags)
338 {
339 struct i80321_softc *sc = device_get_softc(dev);
340 struct resource *rv;
341
342 if (type == SYS_RES_IRQ) {
343 rv = rman_reserve_resource(&sc->sc_irq_rman,
344 start, end, count, flags, child);
345 if (rv != NULL)
346 rman_set_rid(rv, *rid);
347 return (rv);
348 }
349 return (NULL);
350 }
351
352 static int
353 iq80321_setup_intr(device_t dev, device_t child,
354 struct resource *ires, int flags, driver_filter_t *filt,
355 driver_intr_t *intr, void *arg, void **cookiep)
356 {
357 BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, intr,
358 arg, cookiep);
359 intr_enabled |= 1 << rman_get_start(ires);
360 i80321_set_intrmask();
361
362 return (0);
363 }
364
365 static int
366 iq80321_teardown_intr(device_t dev, device_t child, struct resource *res,
367 void *cookie)
368 {
369 return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
370 }
371
372 static device_method_t iq80321_methods[] = {
373 DEVMETHOD(device_probe, iq80321_probe),
374 DEVMETHOD(device_attach, iq80321_attach),
375 DEVMETHOD(device_identify, iq80321_identify),
376 DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
377 DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
378 DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr),
379 {0, 0},
380 };
381
382 static driver_t iq80321_driver = {
383 "iq",
384 iq80321_methods,
385 sizeof(struct i80321_softc),
386 };
387 static devclass_t iq80321_devclass;
388
389 DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0);
Cache object: ee551aaaa5deb0e4afc51f582a8dc24f
|