0001
0002
0003
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 { }
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, ®);
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(®));
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
0088
0089
0090
0091 pcie->need_ib_cfg = of_property_read_bool(np, "dma-ranges");
0092
0093
0094 pcie->phy = devm_phy_optional_get(dev, "pcie-phy");
0095 if (IS_ERR(pcie->phy))
0096 return PTR_ERR(pcie->phy);
0097
0098
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");