Deleted Added
sdiff udiff text old ( 140304 ) new ( 140308 )
full compact
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: head/sys/arm/xscale/i80321/iq80321.c 140308 2005-01-15 18:55:22Z cognet $");
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#define __RMAN_RESOURCE_VISIBLE
55#include <sys/rman.h>
56#include <machine/bus.h>
57#include <machine/intr.h>
58
59#include <arm/xscale/i80321/i80321reg.h>
60#include <arm/xscale/i80321/i80321var.h>
61#include <arm/xscale/i80321/iq80321reg.h>
62#include <arm/xscale/i80321/iq80321var.h>
63#include <arm/xscale/i80321/i80321_intr.h>
64
65#include <dev/pci/pcireg.h>
66
67
68int iq80321_probe(device_t);
69void iq80321_identify(driver_t *, device_t);
70int iq80321_attach(device_t);
71
72int
73iq80321_probe(device_t dev)
74{
75 device_set_desc(dev, "Intel 80321");
76 return (0);
77}
78
79void
80iq80321_identify(driver_t *driver, device_t parent)
81{
82
83 BUS_ADD_CHILD(parent, 0, "iq", 0);
84}
85
86static struct arm32_dma_range i80321_dr;
87static int dma_range_init = 0;
88
89struct arm32_dma_range *
90bus_dma_get_range(void)
91{
92 if (dma_range_init == 0)
93 return (NULL);
94 return (&i80321_dr);
95}
96
97int
98bus_dma_get_range_nb(void)
99{
100 if (dma_range_init == 0)
101 return (0);
102 return (1);
103}
104
105#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
106#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
107void pmap_kenter(vm_offset_t, vm_offset_t);
108int
109iq80321_attach(device_t dev)
110{
111 struct i80321_softc *sc = device_get_softc(dev);
112 int b0u, b0l, b1u, b1l;
113 vm_paddr_t memstart = 0;
114 vm_size_t memsize = 0;
115 int busno;
116
117 /*
118 * Fill in the space tag for the i80321's own devices,
119 * and hand-craft the space handle for it (the device
120 * was mapped during early bootstrap).
121 */
122 i80321_bs_init(&i80321_bs_tag, sc);
123 sc->sc_st = &i80321_bs_tag;
124 sc->sc_sh = IQ80321_80321_VBASE;
125 sc->dev = dev;
126 sc->sc_is_host = 1;
127
128 /*
129 * Slice off a subregion for the Memory Controller -- we need it
130 * here in order read the memory size.
131 */
132 if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
133 VERDE_MCU_SIZE, &sc->sc_mcu_sh))
134 panic("%s: unable to subregion MCU registers",
135 device_get_name(dev));
136
137 if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
138 VERDE_ATU_SIZE, &sc->sc_atu_sh))
139 panic("%s: unable to subregion ATU registers",
140 device_get_name(dev));
141
142 /*
143 * We have mapped the the PCI I/O windows in the early
144 * bootstrap phase.
145 */
146 sc->sc_iow_vaddr = IQ80321_IOW_VBASE;
147
148 /*
149 * Check the configuration of the ATU to see if another BIOS
150 * has configured us. If a PC BIOS didn't configure us, then:
151 * IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
152 * IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
153 * If a BIOS has configured us, at least one of those should be
154 * different. This is pretty fragile, but it's not clear what
155 * would work better.
156 */
157 b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0x0);
158 b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0x4);
159 b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0x8);
160 b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_MAPS+0xc);
161#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
162 b0l &= PCI_MAPREG_MEM_ADDR_MASK;
163 b0u &= PCI_MAPREG_MEM_ADDR_MASK;
164 b1l &= PCI_MAPREG_MEM_ADDR_MASK;
165 b1u &= PCI_MAPREG_MEM_ADDR_MASK;
166
167 if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
168 sc->sc_is_host = 0;
169 else
170 sc->sc_is_host = 1;
171 i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
172 /*
173 * We set up the Inbound Windows as follows:
174 *
175 * 0 Access to i80321 PMMRs
176 *
177 * 1 Reserve space for private devices
178 *
179 * 2 RAM access
180 *
181 * 3 Unused.
182 *
183 * This chunk needs to be customized for each IOP321 application.
184 */
185#if 0
186 sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
187 sc->sc_iwin[0].iwin_base_hi = 0;
188 sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
189 sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
190#endif
191 if (sc->sc_is_host) {
192
193 /* Map PCI:Local 1:1. */
194 sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
195 PCI_MAPREG_MEM_PREFETCHABLE_MASK |
196 PCI_MAPREG_MEM_TYPE_64BIT;
197 sc->sc_iwin[1].iwin_base_hi = 0;
198 } else {
199
200 sc->sc_iwin[1].iwin_base_lo = 0;
201 sc->sc_iwin[1].iwin_base_hi = 0;
202 }
203 sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
204 sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
205
206 if (sc->sc_is_host) {
207 sc->sc_iwin[2].iwin_base_lo = memstart |
208 PCI_MAPREG_MEM_PREFETCHABLE_MASK |
209 PCI_MAPREG_MEM_TYPE_64BIT;
210 sc->sc_iwin[2].iwin_base_hi = 0;
211 } else {
212 sc->sc_iwin[2].iwin_base_lo = 0;
213 sc->sc_iwin[2].iwin_base_hi = 0;
214 }
215 sc->sc_iwin[2].iwin_xlate = memstart;
216 sc->sc_iwin[2].iwin_size = memsize;
217
218 if (sc->sc_is_host) {
219 sc->sc_iwin[3].iwin_base_lo = 0 |
220 PCI_MAPREG_MEM_PREFETCHABLE_MASK |
221 PCI_MAPREG_MEM_TYPE_64BIT;
222 } else {
223 sc->sc_iwin[3].iwin_base_lo = 0;
224 }
225 sc->sc_iwin[3].iwin_base_hi = 0;
226 sc->sc_iwin[3].iwin_xlate = 0;
227 sc->sc_iwin[3].iwin_size = 0;
228
229 /*
230 * We set up the Outbound Windows as follows:
231 *
232 * 0 Access to private PCI space.
233 *
234 * 1 Unused.
235 */
236#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
237 sc->sc_owin[0].owin_xlate_lo =
238 PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
239 sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
240 /*
241 * Set the Secondary Outbound I/O window to map
242 * to PCI address 0 for all 64K of the I/O space.
243 */
244 sc->sc_ioout_xlate = 0;
245 i80321_attach(sc);
246 i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
247 i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
248 i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
249 dma_range_init = 1;
250 busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
251 busno = PCIXSR_BUSNO(busno);
252 if (busno == 0xff)
253 busno = 0;
254 device_add_child(dev, "obio", 0);
255 device_add_child(dev, "itimer", 0);
256 device_add_child(dev, "iopwdog", 0);
257 device_add_child(dev, "iqseg", 0);
258 device_add_child(dev, "pcib", busno);
259 bus_generic_probe(dev);
260 bus_generic_attach(dev);
261
262 return (0);
263}
264
265void
266arm_mask_irqs(int nb)
267{
268 intr_enabled &= ~nb;
269 i80321_set_intrmask();
270}
271
272void
273arm_unmask_irqs(int nb)
274{
275 intr_enabled |= nb;
276 i80321_set_intrmask();
277}
278
279void
280cpu_reset()
281{
282 (void) disable_interrupts(I32_bit|F32_bit);
283 *(__volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE +
284 ATU_PCSR) = PCSR_RIB | PCSR_RPB;
285 printf("Reset failed :'(\n");
286 for(;;);
287}
288
289static struct resource *
290iq80321_alloc_resource(device_t dev, device_t child, int type, int *rid,
291 u_long start, u_long end, u_long count, u_int flags)
292{
293 if (type == SYS_RES_IRQ) {
294 struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
295 res->r_start = start;
296 res->r_end = end;
297 return (res);
298 }
299 return (NULL);
300}
301
302static int
303iq80321_setup_intr(device_t dev, device_t child,
304 struct resource *ires, int flags, driver_intr_t *intr, void *arg,
305 void **cookiep)
306{
307 BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, intr, arg,
308 cookiep);
309 intr_enabled |= 1 << ires->r_start;
310 i80321_set_intrmask();
311
312 return (0);
313}
314static device_method_t iq80321_methods[] = {
315 DEVMETHOD(device_probe, iq80321_probe),
316 DEVMETHOD(device_attach, iq80321_attach),
317 DEVMETHOD(device_identify, iq80321_identify),
318 DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
319 DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
320 {0, 0},
321};
322
323static driver_t iq80321_driver = {
324 "iq",
325 iq80321_methods,
326 sizeof(struct i80321_softc),
327};
328static devclass_t iq80321_devclass;
329
330DRIVER_MODULE(iq, nexus, iq80321_driver, iq80321_devclass, 0, 0);