1/*-
2 * Copyright (c) 2003-2009 RMI Corporation
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, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * RMI_BSD */
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/types.h>
36#include <sys/kernel.h>
37#include <sys/module.h>
38#include <sys/malloc.h>
39#include <sys/bus.h>
40#include <sys/endian.h>
41#include <sys/rman.h>
42
43#include <vm/vm.h>
44#include <vm/vm_param.h>
45#include <vm/pmap.h>
46
47#include <dev/pci/pcivar.h>
48#include <dev/pci/pcireg.h>
49
50#include <machine/bus.h>
51#include <machine/md_var.h>
52#include <machine/intr_machdep.h>
53#include <machine/cpuregs.h>
54
55#include <mips/rmi/rmi_mips_exts.h>
56#include <mips/rmi/interrupt.h>
57#include <mips/rmi/iomap.h>
58#include <mips/rmi/pic.h>
59#include <mips/rmi/board.h>
60#include <mips/rmi/pcibus.h>
61
62#include "pcib_if.h"
63
64#define pci_cfg_offset(bus,slot,devfn,where) (((bus)<<16) + ((slot) << 11)+((devfn)<<8)+(where))
65#define PCIE_LINK_STATE    0x4000
66
67#define LSU_CFG0_REGID       0
68#define LSU_CERRLOG_REGID    9
69#define LSU_CERROVF_REGID    10
70#define LSU_CERRINT_REGID    11
71
72/* MSI support */
73#define MSI_MIPS_ADDR_DEST		0x000ff000
74#define MSI_MIPS_ADDR_RH		0x00000008
75#define MSI_MIPS_ADDR_RH_OFF		0x00000000
76#define MSI_MIPS_ADDR_RH_ON		0x00000008
77#define MSI_MIPS_ADDR_DM		0x00000004
78#define MSI_MIPS_ADDR_DM_PHYSICAL	0x00000000
79#define MSI_MIPS_ADDR_DM_LOGICAL	0x00000004
80
81/* Fields in data for Intel MSI messages. */
82#define MSI_MIPS_DATA_TRGRMOD		0x00008000	/* Trigger mode */
83#define MSI_MIPS_DATA_TRGREDG		0x00000000	/* edge */
84#define MSI_MIPS_DATA_TRGRLVL		0x00008000	/* level */
85
86#define MSI_MIPS_DATA_LEVEL		0x00004000	/* Polarity. */
87#define MSI_MIPS_DATA_DEASSERT		0x00000000
88#define MSI_MIPS_DATA_ASSERT		0x00004000
89
90#define MSI_MIPS_DATA_DELMOD		0x00000700	/* Delivery Mode */
91#define MSI_MIPS_DATA_DELFIXED		0x00000000	/* fixed */
92#define MSI_MIPS_DATA_DELLOPRI		0x00000100	/* lowest priority */
93
94#define MSI_MIPS_DATA_INTVEC		0x000000ff
95
96/*
97 * Build Intel MSI message and data values from a source.  AMD64 systems
98 * seem to be compatible, so we use the same function for both.
99 */
100#define MIPS_MSI_ADDR(cpu)					       \
101        (MSI_MIPS_ADDR_BASE | (cpu) << 12 |			       \
102	 MSI_MIPS_ADDR_RH_OFF | MSI_MIPS_ADDR_DM_PHYSICAL)
103
104#define MIPS_MSI_DATA(irq)					       \
105        (MSI_MIPS_DATA_TRGRLVL | MSI_MIPS_DATA_DELFIXED |	       \
106	 MSI_MIPS_DATA_ASSERT | (irq))
107
108struct xlr_pcib_softc {
109	bus_dma_tag_t	sc_pci_dmat;	/* PCI DMA tag pointer */
110};
111
112static devclass_t pcib_devclass;
113static void *xlr_pci_config_base;
114static struct rman irq_rman, port_rman, mem_rman;
115
116static void
117xlr_pci_init_resources(void)
118{
119
120	irq_rman.rm_start = 0;
121	irq_rman.rm_end = 255;
122	irq_rman.rm_type = RMAN_ARRAY;
123	irq_rman.rm_descr = "PCI Mapped Interrupts";
124	if (rman_init(&irq_rman)
125	    || rman_manage_region(&irq_rman, 0, 255))
126		panic("pci_init_resources irq_rman");
127
128	port_rman.rm_type = RMAN_ARRAY;
129	port_rman.rm_descr = "I/O ports";
130	if (rman_init(&port_rman)
131	    || rman_manage_region(&port_rman, 0x10000000, 0x1fffffff))
132		panic("pci_init_resources port_rman");
133
134	mem_rman.rm_type = RMAN_ARRAY;
135	mem_rman.rm_descr = "I/O memory";
136	if (rman_init(&mem_rman)
137	    || rman_manage_region(&mem_rman, 0xd0000000, 0xdfffffff))
138		panic("pci_init_resources mem_rman");
139}
140
141static int
142xlr_pcib_probe(device_t dev)
143{
144
145	if (xlr_board_info.is_xls)
146		device_set_desc(dev, "XLS PCIe bus");
147	else
148		device_set_desc(dev, "XLR PCI bus");
149
150	xlr_pci_init_resources();
151	xlr_pci_config_base = (void *)MIPS_PHYS_TO_KSEG1(DEFAULT_PCI_CONFIG_BASE);
152
153	return (0);
154}
155
156static int
157xlr_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
158{
159
160	switch (which) {
161	case PCIB_IVAR_DOMAIN:
162		*result = 0;
163		return (0);
164	case PCIB_IVAR_BUS:
165		*result = 0;
166		return (0);
167	}
168	return (ENOENT);
169}
170
171static int
172xlr_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
173{
174	switch (which) {
175	case PCIB_IVAR_DOMAIN:
176		return (EINVAL);
177	case PCIB_IVAR_BUS:
178		return (EINVAL);
179	}
180	return (ENOENT);
181}
182
183static int
184xlr_pcib_maxslots(device_t dev)
185{
186
187	return (PCI_SLOTMAX);
188}
189
190static __inline__ void
191disable_and_clear_cache_error(void)
192{
193	uint64_t lsu_cfg0;
194
195	lsu_cfg0 = read_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID);
196	lsu_cfg0 = lsu_cfg0 & ~0x2e;
197	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0);
198	/* Clear cache error log */
199	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0);
200}
201
202static __inline__ void
203clear_and_enable_cache_error(void)
204{
205	uint64_t lsu_cfg0 = 0;
206
207	/* first clear the cache error logging register */
208	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0);
209	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERROVF_REGID, 0);
210	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRINT_REGID, 0);
211
212	lsu_cfg0 = read_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID);
213	lsu_cfg0 = lsu_cfg0 | 0x2e;
214	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0);
215}
216
217static uint32_t
218pci_cfg_read_32bit(uint32_t addr)
219{
220	uint32_t temp = 0;
221	uint32_t *p = (uint32_t *)xlr_pci_config_base + addr / sizeof(uint32_t);
222	uint64_t cerr_cpu_log = 0;
223
224	disable_and_clear_cache_error();
225	temp = bswap32(*p);
226
227	/* Read cache err log */
228	cerr_cpu_log = read_xlr_ctrl_register(CPU_BLOCKID_LSU,
229	    LSU_CERRLOG_REGID);
230	if (cerr_cpu_log) {
231		/* Device don't exist. */
232		temp = ~0x0;
233	}
234	clear_and_enable_cache_error();
235	return (temp);
236}
237
238static u_int32_t
239xlr_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
240			u_int reg, int width)
241{
242	uint32_t data = 0;
243
244	if ((width == 2) && (reg & 1))
245		return 0xFFFFFFFF;
246	else if ((width == 4) && (reg & 3))
247		return 0xFFFFFFFF;
248
249	data = pci_cfg_read_32bit(pci_cfg_offset(b, s, f, reg));
250
251	if (width == 1)
252		return ((data >> ((reg & 3) << 3)) & 0xff);
253	else if (width == 2)
254		return ((data >> ((reg & 3) << 3)) & 0xffff);
255	else
256		return (data);
257}
258
259static void
260xlr_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
261		u_int reg, u_int32_t val, int width)
262{
263	uint32_t cfgaddr = pci_cfg_offset(b, s, f, reg);
264	uint32_t data = 0, *p;
265
266	if ((width == 2) && (reg & 1))
267		return;
268	else if ((width == 4) && (reg & 3))
269		return;
270
271	if (width == 1) {
272		data = pci_cfg_read_32bit(cfgaddr);
273		data = (data & ~(0xff << ((reg & 3) << 3))) |
274		    (val << ((reg & 3) << 3));
275	} else if (width == 2) {
276		data = pci_cfg_read_32bit(cfgaddr);
277		data = (data & ~(0xffff << ((reg & 3) << 3))) |
278		    (val << ((reg & 3) << 3));
279	} else {
280		data = val;
281	}
282
283	p = (uint32_t *)xlr_pci_config_base + cfgaddr / sizeof(uint32_t);
284	*p = bswap32(data);
285
286	return;
287}
288
289static int
290xlr_pcib_attach(device_t dev)
291{
292	struct xlr_pcib_softc *sc;
293	sc = device_get_softc(dev);
294
295	/*
296	 * XLR C revision chips cannot do DMA above 2G physical address
297	 * create a parent tag with this lowaddr
298	 */
299	if (xlr_is_c_revision()) {
300		if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
301		    0x7fffffff, ~0, NULL, NULL, 0x7fffffff,
302		    0xff, 0x7fffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
303			panic("%s: bus_dma_tag_create failed", __func__);
304	}
305	device_add_child(dev, "pci", -1);
306	bus_generic_attach(dev);
307	return (0);
308}
309
310static void
311xlr_pcib_identify(driver_t * driver, device_t parent)
312{
313
314	BUS_ADD_CHILD(parent, 0, "pcib", 0);
315}
316
317/*
318 * XLS PCIe can have upto 4 links, and each link has its on IRQ
319 * Find the link on which the device is on
320 */
321static int
322xls_pcie_link(device_t pcib, device_t dev)
323{
324	device_t parent, tmp;
325
326	/* find the lane on which the slot is connected to */
327	printf("xls_pcie_link : bus %s dev %s\n", device_get_nameunit(pcib),
328		device_get_nameunit(dev));
329	tmp = dev;
330	while (1) {
331		parent = device_get_parent(tmp);
332		if (parent == NULL || parent == pcib) {
333			device_printf(dev, "Cannot find parent bus\n");
334			return (-1);
335		}
336		if (strcmp(device_get_nameunit(parent), "pci0") == 0)
337			break;
338		tmp = parent;
339	}
340	return (pci_get_slot(tmp));
341}
342
343/*
344 * Find the IRQ for the link, each link has a different interrupt
345 * at the XLS pic
346 */
347static int
348xls_pcie_link_irq(int link)
349{
350
351	switch (link) {
352	case 0:
353		return (PIC_PCIE_LINK0_IRQ);
354	case 1:
355		return (PIC_PCIE_LINK1_IRQ);
356	case 2:
357		if (xlr_is_xls_b0())
358			return (PIC_PCIE_B0_LINK2_IRQ);
359		else
360			return (PIC_PCIE_LINK2_IRQ);
361	case 3:
362		if (xlr_is_xls_b0())
363			return (PIC_PCIE_B0_LINK3_IRQ);
364		else
365			return (PIC_PCIE_LINK3_IRQ);
366	}
367	return (-1);
368}
369
370static int
371xlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
372{
373	int i, link;
374
375	/*
376	 * Each link has 32 MSIs that can be allocated, but for now
377	 * we only support one device per link.
378	 * msi_alloc() equivalent is needed when we start supporting
379	 * bridges on the PCIe link.
380	 */
381	link = xls_pcie_link(pcib, dev);
382	if (link == -1)
383		return (ENXIO);
384
385	/*
386	 * encode the irq so that we know it is a MSI interrupt when we
387	 * setup interrupts
388	 */
389	for (i = 0; i < count; i++)
390		irqs[i] = 64 + link * 32 + i;
391
392	return (0);
393}
394
395static int
396xlr_release_msi(device_t pcib, device_t dev, int count, int *irqs)
397{
398	device_printf(dev, "%s: msi release %d\n", device_get_nameunit(pcib),
399	    count);
400	return (0);
401}
402
403static int
404xlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
405    uint32_t *data)
406{
407	int msi;
408
409	if (irq >= 64) {
410		msi = irq - 64;
411		*addr = MIPS_MSI_ADDR(0);
412		*data = MIPS_MSI_DATA(msi);
413		return (0);
414	} else {
415		device_printf(dev, "%s: map_msi for irq %d  - ignored",
416		    device_get_nameunit(pcib), irq);
417		return (ENXIO);
418	}
419}
420
421static void
422bridge_pcix_ack(int irq)
423{
424
425	(void)xlr_read_reg(xlr_io_mmio(XLR_IO_PCIX_OFFSET), 0x140 >> 2);
426}
427
428static void
429bridge_pcie_ack(int irq)
430{
431	uint32_t reg;
432	xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET);
433
434	switch (irq) {
435	case PIC_PCIE_LINK0_IRQ:
436		reg = PCIE_LINK0_MSI_STATUS;
437		break;
438	case PIC_PCIE_LINK1_IRQ:
439		reg = PCIE_LINK1_MSI_STATUS;
440		break;
441	case PIC_PCIE_LINK2_IRQ:
442	case PIC_PCIE_B0_LINK2_IRQ:
443		reg = PCIE_LINK2_MSI_STATUS;
444		break;
445	case PIC_PCIE_LINK3_IRQ:
446	case PIC_PCIE_B0_LINK3_IRQ:
447		reg = PCIE_LINK3_MSI_STATUS;
448		break;
449	default:
450		return;
451	}
452	xlr_write_reg(pcie_mmio_le, reg>>2, 0xffffffff);
453}
454
455static int
456mips_platform_pci_setup_intr(device_t dev, device_t child,
457    struct resource *irq, int flags, driver_filter_t *filt,
458    driver_intr_t *intr, void *arg, void **cookiep)
459{
460	int error = 0;
461	int xlrirq;
462
463	error = rman_activate_resource(irq);
464	if (error)
465		return error;
466	if (rman_get_start(irq) != rman_get_end(irq)) {
467		device_printf(dev, "Interrupt allocation %ju != %ju\n",
468		    rman_get_start(irq), rman_get_end(irq));
469		return (EINVAL);
470	}
471	xlrirq = rman_get_start(irq);
472
473	if (strcmp(device_get_name(dev), "pcib") != 0)
474		return (0);
475
476	if (xlr_board_info.is_xls == 0) {
477		xlr_establish_intr(device_get_name(child), filt,
478		    intr, arg, PIC_PCIX_IRQ, flags, cookiep, bridge_pcix_ack);
479		pic_setup_intr(PIC_IRT_PCIX_INDEX, PIC_PCIX_IRQ, 0x1, 1);
480	} else {
481		/*
482		 * temporary hack for MSI, we support just one device per
483		 * link, and assign the link interrupt to the device interrupt
484		 */
485		if (xlrirq >= 64) {
486			xlrirq -= 64;
487			if (xlrirq % 32 != 0)
488				return (0);
489			xlrirq = xls_pcie_link_irq(xlrirq / 32);
490			if (xlrirq == -1)
491				return (EINVAL);
492		}
493		xlr_establish_intr(device_get_name(child), filt,
494		    intr, arg, xlrirq, flags, cookiep, bridge_pcie_ack);
495		pic_setup_intr(xlrirq - PIC_IRQ_BASE, xlrirq, 0x1, 1);
496	}
497
498	return (bus_generic_setup_intr(dev, child, irq, flags, filt, intr,
499	    arg, cookiep));
500}
501
502static int
503mips_platform_pci_teardown_intr(device_t dev, device_t child,
504    struct resource *irq, void *cookie)
505{
506	if (strcmp(device_get_name(child), "pci") == 0) {
507		/* if needed reprogram the pic to clear pcix related entry */
508		device_printf(dev, "teardown intr\n");
509	}
510	return (bus_generic_teardown_intr(dev, child, irq, cookie));
511}
512
513static struct resource *
514xlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
515	rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
516{
517	struct rman *rm;
518	struct resource *rv;
519	vm_offset_t va;
520	int needactivate = flags & RF_ACTIVE;
521
522	switch (type) {
523	case SYS_RES_IRQ:
524		rm = &irq_rman;
525		break;
526
527	case SYS_RES_IOPORT:
528		rm = &port_rman;
529		break;
530
531	case SYS_RES_MEMORY:
532		rm = &mem_rman;
533		break;
534
535	default:
536		return (0);
537	}
538
539	rv = rman_reserve_resource(rm, start, end, count, flags, child);
540	if (rv == NULL)
541		return (0);
542
543	rman_set_rid(rv, *rid);
544
545	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
546		va = (vm_offset_t)pmap_mapdev(start, count);
547		rman_set_bushandle(rv, va);
548		/* bushandle is same as virtual addr */
549		rman_set_virtual(rv, (void *)va);
550		rman_set_bustag(rv, rmi_pci_bus_space);
551	}
552
553	if (needactivate) {
554		if (bus_activate_resource(child, type, *rid, rv)) {
555			rman_release_resource(rv);
556			return (NULL);
557		}
558	}
559	return (rv);
560}
561
562static int
563xlr_pci_release_resource(device_t bus, device_t child, int type, int rid,
564		       struct resource *r)
565{
566
567	return (rman_release_resource(r));
568}
569
570static bus_dma_tag_t
571xlr_pci_get_dma_tag(device_t bus, device_t child)
572{
573	struct xlr_pcib_softc *sc;
574
575	sc = device_get_softc(bus);
576	return (sc->sc_pci_dmat);
577}
578
579static int
580xlr_pci_activate_resource(device_t bus, device_t child, int type, int rid,
581                      struct resource *r)
582{
583
584	return (rman_activate_resource(r));
585}
586
587static int
588xlr_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
589                          struct resource *r)
590{
591
592	return (rman_deactivate_resource(r));
593}
594
595static int
596mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
597{
598	int irq, link;
599
600	/*
601	 * Validate requested pin number.
602	 */
603	if ((pin < 1) || (pin > 4))
604		return (255);
605
606	if (xlr_board_info.is_xls) {
607		link = xls_pcie_link(bus, dev);
608		irq = xls_pcie_link_irq(link);
609		if (irq != -1)
610			return (irq);
611	} else {
612		if (pin == 1)
613			return (PIC_PCIX_IRQ);
614	}
615
616	return (255);
617}
618
619static device_method_t xlr_pcib_methods[] = {
620	/* Device interface */
621	DEVMETHOD(device_identify, xlr_pcib_identify),
622	DEVMETHOD(device_probe, xlr_pcib_probe),
623	DEVMETHOD(device_attach, xlr_pcib_attach),
624
625	/* Bus interface */
626	DEVMETHOD(bus_read_ivar, xlr_pcib_read_ivar),
627	DEVMETHOD(bus_write_ivar, xlr_pcib_write_ivar),
628	DEVMETHOD(bus_alloc_resource, xlr_pci_alloc_resource),
629	DEVMETHOD(bus_release_resource, xlr_pci_release_resource),
630	DEVMETHOD(bus_get_dma_tag, xlr_pci_get_dma_tag),
631	DEVMETHOD(bus_activate_resource, xlr_pci_activate_resource),
632	DEVMETHOD(bus_deactivate_resource, xlr_pci_deactivate_resource),
633	DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr),
634	DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr),
635
636	/* pcib interface */
637	DEVMETHOD(pcib_maxslots, xlr_pcib_maxslots),
638	DEVMETHOD(pcib_read_config, xlr_pcib_read_config),
639	DEVMETHOD(pcib_write_config, xlr_pcib_write_config),
640	DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt),
641
642	DEVMETHOD(pcib_alloc_msi, xlr_alloc_msi),
643	DEVMETHOD(pcib_release_msi, xlr_release_msi),
644	DEVMETHOD(pcib_map_msi, xlr_map_msi),
645
646	DEVMETHOD_END
647};
648
649static driver_t xlr_pcib_driver = {
650	"pcib",
651	xlr_pcib_methods,
652	sizeof(struct xlr_pcib_softc),
653};
654
655DRIVER_MODULE(pcib, iodi, xlr_pcib_driver, pcib_devclass, 0, 0);
656