]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/mips/rmi/pcibus.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / 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: src/sys/alpha/pci/pcibus.c,v 1.36 2005/01/05 20:05:52 imp Exp $");
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 = ~0u;
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 = ~0u;
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 }