FreeBSD/Linux Kernel Cross Reference
sys/mips/rmi/pcibus.c
1 /*-
2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
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 unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: releng/8.3/sys/mips/rmi/pcibus.c 223500 2011-06-24 13:41:46Z jhb $");
29
30 #include "opt_isa.h"
31
32 #define __RMAN_RESOURCE_VISIBLE
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/mutex.h>
38 #include <sys/module.h>
39 #include <sys/proc.h>
40 #include <sys/bus.h>
41
42 #include <vm/vm.h>
43 #include <vm/vm_param.h>
44 #include <vm/pmap.h>
45
46 #include <machine/bus.h>
47 #include <machine/pmap.h>
48 #include <sys/interrupt.h>
49 #include <sys/sysctl.h>
50 #include <mips/rmi/iomap.h>
51 #include <mips/rmi/pic.h>
52 #include <mips/rmi/shared_structs.h>
53 #include <mips/rmi/board.h>
54 #include <sys/rman.h>
55
56 #include <dev/pci/pcivar.h>
57 #include <machine/resource.h>
58 #include <machine/md_var.h>
59 #include <machine/intr_machdep.h>
60 #include <mips/rmi/pcibus.h>
61 /*
62 static void bridge_pcix_ack(void *);
63 static void bridge_pcie_ack(void *);
64 static void pic_pcix_ack(void *);
65 static void pic_pcie_ack(void *);
66 */
67
68 extern vm_map_t kernel_map;
69 vm_offset_t kmem_alloc_nofault(vm_map_t map, vm_size_t size);
70
71
72 int
73 mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
74 {
75 /*
76 * Validate requested pin number.
77 */
78 if ((pin < 1) || (pin > 4))
79 return (255);
80
81 if (xlr_board_info.is_xls) {
82 switch (pin) {
83 case 1:
84 return PIC_PCIE_LINK0_IRQ;
85 case 2:
86 return PIC_PCIE_LINK1_IRQ;
87 case 3:
88 return PIC_PCIE_LINK2_IRQ;
89 case 4:
90 return PIC_PCIE_LINK3_IRQ;
91 }
92 } else {
93 if (pin == 1) {
94 return (16);
95 }
96 }
97
98 return (255);
99 }
100
101 static struct rman irq_rman, port_rman, mem_rman;
102
103 /*
104 static void bridge_pcix_ack(void *arg)
105 {
106 xlr_read_reg(xlr_io_mmio(XLR_IO_PCIX_OFFSET), 0x140 >> 2);
107 }
108 */
109 /*
110 static void bridge_pcie_ack(void *arg)
111 {
112 int irq = (int)arg;
113 uint32_t reg;
114 xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET);
115
116 switch (irq) {
117 case PIC_PCIE_LINK0_IRQ : reg = PCIE_LINK0_MSI_STATUS; break;
118 case PIC_PCIE_LINK1_IRQ : reg = PCIE_LINK1_MSI_STATUS; break;
119 case PIC_PCIE_LINK2_IRQ : reg = PCIE_LINK2_MSI_STATUS; break;
120 case PIC_PCIE_LINK3_IRQ : reg = PCIE_LINK3_MSI_STATUS; break;
121 default:
122 return;
123 }
124
125 xlr_write_reg(pcie_mmio_le, reg>>2, 0xffffffff);
126 }
127 */
128 /*
129 static void pic_pcix_ack(void *none)
130 {
131 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
132
133 mtx_lock_spin(&xlr_pic_lock);
134 xlr_write_reg(mmio, PIC_INT_ACK, (1 << PIC_IRT_PCIX_INDEX));
135 mtx_unlock_spin(&xlr_pic_lock);
136 }
137 */
138 /*
139 static void pic_pcie_ack(void *arg)
140 {
141 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
142 int irq = (int) arg;
143
144 mtx_lock_spin(&xlr_pic_lock);
145 xlr_write_reg(mmio, PIC_INT_ACK, (1 << (irq - PIC_IRQ_BASE)));
146 mtx_unlock_spin(&xlr_pic_lock);
147 }
148
149 */
150
151 int
152 mips_platform_pci_setup_intr(device_t dev, device_t child,
153 struct resource *irq, int flags,
154 driver_filter_t * filt,
155 driver_intr_t * intr, void *arg,
156 void **cookiep)
157 {
158 int level;
159 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
160 int error = 0;
161 int xlrirq;
162
163 error = rman_activate_resource(irq);
164 if (error)
165 return error;
166 if (rman_get_start(irq) != rman_get_end(irq)) {
167 device_printf(dev, "Interrupt allocation %lu != %lu\n",
168 rman_get_start(irq), rman_get_end(irq));
169 return EINVAL;
170 }
171 xlrirq = rman_get_start(irq);
172 if (strcmp(device_get_name(dev), "pcib") != 0)
173 return 0;
174
175 if (xlr_board_info.is_xls == 0) {
176
177 if (rmi_spin_mutex_safe) mtx_lock_spin(&xlr_pic_lock);
178 level = PIC_IRQ_IS_EDGE_TRIGGERED(PIC_IRT_PCIX_INDEX);
179 xlr_write_reg(mmio, PIC_IRT_0_PCIX, 0x01);
180 xlr_write_reg(mmio, PIC_IRT_1_PCIX, ((1 << 31) | (level << 30) |
181 (1 << 6) | (PIC_PCIX_IRQ)));
182 if (rmi_spin_mutex_safe) mtx_unlock_spin(&xlr_pic_lock);
183 cpu_establish_hardintr(device_get_name(child), filt,
184 (driver_intr_t *) intr, (void *)arg, PIC_PCIX_IRQ, flags, cookiep);
185
186 } else {
187 if (rmi_spin_mutex_safe) mtx_lock_spin(&xlr_pic_lock);
188 xlr_write_reg(mmio, PIC_IRT_0_BASE + xlrirq - PIC_IRQ_BASE, 0x01);
189 xlr_write_reg(mmio, PIC_IRT_1_BASE + xlrirq - PIC_IRQ_BASE,
190 ((1 << 31) | (1 << 30) | (1 << 6) | xlrirq));
191 if (rmi_spin_mutex_safe) mtx_unlock_spin(&xlr_pic_lock);
192
193 if (flags & INTR_FAST)
194 cpu_establish_hardintr(device_get_name(child), filt,
195 (driver_intr_t *) intr, (void *)arg, xlrirq, flags, cookiep);
196 else
197 cpu_establish_hardintr(device_get_name(child), filt,
198 (driver_intr_t *) intr, (void *)arg, xlrirq, flags, cookiep);
199
200
201 }
202 return bus_generic_setup_intr(dev, child, irq, flags, filt, intr,
203 arg, cookiep);
204 }
205
206
207 int
208 mips_platform_pci_teardown_intr(device_t dev, device_t child,
209 struct resource *irq, void *cookie);
210 int
211 mips_platform_pci_teardown_intr(device_t dev, device_t child,
212 struct resource *irq, void *cookie)
213 {
214 if (strcmp(device_get_name(child), "pci") == 0) {
215 /* if needed reprogram the pic to clear pcix related entry */
216 }
217 return bus_generic_teardown_intr(dev, child, irq, cookie);
218 }
219
220 void
221 pci_init_resources(void)
222 {
223 irq_rman.rm_start = 0;
224 irq_rman.rm_end = 255;
225 irq_rman.rm_type = RMAN_ARRAY;
226 irq_rman.rm_descr = "PCI Mapped Interrupts";
227 if (rman_init(&irq_rman)
228 || rman_manage_region(&irq_rman, 0, 255))
229 panic("pci_init_resources irq_rman");
230
231 port_rman.rm_start = 0;
232 port_rman.rm_end = ~0ul;
233 port_rman.rm_type = RMAN_ARRAY;
234 port_rman.rm_descr = "I/O ports";
235 if (rman_init(&port_rman)
236 || rman_manage_region(&port_rman, 0x10000000, 0x1fffffff))
237 panic("pci_init_resources port_rman");
238
239 mem_rman.rm_start = 0;
240 mem_rman.rm_end = ~0ul;
241 mem_rman.rm_type = RMAN_ARRAY;
242 mem_rman.rm_descr = "I/O memory";
243 if (rman_init(&mem_rman)
244 || rman_manage_region(&mem_rman, 0xd0000000, 0xdfffffff))
245 panic("pci_init_resources mem_rman");
246 }
247
248 /* hack from bus.h in mips/include/bus.h */
249 #ifndef MIPS_BUS_SPACE_PCI
250 #define MIPS_BUS_SPACE_PCI 10
251 #endif
252
253 struct resource *
254 xlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
255 u_long start, u_long end, u_long count, u_int flags)
256 {
257 struct rman *rm;
258 struct resource *rv;
259 vm_offset_t va;
260 int needactivate = flags & RF_ACTIVE;
261
262 #if 0
263 device_printf(bus, "xlr_pci_alloc_resource : child %s, type %d, start %lx end %lx, count %lx, flags %x\n",
264 device_get_nameunit(child), type, start, end, count, flags);
265 #endif
266
267 switch (type) {
268 case SYS_RES_IRQ:
269 rm = &irq_rman;
270 break;
271
272 case SYS_RES_IOPORT:
273 rm = &port_rman;
274 break;
275
276 case SYS_RES_MEMORY:
277 rm = &mem_rman;
278 break;
279
280 default:
281 return 0;
282 }
283
284 rv = rman_reserve_resource(rm, start, end, count, flags, child);
285 if (rv == 0)
286 return 0;
287
288 rman_set_bustag(rv, (bus_space_tag_t) MIPS_BUS_SPACE_PCI);
289 rman_set_rid(rv, *rid);
290
291 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
292 /*
293 * if ((start + count) > (2 << 28)) { va_start =
294 * kmem_alloc_nofault(kernel_map, count); }
295 */
296 /*
297 * This called for pmap_map_uncached, but the pmap_map calls
298 * pmap_kenter which does a is_cacheable_mem() check and
299 * thus sets the PTE_UNCACHED bit. Hopefully this will work
300 * for this guy... RRS
301 */
302 /* va = pmap_map(&va_start, start, start + count, 0); */
303 va = (vm_offset_t)pmap_mapdev(start, start + count);
304 rman_set_bushandle(rv, va);
305 /* bushandle is same as virtual addr */
306 rman_set_virtual(rv, (void *)va);
307 rman_set_bustag(rv, (bus_space_tag_t) MIPS_BUS_SPACE_PCI);
308 }
309 if (needactivate) {
310 if (bus_activate_resource(child, type, *rid, rv)) {
311 rman_release_resource(rv);
312 return (NULL);
313 }
314 }
315 return rv;
316 }
317
318
319 int
320 pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
321 struct resource *r)
322 {
323 return (rman_deactivate_resource(r));
324 }
325
326 /* now in pci.c
327 int
328 pci_activate_resource(device_t bus, device_t child, int type, int rid,
329 struct resource *r)
330 {
331 return (rman_activate_resource(r));
332 }
333
334 int
335 pci_release_resource(device_t bus, device_t child, int type, int rid,
336 struct resource *r)
337 {
338 return (rman_release_resource(r));
339 }
340 */
341
342 struct rman *
343 pci_get_rman(device_t dev, int type)
344 {
345 switch (type) {
346 case SYS_RES_IOPORT:
347 return &port_rman;
348
349 case SYS_RES_MEMORY:
350 return &mem_rman;
351
352 case SYS_RES_IRQ:
353 return &irq_rman;
354 }
355
356 return 0;
357 }
Cache object: 60fb4870378c0508f994ef32dc87d4a8
|