idtpci.c revision 180332
1/* $NetBSD: idtpci.c,v 1.1 2007/03/20 08:52:02 dyoung Exp $ */
2
3/*-
4 * Copyright (c) 2007 David Young.
5 * Copyright (c) 2007 Oleskandr Tymoshenko.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
9 * conditions are met:
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
18 *    written permission.
19 *
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
31 * OF SUCH DAMAGE.
32 */
33/*-
34 * Copyright (c) 2006 Itronix Inc.
35 * All rights reserved.
36 *
37 * Written by Garrett D'Amore for Itronix Inc.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
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.
50 *
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.
62 */
63
64#include <sys/cdefs.h>
65__FBSDID("$FreeBSD: head/sys/mips/idt/idtpci.c 178173 2008-04-13 07:44:55Z imp $");
66
67#include <sys/param.h>
68#include <sys/systm.h>
69
70#include <sys/bus.h>
71#include <sys/interrupt.h>
72#include <sys/malloc.h>
73#include <sys/kernel.h>
74#include <sys/module.h>
75#include <sys/rman.h>
76
77#include <vm/vm.h>
78#include <vm/pmap.h>
79#include <vm/vm_extern.h>
80
81#include <machine/bus.h>
82#include <machine/cpu.h>
83#include <machine/pmap.h>
84
85#include <dev/pci/pcivar.h>
86#include <dev/pci/pcireg.h>
87
88#include <dev/pci/pcib_private.h>
89#include "pcib_if.h"
90
91#include <mips/mips32/idt/idtreg.h>
92
93#ifdef IDTPCI_DEBUG
94int idtpci_debug = 1;
95#define	IDTPCI_DPRINTF(__fmt, ...)		\
96do {						\
97	if (idtpci_debug)			\
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 */
103
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
108
109#define	IDTPCI_MAX_DEVICE
110
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)
113
114unsigned 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
119};
120
121struct idtpci_softc {
122	device_t		sc_dev;
123
124	int			sc_busno;
125	struct rman		sc_mem_rman[2];
126	struct rman		sc_io_rman[2];
127	struct rman		sc_irq_rman;
128	uint32_t		sc_mem;
129	uint32_t		sc_io;
130};
131
132static uint32_t
133idtpci_make_addr(int bus, int slot, int func, int reg)
134{
135
136	return 0x80000000 | (bus << 16) | (slot << 11) | (func << 8) | reg;
137}
138
139static int
140idtpci_probe(device_t dev)
141{
142
143	return (0);
144}
145
146static int
147idtpci_attach(device_t dev)
148{
149	int busno = 0;
150	struct idtpci_softc *sc = device_get_softc(dev);
151	unsigned int pci_data, force_endianess = 0;
152	int		i;
153	bus_addr_t	addr;
154
155	sc->sc_dev = dev;
156	sc->sc_busno = busno;
157
158	sc->sc_io = 0;
159	sc->sc_mem = 0;
160
161	/* TODO: Check for host mode */
162
163	/* Enabled PCI, IG mode, EAP mode */
164	REG_WRITE(IDT_PCI_CNTL, IDT_PCI_CNTL_IGM | IDT_PCI_CNTL_EAP |
165	    IDT_PCI_CNTL_EN);
166	/* Wait while "Reset in progress bit" set */
167	while(1) {
168		pci_data = REG_READ(IDT_PCI_STATUS);
169		if((pci_data & IDT_PCI_STATUS_RIP) == 0)
170			break;
171	}
172
173	/* Reset status register */
174	REG_WRITE(IDT_PCI_STATUS, 0);
175	/* Mask interrupts related to status register */
176	REG_WRITE(IDT_PCI_STATUS_MASK, 0xffffffff);
177
178	/* Disable PCI decoupled access */
179	REG_WRITE(IDT_PCI_DAC, 0);
180	/* Zero status and mask DA interrupts */
181	REG_WRITE(IDT_PCI_DAS, 0);
182	REG_WRITE(IDT_PCI_DASM, 0x7f);
183
184	/* Init PCI messaging unit */
185	/* Disable messaging interrupts */
186	REG_WRITE(IDT_PCI_IIC, 0);
187	REG_WRITE(IDT_PCI_IIM, 0xffffffff);
188	REG_WRITE(IDT_PCI_OIC, 0);
189	REG_WRITE(IDT_PCI_OIM, 0);
190
191#ifdef	__MIPSEB__
192	force_endianess = IDT_PCI_LBA_FE;
193#endif
194
195	/* LBA0 -- memory window */
196	REG_WRITE(IDT_PCI_LBA0, IDT_PCIMEM0_BASE);
197	REG_WRITE(IDT_PCI_LBA0_MAP, IDT_PCIMEM0_BASE);
198	REG_WRITE(IDT_PCI_LBA0_CNTL, IDT_PCI_LBA_SIZE_16MB | force_endianess);
199	pci_data = REG_READ(IDT_PCI_LBA0_CNTL);
200
201	/* LBA1 -- memory window */
202	REG_WRITE(IDT_PCI_LBA1, IDT_PCIMEM1_BASE);
203	REG_WRITE(IDT_PCI_LBA1_MAP, IDT_PCIMEM1_BASE);
204	REG_WRITE(IDT_PCI_LBA1_CNTL, IDT_PCI_LBA_SIZE_256MB | force_endianess);
205	pci_data = REG_READ(IDT_PCI_LBA1_CNTL);
206
207	/* LBA2 -- IO window */
208	REG_WRITE(IDT_PCI_LBA2, IDT_PCIMEM2_BASE);
209	REG_WRITE(IDT_PCI_LBA2_MAP, IDT_PCIMEM2_BASE);
210	REG_WRITE(IDT_PCI_LBA2_CNTL, IDT_PCI_LBA_SIZE_4MB | IDT_PCI_LBA_MSI |
211	    force_endianess);
212	pci_data = REG_READ(IDT_PCI_LBA2_CNTL);
213
214	/* LBA3 -- IO window */
215	REG_WRITE(IDT_PCI_LBA3, IDT_PCIMEM3_BASE);
216	REG_WRITE(IDT_PCI_LBA3_MAP, IDT_PCIMEM3_BASE);
217	REG_WRITE(IDT_PCI_LBA3_CNTL, IDT_PCI_LBA_SIZE_1MB | IDT_PCI_LBA_MSI |
218	    force_endianess);
219	pci_data = REG_READ(IDT_PCI_LBA3_CNTL);
220
221
222	pci_data = REG_READ(IDT_PCI_CNTL) & ~IDT_PCI_CNTL_TNR;
223	REG_WRITE(IDT_PCI_CNTL, pci_data);
224	pci_data = REG_READ(IDT_PCI_CNTL);
225
226	/* Rewrite Target Control register with default values */
227	REG_WRITE(IDT_PCI_TC, (IDT_PCI_TC_DTIMER << 8) | IDT_PCI_TC_RTIMER);
228
229	/* Perform Korina fixup */
230	addr = idtpci_make_addr(0, 0, 0, 4);
231	for (i = 0; i < 24; i++) {
232
233		REG_WRITE(IDT_PCI_CFG_ADDR, addr);
234		REG_WRITE(IDT_PCI_CFG_DATA, korina_fixup[i]);
235		__asm__ volatile ("sync");
236
237		REG_WRITE(IDT_PCI_CFG_ADDR, 0);
238		REG_WRITE(IDT_PCI_CFG_DATA, 0);
239		addr += 4;
240	}
241
242	/* Use KSEG1 to access IO ports for it is uncached */
243	sc->sc_io = 0;
244	sc->sc_io_rman[0].rm_type = RMAN_ARRAY;
245	sc->sc_io_rman[0].rm_descr = "IDTPCI I/O Ports window 1";
246	if (rman_init(&sc->sc_io_rman[0]) != 0 ||
247	  rman_manage_region(&sc->sc_io_rman[0],
248	      IDT_PCIMEM2_BASE, IDT_PCIMEM2_BASE + IDT_PCIMEM2_SIZE - 1) != 0) {
249		panic("idtpci_attach: failed to set up I/O rman");
250	}
251
252	sc->sc_io_rman[1].rm_type = RMAN_ARRAY;
253	sc->sc_io_rman[1].rm_descr = "IDTPCI I/O Ports window 2";
254	if (rman_init(&sc->sc_io_rman[1]) != 0 ||
255	  rman_manage_region(&sc->sc_io_rman[1],
256	      IDT_PCIMEM3_BASE, IDT_PCIMEM3_BASE + IDT_PCIMEM3_SIZE - 1) != 0) {
257		panic("idtpci_attach: failed to set up I/O rman");
258	}
259
260	/* Use KSEG1 to access PCI memory for it is uncached */
261	sc->sc_mem = 0;
262	sc->sc_mem_rman[0].rm_type = RMAN_ARRAY;
263	sc->sc_mem_rman[0].rm_descr = "IDTPCI PCI Memory window 1";
264	if (rman_init(&sc->sc_mem_rman[0]) != 0 ||
265	    rman_manage_region(&sc->sc_mem_rman[0],
266	    IDT_PCIMEM0_BASE, IDT_PCIMEM0_BASE + IDT_PCIMEM0_SIZE) != 0) {
267		panic("idtpci_attach: failed to set up memory rman");
268	}
269
270	sc->sc_mem_rman[1].rm_type = RMAN_ARRAY;
271	sc->sc_mem_rman[1].rm_descr = "IDTPCI PCI Memory window 2";
272	if (rman_init(&sc->sc_mem_rman[1]) != 0 ||
273	    rman_manage_region(&sc->sc_mem_rman[1],
274	    IDT_PCIMEM1_BASE, IDT_PCIMEM1_BASE + IDT_PCIMEM1_SIZE) != 0) {
275		panic("idtpci_attach: failed to set up memory rman");
276	}
277
278	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
279	sc->sc_irq_rman.rm_descr = "IDTPCI PCI IRQs";
280	if (rman_init(&sc->sc_irq_rman) != 0 ||
281	    rman_manage_region(&sc->sc_irq_rman, PCI_IRQ_BASE,
282	        PCI_IRQ_END) != 0)
283		panic("idtpci_attach: failed to set up IRQ rman");
284
285	device_add_child(dev, "pci", busno);
286	return (bus_generic_attach(dev));
287}
288
289static int
290idtpci_maxslots(device_t dev)
291{
292
293	return (PCI_SLOTMAX);
294}
295
296static uint32_t
297idtpci_read_config(device_t dev, int bus, int slot, int func, int reg,
298    int bytes)
299{
300	uint32_t data;
301	uint32_t shift, mask;
302	bus_addr_t addr;
303
304	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__,
305			bus, slot, func, reg, bytes);
306
307	addr = idtpci_make_addr(bus, slot, func, reg);
308
309	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
310	data = REG_READ(IDT_PCI_CFG_DATA);
311
312	switch (reg % 4) {
313	case 3:
314		shift = 24;
315		break;
316	case 2:
317		shift = 16;
318		break;
319	case 1:
320		shift = 8;
321		break;
322	default:
323		shift = 0;
324		break;
325	}
326
327	switch (bytes) {
328	case 1:
329		mask = 0xff;
330		data = (data >> shift) & mask;
331		break;
332	case 2:
333		mask = 0xffff;
334		if (reg % 4 == 0)
335			data = data & mask;
336		else
337			data = (data >> 16) & mask;
338		break;
339	case 4:
340		break;
341	default:
342		panic("%s: wrong bytes count", __func__);
343		break;
344	}
345
346	__asm__ volatile ("sync");
347 	IDTPCI_DPRINTF("%s: read 0x%x\n", __func__, data);
348
349	return (data);
350}
351
352static void
353idtpci_write_config(device_t dev, int bus, int slot, int func, int reg,
354    uint32_t data, int bytes)
355{
356	bus_addr_t addr;
357	uint32_t reg_data;
358	uint32_t shift, mask;
359
360	IDTPCI_DPRINTF("%s: tag (%x, %x, %x) reg %d(%d) data %08x\n", __func__,
361			bus, slot, func, reg, bytes, data);
362
363	if (bytes != 4) {
364		reg_data = idtpci_read_config(dev, bus, slot, func, reg, 4);
365
366		switch (reg % 4) {
367		case 3:
368			shift = 24;
369			break;
370		case 2:
371			shift = 16;
372			break;
373		case 1:
374			shift = 8;
375			break;
376		default:
377			shift = 0;
378			break;
379		}
380
381		switch (bytes) {
382		case 1:
383			mask = 0xff;
384			data = (reg_data & ~ (mask << shift)) | (data << shift);
385			break;
386		case 2:
387			mask = 0xffff;
388			if (reg % 4 == 0)
389				data = (reg_data & ~mask) | data;
390			else
391				data = (reg_data & ~ (mask << shift)) |
392				    (data << shift);
393			break;
394		case 4:
395			break;
396		default:
397			panic("%s: wrong bytes count", __func__);
398			break;
399		}
400	}
401
402	addr = idtpci_make_addr(bus, slot, func, reg);
403
404
405	REG_WRITE(IDT_PCI_CFG_ADDR, addr);
406	REG_WRITE(IDT_PCI_CFG_DATA, data);
407	__asm__ volatile ("sync");
408
409	REG_WRITE(IDT_PCI_CFG_ADDR, 0);
410	REG_WRITE(IDT_PCI_CFG_DATA, 0);
411}
412
413static int
414idtpci_route_interrupt(device_t pcib, device_t device, int pin)
415{
416	static int idt_pci_table[2][12] =
417	{
418		{ 0, 0, 2, 3, 2, 3, 0, 0, 0, 0, 0, 1 },
419		{ 0, 0, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3 }
420	};
421	int dev, bus, irq;
422
423	dev = pci_get_slot(device);
424	bus = pci_get_bus(device);
425	if (bootverbose)
426		device_printf(pcib, "routing pin %d for %s\n", pin,
427		    device_get_nameunit(device));
428	if (bus >= 0 && bus <= 1 &&
429	    dev >= 0 && dev <= 11) {
430		irq = IP_IRQ(6, idt_pci_table[bus][dev] + 4);
431		if (bootverbose)
432			printf("idtpci: %d/%d/%d -> IRQ%d\n",
433			    pci_get_bus(device), dev, pci_get_function(device),
434			    irq);
435		return (irq);
436	} else
437		printf("idtpci: no mapping for %d/%d/%d\n",
438			pci_get_bus(device), dev, pci_get_function(device));
439
440	return (-1);
441}
442
443static int
444idtpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
445{
446	struct idtpci_softc *sc = device_get_softc(dev);
447
448	switch (which) {
449	case PCIB_IVAR_DOMAIN:
450		*result = 0;
451		return (0);
452	case PCIB_IVAR_BUS:
453		*result = sc->sc_busno;
454		return (0);
455	}
456
457	return (ENOENT);
458}
459
460static int
461idtpci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
462{
463	struct idtpci_softc * sc = device_get_softc(dev);
464
465	switch (which) {
466	case PCIB_IVAR_BUS:
467		sc->sc_busno = result;
468		return (0);
469	}
470	return (ENOENT);
471}
472
473static struct resource *
474idtpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
475    u_long start, u_long end, u_long count, u_int flags)
476{
477
478	struct idtpci_softc *sc = device_get_softc(bus);
479	struct resource *rv = NULL;
480	struct rman *rm1, *rm2;
481
482	switch (type) {
483	case SYS_RES_IRQ:
484		rm1 = &sc->sc_irq_rman;
485		rm2 = NULL;
486		break;
487	case SYS_RES_MEMORY:
488		rm1 = &sc->sc_mem_rman[0];
489		rm2 = &sc->sc_mem_rman[1];
490		break;
491	case SYS_RES_IOPORT:
492		rm1 = &sc->sc_io_rman[0];
493		rm2 = &sc->sc_io_rman[1];
494		break;
495	default:
496		return (NULL);
497	}
498
499	rv = rman_reserve_resource(rm1, start, end, count, flags, child);
500
501	/* Try second window if it exists */
502	if ((rv == NULL) && (rm2 != NULL))
503		rv = rman_reserve_resource(rm2, start, end, count, flags,
504		    child);
505
506	if (rv == NULL)
507		return (NULL);
508
509	rman_set_rid(rv, *rid);
510
511	if (flags & RF_ACTIVE) {
512		if (bus_activate_resource(child, type, *rid, rv)) {
513			rman_release_resource(rv);
514			return (NULL);
515		}
516	}
517
518	return (rv);
519}
520
521static int
522idtpci_teardown_intr(device_t dev, device_t child, struct resource *res,
523    void *cookie)
524{
525
526	return (intr_event_remove_handler(cookie));
527}
528
529static device_method_t idtpci_methods[] = {
530	/* Device interface */
531	DEVMETHOD(device_probe,		idtpci_probe),
532	DEVMETHOD(device_attach,	idtpci_attach),
533	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
534	DEVMETHOD(device_suspend,	bus_generic_suspend),
535	DEVMETHOD(device_resume,	bus_generic_resume),
536
537	/* Bus interface */
538	DEVMETHOD(bus_print_child,	bus_generic_print_child),
539	DEVMETHOD(bus_read_ivar,	idtpci_read_ivar),
540	DEVMETHOD(bus_write_ivar,	idtpci_write_ivar),
541	DEVMETHOD(bus_alloc_resource,	idtpci_alloc_resource),
542	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
543	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
544	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
545	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
546	DEVMETHOD(bus_teardown_intr,	idtpci_teardown_intr),
547
548	/* pcib interface */
549	DEVMETHOD(pcib_maxslots,	idtpci_maxslots),
550	DEVMETHOD(pcib_read_config,	idtpci_read_config),
551	DEVMETHOD(pcib_write_config,	idtpci_write_config),
552	DEVMETHOD(pcib_route_interrupt,	idtpci_route_interrupt),
553
554	{0, 0}
555};
556
557static driver_t idtpci_driver = {
558	"pcib",
559	idtpci_methods,
560	sizeof(struct idtpci_softc),
561};
562
563static devclass_t idtpci_devclass;
564
565DRIVER_MODULE(idtpci, obio, idtpci_driver, idtpci_devclass, 0, 0);
566