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: releng/10.3/sys/mips/rmi/xlr_pci.c 227843 2011-11-22 21:28:20Z marius $");
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_start = 0;
129	port_rman.rm_end = ~0ul;
130	port_rman.rm_type = RMAN_ARRAY;
131	port_rman.rm_descr = "I/O ports";
132	if (rman_init(&port_rman)
133	    || rman_manage_region(&port_rman, 0x10000000, 0x1fffffff))
134		panic("pci_init_resources port_rman");
135
136	mem_rman.rm_start = 0;
137	mem_rman.rm_end = ~0ul;
138	mem_rman.rm_type = RMAN_ARRAY;
139	mem_rman.rm_descr = "I/O memory";
140	if (rman_init(&mem_rman)
141	    || rman_manage_region(&mem_rman, 0xd0000000, 0xdfffffff))
142		panic("pci_init_resources mem_rman");
143}
144
145static int
146xlr_pcib_probe(device_t dev)
147{
148
149	if (xlr_board_info.is_xls)
150		device_set_desc(dev, "XLS PCIe bus");
151	else
152		device_set_desc(dev, "XLR PCI bus");
153
154	xlr_pci_init_resources();
155	xlr_pci_config_base = (void *)MIPS_PHYS_TO_KSEG1(DEFAULT_PCI_CONFIG_BASE);
156
157	return (0);
158}
159
160static int
161xlr_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
162{
163
164	switch (which) {
165	case PCIB_IVAR_DOMAIN:
166		*result = 0;
167		return (0);
168	case PCIB_IVAR_BUS:
169		*result = 0;
170		return (0);
171	}
172	return (ENOENT);
173}
174
175static int
176xlr_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
177{
178	switch (which) {
179	case PCIB_IVAR_DOMAIN:
180		return (EINVAL);
181	case PCIB_IVAR_BUS:
182		return (EINVAL);
183	}
184	return (ENOENT);
185}
186
187static int
188xlr_pcib_maxslots(device_t dev)
189{
190
191	return (PCI_SLOTMAX);
192}
193
194static __inline__ void
195disable_and_clear_cache_error(void)
196{
197	uint64_t lsu_cfg0;
198
199	lsu_cfg0 = read_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID);
200	lsu_cfg0 = lsu_cfg0 & ~0x2e;
201	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0);
202	/* Clear cache error log */
203	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0);
204}
205
206static __inline__ void
207clear_and_enable_cache_error(void)
208{
209	uint64_t lsu_cfg0 = 0;
210
211	/* first clear the cache error logging register */
212	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRLOG_REGID, 0);
213	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERROVF_REGID, 0);
214	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CERRINT_REGID, 0);
215
216	lsu_cfg0 = read_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID);
217	lsu_cfg0 = lsu_cfg0 | 0x2e;
218	write_xlr_ctrl_register(CPU_BLOCKID_LSU, LSU_CFG0_REGID, lsu_cfg0);
219}
220
221static uint32_t
222pci_cfg_read_32bit(uint32_t addr)
223{
224	uint32_t temp = 0;
225	uint32_t *p = (uint32_t *)xlr_pci_config_base + addr / sizeof(uint32_t);
226	uint64_t cerr_cpu_log = 0;
227
228	disable_and_clear_cache_error();
229	temp = bswap32(*p);
230
231	/* Read cache err log */
232	cerr_cpu_log = read_xlr_ctrl_register(CPU_BLOCKID_LSU,
233	    LSU_CERRLOG_REGID);
234	if (cerr_cpu_log) {
235		/* Device don't exist. */
236		temp = ~0x0;
237	}
238	clear_and_enable_cache_error();
239	return (temp);
240}
241
242static u_int32_t
243xlr_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
244			u_int reg, int width)
245{
246	uint32_t data = 0;
247
248	if ((width == 2) && (reg & 1))
249		return 0xFFFFFFFF;
250	else if ((width == 4) && (reg & 3))
251		return 0xFFFFFFFF;
252
253	data = pci_cfg_read_32bit(pci_cfg_offset(b, s, f, reg));
254
255	if (width == 1)
256		return ((data >> ((reg & 3) << 3)) & 0xff);
257	else if (width == 2)
258		return ((data >> ((reg & 3) << 3)) & 0xffff);
259	else
260		return (data);
261}
262
263static void
264xlr_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
265		u_int reg, u_int32_t val, int width)
266{
267	uint32_t cfgaddr = pci_cfg_offset(b, s, f, reg);
268	uint32_t data = 0, *p;
269
270	if ((width == 2) && (reg & 1))
271		return;
272	else if ((width == 4) && (reg & 3))
273		return;
274
275	if (width == 1) {
276		data = pci_cfg_read_32bit(cfgaddr);
277		data = (data & ~(0xff << ((reg & 3) << 3))) |
278		    (val << ((reg & 3) << 3));
279	} else if (width == 2) {
280		data = pci_cfg_read_32bit(cfgaddr);
281		data = (data & ~(0xffff << ((reg & 3) << 3))) |
282		    (val << ((reg & 3) << 3));
283	} else {
284		data = val;
285	}
286
287	p = (uint32_t *)xlr_pci_config_base + cfgaddr / sizeof(uint32_t);
288	*p = bswap32(data);
289
290	return;
291}
292
293static int
294xlr_pcib_attach(device_t dev)
295{
296	struct xlr_pcib_softc *sc;
297	sc = device_get_softc(dev);
298
299	/*
300	 * XLR C revision chips cannot do DMA above 2G physical address
301	 * create a parent tag with this lowaddr
302	 */
303	if (xlr_is_c_revision()) {
304		if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
305		    0x7fffffff, ~0, NULL, NULL, 0x7fffffff,
306		    0xff, 0x7fffffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
307			panic("%s: bus_dma_tag_create failed", __func__);
308	}
309	device_add_child(dev, "pci", 0);
310	bus_generic_attach(dev);
311	return (0);
312}
313
314static void
315xlr_pcib_identify(driver_t * driver, device_t parent)
316{
317
318	BUS_ADD_CHILD(parent, 0, "pcib", 0);
319}
320
321/*
322 * XLS PCIe can have upto 4 links, and each link has its on IRQ
323 * Find the link on which the device is on
324 */
325static int
326xls_pcie_link(device_t pcib, device_t dev)
327{
328	device_t parent, tmp;
329
330	/* find the lane on which the slot is connected to */
331	printf("xls_pcie_link : bus %s dev %s\n", device_get_nameunit(pcib),
332		device_get_nameunit(dev));
333	tmp = dev;
334	while (1) {
335		parent = device_get_parent(tmp);
336		if (parent == NULL || parent == pcib) {
337			device_printf(dev, "Cannot find parent bus\n");
338			return (-1);
339		}
340		if (strcmp(device_get_nameunit(parent), "pci0") == 0)
341			break;
342		tmp = parent;
343	}
344	return (pci_get_slot(tmp));
345}
346
347/*
348 * Find the IRQ for the link, each link has a different interrupt
349 * at the XLS pic
350 */
351static int
352xls_pcie_link_irq(int link)
353{
354
355	switch (link) {
356	case 0:
357		return (PIC_PCIE_LINK0_IRQ);
358	case 1:
359		return (PIC_PCIE_LINK1_IRQ);
360	case 2:
361		if (xlr_is_xls_b0())
362			return (PIC_PCIE_B0_LINK2_IRQ);
363		else
364			return (PIC_PCIE_LINK2_IRQ);
365	case 3:
366		if (xlr_is_xls_b0())
367			return (PIC_PCIE_B0_LINK3_IRQ);
368		else
369			return (PIC_PCIE_LINK3_IRQ);
370	}
371	return (-1);
372}
373
374static int
375xlr_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
376{
377	int i, link;
378
379	/*
380	 * Each link has 32 MSIs that can be allocated, but for now
381	 * we only support one device per link.
382	 * msi_alloc() equivalent is needed when we start supporting
383	 * bridges on the PCIe link.
384	 */
385	link = xls_pcie_link(pcib, dev);
386	if (link == -1)
387		return (ENXIO);
388
389	/*
390	 * encode the irq so that we know it is a MSI interrupt when we
391	 * setup interrupts
392	 */
393	for (i = 0; i < count; i++)
394		irqs[i] = 64 + link * 32 + i;
395
396	return (0);
397}
398
399static int
400xlr_release_msi(device_t pcib, device_t dev, int count, int *irqs)
401{
402	device_printf(dev, "%s: msi release %d\n", device_get_nameunit(pcib),
403	    count);
404	return (0);
405}
406
407static int
408xlr_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
409    uint32_t *data)
410{
411	int msi;
412
413	if (irq >= 64) {
414		msi = irq - 64;
415		*addr = MIPS_MSI_ADDR(0);
416		*data = MIPS_MSI_DATA(msi);
417		return (0);
418	} else {
419		device_printf(dev, "%s: map_msi for irq %d  - ignored",
420		    device_get_nameunit(pcib), irq);
421		return (ENXIO);
422	}
423}
424
425static void
426bridge_pcix_ack(int irq)
427{
428
429	(void)xlr_read_reg(xlr_io_mmio(XLR_IO_PCIX_OFFSET), 0x140 >> 2);
430}
431
432static void
433bridge_pcie_ack(int irq)
434{
435	uint32_t reg;
436	xlr_reg_t *pcie_mmio_le = xlr_io_mmio(XLR_IO_PCIE_1_OFFSET);
437
438	switch (irq) {
439	case PIC_PCIE_LINK0_IRQ:
440		reg = PCIE_LINK0_MSI_STATUS;
441		break;
442	case PIC_PCIE_LINK1_IRQ:
443		reg = PCIE_LINK1_MSI_STATUS;
444		break;
445	case PIC_PCIE_LINK2_IRQ:
446	case PIC_PCIE_B0_LINK2_IRQ:
447		reg = PCIE_LINK2_MSI_STATUS;
448		break;
449	case PIC_PCIE_LINK3_IRQ:
450	case PIC_PCIE_B0_LINK3_IRQ:
451		reg = PCIE_LINK3_MSI_STATUS;
452		break;
453	default:
454		return;
455	}
456	xlr_write_reg(pcie_mmio_le, reg>>2, 0xffffffff);
457}
458
459static int
460mips_platform_pci_setup_intr(device_t dev, device_t child,
461    struct resource *irq, int flags, driver_filter_t *filt,
462    driver_intr_t *intr, void *arg, void **cookiep)
463{
464	int error = 0;
465	int xlrirq;
466
467	error = rman_activate_resource(irq);
468	if (error)
469		return error;
470	if (rman_get_start(irq) != rman_get_end(irq)) {
471		device_printf(dev, "Interrupt allocation %lu != %lu\n",
472		    rman_get_start(irq), rman_get_end(irq));
473		return (EINVAL);
474	}
475	xlrirq = rman_get_start(irq);
476
477	if (strcmp(device_get_name(dev), "pcib") != 0)
478		return (0);
479
480	if (xlr_board_info.is_xls == 0) {
481		xlr_establish_intr(device_get_name(child), filt,
482		    intr, arg, PIC_PCIX_IRQ, flags, cookiep, bridge_pcix_ack);
483		pic_setup_intr(PIC_IRT_PCIX_INDEX, PIC_PCIX_IRQ, 0x1, 1);
484	} else {
485		/*
486		 * temporary hack for MSI, we support just one device per
487		 * link, and assign the link interrupt to the device interrupt
488		 */
489		if (xlrirq >= 64) {
490			xlrirq -= 64;
491			if (xlrirq % 32 != 0)
492				return (0);
493			xlrirq = xls_pcie_link_irq(xlrirq / 32);
494			if (xlrirq == -1)
495				return (EINVAL);
496		}
497		xlr_establish_intr(device_get_name(child), filt,
498		    intr, arg, xlrirq, flags, cookiep, bridge_pcie_ack);
499		pic_setup_intr(xlrirq - PIC_IRQ_BASE, xlrirq, 0x1, 1);
500	}
501
502	return (bus_generic_setup_intr(dev, child, irq, flags, filt, intr,
503	    arg, cookiep));
504}
505
506static int
507mips_platform_pci_teardown_intr(device_t dev, device_t child,
508    struct resource *irq, void *cookie)
509{
510	if (strcmp(device_get_name(child), "pci") == 0) {
511		/* if needed reprogram the pic to clear pcix related entry */
512		device_printf(dev, "teardown intr\n");
513	}
514	return (bus_generic_teardown_intr(dev, child, irq, cookie));
515}
516
517static struct resource *
518xlr_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
519	u_long start, u_long end, u_long count, u_int flags)
520{
521	struct rman *rm;
522	struct resource *rv;
523	vm_offset_t va;
524	int needactivate = flags & RF_ACTIVE;
525
526	switch (type) {
527	case SYS_RES_IRQ:
528		rm = &irq_rman;
529		break;
530
531	case SYS_RES_IOPORT:
532		rm = &port_rman;
533		break;
534
535	case SYS_RES_MEMORY:
536		rm = &mem_rman;
537		break;
538
539	default:
540		return (0);
541	}
542
543	rv = rman_reserve_resource(rm, start, end, count, flags, child);
544	if (rv == 0)
545		return (0);
546
547	rman_set_rid(rv, *rid);
548
549	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
550		va = (vm_offset_t)pmap_mapdev(start, count);
551		rman_set_bushandle(rv, va);
552		/* bushandle is same as virtual addr */
553		rman_set_virtual(rv, (void *)va);
554		rman_set_bustag(rv, rmi_pci_bus_space);
555	}
556
557	if (needactivate) {
558		if (bus_activate_resource(child, type, *rid, rv)) {
559			rman_release_resource(rv);
560			return (NULL);
561		}
562	}
563	return (rv);
564}
565
566static int
567xlr_pci_release_resource(device_t bus, device_t child, int type, int rid,
568		       struct resource *r)
569{
570
571	return (rman_release_resource(r));
572}
573
574static bus_dma_tag_t
575xlr_pci_get_dma_tag(device_t bus, device_t child)
576{
577	struct xlr_pcib_softc *sc;
578
579	sc = device_get_softc(bus);
580	return (sc->sc_pci_dmat);
581}
582
583static int
584xlr_pci_activate_resource(device_t bus, device_t child, int type, int rid,
585                      struct resource *r)
586{
587
588	return (rman_activate_resource(r));
589}
590
591static int
592xlr_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
593                          struct resource *r)
594{
595
596	return (rman_deactivate_resource(r));
597}
598
599static int
600mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
601{
602	int irq, link;
603
604	/*
605	 * Validate requested pin number.
606	 */
607	if ((pin < 1) || (pin > 4))
608		return (255);
609
610	if (xlr_board_info.is_xls) {
611		link = xls_pcie_link(bus, dev);
612		irq = xls_pcie_link_irq(link);
613		if (irq != -1)
614			return (irq);
615	} else {
616		if (pin == 1)
617			return (PIC_PCIX_IRQ);
618	}
619
620	return (255);
621}
622
623static device_method_t xlr_pcib_methods[] = {
624	/* Device interface */
625	DEVMETHOD(device_identify, xlr_pcib_identify),
626	DEVMETHOD(device_probe, xlr_pcib_probe),
627	DEVMETHOD(device_attach, xlr_pcib_attach),
628
629	/* Bus interface */
630	DEVMETHOD(bus_read_ivar, xlr_pcib_read_ivar),
631	DEVMETHOD(bus_write_ivar, xlr_pcib_write_ivar),
632	DEVMETHOD(bus_alloc_resource, xlr_pci_alloc_resource),
633	DEVMETHOD(bus_release_resource, xlr_pci_release_resource),
634	DEVMETHOD(bus_get_dma_tag, xlr_pci_get_dma_tag),
635	DEVMETHOD(bus_activate_resource, xlr_pci_activate_resource),
636	DEVMETHOD(bus_deactivate_resource, xlr_pci_deactivate_resource),
637	DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr),
638	DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr),
639
640	/* pcib interface */
641	DEVMETHOD(pcib_maxslots, xlr_pcib_maxslots),
642	DEVMETHOD(pcib_read_config, xlr_pcib_read_config),
643	DEVMETHOD(pcib_write_config, xlr_pcib_write_config),
644	DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt),
645
646	DEVMETHOD(pcib_alloc_msi, xlr_alloc_msi),
647	DEVMETHOD(pcib_release_msi, xlr_release_msi),
648	DEVMETHOD(pcib_map_msi, xlr_map_msi),
649
650	DEVMETHOD_END
651};
652
653static driver_t xlr_pcib_driver = {
654	"pcib",
655	xlr_pcib_methods,
656	sizeof(struct xlr_pcib_softc),
657};
658
659DRIVER_MODULE(pcib, iodi, xlr_pcib_driver, pcib_devclass, 0, 0);
660