2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
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.
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.
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 $");
32 #define __RMAN_RESOURCE_VISIBLE
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
37 #include <sys/mutex.h>
38 #include <sys/module.h>
43 #include <vm/vm_param.h>
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>
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>
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 *);
68 extern vm_map_t kernel_map;
69 vm_offset_t kmem_alloc_nofault(vm_map_t map, vm_size_t size);
73 mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
76 * Validate requested pin number.
78 if ((pin < 1) || (pin > 4))
81 if (xlr_board_info.is_xls) {
84 return PIC_PCIE_LINK0_IRQ;
86 return PIC_PCIE_LINK1_IRQ;
88 return PIC_PCIE_LINK2_IRQ;
90 return PIC_PCIE_LINK3_IRQ;
101 static struct rman irq_rman, port_rman, mem_rman;
104 static void bridge_pcix_ack(void *arg)
106 xlr_read_reg(xlr_io_mmio(XLR_IO_PCIX_OFFSET), 0x140 >> 2);
110 static void bridge_pcie_ack(void *arg)
114 xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET);
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;
125 xlr_write_reg(pcie_mmio_le, reg>>2, 0xffffffff);
129 static void pic_pcix_ack(void *none)
131 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
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);
139 static void pic_pcie_ack(void *arg)
141 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
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);
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,
159 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
163 error = rman_activate_resource(irq);
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));
171 xlrirq = rman_get_start(irq);
172 if (strcmp(device_get_name(dev), "pcib") != 0)
175 if (xlr_board_info.is_xls == 0) {
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);
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);
193 if (flags & INTR_FAST)
194 cpu_establish_hardintr(device_get_name(child), filt,
195 (driver_intr_t *) intr, (void *)arg, xlrirq, flags, cookiep);
197 cpu_establish_hardintr(device_get_name(child), filt,
198 (driver_intr_t *) intr, (void *)arg, xlrirq, flags, cookiep);
202 return bus_generic_setup_intr(dev, child, irq, flags, filt, intr,
208 mips_platform_pci_teardown_intr(device_t dev, device_t child,
209 struct resource *irq, void *cookie);
211 mips_platform_pci_teardown_intr(device_t dev, device_t child,
212 struct resource *irq, void *cookie)
214 if (strcmp(device_get_name(child), "pci") == 0) {
215 /* if needed reprogram the pic to clear pcix related entry */
217 return bus_generic_teardown_intr(dev, child, irq, cookie);
221 pci_init_resources(void)
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");
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");
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");
248 /* hack from bus.h in mips/include/bus.h */
249 #ifndef MIPS_BUS_SPACE_PCI
250 #define MIPS_BUS_SPACE_PCI 10
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)
260 int needactivate = flags & RF_ACTIVE;
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);
284 rv = rman_reserve_resource(rm, start, end, count, flags, child);
288 rman_set_bustag(rv, (bus_space_tag_t) MIPS_BUS_SPACE_PCI);
289 rman_set_rid(rv, *rid);
291 if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
293 * if ((start + count) > (2 << 28)) { va_start =
294 * kmem_alloc_nofault(kernel_map, count); }
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
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);
310 if (bus_activate_resource(child, type, *rid, rv)) {
311 rman_release_resource(rv);
320 pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
323 return (rman_deactivate_resource(r));
328 pci_activate_resource(device_t bus, device_t child, int type, int rid,
331 return (rman_activate_resource(r));
335 pci_release_resource(device_t bus, device_t child, int type, int rid,
338 return (rman_release_resource(r));
343 pci_get_rman(device_t dev, int type)