0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/interrupt.h>
0012 #include <linux/init.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pci.h>
0015 #include <linux/pci-acpi.h>
0016 #include <linux/pci-ecam.h>
0017 #include "../../pci.h"
0018
0019 #if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
0020
0021 struct hisi_pcie {
0022 void __iomem *reg_base;
0023 };
0024
0025 static int hisi_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
0026 int size, u32 *val)
0027 {
0028 struct pci_config_window *cfg = bus->sysdata;
0029 int dev = PCI_SLOT(devfn);
0030
0031 if (bus->number == cfg->busr.start) {
0032
0033 if (dev > 0)
0034 return PCIBIOS_DEVICE_NOT_FOUND;
0035 else
0036 return pci_generic_config_read32(bus, devfn, where,
0037 size, val);
0038 }
0039
0040 return pci_generic_config_read(bus, devfn, where, size, val);
0041 }
0042
0043 static int hisi_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
0044 int where, int size, u32 val)
0045 {
0046 struct pci_config_window *cfg = bus->sysdata;
0047 int dev = PCI_SLOT(devfn);
0048
0049 if (bus->number == cfg->busr.start) {
0050
0051 if (dev > 0)
0052 return PCIBIOS_DEVICE_NOT_FOUND;
0053 else
0054 return pci_generic_config_write32(bus, devfn, where,
0055 size, val);
0056 }
0057
0058 return pci_generic_config_write(bus, devfn, where, size, val);
0059 }
0060
0061 static void __iomem *hisi_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
0062 int where)
0063 {
0064 struct pci_config_window *cfg = bus->sysdata;
0065 struct hisi_pcie *pcie = cfg->priv;
0066
0067 if (bus->number == cfg->busr.start)
0068 return pcie->reg_base + where;
0069 else
0070 return pci_ecam_map_bus(bus, devfn, where);
0071 }
0072
0073 #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
0074
0075 static int hisi_pcie_init(struct pci_config_window *cfg)
0076 {
0077 struct device *dev = cfg->parent;
0078 struct hisi_pcie *pcie;
0079 struct acpi_device *adev = to_acpi_device(dev);
0080 struct acpi_pci_root *root = acpi_driver_data(adev);
0081 struct resource *res;
0082 int ret;
0083
0084 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
0085 if (!pcie)
0086 return -ENOMEM;
0087
0088
0089
0090
0091
0092 res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
0093 if (!res)
0094 return -ENOMEM;
0095
0096 ret = acpi_get_rc_resources(dev, "HISI0081", root->segment, res);
0097 if (ret) {
0098 dev_err(dev, "can't get rc base address\n");
0099 return -ENOMEM;
0100 }
0101
0102 pcie->reg_base = devm_pci_remap_cfgspace(dev, res->start, resource_size(res));
0103 if (!pcie->reg_base)
0104 return -ENOMEM;
0105
0106 cfg->priv = pcie;
0107 return 0;
0108 }
0109
0110 const struct pci_ecam_ops hisi_pcie_ops = {
0111 .init = hisi_pcie_init,
0112 .pci_ops = {
0113 .map_bus = hisi_pcie_map_bus,
0114 .read = hisi_pcie_rd_conf,
0115 .write = hisi_pcie_wr_conf,
0116 }
0117 };
0118
0119 #endif
0120
0121 #ifdef CONFIG_PCI_HISI
0122
0123 static int hisi_pcie_platform_init(struct pci_config_window *cfg)
0124 {
0125 struct device *dev = cfg->parent;
0126 struct hisi_pcie *pcie;
0127 struct platform_device *pdev = to_platform_device(dev);
0128 struct resource *res;
0129
0130 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
0131 if (!pcie)
0132 return -ENOMEM;
0133
0134 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0135 if (!res) {
0136 dev_err(dev, "missing \"reg[1]\"property\n");
0137 return -EINVAL;
0138 }
0139
0140 pcie->reg_base = devm_pci_remap_cfgspace(dev, res->start, resource_size(res));
0141 if (!pcie->reg_base)
0142 return -ENOMEM;
0143
0144 cfg->priv = pcie;
0145 return 0;
0146 }
0147
0148 static const struct pci_ecam_ops hisi_pcie_platform_ops = {
0149 .init = hisi_pcie_platform_init,
0150 .pci_ops = {
0151 .map_bus = hisi_pcie_map_bus,
0152 .read = hisi_pcie_rd_conf,
0153 .write = hisi_pcie_wr_conf,
0154 }
0155 };
0156
0157 static const struct of_device_id hisi_pcie_almost_ecam_of_match[] = {
0158 {
0159 .compatible = "hisilicon,hip06-pcie-ecam",
0160 .data = &hisi_pcie_platform_ops,
0161 },
0162 {
0163 .compatible = "hisilicon,hip07-pcie-ecam",
0164 .data = &hisi_pcie_platform_ops,
0165 },
0166 {},
0167 };
0168
0169 static struct platform_driver hisi_pcie_almost_ecam_driver = {
0170 .probe = pci_host_common_probe,
0171 .driver = {
0172 .name = "hisi-pcie-almost-ecam",
0173 .of_match_table = hisi_pcie_almost_ecam_of_match,
0174 .suppress_bind_attrs = true,
0175 },
0176 };
0177 builtin_platform_driver(hisi_pcie_almost_ecam_driver);
0178
0179 #endif
0180 #endif