xref: /freebsd/sys/arm64/cavium/thunder_pcie_pem_fdt.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
19ccaab6dSZbigniew Bodek /*
29ccaab6dSZbigniew Bodek  * Copyright (C) 2016 Cavium Inc.
39ccaab6dSZbigniew Bodek  * All rights reserved.
49ccaab6dSZbigniew Bodek  *
59ccaab6dSZbigniew Bodek  * Developed by Semihalf.
69ccaab6dSZbigniew Bodek  *
79ccaab6dSZbigniew Bodek  * Redistribution and use in source and binary forms, with or without
89ccaab6dSZbigniew Bodek  * modification, are permitted provided that the following conditions
99ccaab6dSZbigniew Bodek  * are met:
109ccaab6dSZbigniew Bodek  * 1. Redistributions of source code must retain the above copyright
119ccaab6dSZbigniew Bodek  *    notice, this list of conditions and the following disclaimer.
129ccaab6dSZbigniew Bodek  * 2. Redistributions in binary form must reproduce the above copyright
139ccaab6dSZbigniew Bodek  *    notice, this list of conditions and the following disclaimer in the
149ccaab6dSZbigniew Bodek  *    documentation and/or other materials provided with the distribution.
159ccaab6dSZbigniew Bodek  *
169ccaab6dSZbigniew Bodek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179ccaab6dSZbigniew Bodek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189ccaab6dSZbigniew Bodek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199ccaab6dSZbigniew Bodek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209ccaab6dSZbigniew Bodek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219ccaab6dSZbigniew Bodek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229ccaab6dSZbigniew Bodek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239ccaab6dSZbigniew Bodek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249ccaab6dSZbigniew Bodek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259ccaab6dSZbigniew Bodek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269ccaab6dSZbigniew Bodek  * SUCH DAMAGE.
279ccaab6dSZbigniew Bodek  */
289ccaab6dSZbigniew Bodek #include <sys/cdefs.h>
29fb05500bSWojciech Macek #include "opt_platform.h"
30fb05500bSWojciech Macek 
319ccaab6dSZbigniew Bodek #include <sys/param.h>
329ccaab6dSZbigniew Bodek #include <sys/systm.h>
339ccaab6dSZbigniew Bodek #include <sys/malloc.h>
349ccaab6dSZbigniew Bodek #include <sys/types.h>
359ccaab6dSZbigniew Bodek #include <sys/sysctl.h>
369ccaab6dSZbigniew Bodek #include <sys/kernel.h>
379ccaab6dSZbigniew Bodek #include <sys/rman.h>
389ccaab6dSZbigniew Bodek #include <sys/module.h>
399ccaab6dSZbigniew Bodek #include <sys/bus.h>
409ccaab6dSZbigniew Bodek #include <sys/endian.h>
419ccaab6dSZbigniew Bodek #include <sys/cpuset.h>
429ccaab6dSZbigniew Bodek 
439ccaab6dSZbigniew Bodek #include <dev/ofw/openfirm.h>
449ccaab6dSZbigniew Bodek #include <dev/ofw/ofw_bus.h>
459ccaab6dSZbigniew Bodek #include <dev/ofw/ofw_bus_subr.h>
469ccaab6dSZbigniew Bodek 
47fb05500bSWojciech Macek #include <dev/pci/pcivar.h>
48fb05500bSWojciech Macek #include <dev/pci/pcireg.h>
49fb05500bSWojciech Macek #include <dev/pci/pcib_private.h>
50fb05500bSWojciech Macek #include <dev/pci/pci_host_generic.h>
51fb05500bSWojciech Macek 
52fb853e42SAndrew Turner #include <machine/intr.h>
53fb853e42SAndrew Turner 
549ccaab6dSZbigniew Bodek #include "thunder_pcie_common.h"
559ccaab6dSZbigniew Bodek #include "thunder_pcie_pem.h"
569ccaab6dSZbigniew Bodek 
57fb853e42SAndrew Turner #include "pcib_if.h"
58fb853e42SAndrew Turner 
599ccaab6dSZbigniew Bodek static int thunder_pem_fdt_probe(device_t);
60fb853e42SAndrew Turner static int thunder_pem_fdt_alloc_msix(device_t, device_t, int *);
61fb853e42SAndrew Turner static int thunder_pem_fdt_release_msix(device_t, device_t, int);
62fb853e42SAndrew Turner static int thunder_pem_fdt_alloc_msi(device_t, device_t, int, int, int *);
63fb853e42SAndrew Turner static int thunder_pem_fdt_release_msi(device_t, device_t, int, int *);
64fb853e42SAndrew Turner static int thunder_pem_fdt_map_msi(device_t, device_t, int, uint64_t *,
65fb853e42SAndrew Turner     uint32_t *);
661e43b18cSAndrew Turner static int thunder_pem_fdt_get_id(device_t, device_t, enum pci_id_type,
671e43b18cSAndrew Turner     uintptr_t *);
689ccaab6dSZbigniew Bodek 
699ccaab6dSZbigniew Bodek static device_method_t thunder_pem_fdt_methods[] = {
709ccaab6dSZbigniew Bodek 	/* Device interface */
719ccaab6dSZbigniew Bodek 	DEVMETHOD(device_probe,		thunder_pem_fdt_probe),
729ccaab6dSZbigniew Bodek 
73fb853e42SAndrew Turner 	/* pcib interface */
74fb853e42SAndrew Turner 	DEVMETHOD(pcib_alloc_msix,	thunder_pem_fdt_alloc_msix),
75fb853e42SAndrew Turner 	DEVMETHOD(pcib_release_msix,	thunder_pem_fdt_release_msix),
76fb853e42SAndrew Turner 	DEVMETHOD(pcib_alloc_msi,	thunder_pem_fdt_alloc_msi),
77fb853e42SAndrew Turner 	DEVMETHOD(pcib_release_msi,	thunder_pem_fdt_release_msi),
78fb853e42SAndrew Turner 	DEVMETHOD(pcib_map_msi,		thunder_pem_fdt_map_msi),
791e43b18cSAndrew Turner 	DEVMETHOD(pcib_get_id,		thunder_pem_fdt_get_id),
80fb853e42SAndrew Turner 
819ccaab6dSZbigniew Bodek 	/* End */
829ccaab6dSZbigniew Bodek 	DEVMETHOD_END
839ccaab6dSZbigniew Bodek };
849ccaab6dSZbigniew Bodek 
859ccaab6dSZbigniew Bodek DEFINE_CLASS_1(pcib, thunder_pem_fdt_driver, thunder_pem_fdt_methods,
869ccaab6dSZbigniew Bodek     sizeof(struct thunder_pem_softc), thunder_pem_driver);
879ccaab6dSZbigniew Bodek 
88*d99a98d5SJohn Baldwin DRIVER_MODULE(thunder_pem, simplebus, thunder_pem_fdt_driver, 0, 0);
89*d99a98d5SJohn Baldwin DRIVER_MODULE(thunder_pem, ofwbus, thunder_pem_fdt_driver, 0, 0);
909ccaab6dSZbigniew Bodek 
919ccaab6dSZbigniew Bodek static int
thunder_pem_fdt_probe(device_t dev)929ccaab6dSZbigniew Bodek thunder_pem_fdt_probe(device_t dev)
939ccaab6dSZbigniew Bodek {
949ccaab6dSZbigniew Bodek 
959ccaab6dSZbigniew Bodek 	if (!ofw_bus_status_okay(dev))
969ccaab6dSZbigniew Bodek 		return (ENXIO);
979ccaab6dSZbigniew Bodek 
989ccaab6dSZbigniew Bodek 	if (ofw_bus_is_compatible(dev, "cavium,pci-host-thunder-pem")) {
999ccaab6dSZbigniew Bodek 		device_set_desc(dev, THUNDER_PEM_DESC);
1009ccaab6dSZbigniew Bodek 		return (BUS_PROBE_DEFAULT);
1019ccaab6dSZbigniew Bodek 	}
1029ccaab6dSZbigniew Bodek 
1039ccaab6dSZbigniew Bodek 	return (ENXIO);
1049ccaab6dSZbigniew Bodek }
105fb853e42SAndrew Turner 
1064e1763d3SAndrew Turner static int
thunder_pem_fdt_alloc_msi(device_t pci,device_t child,int count,int maxcount,int * irqs)1074e1763d3SAndrew Turner thunder_pem_fdt_alloc_msi(device_t pci, device_t child, int count, int maxcount,
1084e1763d3SAndrew Turner     int *irqs)
1094e1763d3SAndrew Turner {
1104e1763d3SAndrew Turner 	phandle_t msi_parent;
11186b5c436SAndrew Turner 	int err;
1124e1763d3SAndrew Turner 
11386b5c436SAndrew Turner 	err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
11486b5c436SAndrew Turner 	    &msi_parent, NULL);
11586b5c436SAndrew Turner 	if (err != 0)
11686b5c436SAndrew Turner 		return (err);
1174e1763d3SAndrew Turner 	return (intr_alloc_msi(pci, child, msi_parent, count, maxcount,
1184e1763d3SAndrew Turner 	    irqs));
1194e1763d3SAndrew Turner }
1204e1763d3SAndrew Turner 
1214e1763d3SAndrew Turner static int
thunder_pem_fdt_release_msi(device_t pci,device_t child,int count,int * irqs)1224e1763d3SAndrew Turner thunder_pem_fdt_release_msi(device_t pci, device_t child, int count, int *irqs)
1234e1763d3SAndrew Turner {
1244e1763d3SAndrew Turner 	phandle_t msi_parent;
12586b5c436SAndrew Turner 	int err;
1264e1763d3SAndrew Turner 
12786b5c436SAndrew Turner 	err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
12886b5c436SAndrew Turner 	    &msi_parent, NULL);
12986b5c436SAndrew Turner 	if (err != 0)
13086b5c436SAndrew Turner 		return (err);
1314e1763d3SAndrew Turner 	return (intr_release_msi(pci, child, msi_parent, count, irqs));
1324e1763d3SAndrew Turner }
1334e1763d3SAndrew Turner 
1344e1763d3SAndrew Turner static int
thunder_pem_fdt_alloc_msix(device_t pci,device_t child,int * irq)1354e1763d3SAndrew Turner thunder_pem_fdt_alloc_msix(device_t pci, device_t child, int *irq)
1364e1763d3SAndrew Turner {
1374e1763d3SAndrew Turner 	phandle_t msi_parent;
13886b5c436SAndrew Turner 	int err;
1394e1763d3SAndrew Turner 
14086b5c436SAndrew Turner 	err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
14186b5c436SAndrew Turner 	    &msi_parent, NULL);
14286b5c436SAndrew Turner 	if (err != 0)
14386b5c436SAndrew Turner 		return (err);
1444e1763d3SAndrew Turner 	return (intr_alloc_msix(pci, child, msi_parent, irq));
1454e1763d3SAndrew Turner }
1464e1763d3SAndrew Turner 
1474e1763d3SAndrew Turner static int
thunder_pem_fdt_release_msix(device_t pci,device_t child,int irq)1484e1763d3SAndrew Turner thunder_pem_fdt_release_msix(device_t pci, device_t child, int irq)
1494e1763d3SAndrew Turner {
1504e1763d3SAndrew Turner 	phandle_t msi_parent;
15186b5c436SAndrew Turner 	int err;
1524e1763d3SAndrew Turner 
15386b5c436SAndrew Turner 	err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
15486b5c436SAndrew Turner 	    &msi_parent, NULL);
15586b5c436SAndrew Turner 	if (err != 0)
15686b5c436SAndrew Turner 		return (err);
1574e1763d3SAndrew Turner 	return (intr_release_msix(pci, child, msi_parent, irq));
1584e1763d3SAndrew Turner }
1594e1763d3SAndrew Turner 
1604e1763d3SAndrew Turner static int
thunder_pem_fdt_map_msi(device_t pci,device_t child,int irq,uint64_t * addr,uint32_t * data)1614e1763d3SAndrew Turner thunder_pem_fdt_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
1624e1763d3SAndrew Turner     uint32_t *data)
1634e1763d3SAndrew Turner {
1644e1763d3SAndrew Turner 	phandle_t msi_parent;
16586b5c436SAndrew Turner 	int err;
1664e1763d3SAndrew Turner 
16786b5c436SAndrew Turner 	err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
16886b5c436SAndrew Turner 	    &msi_parent, NULL);
16986b5c436SAndrew Turner 	if (err != 0)
17086b5c436SAndrew Turner 		return (err);
1714e1763d3SAndrew Turner 	return (intr_map_msi(pci, child, msi_parent, irq, addr, data));
1724e1763d3SAndrew Turner }
1731e43b18cSAndrew Turner 
1741e43b18cSAndrew Turner static int
thunder_pem_fdt_get_id(device_t dev,device_t child,enum pci_id_type type,uintptr_t * id)1751e43b18cSAndrew Turner thunder_pem_fdt_get_id(device_t dev, device_t child, enum pci_id_type type,
1761e43b18cSAndrew Turner     uintptr_t *id)
1771e43b18cSAndrew Turner {
1781e43b18cSAndrew Turner 	phandle_t node;
17986b5c436SAndrew Turner 	int err;
1801e43b18cSAndrew Turner 	uint32_t rid;
1811e43b18cSAndrew Turner 	uint16_t pci_rid;
1821e43b18cSAndrew Turner 
1831e43b18cSAndrew Turner 	if (type != PCI_ID_MSI)
1841e43b18cSAndrew Turner 		return (pcib_get_id(dev, child, type, id));
1851e43b18cSAndrew Turner 
1861e43b18cSAndrew Turner 	node = ofw_bus_get_node(dev);
1871e43b18cSAndrew Turner 	pci_rid = pci_get_rid(child);
1881e43b18cSAndrew Turner 
18986b5c436SAndrew Turner 	err = ofw_bus_msimap(node, pci_rid, NULL, &rid);
19086b5c436SAndrew Turner 	if (err != 0)
19186b5c436SAndrew Turner 		return (err);
1921e43b18cSAndrew Turner 	*id = rid;
1931e43b18cSAndrew Turner 
1941e43b18cSAndrew Turner 	return (0);
1951e43b18cSAndrew Turner }
196