diff options
-rw-r--r-- | Documentation/devicetree/bindings/pci/designware-pcie.txt | 74 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt | 38 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt | 65 | ||||
-rw-r--r-- | drivers/bus/mvebu-mbus.c | 22 | ||||
-rw-r--r-- | drivers/pci/host/pci-exynos.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 1 | ||||
-rw-r--r-- | drivers/pci/host/pci-mvebu.c | 102 | ||||
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 7 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 26 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.h | 1 |
10 files changed, 222 insertions, 115 deletions
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt index d6fae13ff062..d0d15ee42834 100644 --- a/Documentation/devicetree/bindings/pci/designware-pcie.txt +++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt | |||
@@ -1,15 +1,7 @@ | |||
1 | * Synopsys Designware PCIe interface | 1 | * Synopsys Designware PCIe interface |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: should contain "snps,dw-pcie" to identify the | 4 | - compatible: should contain "snps,dw-pcie" to identify the core. |
5 | core, plus an identifier for the specific instance, such | ||
6 | as "samsung,exynos5440-pcie" or "fsl,imx6q-pcie". | ||
7 | - reg: base addresses and lengths of the pcie controller, | ||
8 | the phy controller, additional register for the phy controller. | ||
9 | - interrupts: interrupt values for level interrupt, | ||
10 | pulse interrupt, special interrupt. | ||
11 | - clocks: from common clock binding: handle to pci clock. | ||
12 | - clock-names: from common clock binding: should be "pcie" and "pcie_bus". | ||
13 | - #address-cells: set to <3> | 5 | - #address-cells: set to <3> |
14 | - #size-cells: set to <2> | 6 | - #size-cells: set to <2> |
15 | - device_type: set to "pci" | 7 | - device_type: set to "pci" |
@@ -19,65 +11,11 @@ Required properties: | |||
19 | to define the mapping of the PCIe interface to interrupt | 11 | to define the mapping of the PCIe interface to interrupt |
20 | numbers. | 12 | numbers. |
21 | - num-lanes: number of lanes to use | 13 | - num-lanes: number of lanes to use |
14 | - clocks: Must contain an entry for each entry in clock-names. | ||
15 | See ../clocks/clock-bindings.txt for details. | ||
16 | - clock-names: Must include the following entries: | ||
17 | - "pcie" | ||
18 | - "pcie_bus" | ||
22 | 19 | ||
23 | Optional properties: | 20 | Optional properties: |
24 | - reset-gpio: gpio pin number of power good signal | 21 | - reset-gpio: gpio pin number of power good signal |
25 | |||
26 | Optional properties for fsl,imx6q-pcie | ||
27 | - power-on-gpio: gpio pin number of power-enable signal | ||
28 | - wake-up-gpio: gpio pin number of incoming wakeup signal | ||
29 | - disable-gpio: gpio pin number of outgoing rfkill/endpoint disable signal | ||
30 | |||
31 | Example: | ||
32 | |||
33 | SoC specific DT Entry: | ||
34 | |||
35 | pcie@290000 { | ||
36 | compatible = "samsung,exynos5440-pcie", "snps,dw-pcie"; | ||
37 | reg = <0x290000 0x1000 | ||
38 | 0x270000 0x1000 | ||
39 | 0x271000 0x40>; | ||
40 | interrupts = <0 20 0>, <0 21 0>, <0 22 0>; | ||
41 | clocks = <&clock 28>, <&clock 27>; | ||
42 | clock-names = "pcie", "pcie_bus"; | ||
43 | #address-cells = <3>; | ||
44 | #size-cells = <2>; | ||
45 | device_type = "pci"; | ||
46 | ranges = <0x00000800 0 0x40000000 0x40000000 0 0x00001000 /* configuration space */ | ||
47 | 0x81000000 0 0 0x40001000 0 0x00010000 /* downstream I/O */ | ||
48 | 0x82000000 0 0x40011000 0x40011000 0 0x1ffef000>; /* non-prefetchable memory */ | ||
49 | #interrupt-cells = <1>; | ||
50 | interrupt-map-mask = <0 0 0 0>; | ||
51 | interrupt-map = <0x0 0 &gic 53>; | ||
52 | num-lanes = <4>; | ||
53 | }; | ||
54 | |||
55 | pcie@2a0000 { | ||
56 | compatible = "samsung,exynos5440-pcie", "snps,dw-pcie"; | ||
57 | reg = <0x2a0000 0x1000 | ||
58 | 0x272000 0x1000 | ||
59 | 0x271040 0x40>; | ||
60 | interrupts = <0 23 0>, <0 24 0>, <0 25 0>; | ||
61 | clocks = <&clock 29>, <&clock 27>; | ||
62 | clock-names = "pcie", "pcie_bus"; | ||
63 | #address-cells = <3>; | ||
64 | #size-cells = <2>; | ||
65 | device_type = "pci"; | ||
66 | ranges = <0x00000800 0 0x60000000 0x60000000 0 0x00001000 /* configuration space */ | ||
67 | 0x81000000 0 0 0x60001000 0 0x00010000 /* downstream I/O */ | ||
68 | 0x82000000 0 0x60011000 0x60011000 0 0x1ffef000>; /* non-prefetchable memory */ | ||
69 | #interrupt-cells = <1>; | ||
70 | interrupt-map-mask = <0 0 0 0>; | ||
71 | interrupt-map = <0x0 0 &gic 56>; | ||
72 | num-lanes = <4>; | ||
73 | }; | ||
74 | |||
75 | Board specific DT Entry: | ||
76 | |||
77 | pcie@290000 { | ||
78 | reset-gpio = <&pin_ctrl 5 0>; | ||
79 | }; | ||
80 | |||
81 | pcie@2a0000 { | ||
82 | reset-gpio = <&pin_ctrl 22 0>; | ||
83 | }; | ||
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt new file mode 100644 index 000000000000..9455fd0ec830 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt | |||
@@ -0,0 +1,38 @@ | |||
1 | * Freescale i.MX6 PCIe interface | ||
2 | |||
3 | This PCIe host controller is based on the Synopsis Designware PCIe IP | ||
4 | and thus inherits all the common properties defined in designware-pcie.txt. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: "fsl,imx6q-pcie" | ||
8 | - reg: base addresse and length of the pcie controller | ||
9 | - interrupts: A list of interrupt outputs of the controller. Must contain an | ||
10 | entry for each entry in the interrupt-names property. | ||
11 | - interrupt-names: Must include the following entries: | ||
12 | - "msi": The interrupt that is asserted when an MSI is received | ||
13 | - clock-names: Must include the following additional entries: | ||
14 | - "pcie_phy" | ||
15 | |||
16 | Example: | ||
17 | |||
18 | pcie@0x01000000 { | ||
19 | compatible = "fsl,imx6q-pcie", "snps,dw-pcie"; | ||
20 | reg = <0x01ffc000 0x4000>; | ||
21 | #address-cells = <3>; | ||
22 | #size-cells = <2>; | ||
23 | device_type = "pci"; | ||
24 | ranges = <0x00000800 0 0x01f00000 0x01f00000 0 0x00080000 | ||
25 | 0x81000000 0 0 0x01f80000 0 0x00010000 | ||
26 | 0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; | ||
27 | num-lanes = <1>; | ||
28 | interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; | ||
29 | interrupt-names = "msi"; | ||
30 | #interrupt-cells = <1>; | ||
31 | interrupt-map-mask = <0 0 0 0x7>; | ||
32 | interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, | ||
33 | <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>, | ||
34 | <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, | ||
35 | <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; | ||
36 | clocks = <&clks 144>, <&clks 206>, <&clks 189>; | ||
37 | clock-names = "pcie", "pcie_bus", "pcie_phy"; | ||
38 | }; | ||
diff --git a/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt b/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt new file mode 100644 index 000000000000..4f9d23d2ed67 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/samsung,exynos5440-pcie.txt | |||
@@ -0,0 +1,65 @@ | |||
1 | * Samsung Exynos 5440 PCIe interface | ||
2 | |||
3 | This PCIe host controller is based on the Synopsis Designware PCIe IP | ||
4 | and thus inherits all the common properties defined in designware-pcie.txt. | ||
5 | |||
6 | Required properties: | ||
7 | - compatible: "samsung,exynos5440-pcie" | ||
8 | - reg: base addresses and lengths of the pcie controller, | ||
9 | the phy controller, additional register for the phy controller. | ||
10 | - interrupts: A list of interrupt outputs for level interrupt, | ||
11 | pulse interrupt, special interrupt. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | SoC specific DT Entry: | ||
16 | |||
17 | pcie@290000 { | ||
18 | compatible = "samsung,exynos5440-pcie", "snps,dw-pcie"; | ||
19 | reg = <0x290000 0x1000 | ||
20 | 0x270000 0x1000 | ||
21 | 0x271000 0x40>; | ||
22 | interrupts = <0 20 0>, <0 21 0>, <0 22 0>; | ||
23 | clocks = <&clock 28>, <&clock 27>; | ||
24 | clock-names = "pcie", "pcie_bus"; | ||
25 | #address-cells = <3>; | ||
26 | #size-cells = <2>; | ||
27 | device_type = "pci"; | ||
28 | ranges = <0x00000800 0 0x40000000 0x40000000 0 0x00001000 /* configuration space */ | ||
29 | 0x81000000 0 0 0x40001000 0 0x00010000 /* downstream I/O */ | ||
30 | 0x82000000 0 0x40011000 0x40011000 0 0x1ffef000>; /* non-prefetchable memory */ | ||
31 | #interrupt-cells = <1>; | ||
32 | interrupt-map-mask = <0 0 0 0>; | ||
33 | interrupt-map = <0 0 0 0 &gic GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; | ||
34 | num-lanes = <4>; | ||
35 | }; | ||
36 | |||
37 | pcie@2a0000 { | ||
38 | compatible = "samsung,exynos5440-pcie", "snps,dw-pcie"; | ||
39 | reg = <0x2a0000 0x1000 | ||
40 | 0x272000 0x1000 | ||
41 | 0x271040 0x40>; | ||
42 | interrupts = <0 23 0>, <0 24 0>, <0 25 0>; | ||
43 | clocks = <&clock 29>, <&clock 27>; | ||
44 | clock-names = "pcie", "pcie_bus"; | ||
45 | #address-cells = <3>; | ||
46 | #size-cells = <2>; | ||
47 | device_type = "pci"; | ||
48 | ranges = <0x00000800 0 0x60000000 0x60000000 0 0x00001000 /* configuration space */ | ||
49 | 0x81000000 0 0 0x60001000 0 0x00010000 /* downstream I/O */ | ||
50 | 0x82000000 0 0x60011000 0x60011000 0 0x1ffef000>; /* non-prefetchable memory */ | ||
51 | #interrupt-cells = <1>; | ||
52 | interrupt-map-mask = <0 0 0 0>; | ||
53 | interrupt-map = <0 0 0 0 &gic GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>; | ||
54 | num-lanes = <4>; | ||
55 | }; | ||
56 | |||
57 | Board specific DT Entry: | ||
58 | |||
59 | pcie@290000 { | ||
60 | reset-gpio = <&pin_ctrl 5 0>; | ||
61 | }; | ||
62 | |||
63 | pcie@2a0000 { | ||
64 | reset-gpio = <&pin_ctrl 22 0>; | ||
65 | }; | ||
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 293e2e0a0a87..00b73448b22e 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/of.h> | 56 | #include <linux/of.h> |
57 | #include <linux/of_address.h> | 57 | #include <linux/of_address.h> |
58 | #include <linux/debugfs.h> | 58 | #include <linux/debugfs.h> |
59 | #include <linux/log2.h> | ||
59 | 60 | ||
60 | /* | 61 | /* |
61 | * DDR target is the same on all platforms. | 62 | * DDR target is the same on all platforms. |
@@ -222,12 +223,6 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus, | |||
222 | */ | 223 | */ |
223 | if ((u64)base < wend && end > wbase) | 224 | if ((u64)base < wend && end > wbase) |
224 | return 0; | 225 | return 0; |
225 | |||
226 | /* | ||
227 | * Check if target/attribute conflicts | ||
228 | */ | ||
229 | if (target == wtarget && attr == wattr) | ||
230 | return 0; | ||
231 | } | 226 | } |
232 | 227 | ||
233 | return 1; | 228 | return 1; |
@@ -266,6 +261,17 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus, | |||
266 | mbus->soc->win_cfg_offset(win); | 261 | mbus->soc->win_cfg_offset(win); |
267 | u32 ctrl, remap_addr; | 262 | u32 ctrl, remap_addr; |
268 | 263 | ||
264 | if (!is_power_of_2(size)) { | ||
265 | WARN(true, "Invalid MBus window size: 0x%zx\n", size); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | if ((base & (phys_addr_t)(size - 1)) != 0) { | ||
270 | WARN(true, "Invalid MBus base/size: %pa len 0x%zx\n", &base, | ||
271 | size); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | |||
269 | ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | | 275 | ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) | |
270 | (attr << WIN_CTRL_ATTR_SHIFT) | | 276 | (attr << WIN_CTRL_ATTR_SHIFT) | |
271 | (target << WIN_CTRL_TGT_SHIFT) | | 277 | (target << WIN_CTRL_TGT_SHIFT) | |
@@ -413,6 +419,10 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v) | |||
413 | win, (unsigned long long)wbase, | 419 | win, (unsigned long long)wbase, |
414 | (unsigned long long)(wbase + wsize), wtarget, wattr); | 420 | (unsigned long long)(wbase + wsize), wtarget, wattr); |
415 | 421 | ||
422 | if (!is_power_of_2(wsize) || | ||
423 | ((wbase & (u64)(wsize - 1)) != 0)) | ||
424 | seq_puts(seq, " (Invalid base/size!!)"); | ||
425 | |||
416 | if (win < mbus->soc->num_remappable_wins) { | 426 | if (win < mbus->soc->num_remappable_wins) { |
417 | seq_printf(seq, " (remap %016llx)\n", | 427 | seq_printf(seq, " (remap %016llx)\n", |
418 | (unsigned long long)wremap); | 428 | (unsigned long long)wremap); |
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 1632661c5b7f..c5d0ca384502 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -545,7 +545,6 @@ static int __init add_pcie_port(struct pcie_port *pp, | |||
545 | pp->root_bus_nr = -1; | 545 | pp->root_bus_nr = -1; |
546 | pp->ops = &exynos_pcie_host_ops; | 546 | pp->ops = &exynos_pcie_host_ops; |
547 | 547 | ||
548 | spin_lock_init(&pp->conf_lock); | ||
549 | ret = dw_pcie_host_init(pp); | 548 | ret = dw_pcie_host_init(pp); |
550 | if (ret) { | 549 | if (ret) { |
551 | dev_err(&pdev->dev, "failed to initialize host\n"); | 550 | dev_err(&pdev->dev, "failed to initialize host\n"); |
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index a5645ae4aef0..a568efaa331c 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -507,7 +507,6 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp, | |||
507 | pp->root_bus_nr = -1; | 507 | pp->root_bus_nr = -1; |
508 | pp->ops = &imx6_pcie_host_ops; | 508 | pp->ops = &imx6_pcie_host_ops; |
509 | 509 | ||
510 | spin_lock_init(&pp->conf_lock); | ||
511 | ret = dw_pcie_host_init(pp); | 510 | ret = dw_pcie_host_init(pp); |
512 | if (ret) { | 511 | if (ret) { |
513 | dev_err(&pdev->dev, "failed to initialize host\n"); | 512 | dev_err(&pdev->dev, "failed to initialize host\n"); |
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index d3d1cfd51e09..7f450322f397 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -113,7 +113,6 @@ struct mvebu_pcie { | |||
113 | struct mvebu_pcie_port { | 113 | struct mvebu_pcie_port { |
114 | char *name; | 114 | char *name; |
115 | void __iomem *base; | 115 | void __iomem *base; |
116 | spinlock_t conf_lock; | ||
117 | u32 port; | 116 | u32 port; |
118 | u32 lane; | 117 | u32 lane; |
119 | int devfn; | 118 | int devfn; |
@@ -293,6 +292,60 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, | |||
293 | return PCIBIOS_SUCCESSFUL; | 292 | return PCIBIOS_SUCCESSFUL; |
294 | } | 293 | } |
295 | 294 | ||
295 | /* | ||
296 | * Remove windows, starting from the largest ones to the smallest | ||
297 | * ones. | ||
298 | */ | ||
299 | static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port, | ||
300 | phys_addr_t base, size_t size) | ||
301 | { | ||
302 | while (size) { | ||
303 | size_t sz = 1 << (fls(size) - 1); | ||
304 | |||
305 | mvebu_mbus_del_window(base, sz); | ||
306 | base += sz; | ||
307 | size -= sz; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * MBus windows can only have a power of two size, but PCI BARs do not | ||
313 | * have this constraint. Therefore, we have to split the PCI BAR into | ||
314 | * areas each having a power of two size. We start from the largest | ||
315 | * one (i.e highest order bit set in the size). | ||
316 | */ | ||
317 | static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, | ||
318 | unsigned int target, unsigned int attribute, | ||
319 | phys_addr_t base, size_t size, | ||
320 | phys_addr_t remap) | ||
321 | { | ||
322 | size_t size_mapped = 0; | ||
323 | |||
324 | while (size) { | ||
325 | size_t sz = 1 << (fls(size) - 1); | ||
326 | int ret; | ||
327 | |||
328 | ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base, | ||
329 | sz, remap); | ||
330 | if (ret) { | ||
331 | phys_addr_t end = base + sz - 1; | ||
332 | |||
333 | dev_err(&port->pcie->pdev->dev, | ||
334 | "Could not create MBus window at [mem %pa-%pa]: %d\n", | ||
335 | &base, &end, ret); | ||
336 | mvebu_pcie_del_windows(port, base - size_mapped, | ||
337 | size_mapped); | ||
338 | return; | ||
339 | } | ||
340 | |||
341 | size -= sz; | ||
342 | size_mapped += sz; | ||
343 | base += sz; | ||
344 | if (remap != MVEBU_MBUS_NO_REMAP) | ||
345 | remap += sz; | ||
346 | } | ||
347 | } | ||
348 | |||
296 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | 349 | static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) |
297 | { | 350 | { |
298 | phys_addr_t iobase; | 351 | phys_addr_t iobase; |
@@ -304,8 +357,8 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
304 | 357 | ||
305 | /* If a window was configured, remove it */ | 358 | /* If a window was configured, remove it */ |
306 | if (port->iowin_base) { | 359 | if (port->iowin_base) { |
307 | mvebu_mbus_del_window(port->iowin_base, | 360 | mvebu_pcie_del_windows(port, port->iowin_base, |
308 | port->iowin_size); | 361 | port->iowin_size); |
309 | port->iowin_base = 0; | 362 | port->iowin_base = 0; |
310 | port->iowin_size = 0; | 363 | port->iowin_size = 0; |
311 | } | 364 | } |
@@ -331,11 +384,11 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) | |||
331 | port->iowin_base = port->pcie->io.start + iobase; | 384 | port->iowin_base = port->pcie->io.start + iobase; |
332 | port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | | 385 | port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) | |
333 | (port->bridge.iolimitupper << 16)) - | 386 | (port->bridge.iolimitupper << 16)) - |
334 | iobase); | 387 | iobase) + 1; |
335 | 388 | ||
336 | mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, | 389 | mvebu_pcie_add_windows(port, port->io_target, port->io_attr, |
337 | port->iowin_base, port->iowin_size, | 390 | port->iowin_base, port->iowin_size, |
338 | iobase); | 391 | iobase); |
339 | } | 392 | } |
340 | 393 | ||
341 | static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | 394 | static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) |
@@ -346,8 +399,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | |||
346 | 399 | ||
347 | /* If a window was configured, remove it */ | 400 | /* If a window was configured, remove it */ |
348 | if (port->memwin_base) { | 401 | if (port->memwin_base) { |
349 | mvebu_mbus_del_window(port->memwin_base, | 402 | mvebu_pcie_del_windows(port, port->memwin_base, |
350 | port->memwin_size); | 403 | port->memwin_size); |
351 | port->memwin_base = 0; | 404 | port->memwin_base = 0; |
352 | port->memwin_size = 0; | 405 | port->memwin_size = 0; |
353 | } | 406 | } |
@@ -364,10 +417,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) | |||
364 | port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); | 417 | port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16); |
365 | port->memwin_size = | 418 | port->memwin_size = |
366 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - | 419 | (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - |
367 | port->memwin_base; | 420 | port->memwin_base + 1; |
368 | 421 | ||
369 | mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, | 422 | mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, |
370 | port->memwin_base, port->memwin_size); | 423 | port->memwin_base, port->memwin_size, |
424 | MVEBU_MBUS_NO_REMAP); | ||
371 | } | 425 | } |
372 | 426 | ||
373 | /* | 427 | /* |
@@ -585,7 +639,6 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
585 | { | 639 | { |
586 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | 640 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); |
587 | struct mvebu_pcie_port *port; | 641 | struct mvebu_pcie_port *port; |
588 | unsigned long flags; | ||
589 | int ret; | 642 | int ret; |
590 | 643 | ||
591 | port = mvebu_pcie_find_port(pcie, bus, devfn); | 644 | port = mvebu_pcie_find_port(pcie, bus, devfn); |
@@ -611,10 +664,8 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
611 | return PCIBIOS_DEVICE_NOT_FOUND; | 664 | return PCIBIOS_DEVICE_NOT_FOUND; |
612 | 665 | ||
613 | /* Access the real PCIe interface */ | 666 | /* Access the real PCIe interface */ |
614 | spin_lock_irqsave(&port->conf_lock, flags); | ||
615 | ret = mvebu_pcie_hw_wr_conf(port, bus, devfn, | 667 | ret = mvebu_pcie_hw_wr_conf(port, bus, devfn, |
616 | where, size, val); | 668 | where, size, val); |
617 | spin_unlock_irqrestore(&port->conf_lock, flags); | ||
618 | 669 | ||
619 | return ret; | 670 | return ret; |
620 | } | 671 | } |
@@ -625,7 +676,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
625 | { | 676 | { |
626 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); | 677 | struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); |
627 | struct mvebu_pcie_port *port; | 678 | struct mvebu_pcie_port *port; |
628 | unsigned long flags; | ||
629 | int ret; | 679 | int ret; |
630 | 680 | ||
631 | port = mvebu_pcie_find_port(pcie, bus, devfn); | 681 | port = mvebu_pcie_find_port(pcie, bus, devfn); |
@@ -657,10 +707,8 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
657 | } | 707 | } |
658 | 708 | ||
659 | /* Access the real PCIe interface */ | 709 | /* Access the real PCIe interface */ |
660 | spin_lock_irqsave(&port->conf_lock, flags); | ||
661 | ret = mvebu_pcie_hw_rd_conf(port, bus, devfn, | 710 | ret = mvebu_pcie_hw_rd_conf(port, bus, devfn, |
662 | where, size, val); | 711 | where, size, val); |
663 | spin_unlock_irqrestore(&port->conf_lock, flags); | ||
664 | 712 | ||
665 | return ret; | 713 | return ret; |
666 | } | 714 | } |
@@ -743,14 +791,21 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, | |||
743 | 791 | ||
744 | /* | 792 | /* |
745 | * On the PCI-to-PCI bridge side, the I/O windows must have at | 793 | * On the PCI-to-PCI bridge side, the I/O windows must have at |
746 | * least a 64 KB size and be aligned on their size, and the | 794 | * least a 64 KB size and the memory windows must have at |
747 | * memory windows must have at least a 1 MB size and be | 795 | * least a 1 MB size. Moreover, MBus windows need to have a |
748 | * aligned on their size | 796 | * base address aligned on their size, and their size must be |
797 | * a power of two. This means that if the BAR doesn't have a | ||
798 | * power of two size, several MBus windows will actually be | ||
799 | * created. We need to ensure that the biggest MBus window | ||
800 | * (which will be the first one) is aligned on its size, which | ||
801 | * explains the rounddown_pow_of_two() being done here. | ||
749 | */ | 802 | */ |
750 | if (res->flags & IORESOURCE_IO) | 803 | if (res->flags & IORESOURCE_IO) |
751 | return round_up(start, max_t(resource_size_t, SZ_64K, size)); | 804 | return round_up(start, max_t(resource_size_t, SZ_64K, |
805 | rounddown_pow_of_two(size))); | ||
752 | else if (res->flags & IORESOURCE_MEM) | 806 | else if (res->flags & IORESOURCE_MEM) |
753 | return round_up(start, max_t(resource_size_t, SZ_1M, size)); | 807 | return round_up(start, max_t(resource_size_t, SZ_1M, |
808 | rounddown_pow_of_two(size))); | ||
754 | else | 809 | else |
755 | return start; | 810 | return start; |
756 | } | 811 | } |
@@ -1000,7 +1055,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
1000 | mvebu_pcie_set_local_dev_nr(port, 1); | 1055 | mvebu_pcie_set_local_dev_nr(port, 1); |
1001 | 1056 | ||
1002 | port->dn = child; | 1057 | port->dn = child; |
1003 | spin_lock_init(&port->conf_lock); | ||
1004 | mvebu_sw_pci_bridge_init(port); | 1058 | mvebu_sw_pci_bridge_init(port); |
1005 | i++; | 1059 | i++; |
1006 | } | 1060 | } |
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 330f7e3a32dd..083cf37ca047 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -639,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) | |||
639 | static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) | 639 | static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) |
640 | { | 640 | { |
641 | struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); | 641 | struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); |
642 | int irq; | ||
642 | 643 | ||
643 | tegra_cpuidle_pcie_irqs_in_use(); | 644 | tegra_cpuidle_pcie_irqs_in_use(); |
644 | 645 | ||
645 | return pcie->irq; | 646 | irq = of_irq_parse_and_map_pci(pdev, slot, pin); |
647 | if (!irq) | ||
648 | irq = pcie->irq; | ||
649 | |||
650 | return irq; | ||
646 | } | 651 | } |
647 | 652 | ||
648 | static void tegra_pcie_add_bus(struct pci_bus *bus) | 653 | static void tegra_pcie_add_bus(struct pci_bus *bus) |
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 77a649dd1473..1eaf4df3618a 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/msi.h> | 18 | #include <linux/msi.h> |
19 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
20 | #include <linux/of_pci.h> | ||
20 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
21 | #include <linux/pci_regs.h> | 22 | #include <linux/pci_regs.h> |
22 | #include <linux/types.h> | 23 | #include <linux/types.h> |
@@ -494,7 +495,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) | |||
494 | dw_pci.nr_controllers = 1; | 495 | dw_pci.nr_controllers = 1; |
495 | dw_pci.private_data = (void **)&pp; | 496 | dw_pci.private_data = (void **)&pp; |
496 | 497 | ||
497 | pci_common_init(&dw_pci); | 498 | pci_common_init_dev(pp->dev, &dw_pci); |
498 | pci_assign_unassigned_resources(); | 499 | pci_assign_unassigned_resources(); |
499 | #ifdef CONFIG_PCI_DOMAINS | 500 | #ifdef CONFIG_PCI_DOMAINS |
500 | dw_pci.domain++; | 501 | dw_pci.domain++; |
@@ -524,13 +525,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) | |||
524 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, | 525 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, |
525 | PCIE_ATU_VIEWPORT); | 526 | PCIE_ATU_VIEWPORT); |
526 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); | 527 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); |
527 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
528 | dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); | 528 | dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); |
529 | dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); | 529 | dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); |
530 | dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, | 530 | dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, |
531 | PCIE_ATU_LIMIT); | 531 | PCIE_ATU_LIMIT); |
532 | dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); | 532 | dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); |
533 | dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); | 533 | dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); |
534 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
534 | } | 535 | } |
535 | 536 | ||
536 | static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) | 537 | static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) |
@@ -539,7 +540,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) | |||
539 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, | 540 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, |
540 | PCIE_ATU_VIEWPORT); | 541 | PCIE_ATU_VIEWPORT); |
541 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); | 542 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); |
542 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
543 | dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); | 543 | dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); |
544 | dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); | 544 | dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); |
545 | dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, | 545 | dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, |
@@ -547,6 +547,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) | |||
547 | dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); | 547 | dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); |
548 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), | 548 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), |
549 | PCIE_ATU_UPPER_TARGET); | 549 | PCIE_ATU_UPPER_TARGET); |
550 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
550 | } | 551 | } |
551 | 552 | ||
552 | static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) | 553 | static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) |
@@ -555,7 +556,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) | |||
555 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, | 556 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, |
556 | PCIE_ATU_VIEWPORT); | 557 | PCIE_ATU_VIEWPORT); |
557 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); | 558 | dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); |
558 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
559 | dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); | 559 | dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); |
560 | dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); | 560 | dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); |
561 | dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, | 561 | dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, |
@@ -563,6 +563,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) | |||
563 | dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); | 563 | dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); |
564 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), | 564 | dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), |
565 | PCIE_ATU_UPPER_TARGET); | 565 | PCIE_ATU_UPPER_TARGET); |
566 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
566 | } | 567 | } |
567 | 568 | ||
568 | static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | 569 | static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, |
@@ -642,7 +643,6 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
642 | int size, u32 *val) | 643 | int size, u32 *val) |
643 | { | 644 | { |
644 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); | 645 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); |
645 | unsigned long flags; | ||
646 | int ret; | 646 | int ret; |
647 | 647 | ||
648 | if (!pp) { | 648 | if (!pp) { |
@@ -655,13 +655,11 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
655 | return PCIBIOS_DEVICE_NOT_FOUND; | 655 | return PCIBIOS_DEVICE_NOT_FOUND; |
656 | } | 656 | } |
657 | 657 | ||
658 | spin_lock_irqsave(&pp->conf_lock, flags); | ||
659 | if (bus->number != pp->root_bus_nr) | 658 | if (bus->number != pp->root_bus_nr) |
660 | ret = dw_pcie_rd_other_conf(pp, bus, devfn, | 659 | ret = dw_pcie_rd_other_conf(pp, bus, devfn, |
661 | where, size, val); | 660 | where, size, val); |
662 | else | 661 | else |
663 | ret = dw_pcie_rd_own_conf(pp, where, size, val); | 662 | ret = dw_pcie_rd_own_conf(pp, where, size, val); |
664 | spin_unlock_irqrestore(&pp->conf_lock, flags); | ||
665 | 663 | ||
666 | return ret; | 664 | return ret; |
667 | } | 665 | } |
@@ -670,7 +668,6 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
670 | int where, int size, u32 val) | 668 | int where, int size, u32 val) |
671 | { | 669 | { |
672 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); | 670 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); |
673 | unsigned long flags; | ||
674 | int ret; | 671 | int ret; |
675 | 672 | ||
676 | if (!pp) { | 673 | if (!pp) { |
@@ -681,13 +678,11 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
681 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) | 678 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) |
682 | return PCIBIOS_DEVICE_NOT_FOUND; | 679 | return PCIBIOS_DEVICE_NOT_FOUND; |
683 | 680 | ||
684 | spin_lock_irqsave(&pp->conf_lock, flags); | ||
685 | if (bus->number != pp->root_bus_nr) | 681 | if (bus->number != pp->root_bus_nr) |
686 | ret = dw_pcie_wr_other_conf(pp, bus, devfn, | 682 | ret = dw_pcie_wr_other_conf(pp, bus, devfn, |
687 | where, size, val); | 683 | where, size, val); |
688 | else | 684 | else |
689 | ret = dw_pcie_wr_own_conf(pp, where, size, val); | 685 | ret = dw_pcie_wr_own_conf(pp, where, size, val); |
690 | spin_unlock_irqrestore(&pp->conf_lock, flags); | ||
691 | 686 | ||
692 | return ret; | 687 | return ret; |
693 | } | 688 | } |
@@ -727,7 +722,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) | |||
727 | 722 | ||
728 | if (pp) { | 723 | if (pp) { |
729 | pp->root_bus_nr = sys->busnr; | 724 | pp->root_bus_nr = sys->busnr; |
730 | bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops, | 725 | bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops, |
731 | sys, &sys->resources); | 726 | sys, &sys->resources); |
732 | } else { | 727 | } else { |
733 | bus = NULL; | 728 | bus = NULL; |
@@ -740,8 +735,13 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) | |||
740 | static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 735 | static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
741 | { | 736 | { |
742 | struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); | 737 | struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); |
738 | int irq; | ||
739 | |||
740 | irq = of_irq_parse_and_map_pci(dev, slot, pin); | ||
741 | if (!irq) | ||
742 | irq = pp->irq; | ||
743 | 743 | ||
744 | return pp->irq; | 744 | return irq; |
745 | } | 745 | } |
746 | 746 | ||
747 | static void dw_pcie_add_bus(struct pci_bus *bus) | 747 | static void dw_pcie_add_bus(struct pci_bus *bus) |
@@ -768,7 +768,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
768 | u32 membase; | 768 | u32 membase; |
769 | u32 memlimit; | 769 | u32 memlimit; |
770 | 770 | ||
771 | /* set the number of lines as 4 */ | 771 | /* set the number of lanes */ |
772 | dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); | 772 | dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); |
773 | val &= ~PORT_LINK_MODE_MASK; | 773 | val &= ~PORT_LINK_MODE_MASK; |
774 | switch (pp->lanes) { | 774 | switch (pp->lanes) { |
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index a169d22d517e..77f592faa7bf 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h | |||
@@ -41,7 +41,6 @@ struct pcie_port { | |||
41 | void __iomem *va_cfg1_base; | 41 | void __iomem *va_cfg1_base; |
42 | u64 io_base; | 42 | u64 io_base; |
43 | u64 mem_base; | 43 | u64 mem_base; |
44 | spinlock_t conf_lock; | ||
45 | struct resource cfg; | 44 | struct resource cfg; |
46 | struct resource io; | 45 | struct resource io; |
47 | struct resource mem; | 46 | struct resource mem; |