1 /* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
4 * Copyright (c) 2007 David Young.
5 * Copyright (c) 2007 Oleskandr Tymoshenko. All rights reserved.
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * 3. The name of the author may not be used to endorse or promote
17 * products derived from this software without specific prior
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
27 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 * Copyright (c) 2006 Itronix Inc.
35 * All rights reserved.
37 * Written by Garrett D'Amore for Itronix Inc.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. The name of Itronix Inc. may not be used to endorse
48 * or promote products derived from this software without specific
49 * prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
55 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58 * ON ANY THEORY OF LIABILITY, WHETHER IN
59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
64 #include <sys/cdefs.h>
65 __FBSDID("$FreeBSD$");
67 #include <sys/param.h>
68 #include <sys/systm.h>
71 #include <sys/interrupt.h>
72 #include <sys/malloc.h>
73 #include <sys/kernel.h>
74 #include <sys/module.h>
79 #include <vm/vm_extern.h>
81 #include <machine/bus.h>
82 #include <machine/cpu.h>
83 #include <machine/pmap.h>
85 #include <dev/pci/pcivar.h>
86 #include <dev/pci/pcireg.h>
88 #include <dev/pci/pcib_private.h>
91 #include <mips/idt/idtreg.h>
95 #define IDTPCI_DPRINTF(__fmt, ...) \
98 printf((__fmt), __VA_ARGS__); \
99 } while (/*CONSTCOND*/0)
100 #else /* !IDTPCI_DEBUG */
101 #define IDTPCI_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0)
102 #endif /* IDTPCI_DEBUG */
104 #define IDTPCI_TAG_BUS_MASK 0x007f0000
105 #define IDTPCI_TAG_DEVICE_MASK 0x00007800
106 #define IDTPCI_TAG_FUNCTION_MASK 0x00000300
107 #define IDTPCI_TAG_REGISTER_MASK 0x0000007c
109 #define IDTPCI_MAX_DEVICE
111 #define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o)))
112 #define REG_WRITE(o,v) (REG_READ(o)) = (v)
114 unsigned int korina_fixup[24] = {
115 0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001,
116 0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000,
117 0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000,
118 0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000
121 struct idtpci_softc {
125 struct rman sc_mem_rman[2];
126 struct rman sc_io_rman[2];
127 struct rman sc_irq_rman;
131 idtpci_make_addr(int bus, int slot, int func, int reg)
134 return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg;
138 idtpci_probe(device_t dev)
145 idtpci_attach(device_t dev)
148 struct idtpci_softc *sc = device_get_softc(dev);
149 unsigned int pci_data, force_endianess = 0;
154 sc->sc_busno = busno;
156 /* TODO: Check for host mode */
158 /* Enabled PCI, IG mode, EAP mode */
159 REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP |
161 /* Wait while "Reset in progress bit" set */
163 pci_data = REG_READ(IDT_PCI_STATUS);
164 if((pci_data & IDT_PCI_STATUS_RIP) == 0)
168 /* Reset status register */
169 REG_WRITE(IDT_PCI_STATUS, 0);
170 /* Mask interrupts related to status register */
171 REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff);
173 /* Disable PCI decoupled access */
174 REG_WRITE(IDT_PCI_DAC, 0);
175 /* Zero status and mask DA interrupts */
176 REG_WRITE(IDT_PCI_DAS, 0);
177 REG_WRITE(IDT_PCI_DASM, 0x7f);
179 /* Init PCI messaging unit */
180 /* Disable messaging interrupts */
181 REG_WRITE(IDT_PCI_IIC, 0);
182 REG_WRITE(IDT_PCI_IIM, 0xffffffff);
183 REG_WRITE(IDT_PCI_OIC, 0);
184 REG_WRITE(IDT_PCI_OIM, 0);
187 force_endianess = IDT_PCI_LBA_FE;
190 /* LBA0 -- memory window */
191 REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE);
192 REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE);
193 REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess);
194 pci_data = REG_READ(IDT_PCI_LBA0_CNTL);
196 /* LBA1 -- memory window */
197 REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE);
198 REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE);
199 REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess);
200 pci_data = REG_READ(IDT_PCI_LBA1_CNTL);
202 /* LBA2 -- IO window */
203 REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE);
204 REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE);
205 REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI |
207 pci_data = REG_READ(IDT_PCI_LBA2_CNTL);
209 /* LBA3 -- IO window */
210 REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE);
211 REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE);
212 REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI |
214 pci_data = REG_READ(IDT_PCI_LBA3_CNTL);
217 pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR;
218 REG_WRITE(IDT_PCI_CNTL, pci_data);
219 pci_data = REG_READ(IDT_PCI_CNTL);
221 /* Rewrite Target Control register with default values */
222 REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER);
224 /* Perform Korina fixup */
225 addr = idtpci_make_addr(0, 0, 0, 4);
226 for (i = 0; i < 24; i++) {
228 REG_WRITE(IDT_PCI_CFG_ADDR, addr);
229 REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]);
230 __asm__ volatile ("sync");
232 REG_WRITE(IDT_PCI_CFG_ADDR, 0);
233 REG_WRITE(IDT_PCI_CFG_DATA, 0);
237 /* Use KSEG1 to access IO ports for it is uncached */
238 sc->sc_io_rman[0].rm_type = RMAN_ARRAY;
239 sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1";
240 if (rman_init(&sc->sc_io_rman[0]) != 0 ||
241 rman_manage_region(&sc->sc_io_rman[0],
242 IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) {
243 panic("idtpci_attach: failed to set up I/O rman");
246 sc->sc_io_rman[1].rm_type = RMAN_ARRAY;
247 sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2";
248 if (rman_init(&sc->sc_io_rman[1]) != 0 ||
249 rman_manage_region(&sc->sc_io_rman[1],
250 IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) {
251 panic("idtpci_attach: failed to set up I/O rman");
254 /* Use KSEG1 to access PCI memory for it is uncached */
255 sc->sc_mem_rman[0].rm_type = RMAN_ARRAY;
256 sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1";
257 if (rman_init(&sc->sc_mem_rman[0]) != 0 ||
258 rman_manage_region(&sc->sc_mem_rman[0],
259 IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) {
260 panic("idtpci_attach: failed to set up memory rman");
263 sc->sc_mem_rman[1].rm_type = RMAN_ARRAY;
264 sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2";
265 if (rman_init(&sc->sc_mem_rman[1]) != 0 ||
266 rman_manage_region(&sc->sc_mem_rman[1],
267 IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) {
268 panic("idtpci_attach: failed to set up memory rman");
271 sc->sc_irq_rman.rm_type = RMAN_ARRAY;
272 sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs";
273 if (rman_init(&sc->sc_irq_rman) != 0 ||
274 rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE,
276 panic("idtpci_attach: failed to set up IRQ rman");
278 device_add_child(dev, "pci", busno);
279 return (bus_generic_attach(dev));
283 idtpci_maxslots(device_t dev)
286 return (PCI_SLOTMAX);
290 idtpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
294 uint32_t shift, mask;
297 IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__,
298 bus, slot, func, reg, bytes);
300 addr = idtpci_make_addr(bus, slot, func, reg);
302 REG_WRITE(IDT_PCI_CFG_ADDR, addr);
303 data = REG_READ(IDT_PCI_CFG_DATA);
323 data = (data >> shift) & mask;
330 data = (data >> 16) & mask;
335 panic("%s: wrong bytes count", __func__);
339 __asm__ volatile ("sync");
340 IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data);
346 idtpci_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
347 uint32_t data, int bytes)
351 uint32_t shift, mask;
353 IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__,
354 bus, slot, func, reg, bytes, data);
357 reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4);
377 data = (reg_data & ~ (mask << shift)) | (data << shift);
382 data = (reg_data & ~mask) | data;
384 data = (reg_data & ~ (mask << shift)) |
390 panic("%s: wrong bytes count", __func__);
395 addr = idtpci_make_addr(bus, slot, func, reg);
398 REG_WRITE(IDT_PCI_CFG_ADDR, addr);
399 REG_WRITE(IDT_PCI_CFG_DATA, data);
400 __asm__ volatile ("sync");
402 REG_WRITE(IDT_PCI_CFG_ADDR, 0);
403 REG_WRITE(IDT_PCI_CFG_DATA, 0);
407 idtpci_route_interrupt(device_t pcib, device_t device, int pin)
409 static int idt_pci_table[2][12] =
411 { 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
412 { 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
416 dev = pci_get_slot(device);
417 bus = pci_get_bus(device);
419 device_printf(pcib, "routing pin %d for %s\n", pin,
420 device_get_nameunit(device));
421 if (bus >= 0 && bus <= 1 &&
422 dev >= 0 && dev <= 11) {
423 irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4);
425 printf("idtpci: %d/%d/%d -> IRQ%d\n",
426 pci_get_bus(device), dev, pci_get_function(device),
430 printf("idtpci: no mapping for %d/%d/%d\n",
431 pci_get_bus(device), dev, pci_get_function(device));
437 idtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
439 struct idtpci_softc *sc = device_get_softc(dev);
442 case PCIB_IVAR_DOMAIN:
446 *result = sc->sc_busno;
454 idtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
456 struct idtpci_softc * sc = device_get_softc(dev);
460 sc->sc_busno = result;
466 static struct resource *
467 idtpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
468 u_long start, u_long end, u_long count, u_int flags)
471 struct idtpci_softc *sc = device_get_softc(bus);
472 struct resource *rv = NULL;
473 struct rman *rm1, *rm2;
477 rm1 = &sc->sc_irq_rman;
481 rm1 = &sc->sc_mem_rman[0];
482 rm2 = &sc->sc_mem_rman[1];
485 rm1 = &sc->sc_io_rman[0];
486 rm2 = &sc->sc_io_rman[1];
492 rv = rman_reserve_resource(rm1, start, end, count, flags, child);
494 /* Try second window if it exists */
495 if ((rv == NULL) && (rm2 != NULL))
496 rv = rman_reserve_resource(rm2, start, end, count, flags,
502 rman_set_rid(rv, *rid);
504 if (flags & RF_ACTIVE) {
505 if (bus_activate_resource(child, type, *rid, rv)) {
506 rman_release_resource(rv);
515 idtpci_teardown_intr(device_t dev, device_t child, struct resource *res,
519 return (intr_event_remove_handler(cookie));
522 static device_method_t idtpci_methods[] = {
523 /* Device interface */
524 DEVMETHOD(device_probe, idtpci_probe),
525 DEVMETHOD(device_attach, idtpci_attach),
526 DEVMETHOD(device_shutdown, bus_generic_shutdown),
527 DEVMETHOD(device_suspend, bus_generic_suspend),
528 DEVMETHOD(device_resume, bus_generic_resume),
531 DEVMETHOD(bus_read_ivar, idtpci_read_ivar),
532 DEVMETHOD(bus_write_ivar, idtpci_write_ivar),
533 DEVMETHOD(bus_alloc_resource, idtpci_alloc_resource),
534 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
535 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
536 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
537 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
538 DEVMETHOD(bus_teardown_intr, idtpci_teardown_intr),
541 DEVMETHOD(pcib_maxslots, idtpci_maxslots),
542 DEVMETHOD(pcib_read_config, idtpci_read_config),
543 DEVMETHOD(pcib_write_config, idtpci_write_config),
544 DEVMETHOD(pcib_route_interrupt, idtpci_route_interrupt),
549 static driver_t idtpci_driver = {
552 sizeof(struct idtpci_softc),
555 static devclass_t idtpci_devclass;
557 DRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0);