diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2017-11-14 13:11:30 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-11-14 13:11:30 -0500 |
commit | d535969614d547f149e9d6d31e54d5434069a31e (patch) | |
tree | 726f1eb61b7fde244b3efa7a7ff5ebb2ff2baebb | |
parent | 807dcfee426b407f7175fefc4c255594c6f257f5 (diff) | |
parent | 19f3f22aade704f9ce82a55c853381e672629a1d (diff) |
Merge branch 'pci/host-generic' into next
* pci/host-generic:
dt-bindings: PCI: designware: Add binding for Designware PCIe in ECAM mode
PCI: generic: Add support for Synopsys DesignWare RC in ECAM mode
-rw-r--r-- | Documentation/devicetree/bindings/pci/designware-pcie-ecam.txt | 42 | ||||
-rw-r--r-- | drivers/pci/host/pci-host-generic.c | 43 |
2 files changed, 85 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie-ecam.txt b/Documentation/devicetree/bindings/pci/designware-pcie-ecam.txt new file mode 100644 index 000000000000..515b2f9542e5 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/designware-pcie-ecam.txt | |||
@@ -0,0 +1,42 @@ | |||
1 | * Synopsys DesignWare PCIe root complex in ECAM shift mode | ||
2 | |||
3 | In some cases, firmware may already have configured the Synopsys DesignWare | ||
4 | PCIe controller in RC mode with static ATU window mappings that cover all | ||
5 | config, MMIO and I/O spaces in a [mostly] ECAM compatible fashion. | ||
6 | In this case, there is no need for the OS to perform any low level setup | ||
7 | of clocks, PHYs or device registers, nor is there any reason for the driver | ||
8 | to reconfigure ATU windows for config and/or IO space accesses at runtime. | ||
9 | |||
10 | In cases where the IP was synthesized with a minimum ATU window size of | ||
11 | 64 KB, it cannot be supported by the generic ECAM driver, because it | ||
12 | requires special config space accessors that filter accesses to device #1 | ||
13 | and beyond on the first bus. | ||
14 | |||
15 | Required properties: | ||
16 | - compatible: "marvell,armada8k-pcie-ecam" or | ||
17 | "socionext,synquacer-pcie-ecam" or | ||
18 | "snps,dw-pcie-ecam" (must be preceded by a more specific match) | ||
19 | |||
20 | Please refer to the binding document of "pci-host-ecam-generic" in the | ||
21 | file host-generic-pci.txt for a description of the remaining required | ||
22 | and optional properties. | ||
23 | |||
24 | Example: | ||
25 | |||
26 | pcie1: pcie@7f000000 { | ||
27 | compatible = "socionext,synquacer-pcie-ecam", "snps,dw-pcie-ecam"; | ||
28 | device_type = "pci"; | ||
29 | reg = <0x0 0x7f000000 0x0 0xf00000>; | ||
30 | bus-range = <0x0 0xe>; | ||
31 | #address-cells = <3>; | ||
32 | #size-cells = <2>; | ||
33 | ranges = <0x1000000 0x00 0x00010000 0x00 0x7ff00000 0x0 0x00010000>, | ||
34 | <0x2000000 0x00 0x70000000 0x00 0x70000000 0x0 0x0f000000>, | ||
35 | <0x3000000 0x3f 0x00000000 0x3f 0x00000000 0x1 0x00000000>; | ||
36 | |||
37 | #interrupt-cells = <0x1>; | ||
38 | interrupt-map-mask = <0x0 0x0 0x0 0x0>; | ||
39 | interrupt-map = <0x0 0x0 0x0 0x0 &gic 0x0 0x0 0x0 182 0x4>; | ||
40 | msi-map = <0x0 &its 0x0 0x10000>; | ||
41 | dma-coherent; | ||
42 | }; | ||
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c index 7d709a7e0aa8..2f05511ce718 100644 --- a/drivers/pci/host/pci-host-generic.c +++ b/drivers/pci/host/pci-host-generic.c | |||
@@ -35,6 +35,40 @@ static struct pci_ecam_ops gen_pci_cfg_cam_bus_ops = { | |||
35 | } | 35 | } |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static bool pci_dw_valid_device(struct pci_bus *bus, unsigned int devfn) | ||
39 | { | ||
40 | struct pci_config_window *cfg = bus->sysdata; | ||
41 | |||
42 | /* | ||
43 | * The Synopsys DesignWare PCIe controller in ECAM mode will not filter | ||
44 | * type 0 config TLPs sent to devices 1 and up on its downstream port, | ||
45 | * resulting in devices appearing multiple times on bus 0 unless we | ||
46 | * filter out those accesses here. | ||
47 | */ | ||
48 | if (bus->number == cfg->busr.start && PCI_SLOT(devfn) > 0) | ||
49 | return false; | ||
50 | |||
51 | return true; | ||
52 | } | ||
53 | |||
54 | static void __iomem *pci_dw_ecam_map_bus(struct pci_bus *bus, | ||
55 | unsigned int devfn, int where) | ||
56 | { | ||
57 | if (!pci_dw_valid_device(bus, devfn)) | ||
58 | return NULL; | ||
59 | |||
60 | return pci_ecam_map_bus(bus, devfn, where); | ||
61 | } | ||
62 | |||
63 | static struct pci_ecam_ops pci_dw_ecam_bus_ops = { | ||
64 | .bus_shift = 20, | ||
65 | .pci_ops = { | ||
66 | .map_bus = pci_dw_ecam_map_bus, | ||
67 | .read = pci_generic_config_read, | ||
68 | .write = pci_generic_config_write, | ||
69 | } | ||
70 | }; | ||
71 | |||
38 | static const struct of_device_id gen_pci_of_match[] = { | 72 | static const struct of_device_id gen_pci_of_match[] = { |
39 | { .compatible = "pci-host-cam-generic", | 73 | { .compatible = "pci-host-cam-generic", |
40 | .data = &gen_pci_cfg_cam_bus_ops }, | 74 | .data = &gen_pci_cfg_cam_bus_ops }, |
@@ -42,6 +76,15 @@ static const struct of_device_id gen_pci_of_match[] = { | |||
42 | { .compatible = "pci-host-ecam-generic", | 76 | { .compatible = "pci-host-ecam-generic", |
43 | .data = &pci_generic_ecam_ops }, | 77 | .data = &pci_generic_ecam_ops }, |
44 | 78 | ||
79 | { .compatible = "marvell,armada8k-pcie-ecam", | ||
80 | .data = &pci_dw_ecam_bus_ops }, | ||
81 | |||
82 | { .compatible = "socionext,synquacer-pcie-ecam", | ||
83 | .data = &pci_dw_ecam_bus_ops }, | ||
84 | |||
85 | { .compatible = "snps,dw-pcie-ecam", | ||
86 | .data = &pci_dw_ecam_bus_ops }, | ||
87 | |||
45 | { }, | 88 | { }, |
46 | }; | 89 | }; |
47 | 90 | ||