Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2015 Broadcom Corporation
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/pci.h>
0008 #include <linux/clk.h>
0009 #include <linux/module.h>
0010 #include <linux/slab.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/of_address.h>
0014 #include <linux/of_pci.h>
0015 #include <linux/of_irq.h>
0016 #include <linux/of_platform.h>
0017 #include <linux/phy/phy.h>
0018 
0019 #include "../pci.h"
0020 #include "pcie-iproc.h"
0021 
0022 static const struct of_device_id iproc_pcie_of_match_table[] = {
0023     {
0024         .compatible = "brcm,iproc-pcie",
0025         .data = (int *)IPROC_PCIE_PAXB,
0026     }, {
0027         .compatible = "brcm,iproc-pcie-paxb-v2",
0028         .data = (int *)IPROC_PCIE_PAXB_V2,
0029     }, {
0030         .compatible = "brcm,iproc-pcie-paxc",
0031         .data = (int *)IPROC_PCIE_PAXC,
0032     }, {
0033         .compatible = "brcm,iproc-pcie-paxc-v2",
0034         .data = (int *)IPROC_PCIE_PAXC_V2,
0035     },
0036     { /* sentinel */ }
0037 };
0038 MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
0039 
0040 static int iproc_pltfm_pcie_probe(struct platform_device *pdev)
0041 {
0042     struct device *dev = &pdev->dev;
0043     struct iproc_pcie *pcie;
0044     struct device_node *np = dev->of_node;
0045     struct resource reg;
0046     struct pci_host_bridge *bridge;
0047     int ret;
0048 
0049     bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
0050     if (!bridge)
0051         return -ENOMEM;
0052 
0053     pcie = pci_host_bridge_priv(bridge);
0054 
0055     pcie->dev = dev;
0056     pcie->type = (enum iproc_pcie_type) of_device_get_match_data(dev);
0057 
0058     ret = of_address_to_resource(np, 0, &reg);
0059     if (ret < 0) {
0060         dev_err(dev, "unable to obtain controller resources\n");
0061         return ret;
0062     }
0063 
0064     pcie->base = devm_pci_remap_cfgspace(dev, reg.start,
0065                          resource_size(&reg));
0066     if (!pcie->base) {
0067         dev_err(dev, "unable to map controller registers\n");
0068         return -ENOMEM;
0069     }
0070     pcie->base_addr = reg.start;
0071 
0072     if (of_property_read_bool(np, "brcm,pcie-ob")) {
0073         u32 val;
0074 
0075         ret = of_property_read_u32(np, "brcm,pcie-ob-axi-offset",
0076                        &val);
0077         if (ret) {
0078             dev_err(dev,
0079                 "missing brcm,pcie-ob-axi-offset property\n");
0080             return ret;
0081         }
0082         pcie->ob.axi_offset = val;
0083         pcie->need_ob_cfg = true;
0084     }
0085 
0086     /*
0087      * DT nodes are not used by all platforms that use the iProc PCIe
0088      * core driver. For platforms that require explicit inbound mapping
0089      * configuration, "dma-ranges" would have been present in DT
0090      */
0091     pcie->need_ib_cfg = of_property_read_bool(np, "dma-ranges");
0092 
0093     /* PHY use is optional */
0094     pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
0095     if (IS_ERR(pcie->phy))
0096         return PTR_ERR(pcie->phy);
0097 
0098     /* PAXC doesn't support legacy IRQs, skip mapping */
0099     switch (pcie->type) {
0100     case IPROC_PCIE_PAXC:
0101     case IPROC_PCIE_PAXC_V2:
0102         pcie->map_irq = NULL;
0103         break;
0104     default:
0105         break;
0106     }
0107 
0108     ret = iproc_pcie_setup(pcie, &bridge->windows);
0109     if (ret) {
0110         dev_err(dev, "PCIe controller setup failed\n");
0111         return ret;
0112     }
0113 
0114     platform_set_drvdata(pdev, pcie);
0115     return 0;
0116 }
0117 
0118 static int iproc_pltfm_pcie_remove(struct platform_device *pdev)
0119 {
0120     struct iproc_pcie *pcie = platform_get_drvdata(pdev);
0121 
0122     return iproc_pcie_remove(pcie);
0123 }
0124 
0125 static void iproc_pltfm_pcie_shutdown(struct platform_device *pdev)
0126 {
0127     struct iproc_pcie *pcie = platform_get_drvdata(pdev);
0128 
0129     iproc_pcie_shutdown(pcie);
0130 }
0131 
0132 static struct platform_driver iproc_pltfm_pcie_driver = {
0133     .driver = {
0134         .name = "iproc-pcie",
0135         .of_match_table = of_match_ptr(iproc_pcie_of_match_table),
0136     },
0137     .probe = iproc_pltfm_pcie_probe,
0138     .remove = iproc_pltfm_pcie_remove,
0139     .shutdown = iproc_pltfm_pcie_shutdown,
0140 };
0141 module_platform_driver(iproc_pltfm_pcie_driver);
0142 
0143 MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
0144 MODULE_DESCRIPTION("Broadcom iPROC PCIe platform driver");
0145 MODULE_LICENSE("GPL v2");