diff options
45 files changed, 2384 insertions, 360 deletions
diff --git a/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt index 45c2a8094a9f..01b88f4e0d5b 100644 --- a/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt +++ b/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt | |||
@@ -1,7 +1,10 @@ | |||
1 | * Broadcom iProc PCIe controller with the platform bus interface | 1 | * Broadcom iProc PCIe controller with the platform bus interface |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Must be "brcm,iproc-pcie" | 4 | - compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc" |
5 | for PAXC. PAXB-based root complex is used for external endpoint devices. | ||
6 | PAXC-based root complex is connected to emulated endpoint devices | ||
7 | internal to the ASIC | ||
5 | - reg: base address and length of the PCIe controller I/O register space | 8 | - reg: base address and length of the PCIe controller I/O register space |
6 | - #interrupt-cells: set to <1> | 9 | - #interrupt-cells: set to <1> |
7 | - interrupt-map-mask and interrupt-map, standard PCI properties to define the | 10 | - interrupt-map-mask and interrupt-map, standard PCI properties to define the |
@@ -32,6 +35,28 @@ Optional: | |||
32 | - brcm,pcie-ob-oarr-size: Some iProc SoCs need the OARR size bit to be set to | 35 | - brcm,pcie-ob-oarr-size: Some iProc SoCs need the OARR size bit to be set to |
33 | increase the outbound window size | 36 | increase the outbound window size |
34 | 37 | ||
38 | MSI support (optional): | ||
39 | |||
40 | For older platforms without MSI integrated in the GIC, iProc PCIe core provides | ||
41 | an event queue based MSI support. The iProc MSI uses host memories to store | ||
42 | MSI posted writes in the event queues | ||
43 | |||
44 | - msi-parent: Link to the device node of the MSI controller. On newer iProc | ||
45 | platforms, the MSI controller may be gicv2m or gicv3-its. On older iProc | ||
46 | platforms without MSI support in its interrupt controller, one may use the | ||
47 | event queue based MSI support integrated within the iProc PCIe core. | ||
48 | |||
49 | When the iProc event queue based MSI is used, one needs to define the | ||
50 | following properties in the MSI device node: | ||
51 | - compatible: Must be "brcm,iproc-msi" | ||
52 | - msi-controller: claims itself as an MSI controller | ||
53 | - interrupt-parent: Link to its parent interrupt device | ||
54 | - interrupts: List of interrupt IDs from its parent interrupt device | ||
55 | |||
56 | Optional properties: | ||
57 | - brcm,pcie-msi-inten: Needs to be present for some older iProc platforms that | ||
58 | require the interrupt enable registers to be set explicitly to enable MSI | ||
59 | |||
35 | Example: | 60 | Example: |
36 | pcie0: pcie@18012000 { | 61 | pcie0: pcie@18012000 { |
37 | compatible = "brcm,iproc-pcie"; | 62 | compatible = "brcm,iproc-pcie"; |
@@ -58,6 +83,19 @@ Example: | |||
58 | brcm,pcie-ob-oarr-size; | 83 | brcm,pcie-ob-oarr-size; |
59 | brcm,pcie-ob-axi-offset = <0x00000000>; | 84 | brcm,pcie-ob-axi-offset = <0x00000000>; |
60 | brcm,pcie-ob-window-size = <256>; | 85 | brcm,pcie-ob-window-size = <256>; |
86 | |||
87 | msi-parent = <&msi0>; | ||
88 | |||
89 | /* iProc event queue based MSI */ | ||
90 | msi0: msi@18012000 { | ||
91 | compatible = "brcm,iproc-msi"; | ||
92 | msi-controller; | ||
93 | interrupt-parent = <&gic>; | ||
94 | interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>, | ||
95 | <GIC_SPI 97 IRQ_TYPE_NONE>, | ||
96 | <GIC_SPI 98 IRQ_TYPE_NONE>, | ||
97 | <GIC_SPI 99 IRQ_TYPE_NONE>, | ||
98 | }; | ||
61 | }; | 99 | }; |
62 | 100 | ||
63 | pcie1: pcie@18013000 { | 101 | pcie1: pcie@18013000 { |
diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt index 17c6ed9c6059..b721beacfe4d 100644 --- a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt +++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | HiSilicon PCIe host bridge DT description | 1 | HiSilicon Hip05 and Hip06 PCIe host bridge DT description |
2 | 2 | ||
3 | HiSilicon PCIe host controller is based on Designware PCI core. | 3 | HiSilicon PCIe host controller is based on Designware PCI core. |
4 | It shares common functions with PCIe Designware core driver and inherits | 4 | It shares common functions with PCIe Designware core driver and inherits |
@@ -7,8 +7,8 @@ Documentation/devicetree/bindings/pci/designware-pci.txt. | |||
7 | 7 | ||
8 | Additional properties are described here: | 8 | Additional properties are described here: |
9 | 9 | ||
10 | Required properties: | 10 | Required properties |
11 | - compatible: Should contain "hisilicon,hip05-pcie". | 11 | - compatible: Should contain "hisilicon,hip05-pcie" or "hisilicon,hip06-pcie". |
12 | - reg: Should contain rc_dbi, config registers location and length. | 12 | - reg: Should contain rc_dbi, config registers location and length. |
13 | - reg-names: Must include the following entries: | 13 | - reg-names: Must include the following entries: |
14 | "rc_dbi": controller configuration registers; | 14 | "rc_dbi": controller configuration registers; |
@@ -20,7 +20,7 @@ Optional properties: | |||
20 | - status: Either "ok" or "disabled". | 20 | - status: Either "ok" or "disabled". |
21 | - dma-coherent: Present if DMA operations are coherent. | 21 | - dma-coherent: Present if DMA operations are coherent. |
22 | 22 | ||
23 | Example: | 23 | Hip05 Example (note that Hip06 is the same except compatible): |
24 | pcie@0xb0080000 { | 24 | pcie@0xb0080000 { |
25 | compatible = "hisilicon,hip05-pcie", "snps,dw-pcie"; | 25 | compatible = "hisilicon,hip05-pcie", "snps,dw-pcie"; |
26 | reg = <0 0xb0080000 0 0x10000>, <0x220 0x00000000 0 0x2000>; | 26 | reg = <0 0xb0080000 0 0x10000>, <0x220 0x00000000 0 0x2000>; |
diff --git a/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt b/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt index 7fab84b33531..4e8b90e43dd8 100644 --- a/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt +++ b/Documentation/devicetree/bindings/pci/pci-rcar-gen2.txt | |||
@@ -8,7 +8,14 @@ OHCI and EHCI controllers. | |||
8 | Required properties: | 8 | Required properties: |
9 | - compatible: "renesas,pci-r8a7790" for the R8A7790 SoC; | 9 | - compatible: "renesas,pci-r8a7790" for the R8A7790 SoC; |
10 | "renesas,pci-r8a7791" for the R8A7791 SoC; | 10 | "renesas,pci-r8a7791" for the R8A7791 SoC; |
11 | "renesas,pci-r8a7794" for the R8A7794 SoC. | 11 | "renesas,pci-r8a7794" for the R8A7794 SoC; |
12 | "renesas,pci-rcar-gen2" for a generic R-Car Gen2 compatible device | ||
13 | |||
14 | |||
15 | When compatible with the generic version, nodes must list the | ||
16 | SoC-specific version corresponding to the platform first | ||
17 | followed by the generic version. | ||
18 | |||
12 | - reg: A list of physical regions to access the device: the first is | 19 | - reg: A list of physical regions to access the device: the first is |
13 | the operational registers for the OHCI/EHCI controllers and the | 20 | the operational registers for the OHCI/EHCI controllers and the |
14 | second is for the bridge configuration and control registers. | 21 | second is for the bridge configuration and control registers. |
@@ -24,10 +31,15 @@ Required properties: | |||
24 | - interrupt-map-mask: standard property that helps to define the interrupt | 31 | - interrupt-map-mask: standard property that helps to define the interrupt |
25 | mapping. | 32 | mapping. |
26 | 33 | ||
34 | Optional properties: | ||
35 | - dma-ranges: a single range for the inbound memory region. If not supplied, | ||
36 | defaults to 1GiB at 0x40000000. Note there are hardware restrictions on the | ||
37 | allowed combinations of address and size. | ||
38 | |||
27 | Example SoC configuration: | 39 | Example SoC configuration: |
28 | 40 | ||
29 | pci0: pci@ee090000 { | 41 | pci0: pci@ee090000 { |
30 | compatible = "renesas,pci-r8a7790"; | 42 | compatible = "renesas,pci-r8a7790", "renesas,pci-rcar-gen2"; |
31 | clocks = <&mstp7_clks R8A7790_CLK_EHCI>; | 43 | clocks = <&mstp7_clks R8A7790_CLK_EHCI>; |
32 | reg = <0x0 0xee090000 0x0 0xc00>, | 44 | reg = <0x0 0xee090000 0x0 0xc00>, |
33 | <0x0 0xee080000 0x0 0x1100>; | 45 | <0x0 0xee080000 0x0 0x1100>; |
@@ -38,6 +50,7 @@ Example SoC configuration: | |||
38 | #address-cells = <3>; | 50 | #address-cells = <3>; |
39 | #size-cells = <2>; | 51 | #size-cells = <2>; |
40 | #interrupt-cells = <1>; | 52 | #interrupt-cells = <1>; |
53 | dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x40000000>; | ||
41 | interrupt-map-mask = <0xff00 0 0 0x7>; | 54 | interrupt-map-mask = <0xff00 0 0 0x7>; |
42 | interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH | 55 | interrupt-map = <0x0000 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH |
43 | 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH | 56 | 0x0800 0 0 1 &gic 0 108 IRQ_TYPE_LEVEL_HIGH |
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt new file mode 100644 index 000000000000..4059a6f89bc1 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt | |||
@@ -0,0 +1,233 @@ | |||
1 | * Qualcomm PCI express root complex | ||
2 | |||
3 | - compatible: | ||
4 | Usage: required | ||
5 | Value type: <stringlist> | ||
6 | Definition: Value should contain | ||
7 | - "qcom,pcie-ipq8064" for ipq8064 | ||
8 | - "qcom,pcie-apq8064" for apq8064 | ||
9 | - "qcom,pcie-apq8084" for apq8084 | ||
10 | |||
11 | - reg: | ||
12 | Usage: required | ||
13 | Value type: <prop-encoded-array> | ||
14 | Definition: Register ranges as listed in the reg-names property | ||
15 | |||
16 | - reg-names: | ||
17 | Usage: required | ||
18 | Value type: <stringlist> | ||
19 | Definition: Must include the following entries | ||
20 | - "parf" Qualcomm specific registers | ||
21 | - "dbi" Designware PCIe registers | ||
22 | - "elbi" External local bus interface registers | ||
23 | - "config" PCIe configuration space | ||
24 | |||
25 | - device_type: | ||
26 | Usage: required | ||
27 | Value type: <string> | ||
28 | Definition: Should be "pci". As specified in designware-pcie.txt | ||
29 | |||
30 | - #address-cells: | ||
31 | Usage: required | ||
32 | Value type: <u32> | ||
33 | Definition: Should be 3. As specified in designware-pcie.txt | ||
34 | |||
35 | - #size-cells: | ||
36 | Usage: required | ||
37 | Value type: <u32> | ||
38 | Definition: Should be 2. As specified in designware-pcie.txt | ||
39 | |||
40 | - ranges: | ||
41 | Usage: required | ||
42 | Value type: <prop-encoded-array> | ||
43 | Definition: As specified in designware-pcie.txt | ||
44 | |||
45 | - interrupts: | ||
46 | Usage: required | ||
47 | Value type: <prop-encoded-array> | ||
48 | Definition: MSI interrupt | ||
49 | |||
50 | - interrupt-names: | ||
51 | Usage: required | ||
52 | Value type: <stringlist> | ||
53 | Definition: Should contain "msi" | ||
54 | |||
55 | - #interrupt-cells: | ||
56 | Usage: required | ||
57 | Value type: <u32> | ||
58 | Definition: Should be 1. As specified in designware-pcie.txt | ||
59 | |||
60 | - interrupt-map-mask: | ||
61 | Usage: required | ||
62 | Value type: <prop-encoded-array> | ||
63 | Definition: As specified in designware-pcie.txt | ||
64 | |||
65 | - interrupt-map: | ||
66 | Usage: required | ||
67 | Value type: <prop-encoded-array> | ||
68 | Definition: As specified in designware-pcie.txt | ||
69 | |||
70 | - clocks: | ||
71 | Usage: required | ||
72 | Value type: <prop-encoded-array> | ||
73 | Definition: List of phandle and clock specifier pairs as listed | ||
74 | in clock-names property | ||
75 | |||
76 | - clock-names: | ||
77 | Usage: required | ||
78 | Value type: <stringlist> | ||
79 | Definition: Should contain the following entries | ||
80 | - "iface" Configuration AHB clock | ||
81 | |||
82 | - clock-names: | ||
83 | Usage: required for ipq/apq8064 | ||
84 | Value type: <stringlist> | ||
85 | Definition: Should contain the following entries | ||
86 | - "core" Clocks the pcie hw block | ||
87 | - "phy" Clocks the pcie PHY block | ||
88 | - clock-names: | ||
89 | Usage: required for apq8084 | ||
90 | Value type: <stringlist> | ||
91 | Definition: Should contain the following entries | ||
92 | - "aux" Auxiliary (AUX) clock | ||
93 | - "bus_master" Master AXI clock | ||
94 | - "bus_slave" Slave AXI clock | ||
95 | - resets: | ||
96 | Usage: required | ||
97 | Value type: <prop-encoded-array> | ||
98 | Definition: List of phandle and reset specifier pairs as listed | ||
99 | in reset-names property | ||
100 | |||
101 | - reset-names: | ||
102 | Usage: required for ipq/apq8064 | ||
103 | Value type: <stringlist> | ||
104 | Definition: Should contain the following entries | ||
105 | - "axi" AXI reset | ||
106 | - "ahb" AHB reset | ||
107 | - "por" POR reset | ||
108 | - "pci" PCI reset | ||
109 | - "phy" PHY reset | ||
110 | |||
111 | - reset-names: | ||
112 | Usage: required for apq8084 | ||
113 | Value type: <stringlist> | ||
114 | Definition: Should contain the following entries | ||
115 | - "core" Core reset | ||
116 | |||
117 | - power-domains: | ||
118 | Usage: required for apq8084 | ||
119 | Value type: <prop-encoded-array> | ||
120 | Definition: A phandle and power domain specifier pair to the | ||
121 | power domain which is responsible for collapsing | ||
122 | and restoring power to the peripheral | ||
123 | |||
124 | - vdda-supply: | ||
125 | Usage: required | ||
126 | Value type: <phandle> | ||
127 | Definition: A phandle to the core analog power supply | ||
128 | |||
129 | - vdda_phy-supply: | ||
130 | Usage: required for ipq/apq8064 | ||
131 | Value type: <phandle> | ||
132 | Definition: A phandle to the analog power supply for PHY | ||
133 | |||
134 | - vdda_refclk-supply: | ||
135 | Usage: required for ipq/apq8064 | ||
136 | Value type: <phandle> | ||
137 | Definition: A phandle to the analog power supply for IC which generates | ||
138 | reference clock | ||
139 | |||
140 | - phys: | ||
141 | Usage: required for apq8084 | ||
142 | Value type: <phandle> | ||
143 | Definition: List of phandle(s) as listed in phy-names property | ||
144 | |||
145 | - phy-names: | ||
146 | Usage: required for apq8084 | ||
147 | Value type: <stringlist> | ||
148 | Definition: Should contain "pciephy" | ||
149 | |||
150 | - <name>-gpios: | ||
151 | Usage: optional | ||
152 | Value type: <prop-encoded-array> | ||
153 | Definition: List of phandle and gpio specifier pairs. Should contain | ||
154 | - "perst-gpios" PCIe endpoint reset signal line | ||
155 | - "wake-gpios" PCIe endpoint wake signal line | ||
156 | |||
157 | * Example for ipq/apq8064 | ||
158 | pcie@1b500000 { | ||
159 | compatible = "qcom,pcie-apq8064", "qcom,pcie-ipq8064", "snps,dw-pcie"; | ||
160 | reg = <0x1b500000 0x1000 | ||
161 | 0x1b502000 0x80 | ||
162 | 0x1b600000 0x100 | ||
163 | 0x0ff00000 0x100000>; | ||
164 | reg-names = "dbi", "elbi", "parf", "config"; | ||
165 | device_type = "pci"; | ||
166 | linux,pci-domain = <0>; | ||
167 | bus-range = <0x00 0xff>; | ||
168 | num-lanes = <1>; | ||
169 | #address-cells = <3>; | ||
170 | #size-cells = <2>; | ||
171 | ranges = <0x81000000 0 0 0x0fe00000 0 0x00100000 /* I/O */ | ||
172 | 0x82000000 0 0 0x08000000 0 0x07e00000>; /* memory */ | ||
173 | interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>; | ||
174 | interrupt-names = "msi"; | ||
175 | #interrupt-cells = <1>; | ||
176 | interrupt-map-mask = <0 0 0 0x7>; | ||
177 | interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||
178 | <0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ | ||
179 | <0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ | ||
180 | <0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ | ||
181 | clocks = <&gcc PCIE_A_CLK>, | ||
182 | <&gcc PCIE_H_CLK>, | ||
183 | <&gcc PCIE_PHY_CLK>; | ||
184 | clock-names = "core", "iface", "phy"; | ||
185 | resets = <&gcc PCIE_ACLK_RESET>, | ||
186 | <&gcc PCIE_HCLK_RESET>, | ||
187 | <&gcc PCIE_POR_RESET>, | ||
188 | <&gcc PCIE_PCI_RESET>, | ||
189 | <&gcc PCIE_PHY_RESET>; | ||
190 | reset-names = "axi", "ahb", "por", "pci", "phy"; | ||
191 | pinctrl-0 = <&pcie_pins_default>; | ||
192 | pinctrl-names = "default"; | ||
193 | }; | ||
194 | |||
195 | * Example for apq8084 | ||
196 | pcie0@fc520000 { | ||
197 | compatible = "qcom,pcie-apq8084", "snps,dw-pcie"; | ||
198 | reg = <0xfc520000 0x2000>, | ||
199 | <0xff000000 0x1000>, | ||
200 | <0xff001000 0x1000>, | ||
201 | <0xff002000 0x2000>; | ||
202 | reg-names = "parf", "dbi", "elbi", "config"; | ||
203 | device_type = "pci"; | ||
204 | linux,pci-domain = <0>; | ||
205 | bus-range = <0x00 0xff>; | ||
206 | num-lanes = <1>; | ||
207 | #address-cells = <3>; | ||
208 | #size-cells = <2>; | ||
209 | ranges = <0x81000000 0 0 0xff200000 0 0x00100000 /* I/O */ | ||
210 | 0x82000000 0 0x00300000 0xff300000 0 0x00d00000>; /* memory */ | ||
211 | interrupts = <GIC_SPI 243 IRQ_TYPE_NONE>; | ||
212 | interrupt-names = "msi"; | ||
213 | #interrupt-cells = <1>; | ||
214 | interrupt-map-mask = <0 0 0 0x7>; | ||
215 | interrupt-map = <0 0 0 1 &intc 0 244 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||
216 | <0 0 0 2 &intc 0 245 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ | ||
217 | <0 0 0 3 &intc 0 247 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ | ||
218 | <0 0 0 4 &intc 0 248 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ | ||
219 | clocks = <&gcc GCC_PCIE_0_CFG_AHB_CLK>, | ||
220 | <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, | ||
221 | <&gcc GCC_PCIE_0_SLV_AXI_CLK>, | ||
222 | <&gcc GCC_PCIE_0_AUX_CLK>; | ||
223 | clock-names = "iface", "master_bus", "slave_bus", "aux"; | ||
224 | resets = <&gcc GCC_PCIE_0_BCR>; | ||
225 | reset-names = "core"; | ||
226 | power-domains = <&gcc PCIE0_GDSC>; | ||
227 | vdda-supply = <&pma8084_l3>; | ||
228 | phys = <&pciephy0>; | ||
229 | phy-names = "pciephy"; | ||
230 | perst-gpio = <&tlmm 70 GPIO_ACTIVE_LOW>; | ||
231 | pinctrl-0 = <&pcie0_pins_default>; | ||
232 | pinctrl-names = "default"; | ||
233 | }; | ||
diff --git a/Documentation/devicetree/bindings/pci/rcar-pci.txt b/Documentation/devicetree/bindings/pci/rcar-pci.txt index 29d3b989d3b0..558fe528ae19 100644 --- a/Documentation/devicetree/bindings/pci/rcar-pci.txt +++ b/Documentation/devicetree/bindings/pci/rcar-pci.txt | |||
@@ -1,8 +1,16 @@ | |||
1 | * Renesas RCar PCIe interface | 1 | * Renesas RCar PCIe interface |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: should contain one of the following | 4 | compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC; |
5 | "renesas,pcie-r8a7779", "renesas,pcie-r8a7790", "renesas,pcie-r8a7791" | 5 | "renesas,pcie-r8a7790" for the R8A7790 SoC; |
6 | "renesas,pcie-r8a7791" for the R8A7791 SoC; | ||
7 | "renesas,pcie-r8a7795" for the R8A7795 SoC; | ||
8 | "renesas,pcie-rcar-gen2" for a generic R-Car Gen2 compatible device. | ||
9 | |||
10 | When compatible with the generic version, nodes must list the | ||
11 | SoC-specific version corresponding to the platform first | ||
12 | followed by the generic version. | ||
13 | |||
6 | - reg: base address and length of the pcie controller registers. | 14 | - reg: base address and length of the pcie controller registers. |
7 | - #address-cells: set to <3> | 15 | - #address-cells: set to <3> |
8 | - #size-cells: set to <2> | 16 | - #size-cells: set to <2> |
@@ -25,7 +33,7 @@ Example: | |||
25 | SoC specific DT Entry: | 33 | SoC specific DT Entry: |
26 | 34 | ||
27 | pcie: pcie@fe000000 { | 35 | pcie: pcie@fe000000 { |
28 | compatible = "renesas,pcie-r8a7791"; | 36 | compatible = "renesas,pcie-r8a7791", "renesas,pcie-rcar-gen2"; |
29 | reg = <0 0xfe000000 0 0x80000>; | 37 | reg = <0 0xfe000000 0 0x80000>; |
30 | #address-cells = <3>; | 38 | #address-cells = <3>; |
31 | #size-cells = <2>; | 39 | #size-cells = <2>; |
diff --git a/MAINTAINERS b/MAINTAINERS index 050d0e77a2cf..9ea78171b43c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8240,11 +8240,19 @@ F: drivers/pci/host/pci-xgene-msi.c | |||
8240 | 8240 | ||
8241 | PCIE DRIVER FOR HISILICON | 8241 | PCIE DRIVER FOR HISILICON |
8242 | M: Zhou Wang <wangzhou1@hisilicon.com> | 8242 | M: Zhou Wang <wangzhou1@hisilicon.com> |
8243 | M: Gabriele Paoloni <gabriele.paoloni@huawei.com> | ||
8243 | L: linux-pci@vger.kernel.org | 8244 | L: linux-pci@vger.kernel.org |
8244 | S: Maintained | 8245 | S: Maintained |
8245 | F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt | 8246 | F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt |
8246 | F: drivers/pci/host/pcie-hisi.c | 8247 | F: drivers/pci/host/pcie-hisi.c |
8247 | 8248 | ||
8249 | PCIE DRIVER FOR QUALCOMM MSM | ||
8250 | M: Stanimir Varbanov <svarbanov@mm-sol.com> | ||
8251 | L: linux-pci@vger.kernel.org | ||
8252 | L: linux-arm-msm@vger.kernel.org | ||
8253 | S: Maintained | ||
8254 | F: drivers/pci/host/*qcom* | ||
8255 | |||
8248 | PCMCIA SUBSYSTEM | 8256 | PCMCIA SUBSYSTEM |
8249 | P: Linux PCMCIA Team | 8257 | P: Linux PCMCIA Team |
8250 | L: linux-pcmcia@lists.infradead.org | 8258 | L: linux-pcmcia@lists.infradead.org |
diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts index 11ac608b6d50..955c697b4dd4 100644 --- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts +++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts | |||
@@ -47,6 +47,18 @@ | |||
47 | bias-disable; | 47 | bias-disable; |
48 | }; | 48 | }; |
49 | }; | 49 | }; |
50 | |||
51 | pcie_pins: pcie_pinmux { | ||
52 | mux { | ||
53 | pins = "gpio27"; | ||
54 | function = "gpio"; | ||
55 | }; | ||
56 | conf { | ||
57 | pins = "gpio27"; | ||
58 | drive-strength = <12>; | ||
59 | bias-disable; | ||
60 | }; | ||
61 | }; | ||
50 | }; | 62 | }; |
51 | 63 | ||
52 | rpm@108000 { | 64 | rpm@108000 { |
@@ -123,6 +135,10 @@ | |||
123 | pm8921_lvs1: lvs1 { | 135 | pm8921_lvs1: lvs1 { |
124 | bias-pull-down; | 136 | bias-pull-down; |
125 | }; | 137 | }; |
138 | |||
139 | lvs6 { | ||
140 | bias-pull-down; | ||
141 | }; | ||
126 | }; | 142 | }; |
127 | }; | 143 | }; |
128 | 144 | ||
@@ -231,6 +247,16 @@ | |||
231 | status = "okay"; | 247 | status = "okay"; |
232 | }; | 248 | }; |
233 | 249 | ||
250 | pci@1b500000 { | ||
251 | status = "ok"; | ||
252 | vdda-supply = <&pm8921_s3>; | ||
253 | vdda_phy-supply = <&pm8921_lvs6>; | ||
254 | vdda_refclk-supply = <&ext_3p3v>; | ||
255 | pinctrl-0 = <&pcie_pins>; | ||
256 | pinctrl-names = "default"; | ||
257 | perst-gpio = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>; | ||
258 | }; | ||
259 | |||
234 | qcom,ssbi@500000 { | 260 | qcom,ssbi@500000 { |
235 | pmic@0 { | 261 | pmic@0 { |
236 | gpio@150 { | 262 | gpio@150 { |
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi index a4c1762b53ea..847150fbfdbf 100644 --- a/arch/arm/boot/dts/qcom-apq8064.dtsi +++ b/arch/arm/boot/dts/qcom-apq8064.dtsi | |||
@@ -659,5 +659,41 @@ | |||
659 | compatible = "qcom,tcsr-apq8064", "syscon"; | 659 | compatible = "qcom,tcsr-apq8064", "syscon"; |
660 | reg = <0x1a400000 0x100>; | 660 | reg = <0x1a400000 0x100>; |
661 | }; | 661 | }; |
662 | |||
663 | pcie: pci@1b500000 { | ||
664 | compatible = "qcom,pcie-apq8064", "snps,dw-pcie"; | ||
665 | reg = <0x1b500000 0x1000 | ||
666 | 0x1b502000 0x80 | ||
667 | 0x1b600000 0x100 | ||
668 | 0x0ff00000 0x100000>; | ||
669 | reg-names = "dbi", "elbi", "parf", "config"; | ||
670 | device_type = "pci"; | ||
671 | linux,pci-domain = <0>; | ||
672 | bus-range = <0x00 0xff>; | ||
673 | num-lanes = <1>; | ||
674 | #address-cells = <3>; | ||
675 | #size-cells = <2>; | ||
676 | ranges = <0x81000000 0 0 0x0fe00000 0 0x00100000 /* I/O */ | ||
677 | 0x82000000 0 0 0x08000000 0 0x07e00000>; /* memory */ | ||
678 | interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>; | ||
679 | interrupt-names = "msi"; | ||
680 | #interrupt-cells = <1>; | ||
681 | interrupt-map-mask = <0 0 0 0x7>; | ||
682 | interrupt-map = <0 0 0 1 &intc 0 36 IRQ_TYPE_LEVEL_HIGH>, /* int_a */ | ||
683 | <0 0 0 2 &intc 0 37 IRQ_TYPE_LEVEL_HIGH>, /* int_b */ | ||
684 | <0 0 0 3 &intc 0 38 IRQ_TYPE_LEVEL_HIGH>, /* int_c */ | ||
685 | <0 0 0 4 &intc 0 39 IRQ_TYPE_LEVEL_HIGH>; /* int_d */ | ||
686 | clocks = <&gcc PCIE_A_CLK>, | ||
687 | <&gcc PCIE_H_CLK>, | ||
688 | <&gcc PCIE_PHY_REF_CLK>; | ||
689 | clock-names = "core", "iface", "phy"; | ||
690 | resets = <&gcc PCIE_ACLK_RESET>, | ||
691 | <&gcc PCIE_HCLK_RESET>, | ||
692 | <&gcc PCIE_POR_RESET>, | ||
693 | <&gcc PCIE_PCI_RESET>, | ||
694 | <&gcc PCIE_PHY_RESET>; | ||
695 | reset-names = "axi", "ahb", "por", "pci", "phy"; | ||
696 | status = "disabled"; | ||
697 | }; | ||
662 | }; | 698 | }; |
663 | }; | 699 | }; |
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 80dfe8965df9..44bca7892f66 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -400,7 +400,7 @@ static void *eeh_rmv_device(void *data, void *userdata) | |||
400 | * support EEH. So we just care about PCI devices for | 400 | * support EEH. So we just care about PCI devices for |
401 | * simplicity here. | 401 | * simplicity here. |
402 | */ | 402 | */ |
403 | if (!dev || (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) | 403 | if (!dev || (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) |
404 | return NULL; | 404 | return NULL; |
405 | 405 | ||
406 | /* | 406 | /* |
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 2e710c15893f..526ac6750e4d 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
@@ -187,9 +187,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
187 | 187 | ||
188 | pci_device_add(dev, bus); | 188 | pci_device_add(dev, bus); |
189 | 189 | ||
190 | /* Setup MSI caps & disable MSI/MSI-X interrupts */ | ||
191 | pci_msi_setup_pci_dev(dev); | ||
192 | |||
193 | return dev; | 190 | return dev; |
194 | } | 191 | } |
195 | EXPORT_SYMBOL(of_create_pci_dev); | 192 | EXPORT_SYMBOL(of_create_pci_dev); |
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index fa1195dae425..46873fbd44e1 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h | |||
@@ -151,11 +151,11 @@ extern struct list_head pci_mmcfg_list; | |||
151 | #define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20) | 151 | #define PCI_MMCFG_BUS_OFFSET(bus) ((bus) << 20) |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * AMD Fam10h CPUs are buggy, and cannot access MMIO config space | 154 | * On AMD Fam10h CPUs, all PCI MMIO configuration space accesses must use |
155 | * on their northbrige except through the * %eax register. As such, you MUST | 155 | * %eax. No other source or target registers may be used. The following |
156 | * NOT use normal IOMEM accesses, you need to only use the magic mmio-config | 156 | * mmio_config_* accessors enforce this. See "BIOS and Kernel Developer's |
157 | * accessor functions. | 157 | * Guide (BKDG) For AMD Family 10h Processors", rev. 3.48, sec 2.11.1, |
158 | * In fact just use pci_config_*, nothing else please. | 158 | * "MMIO Configuration Coding Requirements". |
159 | */ | 159 | */ |
160 | static inline unsigned char mmio_config_readb(void __iomem *pos) | 160 | static inline unsigned char mmio_config_readb(void __iomem *pos) |
161 | { | 161 | { |
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index 9b83b9051ae7..9770e55e768f 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c | |||
@@ -180,6 +180,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, | |||
180 | unsigned long result = 0; | 180 | unsigned long result = 0; |
181 | unsigned long flags; | 181 | unsigned long flags; |
182 | unsigned long bx = (bus << 8) | devfn; | 182 | unsigned long bx = (bus << 8) | devfn; |
183 | u16 number = 0, mask = 0; | ||
183 | 184 | ||
184 | WARN_ON(seg); | 185 | WARN_ON(seg); |
185 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) | 186 | if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) |
@@ -189,53 +190,35 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, | |||
189 | 190 | ||
190 | switch (len) { | 191 | switch (len) { |
191 | case 1: | 192 | case 1: |
192 | __asm__("lcall *(%%esi); cld\n\t" | 193 | number = PCIBIOS_READ_CONFIG_BYTE; |
193 | "jc 1f\n\t" | 194 | mask = 0xff; |
194 | "xor %%ah, %%ah\n" | ||
195 | "1:" | ||
196 | : "=c" (*value), | ||
197 | "=a" (result) | ||
198 | : "1" (PCIBIOS_READ_CONFIG_BYTE), | ||
199 | "b" (bx), | ||
200 | "D" ((long)reg), | ||
201 | "S" (&pci_indirect)); | ||
202 | /* | ||
203 | * Zero-extend the result beyond 8 bits, do not trust the | ||
204 | * BIOS having done it: | ||
205 | */ | ||
206 | *value &= 0xff; | ||
207 | break; | 195 | break; |
208 | case 2: | 196 | case 2: |
209 | __asm__("lcall *(%%esi); cld\n\t" | 197 | number = PCIBIOS_READ_CONFIG_WORD; |
210 | "jc 1f\n\t" | 198 | mask = 0xffff; |
211 | "xor %%ah, %%ah\n" | ||
212 | "1:" | ||
213 | : "=c" (*value), | ||
214 | "=a" (result) | ||
215 | : "1" (PCIBIOS_READ_CONFIG_WORD), | ||
216 | "b" (bx), | ||
217 | "D" ((long)reg), | ||
218 | "S" (&pci_indirect)); | ||
219 | /* | ||
220 | * Zero-extend the result beyond 16 bits, do not trust the | ||
221 | * BIOS having done it: | ||
222 | */ | ||
223 | *value &= 0xffff; | ||
224 | break; | 199 | break; |
225 | case 4: | 200 | case 4: |
226 | __asm__("lcall *(%%esi); cld\n\t" | 201 | number = PCIBIOS_READ_CONFIG_DWORD; |
227 | "jc 1f\n\t" | ||
228 | "xor %%ah, %%ah\n" | ||
229 | "1:" | ||
230 | : "=c" (*value), | ||
231 | "=a" (result) | ||
232 | : "1" (PCIBIOS_READ_CONFIG_DWORD), | ||
233 | "b" (bx), | ||
234 | "D" ((long)reg), | ||
235 | "S" (&pci_indirect)); | ||
236 | break; | 202 | break; |
237 | } | 203 | } |
238 | 204 | ||
205 | __asm__("lcall *(%%esi); cld\n\t" | ||
206 | "jc 1f\n\t" | ||
207 | "xor %%ah, %%ah\n" | ||
208 | "1:" | ||
209 | : "=c" (*value), | ||
210 | "=a" (result) | ||
211 | : "1" (number), | ||
212 | "b" (bx), | ||
213 | "D" ((long)reg), | ||
214 | "S" (&pci_indirect)); | ||
215 | /* | ||
216 | * Zero-extend the result beyond 8 or 16 bits, do not trust the | ||
217 | * BIOS having done it: | ||
218 | */ | ||
219 | if (mask) | ||
220 | *value &= mask; | ||
221 | |||
239 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | 222 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); |
240 | 223 | ||
241 | return (int)((result & 0xff00) >> 8); | 224 | return (int)((result & 0xff00) >> 8); |
@@ -247,6 +230,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, | |||
247 | unsigned long result = 0; | 230 | unsigned long result = 0; |
248 | unsigned long flags; | 231 | unsigned long flags; |
249 | unsigned long bx = (bus << 8) | devfn; | 232 | unsigned long bx = (bus << 8) | devfn; |
233 | u16 number = 0; | ||
250 | 234 | ||
251 | WARN_ON(seg); | 235 | WARN_ON(seg); |
252 | if ((bus > 255) || (devfn > 255) || (reg > 255)) | 236 | if ((bus > 255) || (devfn > 255) || (reg > 255)) |
@@ -256,43 +240,27 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, | |||
256 | 240 | ||
257 | switch (len) { | 241 | switch (len) { |
258 | case 1: | 242 | case 1: |
259 | __asm__("lcall *(%%esi); cld\n\t" | 243 | number = PCIBIOS_WRITE_CONFIG_BYTE; |
260 | "jc 1f\n\t" | ||
261 | "xor %%ah, %%ah\n" | ||
262 | "1:" | ||
263 | : "=a" (result) | ||
264 | : "0" (PCIBIOS_WRITE_CONFIG_BYTE), | ||
265 | "c" (value), | ||
266 | "b" (bx), | ||
267 | "D" ((long)reg), | ||
268 | "S" (&pci_indirect)); | ||
269 | break; | 244 | break; |
270 | case 2: | 245 | case 2: |
271 | __asm__("lcall *(%%esi); cld\n\t" | 246 | number = PCIBIOS_WRITE_CONFIG_WORD; |
272 | "jc 1f\n\t" | ||
273 | "xor %%ah, %%ah\n" | ||
274 | "1:" | ||
275 | : "=a" (result) | ||
276 | : "0" (PCIBIOS_WRITE_CONFIG_WORD), | ||
277 | "c" (value), | ||
278 | "b" (bx), | ||
279 | "D" ((long)reg), | ||
280 | "S" (&pci_indirect)); | ||
281 | break; | 247 | break; |
282 | case 4: | 248 | case 4: |
283 | __asm__("lcall *(%%esi); cld\n\t" | 249 | number = PCIBIOS_WRITE_CONFIG_DWORD; |
284 | "jc 1f\n\t" | ||
285 | "xor %%ah, %%ah\n" | ||
286 | "1:" | ||
287 | : "=a" (result) | ||
288 | : "0" (PCIBIOS_WRITE_CONFIG_DWORD), | ||
289 | "c" (value), | ||
290 | "b" (bx), | ||
291 | "D" ((long)reg), | ||
292 | "S" (&pci_indirect)); | ||
293 | break; | 250 | break; |
294 | } | 251 | } |
295 | 252 | ||
253 | __asm__("lcall *(%%esi); cld\n\t" | ||
254 | "jc 1f\n\t" | ||
255 | "xor %%ah, %%ah\n" | ||
256 | "1:" | ||
257 | : "=a" (result) | ||
258 | : "0" (number), | ||
259 | "c" (value), | ||
260 | "b" (bx), | ||
261 | "D" ((long)reg), | ||
262 | "S" (&pci_indirect)); | ||
263 | |||
296 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | 264 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); |
297 | 265 | ||
298 | return (int)((result & 0xff00) >> 8); | 266 | return (int)((result & 0xff00) >> 8); |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index d3346d23963b..89b3befc7155 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -140,6 +140,8 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, | |||
140 | type_mask |= IORESOURCE_TYPE_BITS; | 140 | type_mask |= IORESOURCE_TYPE_BITS; |
141 | 141 | ||
142 | pci_bus_for_each_resource(bus, r, i) { | 142 | pci_bus_for_each_resource(bus, r, i) { |
143 | resource_size_t min_used = min; | ||
144 | |||
143 | if (!r) | 145 | if (!r) |
144 | continue; | 146 | continue; |
145 | 147 | ||
@@ -163,12 +165,12 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, | |||
163 | * overrides "min". | 165 | * overrides "min". |
164 | */ | 166 | */ |
165 | if (avail.start) | 167 | if (avail.start) |
166 | min = avail.start; | 168 | min_used = avail.start; |
167 | 169 | ||
168 | max = avail.end; | 170 | max = avail.end; |
169 | 171 | ||
170 | /* Ok, try it out.. */ | 172 | /* Ok, try it out.. */ |
171 | ret = allocate_resource(r, res, size, min, max, | 173 | ret = allocate_resource(r, res, size, min_used, max, |
172 | align, alignf, alignf_data); | 174 | align, alignf, alignf_data); |
173 | if (ret == 0) | 175 | if (ret == 0) |
174 | return 0; | 176 | return 0; |
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index f131ba947dc6..6d181ba09ccd 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -48,8 +48,7 @@ config PCI_RCAR_GEN2 | |||
48 | 48 | ||
49 | config PCI_RCAR_GEN2_PCIE | 49 | config PCI_RCAR_GEN2_PCIE |
50 | bool "Renesas R-Car PCIe controller" | 50 | bool "Renesas R-Car PCIe controller" |
51 | depends on ARM | 51 | depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST) |
52 | depends on ARCH_SHMOBILE || COMPILE_TEST | ||
53 | help | 52 | help |
54 | Say Y here if you want PCIe controller support on R-Car Gen2 SoCs. | 53 | Say Y here if you want PCIe controller support on R-Car Gen2 SoCs. |
55 | 54 | ||
@@ -118,13 +117,11 @@ config PCI_VERSATILE | |||
118 | depends on ARCH_VERSATILE | 117 | depends on ARCH_VERSATILE |
119 | 118 | ||
120 | config PCIE_IPROC | 119 | config PCIE_IPROC |
121 | tristate "Broadcom iProc PCIe controller" | 120 | tristate |
122 | depends on OF && (ARM || ARM64) | ||
123 | default n | ||
124 | help | 121 | help |
125 | This enables the iProc PCIe core controller support for Broadcom's | 122 | This enables the iProc PCIe core controller support for Broadcom's |
126 | iProc family of SoCs. An appropriate bus interface driver also needs | 123 | iProc family of SoCs. An appropriate bus interface driver needs |
127 | to be enabled | 124 | to be enabled to select this. |
128 | 125 | ||
129 | config PCIE_IPROC_PLATFORM | 126 | config PCIE_IPROC_PLATFORM |
130 | tristate "Broadcom iProc PCIe platform bus driver" | 127 | tristate "Broadcom iProc PCIe platform bus driver" |
@@ -147,6 +144,16 @@ config PCIE_IPROC_BCMA | |||
147 | Say Y here if you want to use the Broadcom iProc PCIe controller | 144 | Say Y here if you want to use the Broadcom iProc PCIe controller |
148 | through the BCMA bus interface | 145 | through the BCMA bus interface |
149 | 146 | ||
147 | config PCIE_IPROC_MSI | ||
148 | bool "Broadcom iProc PCIe MSI support" | ||
149 | depends on PCIE_IPROC_PLATFORM || PCIE_IPROC_BCMA | ||
150 | depends on PCI_MSI | ||
151 | select PCI_MSI_IRQ_DOMAIN | ||
152 | default ARCH_BCM_IPROC | ||
153 | help | ||
154 | Say Y here if you want to enable MSI support for Broadcom's iProc | ||
155 | PCIe controller | ||
156 | |||
150 | config PCIE_ALTERA | 157 | config PCIE_ALTERA |
151 | bool "Altera PCIe controller" | 158 | bool "Altera PCIe controller" |
152 | depends on ARM || NIOS2 | 159 | depends on ARM || NIOS2 |
@@ -166,10 +173,21 @@ config PCIE_ALTERA_MSI | |||
166 | 173 | ||
167 | config PCI_HISI | 174 | config PCI_HISI |
168 | depends on OF && ARM64 | 175 | depends on OF && ARM64 |
169 | bool "HiSilicon SoC HIP05 PCIe controller" | 176 | bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers" |
170 | select PCIEPORTBUS | 177 | select PCIEPORTBUS |
171 | select PCIE_DW | 178 | select PCIE_DW |
172 | help | 179 | help |
173 | Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC | 180 | Say Y here if you want PCIe controller support on HiSilicon |
181 | Hip05 and Hip06 SoCs | ||
182 | |||
183 | config PCIE_QCOM | ||
184 | bool "Qualcomm PCIe controller" | ||
185 | depends on ARCH_QCOM && OF | ||
186 | select PCIE_DW | ||
187 | select PCIEPORTBUS | ||
188 | help | ||
189 | Say Y here to enable PCIe controller support on Qualcomm SoCs. The | ||
190 | PCIe controller uses the Designware core plus Qualcomm-specific | ||
191 | hardware wrappers. | ||
174 | 192 | ||
175 | endmenu | 193 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 9d4d3c6924a1..7b2f20c6ccc6 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -15,8 +15,10 @@ obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o | |||
15 | obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o | 15 | obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o |
16 | obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o | 16 | obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o |
17 | obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o | 17 | obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o |
18 | obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o | ||
18 | obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o | 19 | obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o |
19 | obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o | 20 | obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o |
20 | obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o | 21 | obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o |
21 | obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o | 22 | obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o |
22 | obj-$(CONFIG_PCI_HISI) += pcie-hisi.o | 23 | obj-$(CONFIG_PCI_HISI) += pcie-hisi.o |
24 | obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o | ||
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 8c3688046c02..923607bdabc5 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c | |||
@@ -302,7 +302,8 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, | |||
302 | } | 302 | } |
303 | 303 | ||
304 | ret = devm_request_irq(&pdev->dev, pp->irq, | 304 | ret = devm_request_irq(&pdev->dev, pp->irq, |
305 | dra7xx_pcie_msi_irq_handler, IRQF_SHARED, | 305 | dra7xx_pcie_msi_irq_handler, |
306 | IRQF_SHARED | IRQF_NO_THREAD, | ||
306 | "dra7-pcie-msi", pp); | 307 | "dra7-pcie-msi", pp); |
307 | if (ret) { | 308 | if (ret) { |
308 | dev_err(&pdev->dev, "failed to request irq\n"); | 309 | dev_err(&pdev->dev, "failed to request irq\n"); |
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 01095e1160a4..d997d22d4231 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -522,7 +522,8 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp, | |||
522 | 522 | ||
523 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, | 523 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, |
524 | exynos_pcie_msi_irq_handler, | 524 | exynos_pcie_msi_irq_handler, |
525 | IRQF_SHARED, "exynos-pcie", pp); | 525 | IRQF_SHARED | IRQF_NO_THREAD, |
526 | "exynos-pcie", pp); | ||
526 | if (ret) { | 527 | if (ret) { |
527 | dev_err(&pdev->dev, "failed to request msi irq\n"); | 528 | dev_err(&pdev->dev, "failed to request msi irq\n"); |
528 | return ret; | 529 | return ret; |
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c index 5434c90db243..1652bc70b145 100644 --- a/drivers/pci/host/pci-host-generic.c +++ b/drivers/pci/host/pci-host-generic.c | |||
@@ -38,16 +38,7 @@ struct gen_pci_cfg_windows { | |||
38 | struct gen_pci_cfg_bus_ops *ops; | 38 | struct gen_pci_cfg_bus_ops *ops; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | ||
42 | * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI | ||
43 | * sysdata. Add pci_sys_data as the first element in struct gen_pci so | ||
44 | * that when we use a gen_pci pointer as sysdata, it is also a pointer to | ||
45 | * a struct pci_sys_data. | ||
46 | */ | ||
47 | struct gen_pci { | 41 | struct gen_pci { |
48 | #ifdef CONFIG_ARM | ||
49 | struct pci_sys_data sys; | ||
50 | #endif | ||
51 | struct pci_host_bridge host; | 42 | struct pci_host_bridge host; |
52 | struct gen_pci_cfg_windows cfg; | 43 | struct gen_pci_cfg_windows cfg; |
53 | struct list_head resources; | 44 | struct list_head resources; |
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 22e8224126fd..b039f0c6c8ff 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) | 32 | #define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) |
33 | 33 | ||
34 | struct imx6_pcie { | 34 | struct imx6_pcie { |
35 | int reset_gpio; | 35 | struct gpio_desc *reset_gpio; |
36 | struct clk *pcie_bus; | 36 | struct clk *pcie_bus; |
37 | struct clk *pcie_phy; | 37 | struct clk *pcie_phy; |
38 | struct clk *pcie; | 38 | struct clk *pcie; |
@@ -287,10 +287,10 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) | |||
287 | usleep_range(200, 500); | 287 | usleep_range(200, 500); |
288 | 288 | ||
289 | /* Some boards don't have PCIe reset GPIO. */ | 289 | /* Some boards don't have PCIe reset GPIO. */ |
290 | if (gpio_is_valid(imx6_pcie->reset_gpio)) { | 290 | if (imx6_pcie->reset_gpio) { |
291 | gpio_set_value(imx6_pcie->reset_gpio, 0); | 291 | gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 0); |
292 | msleep(100); | 292 | msleep(100); |
293 | gpio_set_value(imx6_pcie->reset_gpio, 1); | 293 | gpiod_set_value_cansleep(imx6_pcie->reset_gpio, 1); |
294 | } | 294 | } |
295 | return 0; | 295 | return 0; |
296 | 296 | ||
@@ -537,7 +537,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp, | |||
537 | 537 | ||
538 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, | 538 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, |
539 | imx6_pcie_msi_handler, | 539 | imx6_pcie_msi_handler, |
540 | IRQF_SHARED, "mx6-pcie-msi", pp); | 540 | IRQF_SHARED | IRQF_NO_THREAD, |
541 | "mx6-pcie-msi", pp); | ||
541 | if (ret) { | 542 | if (ret) { |
542 | dev_err(&pdev->dev, "failed to request MSI irq\n"); | 543 | dev_err(&pdev->dev, "failed to request MSI irq\n"); |
543 | return ret; | 544 | return ret; |
@@ -560,7 +561,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) | |||
560 | { | 561 | { |
561 | struct imx6_pcie *imx6_pcie; | 562 | struct imx6_pcie *imx6_pcie; |
562 | struct pcie_port *pp; | 563 | struct pcie_port *pp; |
563 | struct device_node *np = pdev->dev.of_node; | ||
564 | struct resource *dbi_base; | 564 | struct resource *dbi_base; |
565 | int ret; | 565 | int ret; |
566 | 566 | ||
@@ -581,15 +581,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) | |||
581 | return PTR_ERR(pp->dbi_base); | 581 | return PTR_ERR(pp->dbi_base); |
582 | 582 | ||
583 | /* Fetch GPIOs */ | 583 | /* Fetch GPIOs */ |
584 | imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); | 584 | imx6_pcie->reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", |
585 | if (gpio_is_valid(imx6_pcie->reset_gpio)) { | 585 | GPIOD_OUT_LOW); |
586 | ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio, | ||
587 | GPIOF_OUT_INIT_LOW, "PCIe reset"); | ||
588 | if (ret) { | ||
589 | dev_err(&pdev->dev, "unable to get reset gpio\n"); | ||
590 | return ret; | ||
591 | } | ||
592 | } | ||
593 | 586 | ||
594 | /* Fetch clocks */ | 587 | /* Fetch clocks */ |
595 | imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); | 588 | imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); |
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index c4f64bfee551..9980a4bdae7e 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/of_address.h> | ||
18 | #include <linux/of_pci.h> | 19 | #include <linux/of_pci.h> |
19 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
@@ -102,6 +103,8 @@ struct rcar_pci_priv { | |||
102 | unsigned busnr; | 103 | unsigned busnr; |
103 | int irq; | 104 | int irq; |
104 | unsigned long window_size; | 105 | unsigned long window_size; |
106 | unsigned long window_addr; | ||
107 | unsigned long window_pci; | ||
105 | }; | 108 | }; |
106 | 109 | ||
107 | /* PCI configuration space operations */ | 110 | /* PCI configuration space operations */ |
@@ -239,8 +242,8 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) | |||
239 | RCAR_PCI_ARBITER_PCIBP_MODE; | 242 | RCAR_PCI_ARBITER_PCIBP_MODE; |
240 | iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); | 243 | iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); |
241 | 244 | ||
242 | /* PCI-AHB mapping: 0x40000000 base */ | 245 | /* PCI-AHB mapping */ |
243 | iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16, | 246 | iowrite32(priv->window_addr | RCAR_PCIAHB_PREFETCH16, |
244 | reg + RCAR_PCIAHB_WIN1_CTR_REG); | 247 | reg + RCAR_PCIAHB_WIN1_CTR_REG); |
245 | 248 | ||
246 | /* AHB-PCI mapping: OHCI/EHCI registers */ | 249 | /* AHB-PCI mapping: OHCI/EHCI registers */ |
@@ -251,7 +254,7 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys) | |||
251 | iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, | 254 | iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, |
252 | reg + RCAR_AHBPCI_WIN1_CTR_REG); | 255 | reg + RCAR_AHBPCI_WIN1_CTR_REG); |
253 | /* Set PCI-AHB Window1 address */ | 256 | /* Set PCI-AHB Window1 address */ |
254 | iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH, | 257 | iowrite32(priv->window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH, |
255 | reg + PCI_BASE_ADDRESS_1); | 258 | reg + PCI_BASE_ADDRESS_1); |
256 | /* Set AHB-PCI bridge PCI communication area address */ | 259 | /* Set AHB-PCI bridge PCI communication area address */ |
257 | val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; | 260 | val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; |
@@ -284,6 +287,64 @@ static struct pci_ops rcar_pci_ops = { | |||
284 | .write = pci_generic_config_write, | 287 | .write = pci_generic_config_write, |
285 | }; | 288 | }; |
286 | 289 | ||
290 | static int pci_dma_range_parser_init(struct of_pci_range_parser *parser, | ||
291 | struct device_node *node) | ||
292 | { | ||
293 | const int na = 3, ns = 2; | ||
294 | int rlen; | ||
295 | |||
296 | parser->node = node; | ||
297 | parser->pna = of_n_addr_cells(node); | ||
298 | parser->np = parser->pna + na + ns; | ||
299 | |||
300 | parser->range = of_get_property(node, "dma-ranges", &rlen); | ||
301 | if (!parser->range) | ||
302 | return -ENOENT; | ||
303 | |||
304 | parser->end = parser->range + rlen / sizeof(__be32); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int rcar_pci_parse_map_dma_ranges(struct rcar_pci_priv *pci, | ||
309 | struct device_node *np) | ||
310 | { | ||
311 | struct of_pci_range range; | ||
312 | struct of_pci_range_parser parser; | ||
313 | int index = 0; | ||
314 | |||
315 | /* Failure to parse is ok as we fall back to defaults */ | ||
316 | if (pci_dma_range_parser_init(&parser, np)) | ||
317 | return 0; | ||
318 | |||
319 | /* Get the dma-ranges from DT */ | ||
320 | for_each_of_pci_range(&parser, &range) { | ||
321 | /* Hardware only allows one inbound 32-bit range */ | ||
322 | if (index) | ||
323 | return -EINVAL; | ||
324 | |||
325 | pci->window_addr = (unsigned long)range.cpu_addr; | ||
326 | pci->window_pci = (unsigned long)range.pci_addr; | ||
327 | pci->window_size = (unsigned long)range.size; | ||
328 | |||
329 | /* Catch HW limitations */ | ||
330 | if (!(range.flags & IORESOURCE_PREFETCH)) { | ||
331 | dev_err(pci->dev, "window must be prefetchable\n"); | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | if (pci->window_addr) { | ||
335 | u32 lowaddr = 1 << (ffs(pci->window_addr) - 1); | ||
336 | |||
337 | if (lowaddr < pci->window_size) { | ||
338 | dev_err(pci->dev, "invalid window size/addr\n"); | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | } | ||
342 | index++; | ||
343 | } | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
287 | static int rcar_pci_probe(struct platform_device *pdev) | 348 | static int rcar_pci_probe(struct platform_device *pdev) |
288 | { | 349 | { |
289 | struct resource *cfg_res, *mem_res; | 350 | struct resource *cfg_res, *mem_res; |
@@ -329,6 +390,9 @@ static int rcar_pci_probe(struct platform_device *pdev) | |||
329 | return priv->irq; | 390 | return priv->irq; |
330 | } | 391 | } |
331 | 392 | ||
393 | /* default window addr and size if not specified in DT */ | ||
394 | priv->window_addr = 0x40000000; | ||
395 | priv->window_pci = 0x40000000; | ||
332 | priv->window_size = SZ_1G; | 396 | priv->window_size = SZ_1G; |
333 | 397 | ||
334 | if (pdev->dev.of_node) { | 398 | if (pdev->dev.of_node) { |
@@ -344,6 +408,12 @@ static int rcar_pci_probe(struct platform_device *pdev) | |||
344 | priv->busnr = busnr.start; | 408 | priv->busnr = busnr.start; |
345 | if (busnr.end != busnr.start) | 409 | if (busnr.end != busnr.start) |
346 | dev_warn(&pdev->dev, "only one bus number supported\n"); | 410 | dev_warn(&pdev->dev, "only one bus number supported\n"); |
411 | |||
412 | ret = rcar_pci_parse_map_dma_ranges(priv, pdev->dev.of_node); | ||
413 | if (ret < 0) { | ||
414 | dev_err(&pdev->dev, "failed to parse dma-range\n"); | ||
415 | return ret; | ||
416 | } | ||
347 | } else { | 417 | } else { |
348 | priv->busnr = pdev->id; | 418 | priv->busnr = pdev->id; |
349 | } | 419 | } |
@@ -360,6 +430,7 @@ static int rcar_pci_probe(struct platform_device *pdev) | |||
360 | } | 430 | } |
361 | 431 | ||
362 | static struct of_device_id rcar_pci_of_match[] = { | 432 | static struct of_device_id rcar_pci_of_match[] = { |
433 | { .compatible = "renesas,pci-rcar-gen2", }, | ||
363 | { .compatible = "renesas,pci-r8a7790", }, | 434 | { .compatible = "renesas,pci-r8a7790", }, |
364 | { .compatible = "renesas,pci-r8a7791", }, | 435 | { .compatible = "renesas,pci-r8a7791", }, |
365 | { .compatible = "renesas,pci-r8a7794", }, | 436 | { .compatible = "renesas,pci-r8a7794", }, |
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 3018ae52e092..30323114c53c 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -1288,7 +1288,7 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) | |||
1288 | 1288 | ||
1289 | msi->irq = err; | 1289 | msi->irq = err; |
1290 | 1290 | ||
1291 | err = request_irq(msi->irq, tegra_pcie_msi_irq, 0, | 1291 | err = request_irq(msi->irq, tegra_pcie_msi_irq, IRQF_NO_THREAD, |
1292 | tegra_msi_irq_chip.name, pcie); | 1292 | tegra_msi_irq_chip.name, pcie); |
1293 | if (err < 0) { | 1293 | if (err < 0) { |
1294 | dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); | 1294 | dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); |
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index 0863d9cc25f8..f843a72dc51c 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c | |||
@@ -125,9 +125,6 @@ out_release_res: | |||
125 | return err; | 125 | return err; |
126 | } | 126 | } |
127 | 127 | ||
128 | /* Unused, temporary to satisfy ARM arch code */ | ||
129 | struct pci_sys_data sys; | ||
130 | |||
131 | static int versatile_pci_probe(struct platform_device *pdev) | 128 | static int versatile_pci_probe(struct platform_device *pdev) |
132 | { | 129 | { |
133 | struct resource *res; | 130 | struct resource *res; |
@@ -208,7 +205,7 @@ static int versatile_pci_probe(struct platform_device *pdev) | |||
208 | pci_add_flags(PCI_ENABLE_PROC_DOMAINS); | 205 | pci_add_flags(PCI_ENABLE_PROC_DOMAINS); |
209 | pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC); | 206 | pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC); |
210 | 207 | ||
211 | bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, &sys, &pci_res); | 208 | bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, NULL, &pci_res); |
212 | if (!bus) | 209 | if (!bus) |
213 | return -ENOMEM; | 210 | return -ENOMEM; |
214 | 211 | ||
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 540f077c37ea..e28bc0bd3a7d 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -128,32 +128,26 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg) | |||
128 | static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | 128 | static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
129 | u32 *val) | 129 | u32 *val) |
130 | { | 130 | { |
131 | int ret; | ||
132 | |||
133 | if (pp->ops->rd_own_conf) | 131 | if (pp->ops->rd_own_conf) |
134 | ret = pp->ops->rd_own_conf(pp, where, size, val); | 132 | return pp->ops->rd_own_conf(pp, where, size, val); |
135 | else | ||
136 | ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val); | ||
137 | 133 | ||
138 | return ret; | 134 | return dw_pcie_cfg_read(pp->dbi_base + where, size, val); |
139 | } | 135 | } |
140 | 136 | ||
141 | static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | 137 | static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, |
142 | u32 val) | 138 | u32 val) |
143 | { | 139 | { |
144 | int ret; | ||
145 | |||
146 | if (pp->ops->wr_own_conf) | 140 | if (pp->ops->wr_own_conf) |
147 | ret = pp->ops->wr_own_conf(pp, where, size, val); | 141 | return pp->ops->wr_own_conf(pp, where, size, val); |
148 | else | ||
149 | ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val); | ||
150 | 142 | ||
151 | return ret; | 143 | return dw_pcie_cfg_write(pp->dbi_base + where, size, val); |
152 | } | 144 | } |
153 | 145 | ||
154 | static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, | 146 | static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, |
155 | int type, u64 cpu_addr, u64 pci_addr, u32 size) | 147 | int type, u64 cpu_addr, u64 pci_addr, u32 size) |
156 | { | 148 | { |
149 | u32 val; | ||
150 | |||
157 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index, | 151 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index, |
158 | PCIE_ATU_VIEWPORT); | 152 | PCIE_ATU_VIEWPORT); |
159 | dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE); | 153 | dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE); |
@@ -164,6 +158,12 @@ static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, | |||
164 | dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET); | 158 | dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET); |
165 | dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1); | 159 | dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1); |
166 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | 160 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); |
161 | |||
162 | /* | ||
163 | * Make sure ATU enable takes effect before any subsequent config | ||
164 | * and I/O accesses. | ||
165 | */ | ||
166 | dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val); | ||
167 | } | 167 | } |
168 | 168 | ||
169 | static struct irq_chip dw_msi_irq_chip = { | 169 | static struct irq_chip dw_msi_irq_chip = { |
@@ -384,8 +384,8 @@ int dw_pcie_link_up(struct pcie_port *pp) | |||
384 | { | 384 | { |
385 | if (pp->ops->link_up) | 385 | if (pp->ops->link_up) |
386 | return pp->ops->link_up(pp); | 386 | return pp->ops->link_up(pp); |
387 | else | 387 | |
388 | return 0; | 388 | return 0; |
389 | } | 389 | } |
390 | 390 | ||
391 | static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, | 391 | static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, |
@@ -572,6 +572,9 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
572 | u64 cpu_addr; | 572 | u64 cpu_addr; |
573 | void __iomem *va_cfg_base; | 573 | void __iomem *va_cfg_base; |
574 | 574 | ||
575 | if (pp->ops->rd_other_conf) | ||
576 | return pp->ops->rd_other_conf(pp, bus, devfn, where, size, val); | ||
577 | |||
575 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | | 578 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | |
576 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); | 579 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); |
577 | 580 | ||
@@ -606,6 +609,9 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
606 | u64 cpu_addr; | 609 | u64 cpu_addr; |
607 | void __iomem *va_cfg_base; | 610 | void __iomem *va_cfg_base; |
608 | 611 | ||
612 | if (pp->ops->wr_other_conf) | ||
613 | return pp->ops->wr_other_conf(pp, bus, devfn, where, size, val); | ||
614 | |||
609 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | | 615 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | |
610 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); | 616 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); |
611 | 617 | ||
@@ -659,46 +665,30 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
659 | int size, u32 *val) | 665 | int size, u32 *val) |
660 | { | 666 | { |
661 | struct pcie_port *pp = bus->sysdata; | 667 | struct pcie_port *pp = bus->sysdata; |
662 | int ret; | ||
663 | 668 | ||
664 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { | 669 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { |
665 | *val = 0xffffffff; | 670 | *val = 0xffffffff; |
666 | return PCIBIOS_DEVICE_NOT_FOUND; | 671 | return PCIBIOS_DEVICE_NOT_FOUND; |
667 | } | 672 | } |
668 | 673 | ||
669 | if (bus->number != pp->root_bus_nr) | 674 | if (bus->number == pp->root_bus_nr) |
670 | if (pp->ops->rd_other_conf) | 675 | return dw_pcie_rd_own_conf(pp, where, size, val); |
671 | ret = pp->ops->rd_other_conf(pp, bus, devfn, | ||
672 | where, size, val); | ||
673 | else | ||
674 | ret = dw_pcie_rd_other_conf(pp, bus, devfn, | ||
675 | where, size, val); | ||
676 | else | ||
677 | ret = dw_pcie_rd_own_conf(pp, where, size, val); | ||
678 | 676 | ||
679 | return ret; | 677 | return dw_pcie_rd_other_conf(pp, bus, devfn, where, size, val); |
680 | } | 678 | } |
681 | 679 | ||
682 | static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | 680 | static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, |
683 | int where, int size, u32 val) | 681 | int where, int size, u32 val) |
684 | { | 682 | { |
685 | struct pcie_port *pp = bus->sysdata; | 683 | struct pcie_port *pp = bus->sysdata; |
686 | int ret; | ||
687 | 684 | ||
688 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) | 685 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) |
689 | return PCIBIOS_DEVICE_NOT_FOUND; | 686 | return PCIBIOS_DEVICE_NOT_FOUND; |
690 | 687 | ||
691 | if (bus->number != pp->root_bus_nr) | 688 | if (bus->number == pp->root_bus_nr) |
692 | if (pp->ops->wr_other_conf) | 689 | return dw_pcie_wr_own_conf(pp, where, size, val); |
693 | ret = pp->ops->wr_other_conf(pp, bus, devfn, | ||
694 | where, size, val); | ||
695 | else | ||
696 | ret = dw_pcie_wr_other_conf(pp, bus, devfn, | ||
697 | where, size, val); | ||
698 | else | ||
699 | ret = dw_pcie_wr_own_conf(pp, where, size, val); | ||
700 | 690 | ||
701 | return ret; | 691 | return dw_pcie_wr_other_conf(pp, bus, devfn, where, size, val); |
702 | } | 692 | } |
703 | 693 | ||
704 | static struct pci_ops dw_pcie_ops = { | 694 | static struct pci_ops dw_pcie_ops = { |
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c index 35457ecd8e70..4bad6954019b 100644 --- a/drivers/pci/host/pcie-hisi.c +++ b/drivers/pci/host/pcie-hisi.c | |||
@@ -1,10 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * PCIe host controller driver for HiSilicon Hip05 SoC | 2 | * PCIe host controller driver for HiSilicon SoCs |
3 | * | 3 | * |
4 | * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com | 4 | * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com |
5 | * | 5 | * |
6 | * Author: Zhou Wang <wangzhou1@hisilicon.com> | 6 | * Authors: Zhou Wang <wangzhou1@hisilicon.com> |
7 | * Dacai Zhu <zhudacai@hisilicon.com> | 7 | * Dacai Zhu <zhudacai@hisilicon.com> |
8 | * Gabriele Paoloni <gabriele.paoloni@huawei.com> | ||
8 | * | 9 | * |
9 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -16,21 +17,31 @@ | |||
16 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
17 | #include <linux/of_pci.h> | 18 | #include <linux/of_pci.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/of_device.h> | ||
19 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
20 | 22 | ||
21 | #include "pcie-designware.h" | 23 | #include "pcie-designware.h" |
22 | 24 | ||
23 | #define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818 | 25 | #define PCIE_LTSSM_LINKUP_STATE 0x11 |
24 | #define PCIE_LTSSM_LINKUP_STATE 0x11 | 26 | #define PCIE_LTSSM_STATE_MASK 0x3F |
25 | #define PCIE_LTSSM_STATE_MASK 0x3F | 27 | #define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818 |
28 | #define PCIE_SYS_STATE4 0x31c | ||
29 | #define PCIE_HIP06_CTRL_OFF 0x1000 | ||
26 | 30 | ||
27 | #define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp) | 31 | #define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp) |
28 | 32 | ||
33 | struct hisi_pcie; | ||
34 | |||
35 | struct pcie_soc_ops { | ||
36 | int (*hisi_pcie_link_up)(struct hisi_pcie *pcie); | ||
37 | }; | ||
38 | |||
29 | struct hisi_pcie { | 39 | struct hisi_pcie { |
30 | struct regmap *subctrl; | 40 | struct regmap *subctrl; |
31 | void __iomem *reg_base; | 41 | void __iomem *reg_base; |
32 | u32 port_id; | 42 | u32 port_id; |
33 | struct pcie_port pp; | 43 | struct pcie_port pp; |
44 | struct pcie_soc_ops *soc_ops; | ||
34 | }; | 45 | }; |
35 | 46 | ||
36 | static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie, | 47 | static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie, |
@@ -44,7 +55,7 @@ static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg) | |||
44 | return readl(pcie->reg_base + reg); | 55 | return readl(pcie->reg_base + reg); |
45 | } | 56 | } |
46 | 57 | ||
47 | /* Hip05 PCIe host only supports 32-bit config access */ | 58 | /* HipXX PCIe host only supports 32-bit config access */ |
48 | static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, | 59 | static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, |
49 | u32 *val) | 60 | u32 *val) |
50 | { | 61 | { |
@@ -67,7 +78,7 @@ static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, | |||
67 | return PCIBIOS_SUCCESSFUL; | 78 | return PCIBIOS_SUCCESSFUL; |
68 | } | 79 | } |
69 | 80 | ||
70 | /* Hip05 PCIe host only supports 32-bit config access */ | 81 | /* HipXX PCIe host only supports 32-bit config access */ |
71 | static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, | 82 | static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, |
72 | u32 val) | 83 | u32 val) |
73 | { | 84 | { |
@@ -94,10 +105,9 @@ static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, | |||
94 | return PCIBIOS_SUCCESSFUL; | 105 | return PCIBIOS_SUCCESSFUL; |
95 | } | 106 | } |
96 | 107 | ||
97 | static int hisi_pcie_link_up(struct pcie_port *pp) | 108 | static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie) |
98 | { | 109 | { |
99 | u32 val; | 110 | u32 val; |
100 | struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp); | ||
101 | 111 | ||
102 | regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG + | 112 | regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG + |
103 | 0x100 * hisi_pcie->port_id, &val); | 113 | 0x100 * hisi_pcie->port_id, &val); |
@@ -105,6 +115,23 @@ static int hisi_pcie_link_up(struct pcie_port *pp) | |||
105 | return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); | 115 | return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); |
106 | } | 116 | } |
107 | 117 | ||
118 | static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie) | ||
119 | { | ||
120 | u32 val; | ||
121 | |||
122 | val = hisi_pcie_apb_readl(hisi_pcie, PCIE_HIP06_CTRL_OFF + | ||
123 | PCIE_SYS_STATE4); | ||
124 | |||
125 | return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); | ||
126 | } | ||
127 | |||
128 | static int hisi_pcie_link_up(struct pcie_port *pp) | ||
129 | { | ||
130 | struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp); | ||
131 | |||
132 | return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie); | ||
133 | } | ||
134 | |||
108 | static struct pcie_host_ops hisi_pcie_host_ops = { | 135 | static struct pcie_host_ops hisi_pcie_host_ops = { |
109 | .rd_own_conf = hisi_pcie_cfg_read, | 136 | .rd_own_conf = hisi_pcie_cfg_read, |
110 | .wr_own_conf = hisi_pcie_cfg_write, | 137 | .wr_own_conf = hisi_pcie_cfg_write, |
@@ -143,7 +170,9 @@ static int __init hisi_pcie_probe(struct platform_device *pdev) | |||
143 | { | 170 | { |
144 | struct hisi_pcie *hisi_pcie; | 171 | struct hisi_pcie *hisi_pcie; |
145 | struct pcie_port *pp; | 172 | struct pcie_port *pp; |
173 | const struct of_device_id *match; | ||
146 | struct resource *reg; | 174 | struct resource *reg; |
175 | struct device_driver *driver; | ||
147 | int ret; | 176 | int ret; |
148 | 177 | ||
149 | hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL); | 178 | hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL); |
@@ -152,6 +181,10 @@ static int __init hisi_pcie_probe(struct platform_device *pdev) | |||
152 | 181 | ||
153 | pp = &hisi_pcie->pp; | 182 | pp = &hisi_pcie->pp; |
154 | pp->dev = &pdev->dev; | 183 | pp->dev = &pdev->dev; |
184 | driver = (pdev->dev).driver; | ||
185 | |||
186 | match = of_match_device(driver->of_match_table, &pdev->dev); | ||
187 | hisi_pcie->soc_ops = (struct pcie_soc_ops *) match->data; | ||
155 | 188 | ||
156 | hisi_pcie->subctrl = | 189 | hisi_pcie->subctrl = |
157 | syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl"); | 190 | syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl"); |
@@ -180,11 +213,27 @@ static int __init hisi_pcie_probe(struct platform_device *pdev) | |||
180 | return 0; | 213 | return 0; |
181 | } | 214 | } |
182 | 215 | ||
216 | static struct pcie_soc_ops hip05_ops = { | ||
217 | &hisi_pcie_link_up_hip05 | ||
218 | }; | ||
219 | |||
220 | static struct pcie_soc_ops hip06_ops = { | ||
221 | &hisi_pcie_link_up_hip06 | ||
222 | }; | ||
223 | |||
183 | static const struct of_device_id hisi_pcie_of_match[] = { | 224 | static const struct of_device_id hisi_pcie_of_match[] = { |
184 | {.compatible = "hisilicon,hip05-pcie",}, | 225 | { |
226 | .compatible = "hisilicon,hip05-pcie", | ||
227 | .data = (void *) &hip05_ops, | ||
228 | }, | ||
229 | { | ||
230 | .compatible = "hisilicon,hip06-pcie", | ||
231 | .data = (void *) &hip06_ops, | ||
232 | }, | ||
185 | {}, | 233 | {}, |
186 | }; | 234 | }; |
187 | 235 | ||
236 | |||
188 | MODULE_DEVICE_TABLE(of, hisi_pcie_of_match); | 237 | MODULE_DEVICE_TABLE(of, hisi_pcie_of_match); |
189 | 238 | ||
190 | static struct platform_driver hisi_pcie_driver = { | 239 | static struct platform_driver hisi_pcie_driver = { |
@@ -196,3 +245,8 @@ static struct platform_driver hisi_pcie_driver = { | |||
196 | }; | 245 | }; |
197 | 246 | ||
198 | module_platform_driver(hisi_pcie_driver); | 247 | module_platform_driver(hisi_pcie_driver); |
248 | |||
249 | MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>"); | ||
250 | MODULE_AUTHOR("Dacai Zhu <zhudacai@hisilicon.com>"); | ||
251 | MODULE_AUTHOR("Gabriele Paoloni <gabriele.paoloni@huawei.com>"); | ||
252 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-iproc-bcma.c b/drivers/pci/host/pcie-iproc-bcma.c index 96a7d999fd5e..0d7bee4a0d26 100644 --- a/drivers/pci/host/pcie-iproc-bcma.c +++ b/drivers/pci/host/pcie-iproc-bcma.c | |||
@@ -55,6 +55,7 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev) | |||
55 | bcma_set_drvdata(bdev, pcie); | 55 | bcma_set_drvdata(bdev, pcie); |
56 | 56 | ||
57 | pcie->base = bdev->io_addr; | 57 | pcie->base = bdev->io_addr; |
58 | pcie->base_addr = bdev->addr; | ||
58 | 59 | ||
59 | res_mem.start = bdev->addr_s[0]; | 60 | res_mem.start = bdev->addr_s[0]; |
60 | res_mem.end = bdev->addr_s[0] + SZ_128M - 1; | 61 | res_mem.end = bdev->addr_s[0] + SZ_128M - 1; |
diff --git a/drivers/pci/host/pcie-iproc-msi.c b/drivers/pci/host/pcie-iproc-msi.c new file mode 100644 index 000000000000..9a2973bdc78a --- /dev/null +++ b/drivers/pci/host/pcie-iproc-msi.c | |||
@@ -0,0 +1,675 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License as | ||
6 | * published by the Free Software Foundation version 2. | ||
7 | * | ||
8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
9 | * kind, whether express or implied; without even the implied warranty | ||
10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/irqchip/chained_irq.h> | ||
16 | #include <linux/irqdomain.h> | ||
17 | #include <linux/msi.h> | ||
18 | #include <linux/of_irq.h> | ||
19 | #include <linux/of_pci.h> | ||
20 | #include <linux/pci.h> | ||
21 | |||
22 | #include "pcie-iproc.h" | ||
23 | |||
24 | #define IPROC_MSI_INTR_EN_SHIFT 11 | ||
25 | #define IPROC_MSI_INTR_EN BIT(IPROC_MSI_INTR_EN_SHIFT) | ||
26 | #define IPROC_MSI_INT_N_EVENT_SHIFT 1 | ||
27 | #define IPROC_MSI_INT_N_EVENT BIT(IPROC_MSI_INT_N_EVENT_SHIFT) | ||
28 | #define IPROC_MSI_EQ_EN_SHIFT 0 | ||
29 | #define IPROC_MSI_EQ_EN BIT(IPROC_MSI_EQ_EN_SHIFT) | ||
30 | |||
31 | #define IPROC_MSI_EQ_MASK 0x3f | ||
32 | |||
33 | /* Max number of GIC interrupts */ | ||
34 | #define NR_HW_IRQS 6 | ||
35 | |||
36 | /* Number of entries in each event queue */ | ||
37 | #define EQ_LEN 64 | ||
38 | |||
39 | /* Size of each event queue memory region */ | ||
40 | #define EQ_MEM_REGION_SIZE SZ_4K | ||
41 | |||
42 | /* Size of each MSI address region */ | ||
43 | #define MSI_MEM_REGION_SIZE SZ_4K | ||
44 | |||
45 | enum iproc_msi_reg { | ||
46 | IPROC_MSI_EQ_PAGE = 0, | ||
47 | IPROC_MSI_EQ_PAGE_UPPER, | ||
48 | IPROC_MSI_PAGE, | ||
49 | IPROC_MSI_PAGE_UPPER, | ||
50 | IPROC_MSI_CTRL, | ||
51 | IPROC_MSI_EQ_HEAD, | ||
52 | IPROC_MSI_EQ_TAIL, | ||
53 | IPROC_MSI_INTS_EN, | ||
54 | IPROC_MSI_REG_SIZE, | ||
55 | }; | ||
56 | |||
57 | struct iproc_msi; | ||
58 | |||
59 | /** | ||
60 | * iProc MSI group | ||
61 | * | ||
62 | * One MSI group is allocated per GIC interrupt, serviced by one iProc MSI | ||
63 | * event queue. | ||
64 | * | ||
65 | * @msi: pointer to iProc MSI data | ||
66 | * @gic_irq: GIC interrupt | ||
67 | * @eq: Event queue number | ||
68 | */ | ||
69 | struct iproc_msi_grp { | ||
70 | struct iproc_msi *msi; | ||
71 | int gic_irq; | ||
72 | unsigned int eq; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * iProc event queue based MSI | ||
77 | * | ||
78 | * Only meant to be used on platforms without MSI support integrated into the | ||
79 | * GIC. | ||
80 | * | ||
81 | * @pcie: pointer to iProc PCIe data | ||
82 | * @reg_offsets: MSI register offsets | ||
83 | * @grps: MSI groups | ||
84 | * @nr_irqs: number of total interrupts connected to GIC | ||
85 | * @nr_cpus: number of toal CPUs | ||
86 | * @has_inten_reg: indicates the MSI interrupt enable register needs to be | ||
87 | * set explicitly (required for some legacy platforms) | ||
88 | * @bitmap: MSI vector bitmap | ||
89 | * @bitmap_lock: lock to protect access to the MSI bitmap | ||
90 | * @nr_msi_vecs: total number of MSI vectors | ||
91 | * @inner_domain: inner IRQ domain | ||
92 | * @msi_domain: MSI IRQ domain | ||
93 | * @nr_eq_region: required number of 4K aligned memory region for MSI event | ||
94 | * queues | ||
95 | * @nr_msi_region: required number of 4K aligned address region for MSI posted | ||
96 | * writes | ||
97 | * @eq_cpu: pointer to allocated memory region for MSI event queues | ||
98 | * @eq_dma: DMA address of MSI event queues | ||
99 | * @msi_addr: MSI address | ||
100 | */ | ||
101 | struct iproc_msi { | ||
102 | struct iproc_pcie *pcie; | ||
103 | const u16 (*reg_offsets)[IPROC_MSI_REG_SIZE]; | ||
104 | struct iproc_msi_grp *grps; | ||
105 | int nr_irqs; | ||
106 | int nr_cpus; | ||
107 | bool has_inten_reg; | ||
108 | unsigned long *bitmap; | ||
109 | struct mutex bitmap_lock; | ||
110 | unsigned int nr_msi_vecs; | ||
111 | struct irq_domain *inner_domain; | ||
112 | struct irq_domain *msi_domain; | ||
113 | unsigned int nr_eq_region; | ||
114 | unsigned int nr_msi_region; | ||
115 | void *eq_cpu; | ||
116 | dma_addr_t eq_dma; | ||
117 | phys_addr_t msi_addr; | ||
118 | }; | ||
119 | |||
120 | static const u16 iproc_msi_reg_paxb[NR_HW_IRQS][IPROC_MSI_REG_SIZE] = { | ||
121 | { 0x200, 0x2c0, 0x204, 0x2c4, 0x210, 0x250, 0x254, 0x208 }, | ||
122 | { 0x200, 0x2c0, 0x204, 0x2c4, 0x214, 0x258, 0x25c, 0x208 }, | ||
123 | { 0x200, 0x2c0, 0x204, 0x2c4, 0x218, 0x260, 0x264, 0x208 }, | ||
124 | { 0x200, 0x2c0, 0x204, 0x2c4, 0x21c, 0x268, 0x26c, 0x208 }, | ||
125 | { 0x200, 0x2c0, 0x204, 0x2c4, 0x220, 0x270, 0x274, 0x208 }, | ||
126 | { 0x200, 0x2c0, 0x204, 0x2c4, 0x224, 0x278, 0x27c, 0x208 }, | ||
127 | }; | ||
128 | |||
129 | static const u16 iproc_msi_reg_paxc[NR_HW_IRQS][IPROC_MSI_REG_SIZE] = { | ||
130 | { 0xc00, 0xc04, 0xc08, 0xc0c, 0xc40, 0xc50, 0xc60 }, | ||
131 | { 0xc10, 0xc14, 0xc18, 0xc1c, 0xc44, 0xc54, 0xc64 }, | ||
132 | { 0xc20, 0xc24, 0xc28, 0xc2c, 0xc48, 0xc58, 0xc68 }, | ||
133 | { 0xc30, 0xc34, 0xc38, 0xc3c, 0xc4c, 0xc5c, 0xc6c }, | ||
134 | }; | ||
135 | |||
136 | static inline u32 iproc_msi_read_reg(struct iproc_msi *msi, | ||
137 | enum iproc_msi_reg reg, | ||
138 | unsigned int eq) | ||
139 | { | ||
140 | struct iproc_pcie *pcie = msi->pcie; | ||
141 | |||
142 | return readl_relaxed(pcie->base + msi->reg_offsets[eq][reg]); | ||
143 | } | ||
144 | |||
145 | static inline void iproc_msi_write_reg(struct iproc_msi *msi, | ||
146 | enum iproc_msi_reg reg, | ||
147 | int eq, u32 val) | ||
148 | { | ||
149 | struct iproc_pcie *pcie = msi->pcie; | ||
150 | |||
151 | writel_relaxed(val, pcie->base + msi->reg_offsets[eq][reg]); | ||
152 | } | ||
153 | |||
154 | static inline u32 hwirq_to_group(struct iproc_msi *msi, unsigned long hwirq) | ||
155 | { | ||
156 | return (hwirq % msi->nr_irqs); | ||
157 | } | ||
158 | |||
159 | static inline unsigned int iproc_msi_addr_offset(struct iproc_msi *msi, | ||
160 | unsigned long hwirq) | ||
161 | { | ||
162 | if (msi->nr_msi_region > 1) | ||
163 | return hwirq_to_group(msi, hwirq) * MSI_MEM_REGION_SIZE; | ||
164 | else | ||
165 | return hwirq_to_group(msi, hwirq) * sizeof(u32); | ||
166 | } | ||
167 | |||
168 | static inline unsigned int iproc_msi_eq_offset(struct iproc_msi *msi, u32 eq) | ||
169 | { | ||
170 | if (msi->nr_eq_region > 1) | ||
171 | return eq * EQ_MEM_REGION_SIZE; | ||
172 | else | ||
173 | return eq * EQ_LEN * sizeof(u32); | ||
174 | } | ||
175 | |||
176 | static struct irq_chip iproc_msi_irq_chip = { | ||
177 | .name = "iProc-MSI", | ||
178 | }; | ||
179 | |||
180 | static struct msi_domain_info iproc_msi_domain_info = { | ||
181 | .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | | ||
182 | MSI_FLAG_PCI_MSIX, | ||
183 | .chip = &iproc_msi_irq_chip, | ||
184 | }; | ||
185 | |||
186 | /* | ||
187 | * In iProc PCIe core, each MSI group is serviced by a GIC interrupt and a | ||
188 | * dedicated event queue. Each MSI group can support up to 64 MSI vectors. | ||
189 | * | ||
190 | * The number of MSI groups varies between different iProc SoCs. The total | ||
191 | * number of CPU cores also varies. To support MSI IRQ affinity, we | ||
192 | * distribute GIC interrupts across all available CPUs. MSI vector is moved | ||
193 | * from one GIC interrupt to another to steer to the target CPU. | ||
194 | * | ||
195 | * Assuming: | ||
196 | * - the number of MSI groups is M | ||
197 | * - the number of CPU cores is N | ||
198 | * - M is always a multiple of N | ||
199 | * | ||
200 | * Total number of raw MSI vectors = M * 64 | ||
201 | * Total number of supported MSI vectors = (M * 64) / N | ||
202 | */ | ||
203 | static inline int hwirq_to_cpu(struct iproc_msi *msi, unsigned long hwirq) | ||
204 | { | ||
205 | return (hwirq % msi->nr_cpus); | ||
206 | } | ||
207 | |||
208 | static inline unsigned long hwirq_to_canonical_hwirq(struct iproc_msi *msi, | ||
209 | unsigned long hwirq) | ||
210 | { | ||
211 | return (hwirq - hwirq_to_cpu(msi, hwirq)); | ||
212 | } | ||
213 | |||
214 | static int iproc_msi_irq_set_affinity(struct irq_data *data, | ||
215 | const struct cpumask *mask, bool force) | ||
216 | { | ||
217 | struct iproc_msi *msi = irq_data_get_irq_chip_data(data); | ||
218 | int target_cpu = cpumask_first(mask); | ||
219 | int curr_cpu; | ||
220 | |||
221 | curr_cpu = hwirq_to_cpu(msi, data->hwirq); | ||
222 | if (curr_cpu == target_cpu) | ||
223 | return IRQ_SET_MASK_OK_DONE; | ||
224 | |||
225 | /* steer MSI to the target CPU */ | ||
226 | data->hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq) + target_cpu; | ||
227 | |||
228 | return IRQ_SET_MASK_OK; | ||
229 | } | ||
230 | |||
231 | static void iproc_msi_irq_compose_msi_msg(struct irq_data *data, | ||
232 | struct msi_msg *msg) | ||
233 | { | ||
234 | struct iproc_msi *msi = irq_data_get_irq_chip_data(data); | ||
235 | dma_addr_t addr; | ||
236 | |||
237 | addr = msi->msi_addr + iproc_msi_addr_offset(msi, data->hwirq); | ||
238 | msg->address_lo = lower_32_bits(addr); | ||
239 | msg->address_hi = upper_32_bits(addr); | ||
240 | msg->data = data->hwirq; | ||
241 | } | ||
242 | |||
243 | static struct irq_chip iproc_msi_bottom_irq_chip = { | ||
244 | .name = "MSI", | ||
245 | .irq_set_affinity = iproc_msi_irq_set_affinity, | ||
246 | .irq_compose_msi_msg = iproc_msi_irq_compose_msi_msg, | ||
247 | }; | ||
248 | |||
249 | static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, | ||
250 | unsigned int virq, unsigned int nr_irqs, | ||
251 | void *args) | ||
252 | { | ||
253 | struct iproc_msi *msi = domain->host_data; | ||
254 | int hwirq; | ||
255 | |||
256 | mutex_lock(&msi->bitmap_lock); | ||
257 | |||
258 | /* Allocate 'nr_cpus' number of MSI vectors each time */ | ||
259 | hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0, | ||
260 | msi->nr_cpus, 0); | ||
261 | if (hwirq < msi->nr_msi_vecs) { | ||
262 | bitmap_set(msi->bitmap, hwirq, msi->nr_cpus); | ||
263 | } else { | ||
264 | mutex_unlock(&msi->bitmap_lock); | ||
265 | return -ENOSPC; | ||
266 | } | ||
267 | |||
268 | mutex_unlock(&msi->bitmap_lock); | ||
269 | |||
270 | irq_domain_set_info(domain, virq, hwirq, &iproc_msi_bottom_irq_chip, | ||
271 | domain->host_data, handle_simple_irq, NULL, NULL); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static void iproc_msi_irq_domain_free(struct irq_domain *domain, | ||
277 | unsigned int virq, unsigned int nr_irqs) | ||
278 | { | ||
279 | struct irq_data *data = irq_domain_get_irq_data(domain, virq); | ||
280 | struct iproc_msi *msi = irq_data_get_irq_chip_data(data); | ||
281 | unsigned int hwirq; | ||
282 | |||
283 | mutex_lock(&msi->bitmap_lock); | ||
284 | |||
285 | hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq); | ||
286 | bitmap_clear(msi->bitmap, hwirq, msi->nr_cpus); | ||
287 | |||
288 | mutex_unlock(&msi->bitmap_lock); | ||
289 | |||
290 | irq_domain_free_irqs_parent(domain, virq, nr_irqs); | ||
291 | } | ||
292 | |||
293 | static const struct irq_domain_ops msi_domain_ops = { | ||
294 | .alloc = iproc_msi_irq_domain_alloc, | ||
295 | .free = iproc_msi_irq_domain_free, | ||
296 | }; | ||
297 | |||
298 | static inline u32 decode_msi_hwirq(struct iproc_msi *msi, u32 eq, u32 head) | ||
299 | { | ||
300 | u32 *msg, hwirq; | ||
301 | unsigned int offs; | ||
302 | |||
303 | offs = iproc_msi_eq_offset(msi, eq) + head * sizeof(u32); | ||
304 | msg = (u32 *)(msi->eq_cpu + offs); | ||
305 | hwirq = *msg & IPROC_MSI_EQ_MASK; | ||
306 | |||
307 | /* | ||
308 | * Since we have multiple hwirq mapped to a single MSI vector, | ||
309 | * now we need to derive the hwirq at CPU0. It can then be used to | ||
310 | * mapped back to virq. | ||
311 | */ | ||
312 | return hwirq_to_canonical_hwirq(msi, hwirq); | ||
313 | } | ||
314 | |||
315 | static void iproc_msi_handler(struct irq_desc *desc) | ||
316 | { | ||
317 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
318 | struct iproc_msi_grp *grp; | ||
319 | struct iproc_msi *msi; | ||
320 | struct iproc_pcie *pcie; | ||
321 | u32 eq, head, tail, nr_events; | ||
322 | unsigned long hwirq; | ||
323 | int virq; | ||
324 | |||
325 | chained_irq_enter(chip, desc); | ||
326 | |||
327 | grp = irq_desc_get_handler_data(desc); | ||
328 | msi = grp->msi; | ||
329 | pcie = msi->pcie; | ||
330 | eq = grp->eq; | ||
331 | |||
332 | /* | ||
333 | * iProc MSI event queue is tracked by head and tail pointers. Head | ||
334 | * pointer indicates the next entry (MSI data) to be consumed by SW in | ||
335 | * the queue and needs to be updated by SW. iProc MSI core uses the | ||
336 | * tail pointer as the next data insertion point. | ||
337 | * | ||
338 | * Entries between head and tail pointers contain valid MSI data. MSI | ||
339 | * data is guaranteed to be in the event queue memory before the tail | ||
340 | * pointer is updated by the iProc MSI core. | ||
341 | */ | ||
342 | head = iproc_msi_read_reg(msi, IPROC_MSI_EQ_HEAD, | ||
343 | eq) & IPROC_MSI_EQ_MASK; | ||
344 | do { | ||
345 | tail = iproc_msi_read_reg(msi, IPROC_MSI_EQ_TAIL, | ||
346 | eq) & IPROC_MSI_EQ_MASK; | ||
347 | |||
348 | /* | ||
349 | * Figure out total number of events (MSI data) to be | ||
350 | * processed. | ||
351 | */ | ||
352 | nr_events = (tail < head) ? | ||
353 | (EQ_LEN - (head - tail)) : (tail - head); | ||
354 | if (!nr_events) | ||
355 | break; | ||
356 | |||
357 | /* process all outstanding events */ | ||
358 | while (nr_events--) { | ||
359 | hwirq = decode_msi_hwirq(msi, eq, head); | ||
360 | virq = irq_find_mapping(msi->inner_domain, hwirq); | ||
361 | generic_handle_irq(virq); | ||
362 | |||
363 | head++; | ||
364 | head %= EQ_LEN; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Now all outstanding events have been processed. Update the | ||
369 | * head pointer. | ||
370 | */ | ||
371 | iproc_msi_write_reg(msi, IPROC_MSI_EQ_HEAD, eq, head); | ||
372 | |||
373 | /* | ||
374 | * Now go read the tail pointer again to see if there are new | ||
375 | * oustanding events that came in during the above window. | ||
376 | */ | ||
377 | } while (true); | ||
378 | |||
379 | chained_irq_exit(chip, desc); | ||
380 | } | ||
381 | |||
382 | static void iproc_msi_enable(struct iproc_msi *msi) | ||
383 | { | ||
384 | int i, eq; | ||
385 | u32 val; | ||
386 | |||
387 | /* Program memory region for each event queue */ | ||
388 | for (i = 0; i < msi->nr_eq_region; i++) { | ||
389 | dma_addr_t addr = msi->eq_dma + (i * EQ_MEM_REGION_SIZE); | ||
390 | |||
391 | iproc_msi_write_reg(msi, IPROC_MSI_EQ_PAGE, i, | ||
392 | lower_32_bits(addr)); | ||
393 | iproc_msi_write_reg(msi, IPROC_MSI_EQ_PAGE_UPPER, i, | ||
394 | upper_32_bits(addr)); | ||
395 | } | ||
396 | |||
397 | /* Program address region for MSI posted writes */ | ||
398 | for (i = 0; i < msi->nr_msi_region; i++) { | ||
399 | phys_addr_t addr = msi->msi_addr + (i * MSI_MEM_REGION_SIZE); | ||
400 | |||
401 | iproc_msi_write_reg(msi, IPROC_MSI_PAGE, i, | ||
402 | lower_32_bits(addr)); | ||
403 | iproc_msi_write_reg(msi, IPROC_MSI_PAGE_UPPER, i, | ||
404 | upper_32_bits(addr)); | ||
405 | } | ||
406 | |||
407 | for (eq = 0; eq < msi->nr_irqs; eq++) { | ||
408 | /* Enable MSI event queue */ | ||
409 | val = IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT | | ||
410 | IPROC_MSI_EQ_EN; | ||
411 | iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val); | ||
412 | |||
413 | /* | ||
414 | * Some legacy platforms require the MSI interrupt enable | ||
415 | * register to be set explicitly. | ||
416 | */ | ||
417 | if (msi->has_inten_reg) { | ||
418 | val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq); | ||
419 | val |= BIT(eq); | ||
420 | iproc_msi_write_reg(msi, IPROC_MSI_INTS_EN, eq, val); | ||
421 | } | ||
422 | } | ||
423 | } | ||
424 | |||
425 | static void iproc_msi_disable(struct iproc_msi *msi) | ||
426 | { | ||
427 | u32 eq, val; | ||
428 | |||
429 | for (eq = 0; eq < msi->nr_irqs; eq++) { | ||
430 | if (msi->has_inten_reg) { | ||
431 | val = iproc_msi_read_reg(msi, IPROC_MSI_INTS_EN, eq); | ||
432 | val &= ~BIT(eq); | ||
433 | iproc_msi_write_reg(msi, IPROC_MSI_INTS_EN, eq, val); | ||
434 | } | ||
435 | |||
436 | val = iproc_msi_read_reg(msi, IPROC_MSI_CTRL, eq); | ||
437 | val &= ~(IPROC_MSI_INTR_EN | IPROC_MSI_INT_N_EVENT | | ||
438 | IPROC_MSI_EQ_EN); | ||
439 | iproc_msi_write_reg(msi, IPROC_MSI_CTRL, eq, val); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | static int iproc_msi_alloc_domains(struct device_node *node, | ||
444 | struct iproc_msi *msi) | ||
445 | { | ||
446 | msi->inner_domain = irq_domain_add_linear(NULL, msi->nr_msi_vecs, | ||
447 | &msi_domain_ops, msi); | ||
448 | if (!msi->inner_domain) | ||
449 | return -ENOMEM; | ||
450 | |||
451 | msi->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), | ||
452 | &iproc_msi_domain_info, | ||
453 | msi->inner_domain); | ||
454 | if (!msi->msi_domain) { | ||
455 | irq_domain_remove(msi->inner_domain); | ||
456 | return -ENOMEM; | ||
457 | } | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | static void iproc_msi_free_domains(struct iproc_msi *msi) | ||
463 | { | ||
464 | if (msi->msi_domain) | ||
465 | irq_domain_remove(msi->msi_domain); | ||
466 | |||
467 | if (msi->inner_domain) | ||
468 | irq_domain_remove(msi->inner_domain); | ||
469 | } | ||
470 | |||
471 | static void iproc_msi_irq_free(struct iproc_msi *msi, unsigned int cpu) | ||
472 | { | ||
473 | int i; | ||
474 | |||
475 | for (i = cpu; i < msi->nr_irqs; i += msi->nr_cpus) { | ||
476 | irq_set_chained_handler_and_data(msi->grps[i].gic_irq, | ||
477 | NULL, NULL); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | static int iproc_msi_irq_setup(struct iproc_msi *msi, unsigned int cpu) | ||
482 | { | ||
483 | int i, ret; | ||
484 | cpumask_var_t mask; | ||
485 | struct iproc_pcie *pcie = msi->pcie; | ||
486 | |||
487 | for (i = cpu; i < msi->nr_irqs; i += msi->nr_cpus) { | ||
488 | irq_set_chained_handler_and_data(msi->grps[i].gic_irq, | ||
489 | iproc_msi_handler, | ||
490 | &msi->grps[i]); | ||
491 | /* Dedicate GIC interrupt to each CPU core */ | ||
492 | if (alloc_cpumask_var(&mask, GFP_KERNEL)) { | ||
493 | cpumask_clear(mask); | ||
494 | cpumask_set_cpu(cpu, mask); | ||
495 | ret = irq_set_affinity(msi->grps[i].gic_irq, mask); | ||
496 | if (ret) | ||
497 | dev_err(pcie->dev, | ||
498 | "failed to set affinity for IRQ%d\n", | ||
499 | msi->grps[i].gic_irq); | ||
500 | free_cpumask_var(mask); | ||
501 | } else { | ||
502 | dev_err(pcie->dev, "failed to alloc CPU mask\n"); | ||
503 | ret = -EINVAL; | ||
504 | } | ||
505 | |||
506 | if (ret) { | ||
507 | /* Free all configured/unconfigured IRQs */ | ||
508 | iproc_msi_irq_free(msi, cpu); | ||
509 | return ret; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node) | ||
517 | { | ||
518 | struct iproc_msi *msi; | ||
519 | int i, ret; | ||
520 | unsigned int cpu; | ||
521 | |||
522 | if (!of_device_is_compatible(node, "brcm,iproc-msi")) | ||
523 | return -ENODEV; | ||
524 | |||
525 | if (!of_find_property(node, "msi-controller", NULL)) | ||
526 | return -ENODEV; | ||
527 | |||
528 | if (pcie->msi) | ||
529 | return -EBUSY; | ||
530 | |||
531 | msi = devm_kzalloc(pcie->dev, sizeof(*msi), GFP_KERNEL); | ||
532 | if (!msi) | ||
533 | return -ENOMEM; | ||
534 | |||
535 | msi->pcie = pcie; | ||
536 | pcie->msi = msi; | ||
537 | msi->msi_addr = pcie->base_addr; | ||
538 | mutex_init(&msi->bitmap_lock); | ||
539 | msi->nr_cpus = num_possible_cpus(); | ||
540 | |||
541 | msi->nr_irqs = of_irq_count(node); | ||
542 | if (!msi->nr_irqs) { | ||
543 | dev_err(pcie->dev, "found no MSI GIC interrupt\n"); | ||
544 | return -ENODEV; | ||
545 | } | ||
546 | |||
547 | if (msi->nr_irqs > NR_HW_IRQS) { | ||
548 | dev_warn(pcie->dev, "too many MSI GIC interrupts defined %d\n", | ||
549 | msi->nr_irqs); | ||
550 | msi->nr_irqs = NR_HW_IRQS; | ||
551 | } | ||
552 | |||
553 | if (msi->nr_irqs < msi->nr_cpus) { | ||
554 | dev_err(pcie->dev, | ||
555 | "not enough GIC interrupts for MSI affinity\n"); | ||
556 | return -EINVAL; | ||
557 | } | ||
558 | |||
559 | if (msi->nr_irqs % msi->nr_cpus != 0) { | ||
560 | msi->nr_irqs -= msi->nr_irqs % msi->nr_cpus; | ||
561 | dev_warn(pcie->dev, "Reducing number of interrupts to %d\n", | ||
562 | msi->nr_irqs); | ||
563 | } | ||
564 | |||
565 | switch (pcie->type) { | ||
566 | case IPROC_PCIE_PAXB: | ||
567 | msi->reg_offsets = iproc_msi_reg_paxb; | ||
568 | msi->nr_eq_region = 1; | ||
569 | msi->nr_msi_region = 1; | ||
570 | break; | ||
571 | case IPROC_PCIE_PAXC: | ||
572 | msi->reg_offsets = iproc_msi_reg_paxc; | ||
573 | msi->nr_eq_region = msi->nr_irqs; | ||
574 | msi->nr_msi_region = msi->nr_irqs; | ||
575 | break; | ||
576 | default: | ||
577 | dev_err(pcie->dev, "incompatible iProc PCIe interface\n"); | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | if (of_find_property(node, "brcm,pcie-msi-inten", NULL)) | ||
582 | msi->has_inten_reg = true; | ||
583 | |||
584 | msi->nr_msi_vecs = msi->nr_irqs * EQ_LEN; | ||
585 | msi->bitmap = devm_kcalloc(pcie->dev, BITS_TO_LONGS(msi->nr_msi_vecs), | ||
586 | sizeof(*msi->bitmap), GFP_KERNEL); | ||
587 | if (!msi->bitmap) | ||
588 | return -ENOMEM; | ||
589 | |||
590 | msi->grps = devm_kcalloc(pcie->dev, msi->nr_irqs, sizeof(*msi->grps), | ||
591 | GFP_KERNEL); | ||
592 | if (!msi->grps) | ||
593 | return -ENOMEM; | ||
594 | |||
595 | for (i = 0; i < msi->nr_irqs; i++) { | ||
596 | unsigned int irq = irq_of_parse_and_map(node, i); | ||
597 | |||
598 | if (!irq) { | ||
599 | dev_err(pcie->dev, "unable to parse/map interrupt\n"); | ||
600 | ret = -ENODEV; | ||
601 | goto free_irqs; | ||
602 | } | ||
603 | msi->grps[i].gic_irq = irq; | ||
604 | msi->grps[i].msi = msi; | ||
605 | msi->grps[i].eq = i; | ||
606 | } | ||
607 | |||
608 | /* Reserve memory for event queue and make sure memories are zeroed */ | ||
609 | msi->eq_cpu = dma_zalloc_coherent(pcie->dev, | ||
610 | msi->nr_eq_region * EQ_MEM_REGION_SIZE, | ||
611 | &msi->eq_dma, GFP_KERNEL); | ||
612 | if (!msi->eq_cpu) { | ||
613 | ret = -ENOMEM; | ||
614 | goto free_irqs; | ||
615 | } | ||
616 | |||
617 | ret = iproc_msi_alloc_domains(node, msi); | ||
618 | if (ret) { | ||
619 | dev_err(pcie->dev, "failed to create MSI domains\n"); | ||
620 | goto free_eq_dma; | ||
621 | } | ||
622 | |||
623 | for_each_online_cpu(cpu) { | ||
624 | ret = iproc_msi_irq_setup(msi, cpu); | ||
625 | if (ret) | ||
626 | goto free_msi_irq; | ||
627 | } | ||
628 | |||
629 | iproc_msi_enable(msi); | ||
630 | |||
631 | return 0; | ||
632 | |||
633 | free_msi_irq: | ||
634 | for_each_online_cpu(cpu) | ||
635 | iproc_msi_irq_free(msi, cpu); | ||
636 | iproc_msi_free_domains(msi); | ||
637 | |||
638 | free_eq_dma: | ||
639 | dma_free_coherent(pcie->dev, msi->nr_eq_region * EQ_MEM_REGION_SIZE, | ||
640 | msi->eq_cpu, msi->eq_dma); | ||
641 | |||
642 | free_irqs: | ||
643 | for (i = 0; i < msi->nr_irqs; i++) { | ||
644 | if (msi->grps[i].gic_irq) | ||
645 | irq_dispose_mapping(msi->grps[i].gic_irq); | ||
646 | } | ||
647 | pcie->msi = NULL; | ||
648 | return ret; | ||
649 | } | ||
650 | EXPORT_SYMBOL(iproc_msi_init); | ||
651 | |||
652 | void iproc_msi_exit(struct iproc_pcie *pcie) | ||
653 | { | ||
654 | struct iproc_msi *msi = pcie->msi; | ||
655 | unsigned int i, cpu; | ||
656 | |||
657 | if (!msi) | ||
658 | return; | ||
659 | |||
660 | iproc_msi_disable(msi); | ||
661 | |||
662 | for_each_online_cpu(cpu) | ||
663 | iproc_msi_irq_free(msi, cpu); | ||
664 | |||
665 | iproc_msi_free_domains(msi); | ||
666 | |||
667 | dma_free_coherent(pcie->dev, msi->nr_eq_region * EQ_MEM_REGION_SIZE, | ||
668 | msi->eq_cpu, msi->eq_dma); | ||
669 | |||
670 | for (i = 0; i < msi->nr_irqs; i++) { | ||
671 | if (msi->grps[i].gic_irq) | ||
672 | irq_dispose_mapping(msi->grps[i].gic_irq); | ||
673 | } | ||
674 | } | ||
675 | EXPORT_SYMBOL(iproc_msi_exit); | ||
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c index c9550dc8b8ed..1738c5288eb6 100644 --- a/drivers/pci/host/pcie-iproc-platform.c +++ b/drivers/pci/host/pcie-iproc-platform.c | |||
@@ -26,8 +26,21 @@ | |||
26 | 26 | ||
27 | #include "pcie-iproc.h" | 27 | #include "pcie-iproc.h" |
28 | 28 | ||
29 | static const struct of_device_id iproc_pcie_of_match_table[] = { | ||
30 | { | ||
31 | .compatible = "brcm,iproc-pcie", | ||
32 | .data = (int *)IPROC_PCIE_PAXB, | ||
33 | }, { | ||
34 | .compatible = "brcm,iproc-pcie-paxc", | ||
35 | .data = (int *)IPROC_PCIE_PAXC, | ||
36 | }, | ||
37 | { /* sentinel */ } | ||
38 | }; | ||
39 | MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table); | ||
40 | |||
29 | static int iproc_pcie_pltfm_probe(struct platform_device *pdev) | 41 | static int iproc_pcie_pltfm_probe(struct platform_device *pdev) |
30 | { | 42 | { |
43 | const struct of_device_id *of_id; | ||
31 | struct iproc_pcie *pcie; | 44 | struct iproc_pcie *pcie; |
32 | struct device_node *np = pdev->dev.of_node; | 45 | struct device_node *np = pdev->dev.of_node; |
33 | struct resource reg; | 46 | struct resource reg; |
@@ -35,11 +48,16 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev) | |||
35 | LIST_HEAD(res); | 48 | LIST_HEAD(res); |
36 | int ret; | 49 | int ret; |
37 | 50 | ||
51 | of_id = of_match_device(iproc_pcie_of_match_table, &pdev->dev); | ||
52 | if (!of_id) | ||
53 | return -EINVAL; | ||
54 | |||
38 | pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL); | 55 | pcie = devm_kzalloc(&pdev->dev, sizeof(struct iproc_pcie), GFP_KERNEL); |
39 | if (!pcie) | 56 | if (!pcie) |
40 | return -ENOMEM; | 57 | return -ENOMEM; |
41 | 58 | ||
42 | pcie->dev = &pdev->dev; | 59 | pcie->dev = &pdev->dev; |
60 | pcie->type = (enum iproc_pcie_type)of_id->data; | ||
43 | platform_set_drvdata(pdev, pcie); | 61 | platform_set_drvdata(pdev, pcie); |
44 | 62 | ||
45 | ret = of_address_to_resource(np, 0, ®); | 63 | ret = of_address_to_resource(np, 0, ®); |
@@ -53,6 +71,7 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev) | |||
53 | dev_err(pcie->dev, "unable to map controller registers\n"); | 71 | dev_err(pcie->dev, "unable to map controller registers\n"); |
54 | return -ENOMEM; | 72 | return -ENOMEM; |
55 | } | 73 | } |
74 | pcie->base_addr = reg.start; | ||
56 | 75 | ||
57 | if (of_property_read_bool(np, "brcm,pcie-ob")) { | 76 | if (of_property_read_bool(np, "brcm,pcie-ob")) { |
58 | u32 val; | 77 | u32 val; |
@@ -114,12 +133,6 @@ static int iproc_pcie_pltfm_remove(struct platform_device *pdev) | |||
114 | return iproc_pcie_remove(pcie); | 133 | return iproc_pcie_remove(pcie); |
115 | } | 134 | } |
116 | 135 | ||
117 | static const struct of_device_id iproc_pcie_of_match_table[] = { | ||
118 | { .compatible = "brcm,iproc-pcie", }, | ||
119 | { /* sentinel */ } | ||
120 | }; | ||
121 | MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table); | ||
122 | |||
123 | static struct platform_driver iproc_pcie_pltfm_driver = { | 136 | static struct platform_driver iproc_pcie_pltfm_driver = { |
124 | .driver = { | 137 | .driver = { |
125 | .name = "iproc-pcie", | 138 | .name = "iproc-pcie", |
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c index eac719af16aa..5816bceddb65 100644 --- a/drivers/pci/host/pcie-iproc.c +++ b/drivers/pci/host/pcie-iproc.c | |||
@@ -30,20 +30,16 @@ | |||
30 | 30 | ||
31 | #include "pcie-iproc.h" | 31 | #include "pcie-iproc.h" |
32 | 32 | ||
33 | #define CLK_CONTROL_OFFSET 0x000 | ||
34 | #define EP_PERST_SOURCE_SELECT_SHIFT 2 | 33 | #define EP_PERST_SOURCE_SELECT_SHIFT 2 |
35 | #define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT) | 34 | #define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT) |
36 | #define EP_MODE_SURVIVE_PERST_SHIFT 1 | 35 | #define EP_MODE_SURVIVE_PERST_SHIFT 1 |
37 | #define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT) | 36 | #define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT) |
38 | #define RC_PCIE_RST_OUTPUT_SHIFT 0 | 37 | #define RC_PCIE_RST_OUTPUT_SHIFT 0 |
39 | #define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT) | 38 | #define RC_PCIE_RST_OUTPUT BIT(RC_PCIE_RST_OUTPUT_SHIFT) |
39 | #define PAXC_RESET_MASK 0x7f | ||
40 | 40 | ||
41 | #define CFG_IND_ADDR_OFFSET 0x120 | ||
42 | #define CFG_IND_ADDR_MASK 0x00001ffc | 41 | #define CFG_IND_ADDR_MASK 0x00001ffc |
43 | 42 | ||
44 | #define CFG_IND_DATA_OFFSET 0x124 | ||
45 | |||
46 | #define CFG_ADDR_OFFSET 0x1f8 | ||
47 | #define CFG_ADDR_BUS_NUM_SHIFT 20 | 43 | #define CFG_ADDR_BUS_NUM_SHIFT 20 |
48 | #define CFG_ADDR_BUS_NUM_MASK 0x0ff00000 | 44 | #define CFG_ADDR_BUS_NUM_MASK 0x0ff00000 |
49 | #define CFG_ADDR_DEV_NUM_SHIFT 15 | 45 | #define CFG_ADDR_DEV_NUM_SHIFT 15 |
@@ -55,12 +51,8 @@ | |||
55 | #define CFG_ADDR_CFG_TYPE_SHIFT 0 | 51 | #define CFG_ADDR_CFG_TYPE_SHIFT 0 |
56 | #define CFG_ADDR_CFG_TYPE_MASK 0x00000003 | 52 | #define CFG_ADDR_CFG_TYPE_MASK 0x00000003 |
57 | 53 | ||
58 | #define CFG_DATA_OFFSET 0x1fc | ||
59 | |||
60 | #define SYS_RC_INTX_EN 0x330 | ||
61 | #define SYS_RC_INTX_MASK 0xf | 54 | #define SYS_RC_INTX_MASK 0xf |
62 | 55 | ||
63 | #define PCIE_LINK_STATUS_OFFSET 0xf0c | ||
64 | #define PCIE_PHYLINKUP_SHIFT 3 | 56 | #define PCIE_PHYLINKUP_SHIFT 3 |
65 | #define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT) | 57 | #define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT) |
66 | #define PCIE_DL_ACTIVE_SHIFT 2 | 58 | #define PCIE_DL_ACTIVE_SHIFT 2 |
@@ -71,12 +63,54 @@ | |||
71 | #define OARR_SIZE_CFG_SHIFT 1 | 63 | #define OARR_SIZE_CFG_SHIFT 1 |
72 | #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) | 64 | #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) |
73 | 65 | ||
74 | #define OARR_LO(window) (0xd20 + (window) * 8) | ||
75 | #define OARR_HI(window) (0xd24 + (window) * 8) | ||
76 | #define OMAP_LO(window) (0xd40 + (window) * 8) | ||
77 | #define OMAP_HI(window) (0xd44 + (window) * 8) | ||
78 | |||
79 | #define MAX_NUM_OB_WINDOWS 2 | 66 | #define MAX_NUM_OB_WINDOWS 2 |
67 | #define MAX_NUM_PAXC_PF 4 | ||
68 | |||
69 | #define IPROC_PCIE_REG_INVALID 0xffff | ||
70 | |||
71 | enum iproc_pcie_reg { | ||
72 | IPROC_PCIE_CLK_CTRL = 0, | ||
73 | IPROC_PCIE_CFG_IND_ADDR, | ||
74 | IPROC_PCIE_CFG_IND_DATA, | ||
75 | IPROC_PCIE_CFG_ADDR, | ||
76 | IPROC_PCIE_CFG_DATA, | ||
77 | IPROC_PCIE_INTX_EN, | ||
78 | IPROC_PCIE_OARR_LO, | ||
79 | IPROC_PCIE_OARR_HI, | ||
80 | IPROC_PCIE_OMAP_LO, | ||
81 | IPROC_PCIE_OMAP_HI, | ||
82 | IPROC_PCIE_LINK_STATUS, | ||
83 | }; | ||
84 | |||
85 | /* iProc PCIe PAXB registers */ | ||
86 | static const u16 iproc_pcie_reg_paxb[] = { | ||
87 | [IPROC_PCIE_CLK_CTRL] = 0x000, | ||
88 | [IPROC_PCIE_CFG_IND_ADDR] = 0x120, | ||
89 | [IPROC_PCIE_CFG_IND_DATA] = 0x124, | ||
90 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | ||
91 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | ||
92 | [IPROC_PCIE_INTX_EN] = 0x330, | ||
93 | [IPROC_PCIE_OARR_LO] = 0xd20, | ||
94 | [IPROC_PCIE_OARR_HI] = 0xd24, | ||
95 | [IPROC_PCIE_OMAP_LO] = 0xd40, | ||
96 | [IPROC_PCIE_OMAP_HI] = 0xd44, | ||
97 | [IPROC_PCIE_LINK_STATUS] = 0xf0c, | ||
98 | }; | ||
99 | |||
100 | /* iProc PCIe PAXC v1 registers */ | ||
101 | static const u16 iproc_pcie_reg_paxc[] = { | ||
102 | [IPROC_PCIE_CLK_CTRL] = 0x000, | ||
103 | [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, | ||
104 | [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, | ||
105 | [IPROC_PCIE_CFG_ADDR] = 0x1f8, | ||
106 | [IPROC_PCIE_CFG_DATA] = 0x1fc, | ||
107 | [IPROC_PCIE_INTX_EN] = IPROC_PCIE_REG_INVALID, | ||
108 | [IPROC_PCIE_OARR_LO] = IPROC_PCIE_REG_INVALID, | ||
109 | [IPROC_PCIE_OARR_HI] = IPROC_PCIE_REG_INVALID, | ||
110 | [IPROC_PCIE_OMAP_LO] = IPROC_PCIE_REG_INVALID, | ||
111 | [IPROC_PCIE_OMAP_HI] = IPROC_PCIE_REG_INVALID, | ||
112 | [IPROC_PCIE_LINK_STATUS] = IPROC_PCIE_REG_INVALID, | ||
113 | }; | ||
80 | 114 | ||
81 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) | 115 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) |
82 | { | 116 | { |
@@ -91,6 +125,65 @@ static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) | |||
91 | return pcie; | 125 | return pcie; |
92 | } | 126 | } |
93 | 127 | ||
128 | static inline bool iproc_pcie_reg_is_invalid(u16 reg_offset) | ||
129 | { | ||
130 | return !!(reg_offset == IPROC_PCIE_REG_INVALID); | ||
131 | } | ||
132 | |||
133 | static inline u16 iproc_pcie_reg_offset(struct iproc_pcie *pcie, | ||
134 | enum iproc_pcie_reg reg) | ||
135 | { | ||
136 | return pcie->reg_offsets[reg]; | ||
137 | } | ||
138 | |||
139 | static inline u32 iproc_pcie_read_reg(struct iproc_pcie *pcie, | ||
140 | enum iproc_pcie_reg reg) | ||
141 | { | ||
142 | u16 offset = iproc_pcie_reg_offset(pcie, reg); | ||
143 | |||
144 | if (iproc_pcie_reg_is_invalid(offset)) | ||
145 | return 0; | ||
146 | |||
147 | return readl(pcie->base + offset); | ||
148 | } | ||
149 | |||
150 | static inline void iproc_pcie_write_reg(struct iproc_pcie *pcie, | ||
151 | enum iproc_pcie_reg reg, u32 val) | ||
152 | { | ||
153 | u16 offset = iproc_pcie_reg_offset(pcie, reg); | ||
154 | |||
155 | if (iproc_pcie_reg_is_invalid(offset)) | ||
156 | return; | ||
157 | |||
158 | writel(val, pcie->base + offset); | ||
159 | } | ||
160 | |||
161 | static inline void iproc_pcie_ob_write(struct iproc_pcie *pcie, | ||
162 | enum iproc_pcie_reg reg, | ||
163 | unsigned window, u32 val) | ||
164 | { | ||
165 | u16 offset = iproc_pcie_reg_offset(pcie, reg); | ||
166 | |||
167 | if (iproc_pcie_reg_is_invalid(offset)) | ||
168 | return; | ||
169 | |||
170 | writel(val, pcie->base + offset + (window * 8)); | ||
171 | } | ||
172 | |||
173 | static inline bool iproc_pcie_device_is_valid(struct iproc_pcie *pcie, | ||
174 | unsigned int slot, | ||
175 | unsigned int fn) | ||
176 | { | ||
177 | if (slot > 0) | ||
178 | return false; | ||
179 | |||
180 | /* PAXC can only support limited number of functions */ | ||
181 | if (pcie->type == IPROC_PCIE_PAXC && fn >= MAX_NUM_PAXC_PF) | ||
182 | return false; | ||
183 | |||
184 | return true; | ||
185 | } | ||
186 | |||
94 | /** | 187 | /** |
95 | * Note access to the configuration registers are protected at the higher layer | 188 | * Note access to the configuration registers are protected at the higher layer |
96 | * by 'pci_lock' in drivers/pci/access.c | 189 | * by 'pci_lock' in drivers/pci/access.c |
@@ -104,28 +197,34 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, | |||
104 | unsigned fn = PCI_FUNC(devfn); | 197 | unsigned fn = PCI_FUNC(devfn); |
105 | unsigned busno = bus->number; | 198 | unsigned busno = bus->number; |
106 | u32 val; | 199 | u32 val; |
200 | u16 offset; | ||
201 | |||
202 | if (!iproc_pcie_device_is_valid(pcie, slot, fn)) | ||
203 | return NULL; | ||
107 | 204 | ||
108 | /* root complex access */ | 205 | /* root complex access */ |
109 | if (busno == 0) { | 206 | if (busno == 0) { |
110 | if (slot >= 1) | 207 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR, |
208 | where & CFG_IND_ADDR_MASK); | ||
209 | offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_IND_DATA); | ||
210 | if (iproc_pcie_reg_is_invalid(offset)) | ||
111 | return NULL; | 211 | return NULL; |
112 | writel(where & CFG_IND_ADDR_MASK, | 212 | else |
113 | pcie->base + CFG_IND_ADDR_OFFSET); | 213 | return (pcie->base + offset); |
114 | return (pcie->base + CFG_IND_DATA_OFFSET); | ||
115 | } | 214 | } |
116 | 215 | ||
117 | if (fn > 1) | ||
118 | return NULL; | ||
119 | |||
120 | /* EP device access */ | 216 | /* EP device access */ |
121 | val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | | 217 | val = (busno << CFG_ADDR_BUS_NUM_SHIFT) | |
122 | (slot << CFG_ADDR_DEV_NUM_SHIFT) | | 218 | (slot << CFG_ADDR_DEV_NUM_SHIFT) | |
123 | (fn << CFG_ADDR_FUNC_NUM_SHIFT) | | 219 | (fn << CFG_ADDR_FUNC_NUM_SHIFT) | |
124 | (where & CFG_ADDR_REG_NUM_MASK) | | 220 | (where & CFG_ADDR_REG_NUM_MASK) | |
125 | (1 & CFG_ADDR_CFG_TYPE_MASK); | 221 | (1 & CFG_ADDR_CFG_TYPE_MASK); |
126 | writel(val, pcie->base + CFG_ADDR_OFFSET); | 222 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_ADDR, val); |
127 | 223 | offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_DATA); | |
128 | return (pcie->base + CFG_DATA_OFFSET); | 224 | if (iproc_pcie_reg_is_invalid(offset)) |
225 | return NULL; | ||
226 | else | ||
227 | return (pcie->base + offset); | ||
129 | } | 228 | } |
130 | 229 | ||
131 | static struct pci_ops iproc_pcie_ops = { | 230 | static struct pci_ops iproc_pcie_ops = { |
@@ -138,18 +237,29 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie) | |||
138 | { | 237 | { |
139 | u32 val; | 238 | u32 val; |
140 | 239 | ||
240 | if (pcie->type == IPROC_PCIE_PAXC) { | ||
241 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL); | ||
242 | val &= ~PAXC_RESET_MASK; | ||
243 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); | ||
244 | udelay(100); | ||
245 | val |= PAXC_RESET_MASK; | ||
246 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); | ||
247 | udelay(100); | ||
248 | return; | ||
249 | } | ||
250 | |||
141 | /* | 251 | /* |
142 | * Select perst_b signal as reset source. Put the device into reset, | 252 | * Select perst_b signal as reset source. Put the device into reset, |
143 | * and then bring it out of reset | 253 | * and then bring it out of reset |
144 | */ | 254 | */ |
145 | val = readl(pcie->base + CLK_CONTROL_OFFSET); | 255 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_CLK_CTRL); |
146 | val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST & | 256 | val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST & |
147 | ~RC_PCIE_RST_OUTPUT; | 257 | ~RC_PCIE_RST_OUTPUT; |
148 | writel(val, pcie->base + CLK_CONTROL_OFFSET); | 258 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); |
149 | udelay(250); | 259 | udelay(250); |
150 | 260 | ||
151 | val |= RC_PCIE_RST_OUTPUT; | 261 | val |= RC_PCIE_RST_OUTPUT; |
152 | writel(val, pcie->base + CLK_CONTROL_OFFSET); | 262 | iproc_pcie_write_reg(pcie, IPROC_PCIE_CLK_CTRL, val); |
153 | msleep(100); | 263 | msleep(100); |
154 | } | 264 | } |
155 | 265 | ||
@@ -160,7 +270,14 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | |||
160 | u16 pos, link_status; | 270 | u16 pos, link_status; |
161 | bool link_is_active = false; | 271 | bool link_is_active = false; |
162 | 272 | ||
163 | val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); | 273 | /* |
274 | * PAXC connects to emulated endpoint devices directly and does not | ||
275 | * have a Serdes. Therefore skip the link detection logic here. | ||
276 | */ | ||
277 | if (pcie->type == IPROC_PCIE_PAXC) | ||
278 | return 0; | ||
279 | |||
280 | val = iproc_pcie_read_reg(pcie, IPROC_PCIE_LINK_STATUS); | ||
164 | if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { | 281 | if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { |
165 | dev_err(pcie->dev, "PHY or data link is INACTIVE!\n"); | 282 | dev_err(pcie->dev, "PHY or data link is INACTIVE!\n"); |
166 | return -ENODEV; | 283 | return -ENODEV; |
@@ -221,7 +338,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | |||
221 | 338 | ||
222 | static void iproc_pcie_enable(struct iproc_pcie *pcie) | 339 | static void iproc_pcie_enable(struct iproc_pcie *pcie) |
223 | { | 340 | { |
224 | writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); | 341 | iproc_pcie_write_reg(pcie, IPROC_PCIE_INTX_EN, SYS_RC_INTX_MASK); |
225 | } | 342 | } |
226 | 343 | ||
227 | /** | 344 | /** |
@@ -245,7 +362,7 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, | |||
245 | 362 | ||
246 | if (size > max_size) { | 363 | if (size > max_size) { |
247 | dev_err(pcie->dev, | 364 | dev_err(pcie->dev, |
248 | "res size 0x%pap exceeds max supported size 0x%llx\n", | 365 | "res size %pap exceeds max supported size 0x%llx\n", |
249 | &size, max_size); | 366 | &size, max_size); |
250 | return -EINVAL; | 367 | return -EINVAL; |
251 | } | 368 | } |
@@ -272,11 +389,15 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, | |||
272 | axi_addr -= ob->axi_offset; | 389 | axi_addr -= ob->axi_offset; |
273 | 390 | ||
274 | for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) { | 391 | for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) { |
275 | writel(lower_32_bits(axi_addr) | OARR_VALID | | 392 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_LO, i, |
276 | (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i)); | 393 | lower_32_bits(axi_addr) | OARR_VALID | |
277 | writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i)); | 394 | (ob->set_oarr_size ? 1 : 0)); |
278 | writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i)); | 395 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OARR_HI, i, |
279 | writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i)); | 396 | upper_32_bits(axi_addr)); |
397 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_LO, i, | ||
398 | lower_32_bits(pci_addr)); | ||
399 | iproc_pcie_ob_write(pcie, IPROC_PCIE_OMAP_HI, i, | ||
400 | upper_32_bits(pci_addr)); | ||
280 | 401 | ||
281 | size -= ob->window_size; | 402 | size -= ob->window_size; |
282 | if (size == 0) | 403 | if (size == 0) |
@@ -319,6 +440,26 @@ static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, | |||
319 | return 0; | 440 | return 0; |
320 | } | 441 | } |
321 | 442 | ||
443 | static int iproc_pcie_msi_enable(struct iproc_pcie *pcie) | ||
444 | { | ||
445 | struct device_node *msi_node; | ||
446 | |||
447 | msi_node = of_parse_phandle(pcie->dev->of_node, "msi-parent", 0); | ||
448 | if (!msi_node) | ||
449 | return -ENODEV; | ||
450 | |||
451 | /* | ||
452 | * If another MSI controller is being used, the call below should fail | ||
453 | * but that is okay | ||
454 | */ | ||
455 | return iproc_msi_init(pcie, msi_node); | ||
456 | } | ||
457 | |||
458 | static void iproc_pcie_msi_disable(struct iproc_pcie *pcie) | ||
459 | { | ||
460 | iproc_msi_exit(pcie); | ||
461 | } | ||
462 | |||
322 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | 463 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) |
323 | { | 464 | { |
324 | int ret; | 465 | int ret; |
@@ -340,6 +481,19 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
340 | goto err_exit_phy; | 481 | goto err_exit_phy; |
341 | } | 482 | } |
342 | 483 | ||
484 | switch (pcie->type) { | ||
485 | case IPROC_PCIE_PAXB: | ||
486 | pcie->reg_offsets = iproc_pcie_reg_paxb; | ||
487 | break; | ||
488 | case IPROC_PCIE_PAXC: | ||
489 | pcie->reg_offsets = iproc_pcie_reg_paxc; | ||
490 | break; | ||
491 | default: | ||
492 | dev_err(pcie->dev, "incompatible iProc PCIe interface\n"); | ||
493 | ret = -EINVAL; | ||
494 | goto err_power_off_phy; | ||
495 | } | ||
496 | |||
343 | iproc_pcie_reset(pcie); | 497 | iproc_pcie_reset(pcie); |
344 | 498 | ||
345 | if (pcie->need_ob_cfg) { | 499 | if (pcie->need_ob_cfg) { |
@@ -373,6 +527,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
373 | 527 | ||
374 | iproc_pcie_enable(pcie); | 528 | iproc_pcie_enable(pcie); |
375 | 529 | ||
530 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
531 | if (iproc_pcie_msi_enable(pcie)) | ||
532 | dev_info(pcie->dev, "not using iProc MSI\n"); | ||
533 | |||
376 | pci_scan_child_bus(bus); | 534 | pci_scan_child_bus(bus); |
377 | pci_assign_unassigned_bus_resources(bus); | 535 | pci_assign_unassigned_bus_resources(bus); |
378 | pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); | 536 | pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); |
@@ -397,6 +555,8 @@ int iproc_pcie_remove(struct iproc_pcie *pcie) | |||
397 | pci_stop_root_bus(pcie->root_bus); | 555 | pci_stop_root_bus(pcie->root_bus); |
398 | pci_remove_root_bus(pcie->root_bus); | 556 | pci_remove_root_bus(pcie->root_bus); |
399 | 557 | ||
558 | iproc_pcie_msi_disable(pcie); | ||
559 | |||
400 | phy_power_off(pcie->phy); | 560 | phy_power_off(pcie->phy); |
401 | phy_exit(pcie->phy); | 561 | phy_exit(pcie->phy); |
402 | 562 | ||
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h index d3dc940f773a..e84d93c53c7b 100644 --- a/drivers/pci/host/pcie-iproc.h +++ b/drivers/pci/host/pcie-iproc.h | |||
@@ -15,6 +15,20 @@ | |||
15 | #define _PCIE_IPROC_H | 15 | #define _PCIE_IPROC_H |
16 | 16 | ||
17 | /** | 17 | /** |
18 | * iProc PCIe interface type | ||
19 | * | ||
20 | * PAXB is the wrapper used in root complex that can be connected to an | ||
21 | * external endpoint device. | ||
22 | * | ||
23 | * PAXC is the wrapper used in root complex dedicated for internal emulated | ||
24 | * endpoint devices. | ||
25 | */ | ||
26 | enum iproc_pcie_type { | ||
27 | IPROC_PCIE_PAXB = 0, | ||
28 | IPROC_PCIE_PAXC, | ||
29 | }; | ||
30 | |||
31 | /** | ||
18 | * iProc PCIe outbound mapping | 32 | * iProc PCIe outbound mapping |
19 | * @set_oarr_size: indicates the OARR size bit needs to be set | 33 | * @set_oarr_size: indicates the OARR size bit needs to be set |
20 | * @axi_offset: offset from the AXI address to the internal address used by | 34 | * @axi_offset: offset from the AXI address to the internal address used by |
@@ -27,21 +41,30 @@ struct iproc_pcie_ob { | |||
27 | resource_size_t window_size; | 41 | resource_size_t window_size; |
28 | }; | 42 | }; |
29 | 43 | ||
44 | struct iproc_msi; | ||
45 | |||
30 | /** | 46 | /** |
31 | * iProc PCIe device | 47 | * iProc PCIe device |
48 | * | ||
32 | * @dev: pointer to device data structure | 49 | * @dev: pointer to device data structure |
50 | * @type: iProc PCIe interface type | ||
51 | * @reg_offsets: register offsets | ||
33 | * @base: PCIe host controller I/O register base | 52 | * @base: PCIe host controller I/O register base |
53 | * @base_addr: PCIe host controller register base physical address | ||
34 | * @sysdata: Per PCI controller data (ARM-specific) | 54 | * @sysdata: Per PCI controller data (ARM-specific) |
35 | * @root_bus: pointer to root bus | 55 | * @root_bus: pointer to root bus |
36 | * @phy: optional PHY device that controls the Serdes | 56 | * @phy: optional PHY device that controls the Serdes |
37 | * @irqs: interrupt IDs | ||
38 | * @map_irq: function callback to map interrupts | 57 | * @map_irq: function callback to map interrupts |
39 | * @need_ob_cfg: indidates SW needs to configure the outbound mapping window | 58 | * @need_ob_cfg: indicates SW needs to configure the outbound mapping window |
40 | * @ob: outbound mapping parameters | 59 | * @ob: outbound mapping parameters |
60 | * @msi: MSI data | ||
41 | */ | 61 | */ |
42 | struct iproc_pcie { | 62 | struct iproc_pcie { |
43 | struct device *dev; | 63 | struct device *dev; |
64 | enum iproc_pcie_type type; | ||
65 | const u16 *reg_offsets; | ||
44 | void __iomem *base; | 66 | void __iomem *base; |
67 | phys_addr_t base_addr; | ||
45 | #ifdef CONFIG_ARM | 68 | #ifdef CONFIG_ARM |
46 | struct pci_sys_data sysdata; | 69 | struct pci_sys_data sysdata; |
47 | #endif | 70 | #endif |
@@ -50,9 +73,24 @@ struct iproc_pcie { | |||
50 | int (*map_irq)(const struct pci_dev *, u8, u8); | 73 | int (*map_irq)(const struct pci_dev *, u8, u8); |
51 | bool need_ob_cfg; | 74 | bool need_ob_cfg; |
52 | struct iproc_pcie_ob ob; | 75 | struct iproc_pcie_ob ob; |
76 | struct iproc_msi *msi; | ||
53 | }; | 77 | }; |
54 | 78 | ||
55 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); | 79 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); |
56 | int iproc_pcie_remove(struct iproc_pcie *pcie); | 80 | int iproc_pcie_remove(struct iproc_pcie *pcie); |
57 | 81 | ||
82 | #ifdef CONFIG_PCIE_IPROC_MSI | ||
83 | int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node); | ||
84 | void iproc_msi_exit(struct iproc_pcie *pcie); | ||
85 | #else | ||
86 | static inline int iproc_msi_init(struct iproc_pcie *pcie, | ||
87 | struct device_node *node) | ||
88 | { | ||
89 | return -ENODEV; | ||
90 | } | ||
91 | static inline void iproc_msi_exit(struct iproc_pcie *pcie) | ||
92 | { | ||
93 | } | ||
94 | #endif | ||
95 | |||
58 | #endif /* _PCIE_IPROC_H */ | 96 | #endif /* _PCIE_IPROC_H */ |
diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c new file mode 100644 index 000000000000..e845fba19632 --- /dev/null +++ b/drivers/pci/host/pcie-qcom.c | |||
@@ -0,0 +1,616 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. | ||
3 | * Copyright 2015 Linaro Limited. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 and | ||
7 | * only version 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/iopoll.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/of_device.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/phy/phy.h> | ||
28 | #include <linux/regulator/consumer.h> | ||
29 | #include <linux/reset.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/types.h> | ||
32 | |||
33 | #include "pcie-designware.h" | ||
34 | |||
35 | #define PCIE20_PARF_PHY_CTRL 0x40 | ||
36 | #define PCIE20_PARF_PHY_REFCLK 0x4C | ||
37 | #define PCIE20_PARF_DBI_BASE_ADDR 0x168 | ||
38 | #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c | ||
39 | #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 | ||
40 | |||
41 | #define PCIE20_ELBI_SYS_CTRL 0x04 | ||
42 | #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) | ||
43 | |||
44 | #define PCIE20_CAP 0x70 | ||
45 | |||
46 | #define PERST_DELAY_US 1000 | ||
47 | |||
48 | struct qcom_pcie_resources_v0 { | ||
49 | struct clk *iface_clk; | ||
50 | struct clk *core_clk; | ||
51 | struct clk *phy_clk; | ||
52 | struct reset_control *pci_reset; | ||
53 | struct reset_control *axi_reset; | ||
54 | struct reset_control *ahb_reset; | ||
55 | struct reset_control *por_reset; | ||
56 | struct reset_control *phy_reset; | ||
57 | struct regulator *vdda; | ||
58 | struct regulator *vdda_phy; | ||
59 | struct regulator *vdda_refclk; | ||
60 | }; | ||
61 | |||
62 | struct qcom_pcie_resources_v1 { | ||
63 | struct clk *iface; | ||
64 | struct clk *aux; | ||
65 | struct clk *master_bus; | ||
66 | struct clk *slave_bus; | ||
67 | struct reset_control *core; | ||
68 | struct regulator *vdda; | ||
69 | }; | ||
70 | |||
71 | union qcom_pcie_resources { | ||
72 | struct qcom_pcie_resources_v0 v0; | ||
73 | struct qcom_pcie_resources_v1 v1; | ||
74 | }; | ||
75 | |||
76 | struct qcom_pcie; | ||
77 | |||
78 | struct qcom_pcie_ops { | ||
79 | int (*get_resources)(struct qcom_pcie *pcie); | ||
80 | int (*init)(struct qcom_pcie *pcie); | ||
81 | void (*deinit)(struct qcom_pcie *pcie); | ||
82 | }; | ||
83 | |||
84 | struct qcom_pcie { | ||
85 | struct pcie_port pp; | ||
86 | struct device *dev; | ||
87 | union qcom_pcie_resources res; | ||
88 | void __iomem *parf; | ||
89 | void __iomem *dbi; | ||
90 | void __iomem *elbi; | ||
91 | struct phy *phy; | ||
92 | struct gpio_desc *reset; | ||
93 | struct qcom_pcie_ops *ops; | ||
94 | }; | ||
95 | |||
96 | #define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp) | ||
97 | |||
98 | static void qcom_ep_reset_assert(struct qcom_pcie *pcie) | ||
99 | { | ||
100 | gpiod_set_value(pcie->reset, 1); | ||
101 | usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); | ||
102 | } | ||
103 | |||
104 | static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) | ||
105 | { | ||
106 | gpiod_set_value(pcie->reset, 0); | ||
107 | usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); | ||
108 | } | ||
109 | |||
110 | static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg) | ||
111 | { | ||
112 | struct pcie_port *pp = arg; | ||
113 | |||
114 | return dw_handle_msi_irq(pp); | ||
115 | } | ||
116 | |||
117 | static int qcom_pcie_establish_link(struct qcom_pcie *pcie) | ||
118 | { | ||
119 | struct device *dev = pcie->dev; | ||
120 | unsigned int retries = 0; | ||
121 | u32 val; | ||
122 | |||
123 | if (dw_pcie_link_up(&pcie->pp)) | ||
124 | return 0; | ||
125 | |||
126 | /* enable link training */ | ||
127 | val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL); | ||
128 | val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE; | ||
129 | writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL); | ||
130 | |||
131 | do { | ||
132 | if (dw_pcie_link_up(&pcie->pp)) | ||
133 | return 0; | ||
134 | usleep_range(250, 1000); | ||
135 | } while (retries < 200); | ||
136 | |||
137 | dev_warn(dev, "phy link never came up\n"); | ||
138 | |||
139 | return -ETIMEDOUT; | ||
140 | } | ||
141 | |||
142 | static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie) | ||
143 | { | ||
144 | struct qcom_pcie_resources_v0 *res = &pcie->res.v0; | ||
145 | struct device *dev = pcie->dev; | ||
146 | |||
147 | res->vdda = devm_regulator_get(dev, "vdda"); | ||
148 | if (IS_ERR(res->vdda)) | ||
149 | return PTR_ERR(res->vdda); | ||
150 | |||
151 | res->vdda_phy = devm_regulator_get(dev, "vdda_phy"); | ||
152 | if (IS_ERR(res->vdda_phy)) | ||
153 | return PTR_ERR(res->vdda_phy); | ||
154 | |||
155 | res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk"); | ||
156 | if (IS_ERR(res->vdda_refclk)) | ||
157 | return PTR_ERR(res->vdda_refclk); | ||
158 | |||
159 | res->iface_clk = devm_clk_get(dev, "iface"); | ||
160 | if (IS_ERR(res->iface_clk)) | ||
161 | return PTR_ERR(res->iface_clk); | ||
162 | |||
163 | res->core_clk = devm_clk_get(dev, "core"); | ||
164 | if (IS_ERR(res->core_clk)) | ||
165 | return PTR_ERR(res->core_clk); | ||
166 | |||
167 | res->phy_clk = devm_clk_get(dev, "phy"); | ||
168 | if (IS_ERR(res->phy_clk)) | ||
169 | return PTR_ERR(res->phy_clk); | ||
170 | |||
171 | res->pci_reset = devm_reset_control_get(dev, "pci"); | ||
172 | if (IS_ERR(res->pci_reset)) | ||
173 | return PTR_ERR(res->pci_reset); | ||
174 | |||
175 | res->axi_reset = devm_reset_control_get(dev, "axi"); | ||
176 | if (IS_ERR(res->axi_reset)) | ||
177 | return PTR_ERR(res->axi_reset); | ||
178 | |||
179 | res->ahb_reset = devm_reset_control_get(dev, "ahb"); | ||
180 | if (IS_ERR(res->ahb_reset)) | ||
181 | return PTR_ERR(res->ahb_reset); | ||
182 | |||
183 | res->por_reset = devm_reset_control_get(dev, "por"); | ||
184 | if (IS_ERR(res->por_reset)) | ||
185 | return PTR_ERR(res->por_reset); | ||
186 | |||
187 | res->phy_reset = devm_reset_control_get(dev, "phy"); | ||
188 | if (IS_ERR(res->phy_reset)) | ||
189 | return PTR_ERR(res->phy_reset); | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie) | ||
195 | { | ||
196 | struct qcom_pcie_resources_v1 *res = &pcie->res.v1; | ||
197 | struct device *dev = pcie->dev; | ||
198 | |||
199 | res->vdda = devm_regulator_get(dev, "vdda"); | ||
200 | if (IS_ERR(res->vdda)) | ||
201 | return PTR_ERR(res->vdda); | ||
202 | |||
203 | res->iface = devm_clk_get(dev, "iface"); | ||
204 | if (IS_ERR(res->iface)) | ||
205 | return PTR_ERR(res->iface); | ||
206 | |||
207 | res->aux = devm_clk_get(dev, "aux"); | ||
208 | if (IS_ERR(res->aux)) | ||
209 | return PTR_ERR(res->aux); | ||
210 | |||
211 | res->master_bus = devm_clk_get(dev, "master_bus"); | ||
212 | if (IS_ERR(res->master_bus)) | ||
213 | return PTR_ERR(res->master_bus); | ||
214 | |||
215 | res->slave_bus = devm_clk_get(dev, "slave_bus"); | ||
216 | if (IS_ERR(res->slave_bus)) | ||
217 | return PTR_ERR(res->slave_bus); | ||
218 | |||
219 | res->core = devm_reset_control_get(dev, "core"); | ||
220 | if (IS_ERR(res->core)) | ||
221 | return PTR_ERR(res->core); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie) | ||
227 | { | ||
228 | struct qcom_pcie_resources_v0 *res = &pcie->res.v0; | ||
229 | |||
230 | reset_control_assert(res->pci_reset); | ||
231 | reset_control_assert(res->axi_reset); | ||
232 | reset_control_assert(res->ahb_reset); | ||
233 | reset_control_assert(res->por_reset); | ||
234 | reset_control_assert(res->pci_reset); | ||
235 | clk_disable_unprepare(res->iface_clk); | ||
236 | clk_disable_unprepare(res->core_clk); | ||
237 | clk_disable_unprepare(res->phy_clk); | ||
238 | regulator_disable(res->vdda); | ||
239 | regulator_disable(res->vdda_phy); | ||
240 | regulator_disable(res->vdda_refclk); | ||
241 | } | ||
242 | |||
243 | static int qcom_pcie_init_v0(struct qcom_pcie *pcie) | ||
244 | { | ||
245 | struct qcom_pcie_resources_v0 *res = &pcie->res.v0; | ||
246 | struct device *dev = pcie->dev; | ||
247 | u32 val; | ||
248 | int ret; | ||
249 | |||
250 | ret = regulator_enable(res->vdda); | ||
251 | if (ret) { | ||
252 | dev_err(dev, "cannot enable vdda regulator\n"); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | ret = regulator_enable(res->vdda_refclk); | ||
257 | if (ret) { | ||
258 | dev_err(dev, "cannot enable vdda_refclk regulator\n"); | ||
259 | goto err_refclk; | ||
260 | } | ||
261 | |||
262 | ret = regulator_enable(res->vdda_phy); | ||
263 | if (ret) { | ||
264 | dev_err(dev, "cannot enable vdda_phy regulator\n"); | ||
265 | goto err_vdda_phy; | ||
266 | } | ||
267 | |||
268 | ret = reset_control_assert(res->ahb_reset); | ||
269 | if (ret) { | ||
270 | dev_err(dev, "cannot assert ahb reset\n"); | ||
271 | goto err_assert_ahb; | ||
272 | } | ||
273 | |||
274 | ret = clk_prepare_enable(res->iface_clk); | ||
275 | if (ret) { | ||
276 | dev_err(dev, "cannot prepare/enable iface clock\n"); | ||
277 | goto err_assert_ahb; | ||
278 | } | ||
279 | |||
280 | ret = clk_prepare_enable(res->phy_clk); | ||
281 | if (ret) { | ||
282 | dev_err(dev, "cannot prepare/enable phy clock\n"); | ||
283 | goto err_clk_phy; | ||
284 | } | ||
285 | |||
286 | ret = clk_prepare_enable(res->core_clk); | ||
287 | if (ret) { | ||
288 | dev_err(dev, "cannot prepare/enable core clock\n"); | ||
289 | goto err_clk_core; | ||
290 | } | ||
291 | |||
292 | ret = reset_control_deassert(res->ahb_reset); | ||
293 | if (ret) { | ||
294 | dev_err(dev, "cannot deassert ahb reset\n"); | ||
295 | goto err_deassert_ahb; | ||
296 | } | ||
297 | |||
298 | /* enable PCIe clocks and resets */ | ||
299 | val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); | ||
300 | val &= ~BIT(0); | ||
301 | writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); | ||
302 | |||
303 | /* enable external reference clock */ | ||
304 | val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); | ||
305 | val |= BIT(16); | ||
306 | writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); | ||
307 | |||
308 | ret = reset_control_deassert(res->phy_reset); | ||
309 | if (ret) { | ||
310 | dev_err(dev, "cannot deassert phy reset\n"); | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | ret = reset_control_deassert(res->pci_reset); | ||
315 | if (ret) { | ||
316 | dev_err(dev, "cannot deassert pci reset\n"); | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | ret = reset_control_deassert(res->por_reset); | ||
321 | if (ret) { | ||
322 | dev_err(dev, "cannot deassert por reset\n"); | ||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | ret = reset_control_deassert(res->axi_reset); | ||
327 | if (ret) { | ||
328 | dev_err(dev, "cannot deassert axi reset\n"); | ||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | /* wait for clock acquisition */ | ||
333 | usleep_range(1000, 1500); | ||
334 | |||
335 | return 0; | ||
336 | |||
337 | err_deassert_ahb: | ||
338 | clk_disable_unprepare(res->core_clk); | ||
339 | err_clk_core: | ||
340 | clk_disable_unprepare(res->phy_clk); | ||
341 | err_clk_phy: | ||
342 | clk_disable_unprepare(res->iface_clk); | ||
343 | err_assert_ahb: | ||
344 | regulator_disable(res->vdda_phy); | ||
345 | err_vdda_phy: | ||
346 | regulator_disable(res->vdda_refclk); | ||
347 | err_refclk: | ||
348 | regulator_disable(res->vdda); | ||
349 | |||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie) | ||
354 | { | ||
355 | struct qcom_pcie_resources_v1 *res = &pcie->res.v1; | ||
356 | |||
357 | reset_control_assert(res->core); | ||
358 | clk_disable_unprepare(res->slave_bus); | ||
359 | clk_disable_unprepare(res->master_bus); | ||
360 | clk_disable_unprepare(res->iface); | ||
361 | clk_disable_unprepare(res->aux); | ||
362 | regulator_disable(res->vdda); | ||
363 | } | ||
364 | |||
365 | static int qcom_pcie_init_v1(struct qcom_pcie *pcie) | ||
366 | { | ||
367 | struct qcom_pcie_resources_v1 *res = &pcie->res.v1; | ||
368 | struct device *dev = pcie->dev; | ||
369 | int ret; | ||
370 | |||
371 | ret = reset_control_deassert(res->core); | ||
372 | if (ret) { | ||
373 | dev_err(dev, "cannot deassert core reset\n"); | ||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | ret = clk_prepare_enable(res->aux); | ||
378 | if (ret) { | ||
379 | dev_err(dev, "cannot prepare/enable aux clock\n"); | ||
380 | goto err_res; | ||
381 | } | ||
382 | |||
383 | ret = clk_prepare_enable(res->iface); | ||
384 | if (ret) { | ||
385 | dev_err(dev, "cannot prepare/enable iface clock\n"); | ||
386 | goto err_aux; | ||
387 | } | ||
388 | |||
389 | ret = clk_prepare_enable(res->master_bus); | ||
390 | if (ret) { | ||
391 | dev_err(dev, "cannot prepare/enable master_bus clock\n"); | ||
392 | goto err_iface; | ||
393 | } | ||
394 | |||
395 | ret = clk_prepare_enable(res->slave_bus); | ||
396 | if (ret) { | ||
397 | dev_err(dev, "cannot prepare/enable slave_bus clock\n"); | ||
398 | goto err_master; | ||
399 | } | ||
400 | |||
401 | ret = regulator_enable(res->vdda); | ||
402 | if (ret) { | ||
403 | dev_err(dev, "cannot enable vdda regulator\n"); | ||
404 | goto err_slave; | ||
405 | } | ||
406 | |||
407 | /* change DBI base address */ | ||
408 | writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); | ||
409 | |||
410 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
411 | u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); | ||
412 | |||
413 | val |= BIT(31); | ||
414 | writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); | ||
415 | } | ||
416 | |||
417 | return 0; | ||
418 | err_slave: | ||
419 | clk_disable_unprepare(res->slave_bus); | ||
420 | err_master: | ||
421 | clk_disable_unprepare(res->master_bus); | ||
422 | err_iface: | ||
423 | clk_disable_unprepare(res->iface); | ||
424 | err_aux: | ||
425 | clk_disable_unprepare(res->aux); | ||
426 | err_res: | ||
427 | reset_control_assert(res->core); | ||
428 | |||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static int qcom_pcie_link_up(struct pcie_port *pp) | ||
433 | { | ||
434 | struct qcom_pcie *pcie = to_qcom_pcie(pp); | ||
435 | u16 val = readw(pcie->dbi + PCIE20_CAP + PCI_EXP_LNKSTA); | ||
436 | |||
437 | return !!(val & PCI_EXP_LNKSTA_DLLLA); | ||
438 | } | ||
439 | |||
440 | static void qcom_pcie_host_init(struct pcie_port *pp) | ||
441 | { | ||
442 | struct qcom_pcie *pcie = to_qcom_pcie(pp); | ||
443 | int ret; | ||
444 | |||
445 | qcom_ep_reset_assert(pcie); | ||
446 | |||
447 | ret = pcie->ops->init(pcie); | ||
448 | if (ret) | ||
449 | goto err_deinit; | ||
450 | |||
451 | ret = phy_power_on(pcie->phy); | ||
452 | if (ret) | ||
453 | goto err_deinit; | ||
454 | |||
455 | dw_pcie_setup_rc(pp); | ||
456 | |||
457 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
458 | dw_pcie_msi_init(pp); | ||
459 | |||
460 | qcom_ep_reset_deassert(pcie); | ||
461 | |||
462 | ret = qcom_pcie_establish_link(pcie); | ||
463 | if (ret) | ||
464 | goto err; | ||
465 | |||
466 | return; | ||
467 | err: | ||
468 | qcom_ep_reset_assert(pcie); | ||
469 | phy_power_off(pcie->phy); | ||
470 | err_deinit: | ||
471 | pcie->ops->deinit(pcie); | ||
472 | } | ||
473 | |||
474 | static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | ||
475 | u32 *val) | ||
476 | { | ||
477 | /* the device class is not reported correctly from the register */ | ||
478 | if (where == PCI_CLASS_REVISION && size == 4) { | ||
479 | *val = readl(pp->dbi_base + PCI_CLASS_REVISION); | ||
480 | *val &= 0xff; /* keep revision id */ | ||
481 | *val |= PCI_CLASS_BRIDGE_PCI << 16; | ||
482 | return PCIBIOS_SUCCESSFUL; | ||
483 | } | ||
484 | |||
485 | return dw_pcie_cfg_read(pp->dbi_base + where, size, val); | ||
486 | } | ||
487 | |||
488 | static struct pcie_host_ops qcom_pcie_dw_ops = { | ||
489 | .link_up = qcom_pcie_link_up, | ||
490 | .host_init = qcom_pcie_host_init, | ||
491 | .rd_own_conf = qcom_pcie_rd_own_conf, | ||
492 | }; | ||
493 | |||
494 | static const struct qcom_pcie_ops ops_v0 = { | ||
495 | .get_resources = qcom_pcie_get_resources_v0, | ||
496 | .init = qcom_pcie_init_v0, | ||
497 | .deinit = qcom_pcie_deinit_v0, | ||
498 | }; | ||
499 | |||
500 | static const struct qcom_pcie_ops ops_v1 = { | ||
501 | .get_resources = qcom_pcie_get_resources_v1, | ||
502 | .init = qcom_pcie_init_v1, | ||
503 | .deinit = qcom_pcie_deinit_v1, | ||
504 | }; | ||
505 | |||
506 | static int qcom_pcie_probe(struct platform_device *pdev) | ||
507 | { | ||
508 | struct device *dev = &pdev->dev; | ||
509 | struct resource *res; | ||
510 | struct qcom_pcie *pcie; | ||
511 | struct pcie_port *pp; | ||
512 | int ret; | ||
513 | |||
514 | pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); | ||
515 | if (!pcie) | ||
516 | return -ENOMEM; | ||
517 | |||
518 | pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev); | ||
519 | pcie->dev = dev; | ||
520 | |||
521 | pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW); | ||
522 | if (IS_ERR(pcie->reset)) | ||
523 | return PTR_ERR(pcie->reset); | ||
524 | |||
525 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf"); | ||
526 | pcie->parf = devm_ioremap_resource(dev, res); | ||
527 | if (IS_ERR(pcie->parf)) | ||
528 | return PTR_ERR(pcie->parf); | ||
529 | |||
530 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); | ||
531 | pcie->dbi = devm_ioremap_resource(dev, res); | ||
532 | if (IS_ERR(pcie->dbi)) | ||
533 | return PTR_ERR(pcie->dbi); | ||
534 | |||
535 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); | ||
536 | pcie->elbi = devm_ioremap_resource(dev, res); | ||
537 | if (IS_ERR(pcie->elbi)) | ||
538 | return PTR_ERR(pcie->elbi); | ||
539 | |||
540 | pcie->phy = devm_phy_optional_get(dev, "pciephy"); | ||
541 | if (IS_ERR(pcie->phy)) | ||
542 | return PTR_ERR(pcie->phy); | ||
543 | |||
544 | ret = pcie->ops->get_resources(pcie); | ||
545 | if (ret) | ||
546 | return ret; | ||
547 | |||
548 | pp = &pcie->pp; | ||
549 | pp->dev = dev; | ||
550 | pp->dbi_base = pcie->dbi; | ||
551 | pp->root_bus_nr = -1; | ||
552 | pp->ops = &qcom_pcie_dw_ops; | ||
553 | |||
554 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
555 | pp->msi_irq = platform_get_irq_byname(pdev, "msi"); | ||
556 | if (pp->msi_irq < 0) | ||
557 | return pp->msi_irq; | ||
558 | |||
559 | ret = devm_request_irq(dev, pp->msi_irq, | ||
560 | qcom_pcie_msi_irq_handler, | ||
561 | IRQF_SHARED, "qcom-pcie-msi", pp); | ||
562 | if (ret) { | ||
563 | dev_err(dev, "cannot request msi irq\n"); | ||
564 | return ret; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | ret = phy_init(pcie->phy); | ||
569 | if (ret) | ||
570 | return ret; | ||
571 | |||
572 | ret = dw_pcie_host_init(pp); | ||
573 | if (ret) { | ||
574 | dev_err(dev, "cannot initialize host\n"); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | platform_set_drvdata(pdev, pcie); | ||
579 | |||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int qcom_pcie_remove(struct platform_device *pdev) | ||
584 | { | ||
585 | struct qcom_pcie *pcie = platform_get_drvdata(pdev); | ||
586 | |||
587 | qcom_ep_reset_assert(pcie); | ||
588 | phy_power_off(pcie->phy); | ||
589 | phy_exit(pcie->phy); | ||
590 | pcie->ops->deinit(pcie); | ||
591 | |||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static const struct of_device_id qcom_pcie_match[] = { | ||
596 | { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, | ||
597 | { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, | ||
598 | { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, | ||
599 | { } | ||
600 | }; | ||
601 | MODULE_DEVICE_TABLE(of, qcom_pcie_match); | ||
602 | |||
603 | static struct platform_driver qcom_pcie_driver = { | ||
604 | .probe = qcom_pcie_probe, | ||
605 | .remove = qcom_pcie_remove, | ||
606 | .driver = { | ||
607 | .name = "qcom-pcie", | ||
608 | .of_match_table = qcom_pcie_match, | ||
609 | }, | ||
610 | }; | ||
611 | |||
612 | module_platform_driver(qcom_pcie_driver); | ||
613 | |||
614 | MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>"); | ||
615 | MODULE_DESCRIPTION("Qualcomm PCIe root complex driver"); | ||
616 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index f4fa6c537448..4edb5181f4e2 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/of_platform.h> | 26 | #include <linux/of_platform.h> |
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/pm_runtime.h> | ||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | 31 | ||
31 | #define DRV_NAME "rcar-pcie" | 32 | #define DRV_NAME "rcar-pcie" |
@@ -94,6 +95,11 @@ | |||
94 | #define H1_PCIEPHYDOUTR 0x040014 | 95 | #define H1_PCIEPHYDOUTR 0x040014 |
95 | #define H1_PCIEPHYSR 0x040018 | 96 | #define H1_PCIEPHYSR 0x040018 |
96 | 97 | ||
98 | /* R-Car Gen2 PHY */ | ||
99 | #define GEN2_PCIEPHYADDR 0x780 | ||
100 | #define GEN2_PCIEPHYDATA 0x784 | ||
101 | #define GEN2_PCIEPHYCTRL 0x78c | ||
102 | |||
97 | #define INT_PCI_MSI_NR 32 | 103 | #define INT_PCI_MSI_NR 32 |
98 | 104 | ||
99 | #define RCONF(x) (PCICONF(0)+(x)) | 105 | #define RCONF(x) (PCICONF(0)+(x)) |
@@ -108,8 +114,6 @@ | |||
108 | #define RCAR_PCI_MAX_RESOURCES 4 | 114 | #define RCAR_PCI_MAX_RESOURCES 4 |
109 | #define MAX_NR_INBOUND_MAPS 6 | 115 | #define MAX_NR_INBOUND_MAPS 6 |
110 | 116 | ||
111 | static unsigned long global_io_offset; | ||
112 | |||
113 | struct rcar_msi { | 117 | struct rcar_msi { |
114 | DECLARE_BITMAP(used, INT_PCI_MSI_NR); | 118 | DECLARE_BITMAP(used, INT_PCI_MSI_NR); |
115 | struct irq_domain *domain; | 119 | struct irq_domain *domain; |
@@ -126,20 +130,10 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) | |||
126 | } | 130 | } |
127 | 131 | ||
128 | /* Structure representing the PCIe interface */ | 132 | /* Structure representing the PCIe interface */ |
129 | /* | ||
130 | * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI | ||
131 | * sysdata. Add pci_sys_data as the first element in struct gen_pci so | ||
132 | * that when we use a gen_pci pointer as sysdata, it is also a pointer to | ||
133 | * a struct pci_sys_data. | ||
134 | */ | ||
135 | struct rcar_pcie { | 133 | struct rcar_pcie { |
136 | #ifdef CONFIG_ARM | ||
137 | struct pci_sys_data sys; | ||
138 | #endif | ||
139 | struct device *dev; | 134 | struct device *dev; |
140 | void __iomem *base; | 135 | void __iomem *base; |
141 | struct resource res[RCAR_PCI_MAX_RESOURCES]; | 136 | struct list_head resources; |
142 | struct resource busn; | ||
143 | int root_bus_nr; | 137 | int root_bus_nr; |
144 | struct clk *clk; | 138 | struct clk *clk; |
145 | struct clk *bus_clk; | 139 | struct clk *bus_clk; |
@@ -323,10 +317,9 @@ static struct pci_ops rcar_pcie_ops = { | |||
323 | .write = rcar_pcie_write_conf, | 317 | .write = rcar_pcie_write_conf, |
324 | }; | 318 | }; |
325 | 319 | ||
326 | static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) | 320 | static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie, |
321 | struct resource *res) | ||
327 | { | 322 | { |
328 | struct resource *res = &pcie->res[win]; | ||
329 | |||
330 | /* Setup PCIe address space mappings for each resource */ | 323 | /* Setup PCIe address space mappings for each resource */ |
331 | resource_size_t size; | 324 | resource_size_t size; |
332 | resource_size_t res_start; | 325 | resource_size_t res_start; |
@@ -359,31 +352,33 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) | |||
359 | rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win)); | 352 | rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win)); |
360 | } | 353 | } |
361 | 354 | ||
362 | static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie) | 355 | static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci) |
363 | { | 356 | { |
364 | struct resource *res; | 357 | struct resource_entry *win; |
365 | int i; | 358 | int i = 0; |
366 | |||
367 | pcie->root_bus_nr = pcie->busn.start; | ||
368 | 359 | ||
369 | /* Setup PCI resources */ | 360 | /* Setup PCI resources */ |
370 | for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) { | 361 | resource_list_for_each_entry(win, &pci->resources) { |
362 | struct resource *res = win->res; | ||
371 | 363 | ||
372 | res = &pcie->res[i]; | ||
373 | if (!res->flags) | 364 | if (!res->flags) |
374 | continue; | 365 | continue; |
375 | 366 | ||
376 | rcar_pcie_setup_window(i, pcie); | 367 | switch (resource_type(res)) { |
377 | 368 | case IORESOURCE_IO: | |
378 | if (res->flags & IORESOURCE_IO) { | 369 | case IORESOURCE_MEM: |
379 | phys_addr_t io_start = pci_pio_to_address(res->start); | 370 | rcar_pcie_setup_window(i, pci, res); |
380 | pci_ioremap_io(global_io_offset, io_start); | 371 | i++; |
381 | global_io_offset += SZ_64K; | 372 | break; |
373 | case IORESOURCE_BUS: | ||
374 | pci->root_bus_nr = res->start; | ||
375 | break; | ||
376 | default: | ||
377 | continue; | ||
382 | } | 378 | } |
383 | 379 | ||
384 | pci_add_resource(resource, res); | 380 | pci_add_resource(resource, res); |
385 | } | 381 | } |
386 | pci_add_resource(resource, &pcie->busn); | ||
387 | 382 | ||
388 | return 1; | 383 | return 1; |
389 | } | 384 | } |
@@ -578,6 +573,26 @@ static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie) | |||
578 | return -ETIMEDOUT; | 573 | return -ETIMEDOUT; |
579 | } | 574 | } |
580 | 575 | ||
576 | static int rcar_pcie_hw_init_gen2(struct rcar_pcie *pcie) | ||
577 | { | ||
578 | /* | ||
579 | * These settings come from the R-Car Series, 2nd Generation User's | ||
580 | * Manual, section 50.3.1 (2) Initialization of the physical layer. | ||
581 | */ | ||
582 | rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR); | ||
583 | rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA); | ||
584 | rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL); | ||
585 | rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL); | ||
586 | |||
587 | rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR); | ||
588 | /* The following value is for DC connection, no termination resistor */ | ||
589 | rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA); | ||
590 | rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL); | ||
591 | rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL); | ||
592 | |||
593 | return rcar_pcie_hw_init(pcie); | ||
594 | } | ||
595 | |||
581 | static int rcar_msi_alloc(struct rcar_msi *chip) | 596 | static int rcar_msi_alloc(struct rcar_msi *chip) |
582 | { | 597 | { |
583 | int msi; | 598 | int msi; |
@@ -720,14 +735,16 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie) | |||
720 | 735 | ||
721 | /* Two irqs are for MSI, but they are also used for non-MSI irqs */ | 736 | /* Two irqs are for MSI, but they are also used for non-MSI irqs */ |
722 | err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq, | 737 | err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq, |
723 | IRQF_SHARED, rcar_msi_irq_chip.name, pcie); | 738 | IRQF_SHARED | IRQF_NO_THREAD, |
739 | rcar_msi_irq_chip.name, pcie); | ||
724 | if (err < 0) { | 740 | if (err < 0) { |
725 | dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); | 741 | dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); |
726 | goto err; | 742 | goto err; |
727 | } | 743 | } |
728 | 744 | ||
729 | err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq, | 745 | err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq, |
730 | IRQF_SHARED, rcar_msi_irq_chip.name, pcie); | 746 | IRQF_SHARED | IRQF_NO_THREAD, |
747 | rcar_msi_irq_chip.name, pcie); | ||
731 | if (err < 0) { | 748 | if (err < 0) { |
732 | dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); | 749 | dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); |
733 | goto err; | 750 | goto err; |
@@ -917,20 +934,71 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, | |||
917 | 934 | ||
918 | static const struct of_device_id rcar_pcie_of_match[] = { | 935 | static const struct of_device_id rcar_pcie_of_match[] = { |
919 | { .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 }, | 936 | { .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 }, |
920 | { .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init }, | 937 | { .compatible = "renesas,pcie-rcar-gen2", .data = rcar_pcie_hw_init_gen2 }, |
921 | { .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init }, | 938 | { .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init_gen2 }, |
939 | { .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init_gen2 }, | ||
940 | { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init }, | ||
922 | {}, | 941 | {}, |
923 | }; | 942 | }; |
924 | MODULE_DEVICE_TABLE(of, rcar_pcie_of_match); | 943 | MODULE_DEVICE_TABLE(of, rcar_pcie_of_match); |
925 | 944 | ||
945 | static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci) | ||
946 | { | ||
947 | pci_free_resource_list(&pci->resources); | ||
948 | } | ||
949 | |||
950 | static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) | ||
951 | { | ||
952 | int err; | ||
953 | struct device *dev = pci->dev; | ||
954 | struct device_node *np = dev->of_node; | ||
955 | resource_size_t iobase; | ||
956 | struct resource_entry *win; | ||
957 | |||
958 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); | ||
959 | if (err) | ||
960 | return err; | ||
961 | |||
962 | resource_list_for_each_entry(win, &pci->resources) { | ||
963 | struct resource *parent, *res = win->res; | ||
964 | |||
965 | switch (resource_type(res)) { | ||
966 | case IORESOURCE_IO: | ||
967 | parent = &ioport_resource; | ||
968 | err = pci_remap_iospace(res, iobase); | ||
969 | if (err) { | ||
970 | dev_warn(dev, "error %d: failed to map resource %pR\n", | ||
971 | err, res); | ||
972 | continue; | ||
973 | } | ||
974 | break; | ||
975 | case IORESOURCE_MEM: | ||
976 | parent = &iomem_resource; | ||
977 | break; | ||
978 | |||
979 | case IORESOURCE_BUS: | ||
980 | default: | ||
981 | continue; | ||
982 | } | ||
983 | |||
984 | err = devm_request_resource(dev, parent, res); | ||
985 | if (err) | ||
986 | goto out_release_res; | ||
987 | } | ||
988 | |||
989 | return 0; | ||
990 | |||
991 | out_release_res: | ||
992 | rcar_pcie_release_of_pci_ranges(pci); | ||
993 | return err; | ||
994 | } | ||
995 | |||
926 | static int rcar_pcie_probe(struct platform_device *pdev) | 996 | static int rcar_pcie_probe(struct platform_device *pdev) |
927 | { | 997 | { |
928 | struct rcar_pcie *pcie; | 998 | struct rcar_pcie *pcie; |
929 | unsigned int data; | 999 | unsigned int data; |
930 | struct of_pci_range range; | ||
931 | struct of_pci_range_parser parser; | ||
932 | const struct of_device_id *of_id; | 1000 | const struct of_device_id *of_id; |
933 | int err, win = 0; | 1001 | int err; |
934 | int (*hw_init_fn)(struct rcar_pcie *); | 1002 | int (*hw_init_fn)(struct rcar_pcie *); |
935 | 1003 | ||
936 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | 1004 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); |
@@ -940,16 +1008,9 @@ static int rcar_pcie_probe(struct platform_device *pdev) | |||
940 | pcie->dev = &pdev->dev; | 1008 | pcie->dev = &pdev->dev; |
941 | platform_set_drvdata(pdev, pcie); | 1009 | platform_set_drvdata(pdev, pcie); |
942 | 1010 | ||
943 | /* Get the bus range */ | 1011 | INIT_LIST_HEAD(&pcie->resources); |
944 | if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) { | ||
945 | dev_err(&pdev->dev, "failed to parse bus-range property\n"); | ||
946 | return -EINVAL; | ||
947 | } | ||
948 | 1012 | ||
949 | if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) { | 1013 | rcar_pcie_parse_request_of_pci_ranges(pcie); |
950 | dev_err(&pdev->dev, "missing ranges property\n"); | ||
951 | return -EINVAL; | ||
952 | } | ||
953 | 1014 | ||
954 | err = rcar_pcie_get_resources(pdev, pcie); | 1015 | err = rcar_pcie_get_resources(pdev, pcie); |
955 | if (err < 0) { | 1016 | if (err < 0) { |
@@ -957,46 +1018,55 @@ static int rcar_pcie_probe(struct platform_device *pdev) | |||
957 | return err; | 1018 | return err; |
958 | } | 1019 | } |
959 | 1020 | ||
960 | for_each_of_pci_range(&parser, &range) { | ||
961 | err = of_pci_range_to_resource(&range, pdev->dev.of_node, | ||
962 | &pcie->res[win++]); | ||
963 | if (err < 0) | ||
964 | return err; | ||
965 | |||
966 | if (win > RCAR_PCI_MAX_RESOURCES) | ||
967 | break; | ||
968 | } | ||
969 | |||
970 | err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); | 1021 | err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); |
971 | if (err) | 1022 | if (err) |
972 | return err; | 1023 | return err; |
973 | 1024 | ||
974 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
975 | err = rcar_pcie_enable_msi(pcie); | ||
976 | if (err < 0) { | ||
977 | dev_err(&pdev->dev, | ||
978 | "failed to enable MSI support: %d\n", | ||
979 | err); | ||
980 | return err; | ||
981 | } | ||
982 | } | ||
983 | |||
984 | of_id = of_match_device(rcar_pcie_of_match, pcie->dev); | 1025 | of_id = of_match_device(rcar_pcie_of_match, pcie->dev); |
985 | if (!of_id || !of_id->data) | 1026 | if (!of_id || !of_id->data) |
986 | return -EINVAL; | 1027 | return -EINVAL; |
987 | hw_init_fn = of_id->data; | 1028 | hw_init_fn = of_id->data; |
988 | 1029 | ||
1030 | pm_runtime_enable(pcie->dev); | ||
1031 | err = pm_runtime_get_sync(pcie->dev); | ||
1032 | if (err < 0) { | ||
1033 | dev_err(pcie->dev, "pm_runtime_get_sync failed\n"); | ||
1034 | goto err_pm_disable; | ||
1035 | } | ||
1036 | |||
989 | /* Failure to get a link might just be that no cards are inserted */ | 1037 | /* Failure to get a link might just be that no cards are inserted */ |
990 | err = hw_init_fn(pcie); | 1038 | err = hw_init_fn(pcie); |
991 | if (err) { | 1039 | if (err) { |
992 | dev_info(&pdev->dev, "PCIe link down\n"); | 1040 | dev_info(&pdev->dev, "PCIe link down\n"); |
993 | return 0; | 1041 | err = 0; |
1042 | goto err_pm_put; | ||
994 | } | 1043 | } |
995 | 1044 | ||
996 | data = rcar_pci_read_reg(pcie, MACSR); | 1045 | data = rcar_pci_read_reg(pcie, MACSR); |
997 | dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); | 1046 | dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); |
998 | 1047 | ||
999 | return rcar_pcie_enable(pcie); | 1048 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
1049 | err = rcar_pcie_enable_msi(pcie); | ||
1050 | if (err < 0) { | ||
1051 | dev_err(&pdev->dev, | ||
1052 | "failed to enable MSI support: %d\n", | ||
1053 | err); | ||
1054 | goto err_pm_put; | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | err = rcar_pcie_enable(pcie); | ||
1059 | if (err) | ||
1060 | goto err_pm_put; | ||
1061 | |||
1062 | return 0; | ||
1063 | |||
1064 | err_pm_put: | ||
1065 | pm_runtime_put(pcie->dev); | ||
1066 | |||
1067 | err_pm_disable: | ||
1068 | pm_runtime_disable(pcie->dev); | ||
1069 | return err; | ||
1000 | } | 1070 | } |
1001 | 1071 | ||
1002 | static struct platform_driver rcar_pcie_driver = { | 1072 | static struct platform_driver rcar_pcie_driver = { |
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c index b95b7563c052..a6cd8233e8c0 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/host/pcie-spear13xx.c | |||
@@ -279,7 +279,8 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp, | |||
279 | return -ENODEV; | 279 | return -ENODEV; |
280 | } | 280 | } |
281 | ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler, | 281 | ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler, |
282 | IRQF_SHARED, "spear1340-pcie", pp); | 282 | IRQF_SHARED | IRQF_NO_THREAD, |
283 | "spear1340-pcie", pp); | ||
283 | if (ret) { | 284 | if (ret) { |
284 | dev_err(dev, "failed to request irq %d\n", pp->irq); | 285 | dev_err(dev, "failed to request irq %d\n", pp->irq); |
285 | return ret; | 286 | return ret; |
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index 3c7a0d580b1e..4cfa46360d12 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c | |||
@@ -781,7 +781,8 @@ static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port) | |||
781 | 781 | ||
782 | port->irq = irq_of_parse_and_map(node, 0); | 782 | port->irq = irq_of_parse_and_map(node, 0); |
783 | err = devm_request_irq(dev, port->irq, xilinx_pcie_intr_handler, | 783 | err = devm_request_irq(dev, port->irq, xilinx_pcie_intr_handler, |
784 | IRQF_SHARED, "xilinx-pcie", port); | 784 | IRQF_SHARED | IRQF_NO_THREAD, |
785 | "xilinx-pcie", port); | ||
785 | if (err) { | 786 | if (err) { |
786 | dev_err(dev, "unable to request irq %d\n", port->irq); | 787 | dev_err(dev, "unable to request irq %d\n", port->irq); |
787 | return err; | 788 | return err; |
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 814cea22a9fa..5824df538f72 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c | |||
@@ -1119,7 +1119,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func *func, u8 busno) | |||
1119 | pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class); | 1119 | pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class); |
1120 | 1120 | ||
1121 | debug ("hdr_type behind the bridge is %x\n", hdr_type); | 1121 | debug ("hdr_type behind the bridge is %x\n", hdr_type); |
1122 | if (hdr_type & PCI_HEADER_TYPE_BRIDGE) { | 1122 | if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) { |
1123 | err ("embedded bridges not supported for hot-plugging.\n"); | 1123 | err ("embedded bridges not supported for hot-plugging.\n"); |
1124 | amount->not_correct = 1; | 1124 | amount->not_correct = 1; |
1125 | return amount; | 1125 | return amount; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 53e463244bb7..b64d26719906 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -1024,10 +1024,6 @@ int pci_msi_enabled(void) | |||
1024 | } | 1024 | } |
1025 | EXPORT_SYMBOL(pci_msi_enabled); | 1025 | EXPORT_SYMBOL(pci_msi_enabled); |
1026 | 1026 | ||
1027 | void pci_msi_init_pci_dev(struct pci_dev *dev) | ||
1028 | { | ||
1029 | } | ||
1030 | |||
1031 | /** | 1027 | /** |
1032 | * pci_enable_msi_range - configure device's MSI capability structure | 1028 | * pci_enable_msi_range - configure device's MSI capability structure |
1033 | * @dev: device to configure | 1029 | * @dev: device to configure |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 92618686604c..9cd27b703dd6 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -1369,10 +1369,10 @@ int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev) | |||
1369 | if (!sysfs_initialized) | 1369 | if (!sysfs_initialized) |
1370 | return -EACCES; | 1370 | return -EACCES; |
1371 | 1371 | ||
1372 | if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) | 1372 | if (pdev->cfg_size > PCI_CFG_SPACE_SIZE) |
1373 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); | ||
1374 | else | ||
1375 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); | 1373 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); |
1374 | else | ||
1375 | retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); | ||
1376 | if (retval) | 1376 | if (retval) |
1377 | goto err; | 1377 | goto err; |
1378 | 1378 | ||
@@ -1424,10 +1424,10 @@ err_rom_file: | |||
1424 | err_resource_files: | 1424 | err_resource_files: |
1425 | pci_remove_resource_files(pdev); | 1425 | pci_remove_resource_files(pdev); |
1426 | err_config_file: | 1426 | err_config_file: |
1427 | if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) | 1427 | if (pdev->cfg_size > PCI_CFG_SPACE_SIZE) |
1428 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); | ||
1429 | else | ||
1430 | sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); | 1428 | sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); |
1429 | else | ||
1430 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); | ||
1431 | err: | 1431 | err: |
1432 | return retval; | 1432 | return retval; |
1433 | } | 1433 | } |
@@ -1461,10 +1461,10 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
1461 | 1461 | ||
1462 | pci_remove_capabilities_sysfs(pdev); | 1462 | pci_remove_capabilities_sysfs(pdev); |
1463 | 1463 | ||
1464 | if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) | 1464 | if (pdev->cfg_size > PCI_CFG_SPACE_SIZE) |
1465 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); | ||
1466 | else | ||
1467 | sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); | 1465 | sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr); |
1466 | else | ||
1467 | sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); | ||
1468 | 1468 | ||
1469 | pci_remove_resource_files(pdev); | 1469 | pci_remove_resource_files(pdev); |
1470 | 1470 | ||
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index fd2f03fa53f3..44d9859057b4 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -144,10 +144,8 @@ extern unsigned int pci_pm_d3_delay; | |||
144 | 144 | ||
145 | #ifdef CONFIG_PCI_MSI | 145 | #ifdef CONFIG_PCI_MSI |
146 | void pci_no_msi(void); | 146 | void pci_no_msi(void); |
147 | void pci_msi_init_pci_dev(struct pci_dev *dev); | ||
148 | #else | 147 | #else |
149 | static inline void pci_no_msi(void) { } | 148 | static inline void pci_no_msi(void) { } |
150 | static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } | ||
151 | #endif | 149 | #endif |
152 | 150 | ||
153 | static inline void pci_msi_set_enable(struct pci_dev *dev, int enable) | 151 | static inline void pci_msi_set_enable(struct pci_dev *dev, int enable) |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index fba785e9df75..712392504ed9 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -246,7 +246,7 @@ static int report_error_detected(struct pci_dev *dev, void *data) | |||
246 | !dev->driver->err_handler || | 246 | !dev->driver->err_handler || |
247 | !dev->driver->err_handler->error_detected) { | 247 | !dev->driver->err_handler->error_detected) { |
248 | if (result_data->state == pci_channel_io_frozen && | 248 | if (result_data->state == pci_channel_io_frozen && |
249 | !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) { | 249 | dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { |
250 | /* | 250 | /* |
251 | * In case of fatal recovery, if one of down- | 251 | * In case of fatal recovery, if one of down- |
252 | * stream device has no driver. We might be | 252 | * stream device has no driver. We might be |
@@ -269,7 +269,7 @@ static int report_error_detected(struct pci_dev *dev, void *data) | |||
269 | * without recovery. | 269 | * without recovery. |
270 | */ | 270 | */ |
271 | 271 | ||
272 | if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) | 272 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) |
273 | vote = PCI_ERS_RESULT_NO_AER_DRIVER; | 273 | vote = PCI_ERS_RESULT_NO_AER_DRIVER; |
274 | else | 274 | else |
275 | vote = PCI_ERS_RESULT_NONE; | 275 | vote = PCI_ERS_RESULT_NONE; |
@@ -369,7 +369,7 @@ static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, | |||
369 | else | 369 | else |
370 | result_data.result = PCI_ERS_RESULT_RECOVERED; | 370 | result_data.result = PCI_ERS_RESULT_RECOVERED; |
371 | 371 | ||
372 | if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { | 372 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
373 | /* | 373 | /* |
374 | * If the error is reported by a bridge, we think this error | 374 | * If the error is reported by a bridge, we think this error |
375 | * is related to the downstream link of the bridge, so we | 375 | * is related to the downstream link of the bridge, so we |
@@ -440,7 +440,7 @@ static pci_ers_result_t reset_link(struct pci_dev *dev) | |||
440 | pci_ers_result_t status; | 440 | pci_ers_result_t status; |
441 | struct pcie_port_service_driver *driver; | 441 | struct pcie_port_service_driver *driver; |
442 | 442 | ||
443 | if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) { | 443 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
444 | /* Reset this port for all subordinates */ | 444 | /* Reset this port for all subordinates */ |
445 | udev = dev; | 445 | udev = dev; |
446 | } else { | 446 | } else { |
@@ -660,7 +660,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) | |||
660 | &info->mask); | 660 | &info->mask); |
661 | if (!(info->status & ~info->mask)) | 661 | if (!(info->status & ~info->mask)) |
662 | return 0; | 662 | return 0; |
663 | } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE || | 663 | } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
664 | info->severity == AER_NONFATAL) { | 664 | info->severity == AER_NONFATAL) { |
665 | 665 | ||
666 | /* Link is still healthy for IO reads */ | 666 | /* Link is still healthy for IO reads */ |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 317e3558a35e..2dfe7fdb77e7 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -834,21 +834,15 @@ static ssize_t link_state_store(struct device *dev, | |||
834 | { | 834 | { |
835 | struct pci_dev *pdev = to_pci_dev(dev); | 835 | struct pci_dev *pdev = to_pci_dev(dev); |
836 | struct pcie_link_state *link, *root = pdev->link_state->root; | 836 | struct pcie_link_state *link, *root = pdev->link_state->root; |
837 | u32 val, state = 0; | 837 | u32 state; |
838 | |||
839 | if (kstrtouint(buf, 10, &val)) | ||
840 | return -EINVAL; | ||
841 | 838 | ||
842 | if (aspm_disabled) | 839 | if (aspm_disabled) |
843 | return -EPERM; | 840 | return -EPERM; |
844 | if (n < 1 || val > 3) | ||
845 | return -EINVAL; | ||
846 | 841 | ||
847 | /* Convert requested state to ASPM state */ | 842 | if (kstrtouint(buf, 10, &state)) |
848 | if (val & PCIE_LINK_STATE_L0S) | 843 | return -EINVAL; |
849 | state |= ASPM_STATE_L0S; | 844 | if ((state & ~ASPM_STATE_ALL) != 0) |
850 | if (val & PCIE_LINK_STATE_L1) | 845 | return -EINVAL; |
851 | state |= ASPM_STATE_L1; | ||
852 | 846 | ||
853 | down_read(&pci_bus_sem); | 847 | down_read(&pci_bus_sem); |
854 | mutex_lock(&aspm_lock); | 848 | mutex_lock(&aspm_lock); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index edb1984201e9..32b9f1b88266 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1107,14 +1107,11 @@ static int pci_cfg_space_size_ext(struct pci_dev *dev) | |||
1107 | int pos = PCI_CFG_SPACE_SIZE; | 1107 | int pos = PCI_CFG_SPACE_SIZE; |
1108 | 1108 | ||
1109 | if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL) | 1109 | if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL) |
1110 | goto fail; | 1110 | return PCI_CFG_SPACE_SIZE; |
1111 | if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev)) | 1111 | if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev)) |
1112 | goto fail; | 1112 | return PCI_CFG_SPACE_SIZE; |
1113 | 1113 | ||
1114 | return PCI_CFG_SPACE_EXP_SIZE; | 1114 | return PCI_CFG_SPACE_EXP_SIZE; |
1115 | |||
1116 | fail: | ||
1117 | return PCI_CFG_SPACE_SIZE; | ||
1118 | } | 1115 | } |
1119 | 1116 | ||
1120 | int pci_cfg_space_size(struct pci_dev *dev) | 1117 | int pci_cfg_space_size(struct pci_dev *dev) |
@@ -1127,25 +1124,23 @@ int pci_cfg_space_size(struct pci_dev *dev) | |||
1127 | if (class == PCI_CLASS_BRIDGE_HOST) | 1124 | if (class == PCI_CLASS_BRIDGE_HOST) |
1128 | return pci_cfg_space_size_ext(dev); | 1125 | return pci_cfg_space_size_ext(dev); |
1129 | 1126 | ||
1130 | if (!pci_is_pcie(dev)) { | 1127 | if (pci_is_pcie(dev)) |
1131 | pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); | 1128 | return pci_cfg_space_size_ext(dev); |
1132 | if (!pos) | ||
1133 | goto fail; | ||
1134 | 1129 | ||
1135 | pci_read_config_dword(dev, pos + PCI_X_STATUS, &status); | 1130 | pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); |
1136 | if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))) | 1131 | if (!pos) |
1137 | goto fail; | 1132 | return PCI_CFG_SPACE_SIZE; |
1138 | } | ||
1139 | 1133 | ||
1140 | return pci_cfg_space_size_ext(dev); | 1134 | pci_read_config_dword(dev, pos + PCI_X_STATUS, &status); |
1135 | if (status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)) | ||
1136 | return pci_cfg_space_size_ext(dev); | ||
1141 | 1137 | ||
1142 | fail: | ||
1143 | return PCI_CFG_SPACE_SIZE; | 1138 | return PCI_CFG_SPACE_SIZE; |
1144 | } | 1139 | } |
1145 | 1140 | ||
1146 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) | 1141 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) |
1147 | 1142 | ||
1148 | void pci_msi_setup_pci_dev(struct pci_dev *dev) | 1143 | static void pci_msi_setup_pci_dev(struct pci_dev *dev) |
1149 | { | 1144 | { |
1150 | /* | 1145 | /* |
1151 | * Disable the MSI hardware to avoid screaming interrupts | 1146 | * Disable the MSI hardware to avoid screaming interrupts |
@@ -1212,8 +1207,6 @@ int pci_setup_device(struct pci_dev *dev) | |||
1212 | /* "Unknown power state" */ | 1207 | /* "Unknown power state" */ |
1213 | dev->current_state = PCI_UNKNOWN; | 1208 | dev->current_state = PCI_UNKNOWN; |
1214 | 1209 | ||
1215 | pci_msi_setup_pci_dev(dev); | ||
1216 | |||
1217 | /* Early fixups, before probing the BARs */ | 1210 | /* Early fixups, before probing the BARs */ |
1218 | pci_fixup_device(pci_fixup_early, dev); | 1211 | pci_fixup_device(pci_fixup_early, dev); |
1219 | /* device class may be changed after fixup */ | 1212 | /* device class may be changed after fixup */ |
@@ -1603,8 +1596,8 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1603 | /* Enhanced Allocation */ | 1596 | /* Enhanced Allocation */ |
1604 | pci_ea_init(dev); | 1597 | pci_ea_init(dev); |
1605 | 1598 | ||
1606 | /* MSI/MSI-X list */ | 1599 | /* Setup MSI caps & disable MSI/MSI-X interrupts */ |
1607 | pci_msi_init_pci_dev(dev); | 1600 | pci_msi_setup_pci_dev(dev); |
1608 | 1601 | ||
1609 | /* Buffers for saving PCIe and PCI-X capabilities */ | 1602 | /* Buffers for saving PCIe and PCI-X capabilities */ |
1610 | pci_allocate_cap_save_buffers(dev); | 1603 | pci_allocate_cap_save_buffers(dev); |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 7e327309cf69..83e93d7ca4b9 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -287,6 +287,17 @@ static void quirk_citrine(struct pci_dev *dev) | |||
287 | } | 287 | } |
288 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine); | 288 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine); |
289 | 289 | ||
290 | /* | ||
291 | * This chip can cause bus lockups if config addresses above 0x600 | ||
292 | * are read or written. | ||
293 | */ | ||
294 | static void quirk_nfp6000(struct pci_dev *dev) | ||
295 | { | ||
296 | dev->cfg_size = 0x600; | ||
297 | } | ||
298 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000, quirk_nfp6000); | ||
299 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETRONOME, PCI_DEVICE_ID_NETRONOME_NFP6000_VF, quirk_nfp6000); | ||
300 | |||
290 | /* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */ | 301 | /* On IBM Crocodile ipr SAS adapters, expand BAR to system page size */ |
291 | static void quirk_extend_bar_to_page(struct pci_dev *dev) | 302 | static void quirk_extend_bar_to_page(struct pci_dev *dev) |
292 | { | 303 | { |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index eb0ad530dc43..9eaca39ef38d 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -77,25 +77,24 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) | |||
77 | do { | 77 | do { |
78 | void __iomem *pds; | 78 | void __iomem *pds; |
79 | /* Standard PCI ROMs start out with these bytes 55 AA */ | 79 | /* Standard PCI ROMs start out with these bytes 55 AA */ |
80 | if (readb(image) != 0x55) { | 80 | if (readw(image) != 0xAA55) { |
81 | dev_err(&pdev->dev, "Invalid ROM contents\n"); | 81 | dev_err(&pdev->dev, "Invalid PCI ROM header signature: expecting 0xaa55, got %#06x\n", |
82 | readw(image)); | ||
82 | break; | 83 | break; |
83 | } | 84 | } |
84 | if (readb(image + 1) != 0xAA) | 85 | /* get the PCI data structure and check its "PCIR" signature */ |
85 | break; | ||
86 | /* get the PCI data structure and check its signature */ | ||
87 | pds = image + readw(image + 24); | 86 | pds = image + readw(image + 24); |
88 | if (readb(pds) != 'P') | 87 | if (readl(pds) != 0x52494350) { |
89 | break; | 88 | dev_err(&pdev->dev, "Invalid PCI ROM data signature: expecting 0x52494350, got %#010x\n", |
90 | if (readb(pds + 1) != 'C') | 89 | readl(pds)); |
91 | break; | ||
92 | if (readb(pds + 2) != 'I') | ||
93 | break; | ||
94 | if (readb(pds + 3) != 'R') | ||
95 | break; | 90 | break; |
91 | } | ||
96 | last_image = readb(pds + 21) & 0x80; | 92 | last_image = readb(pds + 21) & 0x80; |
97 | length = readw(pds + 16); | 93 | length = readw(pds + 16); |
98 | image += length * 512; | 94 | image += length * 512; |
95 | /* Avoid iterating through memory outside the resource window */ | ||
96 | if (image > rom + size) | ||
97 | break; | ||
99 | } while (length && !last_image); | 98 | } while (length && !last_image); |
100 | 99 | ||
101 | /* never return a size larger than the PCI resource window */ | 100 | /* never return a size larger than the PCI resource window */ |
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h index 2c51ee78b1c0..f6e9e85164e8 100644 --- a/include/linux/of_pci.h +++ b/include/linux/of_pci.h | |||
@@ -59,6 +59,13 @@ static inline void of_pci_check_probe_only(void) { } | |||
59 | int of_pci_get_host_bridge_resources(struct device_node *dev, | 59 | int of_pci_get_host_bridge_resources(struct device_node *dev, |
60 | unsigned char busno, unsigned char bus_max, | 60 | unsigned char busno, unsigned char bus_max, |
61 | struct list_head *resources, resource_size_t *io_base); | 61 | struct list_head *resources, resource_size_t *io_base); |
62 | #else | ||
63 | static inline int of_pci_get_host_bridge_resources(struct device_node *dev, | ||
64 | unsigned char busno, unsigned char bus_max, | ||
65 | struct list_head *resources, resource_size_t *io_base) | ||
66 | { | ||
67 | return -EINVAL; | ||
68 | } | ||
62 | #endif | 69 | #endif |
63 | 70 | ||
64 | #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI) | 71 | #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI) |
diff --git a/include/linux/pci.h b/include/linux/pci.h index e828e7b4afec..f9f79add0afb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -1248,8 +1248,6 @@ struct msix_entry { | |||
1248 | u16 entry; /* driver uses to specify entry, OS writes */ | 1248 | u16 entry; /* driver uses to specify entry, OS writes */ |
1249 | }; | 1249 | }; |
1250 | 1250 | ||
1251 | void pci_msi_setup_pci_dev(struct pci_dev *dev); | ||
1252 | |||
1253 | #ifdef CONFIG_PCI_MSI | 1251 | #ifdef CONFIG_PCI_MSI |
1254 | int pci_msi_vec_count(struct pci_dev *dev); | 1252 | int pci_msi_vec_count(struct pci_dev *dev); |
1255 | void pci_msi_shutdown(struct pci_dev *dev); | 1253 | void pci_msi_shutdown(struct pci_dev *dev); |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d9ba49cedc5d..526e2c12ae59 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2495,6 +2495,12 @@ | |||
2495 | #define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700 | 2495 | #define PCI_DEVICE_ID_KORENIX_JETCARDF2 0x1700 |
2496 | #define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff | 2496 | #define PCI_DEVICE_ID_KORENIX_JETCARDF3 0x17ff |
2497 | 2497 | ||
2498 | #define PCI_VENDOR_ID_NETRONOME 0x19ee | ||
2499 | #define PCI_DEVICE_ID_NETRONOME_NFP3200 0x3200 | ||
2500 | #define PCI_DEVICE_ID_NETRONOME_NFP3240 0x3240 | ||
2501 | #define PCI_DEVICE_ID_NETRONOME_NFP6000 0x6000 | ||
2502 | #define PCI_DEVICE_ID_NETRONOME_NFP6000_VF 0x6003 | ||
2503 | |||
2498 | #define PCI_VENDOR_ID_QMI 0x1a32 | 2504 | #define PCI_VENDOR_ID_QMI 0x1a32 |
2499 | 2505 | ||
2500 | #define PCI_VENDOR_ID_AZWAVE 0x1a3b | 2506 | #define PCI_VENDOR_ID_AZWAVE 0x1a3b |