0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/delay.h>
0011 #include <linux/gpio.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/of_device.h>
0016 #include <linux/pci.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/resource.h>
0019 #include <linux/types.h>
0020
0021 #include "pcie-designware.h"
0022
0023 struct dw_plat_pcie {
0024 struct dw_pcie *pci;
0025 enum dw_pcie_device_mode mode;
0026 };
0027
0028 struct dw_plat_pcie_of_data {
0029 enum dw_pcie_device_mode mode;
0030 };
0031
0032 static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
0033 };
0034
0035 static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
0036 {
0037 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0038 enum pci_barno bar;
0039
0040 for (bar = 0; bar < PCI_STD_NUM_BARS; bar++)
0041 dw_pcie_ep_reset_bar(pci, bar);
0042 }
0043
0044 static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
0045 enum pci_epc_irq_type type,
0046 u16 interrupt_num)
0047 {
0048 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
0049
0050 switch (type) {
0051 case PCI_EPC_IRQ_LEGACY:
0052 return dw_pcie_ep_raise_legacy_irq(ep, func_no);
0053 case PCI_EPC_IRQ_MSI:
0054 return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
0055 case PCI_EPC_IRQ_MSIX:
0056 return dw_pcie_ep_raise_msix_irq(ep, func_no, interrupt_num);
0057 default:
0058 dev_err(pci->dev, "UNKNOWN IRQ type\n");
0059 }
0060
0061 return 0;
0062 }
0063
0064 static const struct pci_epc_features dw_plat_pcie_epc_features = {
0065 .linkup_notifier = false,
0066 .msi_capable = true,
0067 .msix_capable = true,
0068 };
0069
0070 static const struct pci_epc_features*
0071 dw_plat_pcie_get_features(struct dw_pcie_ep *ep)
0072 {
0073 return &dw_plat_pcie_epc_features;
0074 }
0075
0076 static const struct dw_pcie_ep_ops pcie_ep_ops = {
0077 .ep_init = dw_plat_pcie_ep_init,
0078 .raise_irq = dw_plat_pcie_ep_raise_irq,
0079 .get_features = dw_plat_pcie_get_features,
0080 };
0081
0082 static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie,
0083 struct platform_device *pdev)
0084 {
0085 struct dw_pcie *pci = dw_plat_pcie->pci;
0086 struct dw_pcie_rp *pp = &pci->pp;
0087 struct device *dev = &pdev->dev;
0088 int ret;
0089
0090 pp->irq = platform_get_irq(pdev, 1);
0091 if (pp->irq < 0)
0092 return pp->irq;
0093
0094 pp->num_vectors = MAX_MSI_IRQS;
0095 pp->ops = &dw_plat_pcie_host_ops;
0096
0097 ret = dw_pcie_host_init(pp);
0098 if (ret) {
0099 dev_err(dev, "Failed to initialize host\n");
0100 return ret;
0101 }
0102
0103 return 0;
0104 }
0105
0106 static int dw_plat_pcie_probe(struct platform_device *pdev)
0107 {
0108 struct device *dev = &pdev->dev;
0109 struct dw_plat_pcie *dw_plat_pcie;
0110 struct dw_pcie *pci;
0111 int ret;
0112 const struct dw_plat_pcie_of_data *data;
0113 enum dw_pcie_device_mode mode;
0114
0115 data = of_device_get_match_data(dev);
0116 if (!data)
0117 return -EINVAL;
0118
0119 mode = (enum dw_pcie_device_mode)data->mode;
0120
0121 dw_plat_pcie = devm_kzalloc(dev, sizeof(*dw_plat_pcie), GFP_KERNEL);
0122 if (!dw_plat_pcie)
0123 return -ENOMEM;
0124
0125 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
0126 if (!pci)
0127 return -ENOMEM;
0128
0129 pci->dev = dev;
0130
0131 dw_plat_pcie->pci = pci;
0132 dw_plat_pcie->mode = mode;
0133
0134 platform_set_drvdata(pdev, dw_plat_pcie);
0135
0136 switch (dw_plat_pcie->mode) {
0137 case DW_PCIE_RC_TYPE:
0138 if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_HOST))
0139 return -ENODEV;
0140
0141 ret = dw_plat_add_pcie_port(dw_plat_pcie, pdev);
0142 break;
0143 case DW_PCIE_EP_TYPE:
0144 if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_EP))
0145 return -ENODEV;
0146
0147 pci->ep.ops = &pcie_ep_ops;
0148 ret = dw_pcie_ep_init(&pci->ep);
0149 break;
0150 default:
0151 dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);
0152 ret = -EINVAL;
0153 break;
0154 }
0155
0156 return ret;
0157 }
0158
0159 static const struct dw_plat_pcie_of_data dw_plat_pcie_rc_of_data = {
0160 .mode = DW_PCIE_RC_TYPE,
0161 };
0162
0163 static const struct dw_plat_pcie_of_data dw_plat_pcie_ep_of_data = {
0164 .mode = DW_PCIE_EP_TYPE,
0165 };
0166
0167 static const struct of_device_id dw_plat_pcie_of_match[] = {
0168 {
0169 .compatible = "snps,dw-pcie",
0170 .data = &dw_plat_pcie_rc_of_data,
0171 },
0172 {
0173 .compatible = "snps,dw-pcie-ep",
0174 .data = &dw_plat_pcie_ep_of_data,
0175 },
0176 {},
0177 };
0178
0179 static struct platform_driver dw_plat_pcie_driver = {
0180 .driver = {
0181 .name = "dw-pcie",
0182 .of_match_table = dw_plat_pcie_of_match,
0183 .suppress_bind_attrs = true,
0184 },
0185 .probe = dw_plat_pcie_probe,
0186 };
0187 builtin_platform_driver(dw_plat_pcie_driver);