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>
84 #include <dev/pci/pcivar.h>
85 #include <dev/pci/pcireg.h>
87 #include <dev/pci/pcib_private.h>
90 #include <mips/idt/idtreg.h>
94 #define IDTPCI_DPRINTF(__fmt, ...) \
97 printf((__fmt), __VA_ARGS__); \
98 } while (/*CONSTCOND*/0)
99 #else /* !IDTPCI_DEBUG */
100 #define IDTPCI_DPRINTF(__fmt, ...) do { } while (/*CONSTCOND*/0)
101 #endif /* IDTPCI_DEBUG */
103 #define IDTPCI_TAG_BUS_MASK 0x007f0000
104 #define IDTPCI_TAG_DEVICE_MASK 0x00007800
105 #define IDTPCI_TAG_FUNCTION_MASK 0x00000300
106 #define IDTPCI_TAG_REGISTER_MASK 0x0000007c
108 #define IDTPCI_MAX_DEVICE
110 #define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(IDT_BASE_PCI + (o)))
111 #define REG_WRITE(o,v) (REG_READ(o)) = (v)
113 unsigned int korina_fixup
[24] = {
114 0x00000157, 0x00000000, 0x00003c04, 0x00000008, 0x18800001, 0x18000001,
115 0x48000008, 0x00000000, 0x00000000, 0x00000000, 0x011d0214, 0x00000000,
116 0x00000000, 0x00000000, 0x38080101, 0x00008080, 0x00000d6e, 0x00000000,
117 0x00000051, 0x00000000, 0x00000055, 0x18000000, 0x00000000, 0x00000000
120 struct idtpci_softc
{
124 struct rman sc_mem_rman
[2];
125 struct rman sc_io_rman
[2];
126 struct rman sc_irq_rman
;
130 idtpci_make_addr(int bus
, int slot
, int func
, int reg
)
133 return 0x80000000 | (bus
<< 16) | (slot
<< 11) | (func
<< 8) | reg
;
137 idtpci_probe(device_t dev
)
144 idtpci_attach(device_t dev
)
147 struct idtpci_softc
*sc
= device_get_softc(dev
);
148 unsigned int pci_data
, force_endianess
= 0;
153 sc
->sc_busno
= busno
;
155 /* TODO: Check for host mode */
157 /* Enabled PCI, IG mode, EAP mode */
158 REG_WRITE(IDT_PCI_CNTL
, IDT_PCI_CNTL_IGM
| IDT_PCI_CNTL_EAP
|
160 /* Wait while "Reset in progress bit" set */
162 pci_data
= REG_READ(IDT_PCI_STATUS
);
163 if((pci_data
& IDT_PCI_STATUS_RIP
) == 0)
167 /* Reset status register */
168 REG_WRITE(IDT_PCI_STATUS
, 0);
169 /* Mask interrupts related to status register */
170 REG_WRITE(IDT_PCI_STATUS_MASK
, 0xffffffff);
172 /* Disable PCI decoupled access */
173 REG_WRITE(IDT_PCI_DAC
, 0);
174 /* Zero status and mask DA interrupts */
175 REG_WRITE(IDT_PCI_DAS
, 0);
176 REG_WRITE(IDT_PCI_DASM
, 0x7f);
178 /* Init PCI messaging unit */
179 /* Disable messaging interrupts */
180 REG_WRITE(IDT_PCI_IIC
, 0);
181 REG_WRITE(IDT_PCI_IIM
, 0xffffffff);
182 REG_WRITE(IDT_PCI_OIC
, 0);
183 REG_WRITE(IDT_PCI_OIM
, 0);
186 force_endianess
= IDT_PCI_LBA_FE
;
189 /* LBA0 -- memory window */
190 REG_WRITE(IDT_PCI_LBA0
, IDT_PCIMEM0_BASE
);
191 REG_WRITE(IDT_PCI_LBA0_MAP
, IDT_PCIMEM0_BASE
);
192 REG_WRITE(IDT_PCI_LBA0_CNTL
, IDT_PCI_LBA_SIZE_16MB
| force_endianess
);
193 pci_data
= REG_READ(IDT_PCI_LBA0_CNTL
);
195 /* LBA1 -- memory window */
196 REG_WRITE(IDT_PCI_LBA1
, IDT_PCIMEM1_BASE
);
197 REG_WRITE(IDT_PCI_LBA1_MAP
, IDT_PCIMEM1_BASE
);
198 REG_WRITE(IDT_PCI_LBA1_CNTL
, IDT_PCI_LBA_SIZE_256MB
| force_endianess
);
199 pci_data
= REG_READ(IDT_PCI_LBA1_CNTL
);
201 /* LBA2 -- IO window */
202 REG_WRITE(IDT_PCI_LBA2
, IDT_PCIMEM2_BASE
);
203 REG_WRITE(IDT_PCI_LBA2_MAP
, IDT_PCIMEM2_BASE
);
204 REG_WRITE(IDT_PCI_LBA2_CNTL
, IDT_PCI_LBA_SIZE_4MB
| IDT_PCI_LBA_MSI
|
206 pci_data
= REG_READ(IDT_PCI_LBA2_CNTL
);
208 /* LBA3 -- IO window */
209 REG_WRITE(IDT_PCI_LBA3
, IDT_PCIMEM3_BASE
);
210 REG_WRITE(IDT_PCI_LBA3_MAP
, IDT_PCIMEM3_BASE
);
211 REG_WRITE(IDT_PCI_LBA3_CNTL
, IDT_PCI_LBA_SIZE_1MB
| IDT_PCI_LBA_MSI
|
213 pci_data
= REG_READ(IDT_PCI_LBA3_CNTL
);
216 pci_data
= REG_READ(IDT_PCI_CNTL
) & ~IDT_PCI_CNTL_TNR
;
217 REG_WRITE(IDT_PCI_CNTL
, pci_data
);
218 pci_data
= REG_READ(IDT_PCI_CNTL
);
220 /* Rewrite Target Control register with default values */
221 REG_WRITE(IDT_PCI_TC
, (IDT_PCI_TC_DTIMER
<< 8) | IDT_PCI_TC_RTIMER
);
223 /* Perform Korina fixup */
224 addr
= idtpci_make_addr(0, 0, 0, 4);
225 for (i
= 0; i
< 24; i
++) {
227 REG_WRITE(IDT_PCI_CFG_ADDR
, addr
);
228 REG_WRITE(IDT_PCI_CFG_DATA
, korina_fixup
[i
]);
229 __asm__
volatile ("sync");
231 REG_WRITE(IDT_PCI_CFG_ADDR
, 0);
232 REG_WRITE(IDT_PCI_CFG_DATA
, 0);
236 /* Use KSEG1 to access IO ports for it is uncached */
237 sc
->sc_io_rman
[0].rm_type
= RMAN_ARRAY
;
238 sc
->sc_io_rman
[0].rm_descr
= "IDTPCI I/O Ports window 1";
239 if (rman_init(&sc
->sc_io_rman
[0]) != 0 ||
240 rman_manage_region(&sc
->sc_io_rman
[0],
241 IDT_PCIMEM2_BASE
, IDT_PCIMEM2_BASE
+ IDT_PCIMEM2_SIZE
- 1) != 0) {
242 panic("idtpci_attach: failed to set up I/O rman");
245 sc
->sc_io_rman
[1].rm_type
= RMAN_ARRAY
;
246 sc
->sc_io_rman
[1].rm_descr
= "IDTPCI I/O Ports window 2";
247 if (rman_init(&sc
->sc_io_rman
[1]) != 0 ||
248 rman_manage_region(&sc
->sc_io_rman
[1],
249 IDT_PCIMEM3_BASE
, IDT_PCIMEM3_BASE
+ IDT_PCIMEM3_SIZE
- 1) != 0) {
250 panic("idtpci_attach: failed to set up I/O rman");
253 /* Use KSEG1 to access PCI memory for it is uncached */
254 sc
->sc_mem_rman
[0].rm_type
= RMAN_ARRAY
;
255 sc
->sc_mem_rman
[0].rm_descr
= "IDTPCI PCI Memory window 1";
256 if (rman_init(&sc
->sc_mem_rman
[0]) != 0 ||
257 rman_manage_region(&sc
->sc_mem_rman
[0],
258 IDT_PCIMEM0_BASE
, IDT_PCIMEM0_BASE
+ IDT_PCIMEM0_SIZE
) != 0) {
259 panic("idtpci_attach: failed to set up memory rman");
262 sc
->sc_mem_rman
[1].rm_type
= RMAN_ARRAY
;
263 sc
->sc_mem_rman
[1].rm_descr
= "IDTPCI PCI Memory window 2";
264 if (rman_init(&sc
->sc_mem_rman
[1]) != 0 ||
265 rman_manage_region(&sc
->sc_mem_rman
[1],
266 IDT_PCIMEM1_BASE
, IDT_PCIMEM1_BASE
+ IDT_PCIMEM1_SIZE
) != 0) {
267 panic("idtpci_attach: failed to set up memory rman");
270 sc
->sc_irq_rman
.rm_type
= RMAN_ARRAY
;
271 sc
->sc_irq_rman
.rm_descr
= "IDTPCI PCI IRQs";
272 if (rman_init(&sc
->sc_irq_rman
) != 0 ||
273 rman_manage_region(&sc
->sc_irq_rman
, PCI_IRQ_BASE
,
275 panic("idtpci_attach: failed to set up IRQ rman");
277 device_add_child(dev
, "pci", -1);
278 return (bus_generic_attach(dev
));
282 idtpci_maxslots(device_t dev
)
285 return (PCI_SLOTMAX
);
289 idtpci_read_config(device_t dev
, u_int bus
, u_int slot
, u_int func
, u_int reg
,
293 uint32_t shift
, mask
;
296 IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__
,
297 bus
, slot
, func
, reg
, bytes
);
299 addr
= idtpci_make_addr(bus
, slot
, func
, reg
);
301 REG_WRITE(IDT_PCI_CFG_ADDR
, addr
);
302 data
= REG_READ(IDT_PCI_CFG_DATA
);
322 data
= (data
>> shift
) & mask
;
329 data
= (data
>> 16) & mask
;
334 panic("%s: wrong bytes count", __func__
);
338 __asm__
volatile ("sync");
339 IDTPCI_DPRINTF("%s: read 0x%x\n", __func__
, data
);
345 idtpci_write_config(device_t dev
, u_int bus
, u_int slot
, u_int func
, u_int reg
,
346 uint32_t data
, int bytes
)
350 uint32_t shift
, mask
;
352 IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__
,
353 bus
, slot
, func
, reg
, bytes
, data
);
356 reg_data
= idtpci_read_config(dev
, bus
, slot
, func
, reg
, 4);
376 data
= (reg_data
& ~ (mask
<< shift
)) | (data
<< shift
);
381 data
= (reg_data
& ~mask
) | data
;
383 data
= (reg_data
& ~ (mask
<< shift
)) |
389 panic("%s: wrong bytes count", __func__
);
394 addr
= idtpci_make_addr(bus
, slot
, func
, reg
);
397 REG_WRITE(IDT_PCI_CFG_ADDR
, addr
);
398 REG_WRITE(IDT_PCI_CFG_DATA
, data
);
399 __asm__
volatile ("sync");
401 REG_WRITE(IDT_PCI_CFG_ADDR
, 0);
402 REG_WRITE(IDT_PCI_CFG_DATA
, 0);
406 idtpci_route_interrupt(device_t pcib
, device_t device
, int pin
)
408 static int idt_pci_table
[2][12] =
410 { 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
411 { 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
415 dev
= pci_get_slot(device
);
416 bus
= pci_get_bus(device
);
418 device_printf(pcib
, "routing pin %d for %s\n", pin
,
419 device_get_nameunit(device
));
420 if (bus
>= 0 && bus
<= 1 &&
421 dev
>= 0 && dev
<= 11) {
422 irq
= IP_IRQ(6, idt_pci_table
[bus
][dev
] + 4);
424 printf("idtpci: %d/%d/%d -> IRQ%d\n",
425 pci_get_bus(device
), dev
, pci_get_function(device
),
429 printf("idtpci: no mapping for %d/%d/%d\n",
430 pci_get_bus(device
), dev
, pci_get_function(device
));
436 idtpci_read_ivar(device_t dev
, device_t child
, int which
, uintptr_t *result
)
438 struct idtpci_softc
*sc
= device_get_softc(dev
);
441 case PCIB_IVAR_DOMAIN
:
445 *result
= sc
->sc_busno
;
453 idtpci_write_ivar(device_t dev
, device_t child
, int which
, uintptr_t result
)
455 struct idtpci_softc
* sc
= device_get_softc(dev
);
459 sc
->sc_busno
= result
;
465 static struct resource
*
466 idtpci_alloc_resource(device_t bus
, device_t child
, int type
, int *rid
,
467 rman_res_t start
, rman_res_t end
, rman_res_t count
, u_int flags
)
470 struct idtpci_softc
*sc
= device_get_softc(bus
);
471 struct resource
*rv
= NULL
;
472 struct rman
*rm1
, *rm2
;
476 rm1
= &sc
->sc_irq_rman
;
480 rm1
= &sc
->sc_mem_rman
[0];
481 rm2
= &sc
->sc_mem_rman
[1];
484 rm1
= &sc
->sc_io_rman
[0];
485 rm2
= &sc
->sc_io_rman
[1];
491 rv
= rman_reserve_resource(rm1
, start
, end
, count
, flags
, child
);
493 /* Try second window if it exists */
494 if ((rv
== NULL
) && (rm2
!= NULL
))
495 rv
= rman_reserve_resource(rm2
, start
, end
, count
, flags
,
501 rman_set_rid(rv
, *rid
);
503 if (flags
& RF_ACTIVE
) {
504 if (bus_activate_resource(child
, type
, *rid
, rv
)) {
505 rman_release_resource(rv
);
514 idtpci_teardown_intr(device_t dev
, device_t child
, struct resource
*res
,
518 return (intr_event_remove_handler(cookie
));
521 static device_method_t idtpci_methods
[] = {
522 /* Device interface */
523 DEVMETHOD(device_probe
, idtpci_probe
),
524 DEVMETHOD(device_attach
, idtpci_attach
),
525 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
526 DEVMETHOD(device_suspend
, bus_generic_suspend
),
527 DEVMETHOD(device_resume
, bus_generic_resume
),
530 DEVMETHOD(bus_read_ivar
, idtpci_read_ivar
),
531 DEVMETHOD(bus_write_ivar
, idtpci_write_ivar
),
532 DEVMETHOD(bus_alloc_resource
, idtpci_alloc_resource
),
533 DEVMETHOD(bus_release_resource
, bus_generic_release_resource
),
534 DEVMETHOD(bus_activate_resource
, bus_generic_activate_resource
),
535 DEVMETHOD(bus_deactivate_resource
, bus_generic_deactivate_resource
),
536 DEVMETHOD(bus_setup_intr
, bus_generic_setup_intr
),
537 DEVMETHOD(bus_teardown_intr
, idtpci_teardown_intr
),
540 DEVMETHOD(pcib_maxslots
, idtpci_maxslots
),
541 DEVMETHOD(pcib_read_config
, idtpci_read_config
),
542 DEVMETHOD(pcib_write_config
, idtpci_write_config
),
543 DEVMETHOD(pcib_route_interrupt
, idtpci_route_interrupt
),
548 static driver_t idtpci_driver
= {
551 sizeof(struct idtpci_softc
),
554 static devclass_t idtpci_devclass
;
556 DRIVER_MODULE(idtpci
, obio
, idtpci_driver
, idtpci_devclass
, 0, 0);