1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * PCIe controller EP driver for Freescale Layerscape SoCs 4 * 5 * Copyright (C) 2018 NXP Semiconductor. 6 * 7 * Author: Xiaowei Bao <xiaowei.bao@nxp.com> 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/init.h> 12 #include <linux/of_pci.h> 13 #include <linux/of_platform.h> 14 #include <linux/of_address.h> 15 #include <linux/pci.h> 16 #include <linux/platform_device.h> 17 #include <linux/resource.h> 18 19 #include "pcie-designware.h" 20 21 #define to_ls_pcie_ep(x) dev_get_drvdata((x)->dev) 22 23 struct ls_pcie_ep_drvdata { 24 u32 func_offset; 25 const struct dw_pcie_ep_ops *ops; 26 const struct dw_pcie_ops *dw_pcie_ops; 27 }; 28 29 struct ls_pcie_ep { 30 struct dw_pcie *pci; 31 struct pci_epc_features *ls_epc; 32 const struct ls_pcie_ep_drvdata *drvdata; 33 }; 34 35 static const struct pci_epc_features* 36 ls_pcie_ep_get_features(struct dw_pcie_ep *ep) 37 { 38 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 39 struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci); 40 41 return pcie->ls_epc; 42 } 43 44 static void ls_pcie_ep_init(struct dw_pcie_ep *ep) 45 { 46 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 47 struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci); 48 struct dw_pcie_ep_func *ep_func; 49 enum pci_barno bar; 50 51 ep_func = dw_pcie_ep_get_func_from_ep(ep, 0); 52 if (!ep_func) 53 return; 54 55 for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) 56 dw_pcie_ep_reset_bar(pci, bar); 57 58 pcie->ls_epc->msi_capable = ep_func->msi_cap ? true : false; 59 pcie->ls_epc->msix_capable = ep_func->msix_cap ? true : false; 60 } 61 62 static int ls_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 63 enum pci_epc_irq_type type, u16 interrupt_num) 64 { 65 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 66 67 switch (type) { 68 case PCI_EPC_IRQ_LEGACY: 69 return dw_pcie_ep_raise_legacy_irq(ep, func_no); 70 case PCI_EPC_IRQ_MSI: 71 return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); 72 case PCI_EPC_IRQ_MSIX: 73 return dw_pcie_ep_raise_msix_irq_doorbell(ep, func_no, 74 interrupt_num); 75 default: 76 dev_err(pci->dev, "UNKNOWN IRQ type\n"); 77 return -EINVAL; 78 } 79 } 80 81 static unsigned int ls_pcie_ep_func_conf_select(struct dw_pcie_ep *ep, 82 u8 func_no) 83 { 84 struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 85 struct ls_pcie_ep *pcie = to_ls_pcie_ep(pci); 86 87 WARN_ON(func_no && !pcie->drvdata->func_offset); 88 return pcie->drvdata->func_offset * func_no; 89 } 90 91 static const struct dw_pcie_ep_ops ls_pcie_ep_ops = { 92 .ep_init = ls_pcie_ep_init, 93 .raise_irq = ls_pcie_ep_raise_irq, 94 .get_features = ls_pcie_ep_get_features, 95 .func_conf_select = ls_pcie_ep_func_conf_select, 96 }; 97 98 static const struct ls_pcie_ep_drvdata ls1_ep_drvdata = { 99 .ops = &ls_pcie_ep_ops, 100 }; 101 102 static const struct ls_pcie_ep_drvdata ls2_ep_drvdata = { 103 .func_offset = 0x20000, 104 .ops = &ls_pcie_ep_ops, 105 }; 106 107 static const struct ls_pcie_ep_drvdata lx2_ep_drvdata = { 108 .func_offset = 0x8000, 109 .ops = &ls_pcie_ep_ops, 110 }; 111 112 static const struct of_device_id ls_pcie_ep_of_match[] = { 113 { .compatible = "fsl,ls1028a-pcie-ep", .data = &ls1_ep_drvdata }, 114 { .compatible = "fsl,ls1046a-pcie-ep", .data = &ls1_ep_drvdata }, 115 { .compatible = "fsl,ls1088a-pcie-ep", .data = &ls2_ep_drvdata }, 116 { .compatible = "fsl,ls2088a-pcie-ep", .data = &ls2_ep_drvdata }, 117 { .compatible = "fsl,lx2160ar2-pcie-ep", .data = &lx2_ep_drvdata }, 118 { }, 119 }; 120 121 static int __init ls_pcie_ep_probe(struct platform_device *pdev) 122 { 123 struct device *dev = &pdev->dev; 124 struct dw_pcie *pci; 125 struct ls_pcie_ep *pcie; 126 struct pci_epc_features *ls_epc; 127 struct resource *dbi_base; 128 129 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 130 if (!pcie) 131 return -ENOMEM; 132 133 pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 134 if (!pci) 135 return -ENOMEM; 136 137 ls_epc = devm_kzalloc(dev, sizeof(*ls_epc), GFP_KERNEL); 138 if (!ls_epc) 139 return -ENOMEM; 140 141 pcie->drvdata = of_device_get_match_data(dev); 142 143 pci->dev = dev; 144 pci->ops = pcie->drvdata->dw_pcie_ops; 145 146 ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4); 147 148 pcie->pci = pci; 149 pcie->ls_epc = ls_epc; 150 151 dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); 152 pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base); 153 if (IS_ERR(pci->dbi_base)) 154 return PTR_ERR(pci->dbi_base); 155 156 pci->ep.ops = &ls_pcie_ep_ops; 157 158 platform_set_drvdata(pdev, pcie); 159 160 return dw_pcie_ep_init(&pci->ep); 161 } 162 163 static struct platform_driver ls_pcie_ep_driver = { 164 .driver = { 165 .name = "layerscape-pcie-ep", 166 .of_match_table = ls_pcie_ep_of_match, 167 .suppress_bind_attrs = true, 168 }, 169 }; 170 builtin_platform_driver_probe(ls_pcie_ep_driver, ls_pcie_ep_probe); 171