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