diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/host/Kconfig | 14 | ||||
-rw-r--r-- | drivers/pci/host/Makefile | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-exynos.c | 132 | ||||
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 568 | ||||
-rw-r--r-- | drivers/pci/host/pci-rcar-gen2.c | 333 | ||||
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 4 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.c | 257 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.h | 26 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 2 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp.h | 2 | ||||
-rw-r--r-- | drivers/pci/pci-driver.c | 17 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 100 | ||||
-rw-r--r-- | drivers/pci/pci.c | 2 | ||||
-rw-r--r-- | drivers/pci/pci.h | 4 | ||||
-rw-r--r-- | drivers/pci/probe.c | 3 |
15 files changed, 1395 insertions, 71 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 3d9504811126..d0cf0faab407 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -15,8 +15,22 @@ config PCI_EXYNOS | |||
15 | select PCIEPORTBUS | 15 | select PCIEPORTBUS |
16 | select PCIE_DW | 16 | select PCIE_DW |
17 | 17 | ||
18 | config PCI_IMX6 | ||
19 | bool "Freescale i.MX6 PCIe controller" | ||
20 | depends on SOC_IMX6Q | ||
21 | select PCIEPORTBUS | ||
22 | select PCIE_DW | ||
23 | |||
18 | config PCI_TEGRA | 24 | config PCI_TEGRA |
19 | bool "NVIDIA Tegra PCIe controller" | 25 | bool "NVIDIA Tegra PCIe controller" |
20 | depends on ARCH_TEGRA | 26 | depends on ARCH_TEGRA |
21 | 27 | ||
28 | config PCI_RCAR_GEN2 | ||
29 | bool "Renesas R-Car Gen2 Internal PCI controller" | ||
30 | depends on ARM && (ARCH_R8A7790 || ARCH_R8A7791 || COMPILE_TEST) | ||
31 | help | ||
32 | Say Y here if you want internal PCI support on R-Car Gen2 SoC. | ||
33 | There are 3 internal PCI controllers available with a single | ||
34 | built-in EHCI/OHCI host controller present on each one. | ||
35 | |||
22 | endmenu | 36 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index c9a997b2690d..13fb3333aa05 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | obj-$(CONFIG_PCIE_DW) += pcie-designware.o | 1 | obj-$(CONFIG_PCIE_DW) += pcie-designware.o |
2 | obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o | 2 | obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o |
3 | obj-$(CONFIG_PCI_IMX6) += pci-imx6.o | ||
3 | obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o | 4 | obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o |
4 | obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o | 5 | obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o |
6 | obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o | ||
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 94e096bb2d0a..24beed38ddc7 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -48,6 +48,7 @@ struct exynos_pcie { | |||
48 | #define PCIE_IRQ_SPECIAL 0x008 | 48 | #define PCIE_IRQ_SPECIAL 0x008 |
49 | #define PCIE_IRQ_EN_PULSE 0x00c | 49 | #define PCIE_IRQ_EN_PULSE 0x00c |
50 | #define PCIE_IRQ_EN_LEVEL 0x010 | 50 | #define PCIE_IRQ_EN_LEVEL 0x010 |
51 | #define IRQ_MSI_ENABLE (0x1 << 2) | ||
51 | #define PCIE_IRQ_EN_SPECIAL 0x014 | 52 | #define PCIE_IRQ_EN_SPECIAL 0x014 |
52 | #define PCIE_PWR_RESET 0x018 | 53 | #define PCIE_PWR_RESET 0x018 |
53 | #define PCIE_CORE_RESET 0x01c | 54 | #define PCIE_CORE_RESET 0x01c |
@@ -77,18 +78,28 @@ struct exynos_pcie { | |||
77 | #define PCIE_PHY_PLL_BIAS 0x00c | 78 | #define PCIE_PHY_PLL_BIAS 0x00c |
78 | #define PCIE_PHY_DCC_FEEDBACK 0x014 | 79 | #define PCIE_PHY_DCC_FEEDBACK 0x014 |
79 | #define PCIE_PHY_PLL_DIV_1 0x05c | 80 | #define PCIE_PHY_PLL_DIV_1 0x05c |
81 | #define PCIE_PHY_COMMON_POWER 0x064 | ||
82 | #define PCIE_PHY_COMMON_PD_CMN (0x1 << 3) | ||
80 | #define PCIE_PHY_TRSV0_EMP_LVL 0x084 | 83 | #define PCIE_PHY_TRSV0_EMP_LVL 0x084 |
81 | #define PCIE_PHY_TRSV0_DRV_LVL 0x088 | 84 | #define PCIE_PHY_TRSV0_DRV_LVL 0x088 |
82 | #define PCIE_PHY_TRSV0_RXCDR 0x0ac | 85 | #define PCIE_PHY_TRSV0_RXCDR 0x0ac |
86 | #define PCIE_PHY_TRSV0_POWER 0x0c4 | ||
87 | #define PCIE_PHY_TRSV0_PD_TSV (0x1 << 7) | ||
83 | #define PCIE_PHY_TRSV0_LVCC 0x0dc | 88 | #define PCIE_PHY_TRSV0_LVCC 0x0dc |
84 | #define PCIE_PHY_TRSV1_EMP_LVL 0x144 | 89 | #define PCIE_PHY_TRSV1_EMP_LVL 0x144 |
85 | #define PCIE_PHY_TRSV1_RXCDR 0x16c | 90 | #define PCIE_PHY_TRSV1_RXCDR 0x16c |
91 | #define PCIE_PHY_TRSV1_POWER 0x184 | ||
92 | #define PCIE_PHY_TRSV1_PD_TSV (0x1 << 7) | ||
86 | #define PCIE_PHY_TRSV1_LVCC 0x19c | 93 | #define PCIE_PHY_TRSV1_LVCC 0x19c |
87 | #define PCIE_PHY_TRSV2_EMP_LVL 0x204 | 94 | #define PCIE_PHY_TRSV2_EMP_LVL 0x204 |
88 | #define PCIE_PHY_TRSV2_RXCDR 0x22c | 95 | #define PCIE_PHY_TRSV2_RXCDR 0x22c |
96 | #define PCIE_PHY_TRSV2_POWER 0x244 | ||
97 | #define PCIE_PHY_TRSV2_PD_TSV (0x1 << 7) | ||
89 | #define PCIE_PHY_TRSV2_LVCC 0x25c | 98 | #define PCIE_PHY_TRSV2_LVCC 0x25c |
90 | #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 | 99 | #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 |
91 | #define PCIE_PHY_TRSV3_RXCDR 0x2ec | 100 | #define PCIE_PHY_TRSV3_RXCDR 0x2ec |
101 | #define PCIE_PHY_TRSV3_POWER 0x304 | ||
102 | #define PCIE_PHY_TRSV3_PD_TSV (0x1 << 7) | ||
92 | #define PCIE_PHY_TRSV3_LVCC 0x31c | 103 | #define PCIE_PHY_TRSV3_LVCC 0x31c |
93 | 104 | ||
94 | static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg) | 105 | static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg) |
@@ -202,6 +213,58 @@ static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp) | |||
202 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET); | 213 | exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET); |
203 | } | 214 | } |
204 | 215 | ||
216 | static void exynos_pcie_power_on_phy(struct pcie_port *pp) | ||
217 | { | ||
218 | u32 val; | ||
219 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); | ||
220 | |||
221 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); | ||
222 | val &= ~PCIE_PHY_COMMON_PD_CMN; | ||
223 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); | ||
224 | |||
225 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); | ||
226 | val &= ~PCIE_PHY_TRSV0_PD_TSV; | ||
227 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); | ||
228 | |||
229 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); | ||
230 | val &= ~PCIE_PHY_TRSV1_PD_TSV; | ||
231 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); | ||
232 | |||
233 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); | ||
234 | val &= ~PCIE_PHY_TRSV2_PD_TSV; | ||
235 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); | ||
236 | |||
237 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); | ||
238 | val &= ~PCIE_PHY_TRSV3_PD_TSV; | ||
239 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); | ||
240 | } | ||
241 | |||
242 | static void exynos_pcie_power_off_phy(struct pcie_port *pp) | ||
243 | { | ||
244 | u32 val; | ||
245 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); | ||
246 | |||
247 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); | ||
248 | val |= PCIE_PHY_COMMON_PD_CMN; | ||
249 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); | ||
250 | |||
251 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); | ||
252 | val |= PCIE_PHY_TRSV0_PD_TSV; | ||
253 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); | ||
254 | |||
255 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); | ||
256 | val |= PCIE_PHY_TRSV1_PD_TSV; | ||
257 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); | ||
258 | |||
259 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); | ||
260 | val |= PCIE_PHY_TRSV2_PD_TSV; | ||
261 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); | ||
262 | |||
263 | val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); | ||
264 | val |= PCIE_PHY_TRSV3_PD_TSV; | ||
265 | exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); | ||
266 | } | ||
267 | |||
205 | static void exynos_pcie_init_phy(struct pcie_port *pp) | 268 | static void exynos_pcie_init_phy(struct pcie_port *pp) |
206 | { | 269 | { |
207 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); | 270 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); |
@@ -270,6 +333,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp) | |||
270 | /* de-assert phy reset */ | 333 | /* de-assert phy reset */ |
271 | exynos_pcie_deassert_phy_reset(pp); | 334 | exynos_pcie_deassert_phy_reset(pp); |
272 | 335 | ||
336 | /* power on phy */ | ||
337 | exynos_pcie_power_on_phy(pp); | ||
338 | |||
273 | /* initialize phy */ | 339 | /* initialize phy */ |
274 | exynos_pcie_init_phy(pp); | 340 | exynos_pcie_init_phy(pp); |
275 | 341 | ||
@@ -302,6 +368,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp) | |||
302 | PCIE_PHY_PLL_LOCKED); | 368 | PCIE_PHY_PLL_LOCKED); |
303 | dev_info(pp->dev, "PLL Locked: 0x%x\n", val); | 369 | dev_info(pp->dev, "PLL Locked: 0x%x\n", val); |
304 | } | 370 | } |
371 | /* power off phy */ | ||
372 | exynos_pcie_power_off_phy(pp); | ||
373 | |||
305 | dev_err(pp->dev, "PCIe Link Fail\n"); | 374 | dev_err(pp->dev, "PCIe Link Fail\n"); |
306 | return -EINVAL; | 375 | return -EINVAL; |
307 | } | 376 | } |
@@ -342,9 +411,36 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) | |||
342 | return IRQ_HANDLED; | 411 | return IRQ_HANDLED; |
343 | } | 412 | } |
344 | 413 | ||
414 | static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg) | ||
415 | { | ||
416 | struct pcie_port *pp = arg; | ||
417 | |||
418 | dw_handle_msi_irq(pp); | ||
419 | |||
420 | return IRQ_HANDLED; | ||
421 | } | ||
422 | |||
423 | static void exynos_pcie_msi_init(struct pcie_port *pp) | ||
424 | { | ||
425 | u32 val; | ||
426 | struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); | ||
427 | |||
428 | dw_pcie_msi_init(pp); | ||
429 | |||
430 | /* enable MSI interrupt */ | ||
431 | val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); | ||
432 | val |= IRQ_MSI_ENABLE; | ||
433 | exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); | ||
434 | return; | ||
435 | } | ||
436 | |||
345 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) | 437 | static void exynos_pcie_enable_interrupts(struct pcie_port *pp) |
346 | { | 438 | { |
347 | exynos_pcie_enable_irq_pulse(pp); | 439 | exynos_pcie_enable_irq_pulse(pp); |
440 | |||
441 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
442 | exynos_pcie_msi_init(pp); | ||
443 | |||
348 | return; | 444 | return; |
349 | } | 445 | } |
350 | 446 | ||
@@ -430,6 +526,22 @@ static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev) | |||
430 | return ret; | 526 | return ret; |
431 | } | 527 | } |
432 | 528 | ||
529 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
530 | pp->msi_irq = platform_get_irq(pdev, 0); | ||
531 | if (!pp->msi_irq) { | ||
532 | dev_err(&pdev->dev, "failed to get msi irq\n"); | ||
533 | return -ENODEV; | ||
534 | } | ||
535 | |||
536 | ret = devm_request_irq(&pdev->dev, pp->msi_irq, | ||
537 | exynos_pcie_msi_irq_handler, | ||
538 | IRQF_SHARED, "exynos-pcie", pp); | ||
539 | if (ret) { | ||
540 | dev_err(&pdev->dev, "failed to request msi irq\n"); | ||
541 | return ret; | ||
542 | } | ||
543 | } | ||
544 | |||
433 | pp->root_bus_nr = -1; | 545 | pp->root_bus_nr = -1; |
434 | pp->ops = &exynos_pcie_host_ops; | 546 | pp->ops = &exynos_pcie_host_ops; |
435 | 547 | ||
@@ -487,18 +599,24 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
487 | 599 | ||
488 | elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 600 | elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
489 | exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base); | 601 | exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base); |
490 | if (IS_ERR(exynos_pcie->elbi_base)) | 602 | if (IS_ERR(exynos_pcie->elbi_base)) { |
491 | return PTR_ERR(exynos_pcie->elbi_base); | 603 | ret = PTR_ERR(exynos_pcie->elbi_base); |
604 | goto fail_bus_clk; | ||
605 | } | ||
492 | 606 | ||
493 | phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 607 | phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
494 | exynos_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base); | 608 | exynos_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base); |
495 | if (IS_ERR(exynos_pcie->phy_base)) | 609 | if (IS_ERR(exynos_pcie->phy_base)) { |
496 | return PTR_ERR(exynos_pcie->phy_base); | 610 | ret = PTR_ERR(exynos_pcie->phy_base); |
611 | goto fail_bus_clk; | ||
612 | } | ||
497 | 613 | ||
498 | block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2); | 614 | block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2); |
499 | exynos_pcie->block_base = devm_ioremap_resource(&pdev->dev, block_base); | 615 | exynos_pcie->block_base = devm_ioremap_resource(&pdev->dev, block_base); |
500 | if (IS_ERR(exynos_pcie->block_base)) | 616 | if (IS_ERR(exynos_pcie->block_base)) { |
501 | return PTR_ERR(exynos_pcie->block_base); | 617 | ret = PTR_ERR(exynos_pcie->block_base); |
618 | goto fail_bus_clk; | ||
619 | } | ||
502 | 620 | ||
503 | ret = add_pcie_port(pp, pdev); | 621 | ret = add_pcie_port(pp, pdev); |
504 | if (ret < 0) | 622 | if (ret < 0) |
@@ -535,7 +653,7 @@ static struct platform_driver exynos_pcie_driver = { | |||
535 | .driver = { | 653 | .driver = { |
536 | .name = "exynos-pcie", | 654 | .name = "exynos-pcie", |
537 | .owner = THIS_MODULE, | 655 | .owner = THIS_MODULE, |
538 | .of_match_table = of_match_ptr(exynos_pcie_of_match), | 656 | .of_match_table = exynos_pcie_of_match, |
539 | }, | 657 | }, |
540 | }; | 658 | }; |
541 | 659 | ||
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c new file mode 100644 index 000000000000..bd70af8f31ac --- /dev/null +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -0,0 +1,568 @@ | |||
1 | /* | ||
2 | * PCIe host controller driver for Freescale i.MX6 SoCs | ||
3 | * | ||
4 | * Copyright (C) 2013 Kosagi | ||
5 | * http://www.kosagi.com | ||
6 | * | ||
7 | * Author: Sean Cross <xobs@kosagi.com> | ||
8 | * | ||
9 | * 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 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/clk.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/gpio.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/mfd/syscon.h> | ||
19 | #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/of_gpio.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/resource.h> | ||
26 | #include <linux/signal.h> | ||
27 | #include <linux/types.h> | ||
28 | |||
29 | #include "pcie-designware.h" | ||
30 | |||
31 | #define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) | ||
32 | |||
33 | struct imx6_pcie { | ||
34 | int reset_gpio; | ||
35 | int power_on_gpio; | ||
36 | int wake_up_gpio; | ||
37 | int disable_gpio; | ||
38 | struct clk *lvds_gate; | ||
39 | struct clk *sata_ref_100m; | ||
40 | struct clk *pcie_ref_125m; | ||
41 | struct clk *pcie_axi; | ||
42 | struct pcie_port pp; | ||
43 | struct regmap *iomuxc_gpr; | ||
44 | void __iomem *mem_base; | ||
45 | }; | ||
46 | |||
47 | /* PCIe Port Logic registers (memory-mapped) */ | ||
48 | #define PL_OFFSET 0x700 | ||
49 | #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) | ||
50 | #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) | ||
51 | |||
52 | #define PCIE_PHY_CTRL (PL_OFFSET + 0x114) | ||
53 | #define PCIE_PHY_CTRL_DATA_LOC 0 | ||
54 | #define PCIE_PHY_CTRL_CAP_ADR_LOC 16 | ||
55 | #define PCIE_PHY_CTRL_CAP_DAT_LOC 17 | ||
56 | #define PCIE_PHY_CTRL_WR_LOC 18 | ||
57 | #define PCIE_PHY_CTRL_RD_LOC 19 | ||
58 | |||
59 | #define PCIE_PHY_STAT (PL_OFFSET + 0x110) | ||
60 | #define PCIE_PHY_STAT_ACK_LOC 16 | ||
61 | |||
62 | /* PHY registers (not memory-mapped) */ | ||
63 | #define PCIE_PHY_RX_ASIC_OUT 0x100D | ||
64 | |||
65 | #define PHY_RX_OVRD_IN_LO 0x1005 | ||
66 | #define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) | ||
67 | #define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) | ||
68 | |||
69 | static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val) | ||
70 | { | ||
71 | u32 val; | ||
72 | u32 max_iterations = 10; | ||
73 | u32 wait_counter = 0; | ||
74 | |||
75 | do { | ||
76 | val = readl(dbi_base + PCIE_PHY_STAT); | ||
77 | val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1; | ||
78 | wait_counter++; | ||
79 | |||
80 | if (val == exp_val) | ||
81 | return 0; | ||
82 | |||
83 | udelay(1); | ||
84 | } while (wait_counter < max_iterations); | ||
85 | |||
86 | return -ETIMEDOUT; | ||
87 | } | ||
88 | |||
89 | static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr) | ||
90 | { | ||
91 | u32 val; | ||
92 | int ret; | ||
93 | |||
94 | val = addr << PCIE_PHY_CTRL_DATA_LOC; | ||
95 | writel(val, dbi_base + PCIE_PHY_CTRL); | ||
96 | |||
97 | val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC); | ||
98 | writel(val, dbi_base + PCIE_PHY_CTRL); | ||
99 | |||
100 | ret = pcie_phy_poll_ack(dbi_base, 1); | ||
101 | if (ret) | ||
102 | return ret; | ||
103 | |||
104 | val = addr << PCIE_PHY_CTRL_DATA_LOC; | ||
105 | writel(val, dbi_base + PCIE_PHY_CTRL); | ||
106 | |||
107 | ret = pcie_phy_poll_ack(dbi_base, 0); | ||
108 | if (ret) | ||
109 | return ret; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */ | ||
115 | static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data) | ||
116 | { | ||
117 | u32 val, phy_ctl; | ||
118 | int ret; | ||
119 | |||
120 | ret = pcie_phy_wait_ack(dbi_base, addr); | ||
121 | if (ret) | ||
122 | return ret; | ||
123 | |||
124 | /* assert Read signal */ | ||
125 | phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC; | ||
126 | writel(phy_ctl, dbi_base + PCIE_PHY_CTRL); | ||
127 | |||
128 | ret = pcie_phy_poll_ack(dbi_base, 1); | ||
129 | if (ret) | ||
130 | return ret; | ||
131 | |||
132 | val = readl(dbi_base + PCIE_PHY_STAT); | ||
133 | *data = val & 0xffff; | ||
134 | |||
135 | /* deassert Read signal */ | ||
136 | writel(0x00, dbi_base + PCIE_PHY_CTRL); | ||
137 | |||
138 | ret = pcie_phy_poll_ack(dbi_base, 0); | ||
139 | if (ret) | ||
140 | return ret; | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int pcie_phy_write(void __iomem *dbi_base, int addr, int data) | ||
146 | { | ||
147 | u32 var; | ||
148 | int ret; | ||
149 | |||
150 | /* write addr */ | ||
151 | /* cap addr */ | ||
152 | ret = pcie_phy_wait_ack(dbi_base, addr); | ||
153 | if (ret) | ||
154 | return ret; | ||
155 | |||
156 | var = data << PCIE_PHY_CTRL_DATA_LOC; | ||
157 | writel(var, dbi_base + PCIE_PHY_CTRL); | ||
158 | |||
159 | /* capture data */ | ||
160 | var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC); | ||
161 | writel(var, dbi_base + PCIE_PHY_CTRL); | ||
162 | |||
163 | ret = pcie_phy_poll_ack(dbi_base, 1); | ||
164 | if (ret) | ||
165 | return ret; | ||
166 | |||
167 | /* deassert cap data */ | ||
168 | var = data << PCIE_PHY_CTRL_DATA_LOC; | ||
169 | writel(var, dbi_base + PCIE_PHY_CTRL); | ||
170 | |||
171 | /* wait for ack de-assertion */ | ||
172 | ret = pcie_phy_poll_ack(dbi_base, 0); | ||
173 | if (ret) | ||
174 | return ret; | ||
175 | |||
176 | /* assert wr signal */ | ||
177 | var = 0x1 << PCIE_PHY_CTRL_WR_LOC; | ||
178 | writel(var, dbi_base + PCIE_PHY_CTRL); | ||
179 | |||
180 | /* wait for ack */ | ||
181 | ret = pcie_phy_poll_ack(dbi_base, 1); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | |||
185 | /* deassert wr signal */ | ||
186 | var = data << PCIE_PHY_CTRL_DATA_LOC; | ||
187 | writel(var, dbi_base + PCIE_PHY_CTRL); | ||
188 | |||
189 | /* wait for ack de-assertion */ | ||
190 | ret = pcie_phy_poll_ack(dbi_base, 0); | ||
191 | if (ret) | ||
192 | return ret; | ||
193 | |||
194 | writel(0x0, dbi_base + PCIE_PHY_CTRL); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | /* Added for PCI abort handling */ | ||
200 | static int imx6q_pcie_abort_handler(unsigned long addr, | ||
201 | unsigned int fsr, struct pt_regs *regs) | ||
202 | { | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int imx6_pcie_assert_core_reset(struct pcie_port *pp) | ||
207 | { | ||
208 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); | ||
209 | |||
210 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, | ||
211 | IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); | ||
212 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
213 | IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); | ||
214 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, | ||
215 | IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); | ||
216 | |||
217 | gpio_set_value(imx6_pcie->reset_gpio, 0); | ||
218 | msleep(100); | ||
219 | gpio_set_value(imx6_pcie->reset_gpio, 1); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) | ||
225 | { | ||
226 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); | ||
227 | int ret; | ||
228 | |||
229 | if (gpio_is_valid(imx6_pcie->power_on_gpio)) | ||
230 | gpio_set_value(imx6_pcie->power_on_gpio, 1); | ||
231 | |||
232 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, | ||
233 | IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18); | ||
234 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, | ||
235 | IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); | ||
236 | |||
237 | ret = clk_prepare_enable(imx6_pcie->sata_ref_100m); | ||
238 | if (ret) { | ||
239 | dev_err(pp->dev, "unable to enable sata_ref_100m\n"); | ||
240 | goto err_sata_ref; | ||
241 | } | ||
242 | |||
243 | ret = clk_prepare_enable(imx6_pcie->pcie_ref_125m); | ||
244 | if (ret) { | ||
245 | dev_err(pp->dev, "unable to enable pcie_ref_125m\n"); | ||
246 | goto err_pcie_ref; | ||
247 | } | ||
248 | |||
249 | ret = clk_prepare_enable(imx6_pcie->lvds_gate); | ||
250 | if (ret) { | ||
251 | dev_err(pp->dev, "unable to enable lvds_gate\n"); | ||
252 | goto err_lvds_gate; | ||
253 | } | ||
254 | |||
255 | ret = clk_prepare_enable(imx6_pcie->pcie_axi); | ||
256 | if (ret) { | ||
257 | dev_err(pp->dev, "unable to enable pcie_axi\n"); | ||
258 | goto err_pcie_axi; | ||
259 | } | ||
260 | |||
261 | /* allow the clocks to stabilize */ | ||
262 | usleep_range(200, 500); | ||
263 | |||
264 | return 0; | ||
265 | |||
266 | err_pcie_axi: | ||
267 | clk_disable_unprepare(imx6_pcie->lvds_gate); | ||
268 | err_lvds_gate: | ||
269 | clk_disable_unprepare(imx6_pcie->pcie_ref_125m); | ||
270 | err_pcie_ref: | ||
271 | clk_disable_unprepare(imx6_pcie->sata_ref_100m); | ||
272 | err_sata_ref: | ||
273 | return ret; | ||
274 | |||
275 | } | ||
276 | |||
277 | static void imx6_pcie_init_phy(struct pcie_port *pp) | ||
278 | { | ||
279 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); | ||
280 | |||
281 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
282 | IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); | ||
283 | |||
284 | /* configure constant input signal to the pcie ctrl and phy */ | ||
285 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
286 | IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); | ||
287 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
288 | IMX6Q_GPR12_LOS_LEVEL, 9 << 4); | ||
289 | |||
290 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, | ||
291 | IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0); | ||
292 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, | ||
293 | IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6); | ||
294 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, | ||
295 | IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12); | ||
296 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, | ||
297 | IMX6Q_GPR8_TX_SWING_FULL, 127 << 18); | ||
298 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, | ||
299 | IMX6Q_GPR8_TX_SWING_LOW, 127 << 25); | ||
300 | } | ||
301 | |||
302 | static void imx6_pcie_host_init(struct pcie_port *pp) | ||
303 | { | ||
304 | int count = 0; | ||
305 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); | ||
306 | |||
307 | imx6_pcie_assert_core_reset(pp); | ||
308 | |||
309 | imx6_pcie_init_phy(pp); | ||
310 | |||
311 | imx6_pcie_deassert_core_reset(pp); | ||
312 | |||
313 | dw_pcie_setup_rc(pp); | ||
314 | |||
315 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
316 | IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); | ||
317 | |||
318 | while (!dw_pcie_link_up(pp)) { | ||
319 | usleep_range(100, 1000); | ||
320 | count++; | ||
321 | if (count >= 200) { | ||
322 | dev_err(pp->dev, "phy link never came up\n"); | ||
323 | dev_dbg(pp->dev, | ||
324 | "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", | ||
325 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), | ||
326 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); | ||
327 | break; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | return; | ||
332 | } | ||
333 | |||
334 | static int imx6_pcie_link_up(struct pcie_port *pp) | ||
335 | { | ||
336 | u32 rc, ltssm, rx_valid, temp; | ||
337 | |||
338 | /* link is debug bit 36, debug register 1 starts at bit 32 */ | ||
339 | rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32)); | ||
340 | if (rc) | ||
341 | return -EAGAIN; | ||
342 | |||
343 | /* | ||
344 | * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. | ||
345 | * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2). | ||
346 | * If (MAC/LTSSM.state == Recovery.RcvrLock) | ||
347 | * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition | ||
348 | * to gen2 is stuck | ||
349 | */ | ||
350 | pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); | ||
351 | ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F; | ||
352 | |||
353 | if (rx_valid & 0x01) | ||
354 | return 0; | ||
355 | |||
356 | if (ltssm != 0x0d) | ||
357 | return 0; | ||
358 | |||
359 | dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); | ||
360 | |||
361 | pcie_phy_read(pp->dbi_base, | ||
362 | PHY_RX_OVRD_IN_LO, &temp); | ||
363 | temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | ||
364 | | PHY_RX_OVRD_IN_LO_RX_PLL_EN); | ||
365 | pcie_phy_write(pp->dbi_base, | ||
366 | PHY_RX_OVRD_IN_LO, temp); | ||
367 | |||
368 | usleep_range(2000, 3000); | ||
369 | |||
370 | pcie_phy_read(pp->dbi_base, | ||
371 | PHY_RX_OVRD_IN_LO, &temp); | ||
372 | temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | ||
373 | | PHY_RX_OVRD_IN_LO_RX_PLL_EN); | ||
374 | pcie_phy_write(pp->dbi_base, | ||
375 | PHY_RX_OVRD_IN_LO, temp); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static struct pcie_host_ops imx6_pcie_host_ops = { | ||
381 | .link_up = imx6_pcie_link_up, | ||
382 | .host_init = imx6_pcie_host_init, | ||
383 | }; | ||
384 | |||
385 | static int imx6_add_pcie_port(struct pcie_port *pp, | ||
386 | struct platform_device *pdev) | ||
387 | { | ||
388 | int ret; | ||
389 | |||
390 | pp->irq = platform_get_irq(pdev, 0); | ||
391 | if (!pp->irq) { | ||
392 | dev_err(&pdev->dev, "failed to get irq\n"); | ||
393 | return -ENODEV; | ||
394 | } | ||
395 | |||
396 | pp->root_bus_nr = -1; | ||
397 | pp->ops = &imx6_pcie_host_ops; | ||
398 | |||
399 | spin_lock_init(&pp->conf_lock); | ||
400 | ret = dw_pcie_host_init(pp); | ||
401 | if (ret) { | ||
402 | dev_err(&pdev->dev, "failed to initialize host\n"); | ||
403 | return ret; | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static int __init imx6_pcie_probe(struct platform_device *pdev) | ||
410 | { | ||
411 | struct imx6_pcie *imx6_pcie; | ||
412 | struct pcie_port *pp; | ||
413 | struct device_node *np = pdev->dev.of_node; | ||
414 | struct resource *dbi_base; | ||
415 | int ret; | ||
416 | |||
417 | imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL); | ||
418 | if (!imx6_pcie) | ||
419 | return -ENOMEM; | ||
420 | |||
421 | pp = &imx6_pcie->pp; | ||
422 | pp->dev = &pdev->dev; | ||
423 | |||
424 | /* Added for PCI abort handling */ | ||
425 | hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, | ||
426 | "imprecise external abort"); | ||
427 | |||
428 | dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
429 | if (!dbi_base) { | ||
430 | dev_err(&pdev->dev, "dbi_base memory resource not found\n"); | ||
431 | return -ENODEV; | ||
432 | } | ||
433 | |||
434 | pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base); | ||
435 | if (IS_ERR(pp->dbi_base)) { | ||
436 | ret = PTR_ERR(pp->dbi_base); | ||
437 | goto err; | ||
438 | } | ||
439 | |||
440 | /* Fetch GPIOs */ | ||
441 | imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); | ||
442 | if (!gpio_is_valid(imx6_pcie->reset_gpio)) { | ||
443 | dev_err(&pdev->dev, "no reset-gpio defined\n"); | ||
444 | ret = -ENODEV; | ||
445 | } | ||
446 | ret = devm_gpio_request_one(&pdev->dev, | ||
447 | imx6_pcie->reset_gpio, | ||
448 | GPIOF_OUT_INIT_LOW, | ||
449 | "PCIe reset"); | ||
450 | if (ret) { | ||
451 | dev_err(&pdev->dev, "unable to get reset gpio\n"); | ||
452 | goto err; | ||
453 | } | ||
454 | |||
455 | imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); | ||
456 | if (gpio_is_valid(imx6_pcie->power_on_gpio)) { | ||
457 | ret = devm_gpio_request_one(&pdev->dev, | ||
458 | imx6_pcie->power_on_gpio, | ||
459 | GPIOF_OUT_INIT_LOW, | ||
460 | "PCIe power enable"); | ||
461 | if (ret) { | ||
462 | dev_err(&pdev->dev, "unable to get power-on gpio\n"); | ||
463 | goto err; | ||
464 | } | ||
465 | } | ||
466 | |||
467 | imx6_pcie->wake_up_gpio = of_get_named_gpio(np, "wake-up-gpio", 0); | ||
468 | if (gpio_is_valid(imx6_pcie->wake_up_gpio)) { | ||
469 | ret = devm_gpio_request_one(&pdev->dev, | ||
470 | imx6_pcie->wake_up_gpio, | ||
471 | GPIOF_IN, | ||
472 | "PCIe wake up"); | ||
473 | if (ret) { | ||
474 | dev_err(&pdev->dev, "unable to get wake-up gpio\n"); | ||
475 | goto err; | ||
476 | } | ||
477 | } | ||
478 | |||
479 | imx6_pcie->disable_gpio = of_get_named_gpio(np, "disable-gpio", 0); | ||
480 | if (gpio_is_valid(imx6_pcie->disable_gpio)) { | ||
481 | ret = devm_gpio_request_one(&pdev->dev, | ||
482 | imx6_pcie->disable_gpio, | ||
483 | GPIOF_OUT_INIT_HIGH, | ||
484 | "PCIe disable endpoint"); | ||
485 | if (ret) { | ||
486 | dev_err(&pdev->dev, "unable to get disable-ep gpio\n"); | ||
487 | goto err; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /* Fetch clocks */ | ||
492 | imx6_pcie->lvds_gate = devm_clk_get(&pdev->dev, "lvds_gate"); | ||
493 | if (IS_ERR(imx6_pcie->lvds_gate)) { | ||
494 | dev_err(&pdev->dev, | ||
495 | "lvds_gate clock select missing or invalid\n"); | ||
496 | ret = PTR_ERR(imx6_pcie->lvds_gate); | ||
497 | goto err; | ||
498 | } | ||
499 | |||
500 | imx6_pcie->sata_ref_100m = devm_clk_get(&pdev->dev, "sata_ref_100m"); | ||
501 | if (IS_ERR(imx6_pcie->sata_ref_100m)) { | ||
502 | dev_err(&pdev->dev, | ||
503 | "sata_ref_100m clock source missing or invalid\n"); | ||
504 | ret = PTR_ERR(imx6_pcie->sata_ref_100m); | ||
505 | goto err; | ||
506 | } | ||
507 | |||
508 | imx6_pcie->pcie_ref_125m = devm_clk_get(&pdev->dev, "pcie_ref_125m"); | ||
509 | if (IS_ERR(imx6_pcie->pcie_ref_125m)) { | ||
510 | dev_err(&pdev->dev, | ||
511 | "pcie_ref_125m clock source missing or invalid\n"); | ||
512 | ret = PTR_ERR(imx6_pcie->pcie_ref_125m); | ||
513 | goto err; | ||
514 | } | ||
515 | |||
516 | imx6_pcie->pcie_axi = devm_clk_get(&pdev->dev, "pcie_axi"); | ||
517 | if (IS_ERR(imx6_pcie->pcie_axi)) { | ||
518 | dev_err(&pdev->dev, | ||
519 | "pcie_axi clock source missing or invalid\n"); | ||
520 | ret = PTR_ERR(imx6_pcie->pcie_axi); | ||
521 | goto err; | ||
522 | } | ||
523 | |||
524 | /* Grab GPR config register range */ | ||
525 | imx6_pcie->iomuxc_gpr = | ||
526 | syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); | ||
527 | if (IS_ERR(imx6_pcie->iomuxc_gpr)) { | ||
528 | dev_err(&pdev->dev, "unable to find iomuxc registers\n"); | ||
529 | ret = PTR_ERR(imx6_pcie->iomuxc_gpr); | ||
530 | goto err; | ||
531 | } | ||
532 | |||
533 | ret = imx6_add_pcie_port(pp, pdev); | ||
534 | if (ret < 0) | ||
535 | goto err; | ||
536 | |||
537 | platform_set_drvdata(pdev, imx6_pcie); | ||
538 | return 0; | ||
539 | |||
540 | err: | ||
541 | return ret; | ||
542 | } | ||
543 | |||
544 | static const struct of_device_id imx6_pcie_of_match[] = { | ||
545 | { .compatible = "fsl,imx6q-pcie", }, | ||
546 | {}, | ||
547 | }; | ||
548 | MODULE_DEVICE_TABLE(of, imx6_pcie_of_match); | ||
549 | |||
550 | static struct platform_driver imx6_pcie_driver = { | ||
551 | .driver = { | ||
552 | .name = "imx6q-pcie", | ||
553 | .owner = THIS_MODULE, | ||
554 | .of_match_table = imx6_pcie_of_match, | ||
555 | }, | ||
556 | }; | ||
557 | |||
558 | /* Freescale PCIe driver does not allow module unload */ | ||
559 | |||
560 | static int __init imx6_pcie_init(void) | ||
561 | { | ||
562 | return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); | ||
563 | } | ||
564 | fs_initcall(imx6_pcie_init); | ||
565 | |||
566 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
567 | MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver"); | ||
568 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c new file mode 100644 index 000000000000..cbaa5c4397e3 --- /dev/null +++ b/drivers/pci/host/pci-rcar-gen2.c | |||
@@ -0,0 +1,333 @@ | |||
1 | /* | ||
2 | * pci-rcar-gen2: internal PCI bus support | ||
3 | * | ||
4 | * Copyright (C) 2013 Renesas Solutions Corp. | ||
5 | * Copyright (C) 2013 Cogent Embedded, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/delay.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | /* AHB-PCI Bridge PCI communication registers */ | ||
23 | #define RCAR_AHBPCI_PCICOM_OFFSET 0x800 | ||
24 | |||
25 | #define RCAR_PCIAHB_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x00) | ||
26 | #define RCAR_PCIAHB_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x04) | ||
27 | #define RCAR_PCIAHB_PREFETCH0 0x0 | ||
28 | #define RCAR_PCIAHB_PREFETCH4 0x1 | ||
29 | #define RCAR_PCIAHB_PREFETCH8 0x2 | ||
30 | #define RCAR_PCIAHB_PREFETCH16 0x3 | ||
31 | |||
32 | #define RCAR_AHBPCI_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x10) | ||
33 | #define RCAR_AHBPCI_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x14) | ||
34 | #define RCAR_AHBPCI_WIN_CTR_MEM (3 << 1) | ||
35 | #define RCAR_AHBPCI_WIN_CTR_CFG (5 << 1) | ||
36 | #define RCAR_AHBPCI_WIN1_HOST (1 << 30) | ||
37 | #define RCAR_AHBPCI_WIN1_DEVICE (1 << 31) | ||
38 | |||
39 | #define RCAR_PCI_INT_ENABLE_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x20) | ||
40 | #define RCAR_PCI_INT_STATUS_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x24) | ||
41 | #define RCAR_PCI_INT_A (1 << 16) | ||
42 | #define RCAR_PCI_INT_B (1 << 17) | ||
43 | #define RCAR_PCI_INT_PME (1 << 19) | ||
44 | |||
45 | #define RCAR_AHB_BUS_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x30) | ||
46 | #define RCAR_AHB_BUS_MMODE_HTRANS (1 << 0) | ||
47 | #define RCAR_AHB_BUS_MMODE_BYTE_BURST (1 << 1) | ||
48 | #define RCAR_AHB_BUS_MMODE_WR_INCR (1 << 2) | ||
49 | #define RCAR_AHB_BUS_MMODE_HBUS_REQ (1 << 7) | ||
50 | #define RCAR_AHB_BUS_SMODE_READYCTR (1 << 17) | ||
51 | #define RCAR_AHB_BUS_MODE (RCAR_AHB_BUS_MMODE_HTRANS | \ | ||
52 | RCAR_AHB_BUS_MMODE_BYTE_BURST | \ | ||
53 | RCAR_AHB_BUS_MMODE_WR_INCR | \ | ||
54 | RCAR_AHB_BUS_MMODE_HBUS_REQ | \ | ||
55 | RCAR_AHB_BUS_SMODE_READYCTR) | ||
56 | |||
57 | #define RCAR_USBCTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x34) | ||
58 | #define RCAR_USBCTR_USBH_RST (1 << 0) | ||
59 | #define RCAR_USBCTR_PCICLK_MASK (1 << 1) | ||
60 | #define RCAR_USBCTR_PLL_RST (1 << 2) | ||
61 | #define RCAR_USBCTR_DIRPD (1 << 8) | ||
62 | #define RCAR_USBCTR_PCIAHB_WIN2_EN (1 << 9) | ||
63 | #define RCAR_USBCTR_PCIAHB_WIN1_256M (0 << 10) | ||
64 | #define RCAR_USBCTR_PCIAHB_WIN1_512M (1 << 10) | ||
65 | #define RCAR_USBCTR_PCIAHB_WIN1_1G (2 << 10) | ||
66 | #define RCAR_USBCTR_PCIAHB_WIN1_2G (3 << 10) | ||
67 | #define RCAR_USBCTR_PCIAHB_WIN1_MASK (3 << 10) | ||
68 | |||
69 | #define RCAR_PCI_ARBITER_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x40) | ||
70 | #define RCAR_PCI_ARBITER_PCIREQ0 (1 << 0) | ||
71 | #define RCAR_PCI_ARBITER_PCIREQ1 (1 << 1) | ||
72 | #define RCAR_PCI_ARBITER_PCIBP_MODE (1 << 12) | ||
73 | |||
74 | #define RCAR_PCI_UNIT_REV_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x48) | ||
75 | |||
76 | /* Number of internal PCI controllers */ | ||
77 | #define RCAR_PCI_NR_CONTROLLERS 3 | ||
78 | |||
79 | struct rcar_pci_priv { | ||
80 | void __iomem *reg; | ||
81 | struct resource io_res; | ||
82 | struct resource mem_res; | ||
83 | struct resource *cfg_res; | ||
84 | int irq; | ||
85 | }; | ||
86 | |||
87 | /* PCI configuration space operations */ | ||
88 | static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn, | ||
89 | int where) | ||
90 | { | ||
91 | struct pci_sys_data *sys = bus->sysdata; | ||
92 | struct rcar_pci_priv *priv = sys->private_data; | ||
93 | int slot, val; | ||
94 | |||
95 | if (sys->busnr != bus->number || PCI_FUNC(devfn)) | ||
96 | return NULL; | ||
97 | |||
98 | /* Only one EHCI/OHCI device built-in */ | ||
99 | slot = PCI_SLOT(devfn); | ||
100 | if (slot > 2) | ||
101 | return NULL; | ||
102 | |||
103 | val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG : | ||
104 | RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG; | ||
105 | |||
106 | iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); | ||
107 | return priv->reg + (slot >> 1) * 0x100 + where; | ||
108 | } | ||
109 | |||
110 | static int rcar_pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
111 | int where, int size, u32 *val) | ||
112 | { | ||
113 | void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where); | ||
114 | |||
115 | if (!reg) | ||
116 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
117 | |||
118 | switch (size) { | ||
119 | case 1: | ||
120 | *val = ioread8(reg); | ||
121 | break; | ||
122 | case 2: | ||
123 | *val = ioread16(reg); | ||
124 | break; | ||
125 | default: | ||
126 | *val = ioread32(reg); | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | return PCIBIOS_SUCCESSFUL; | ||
131 | } | ||
132 | |||
133 | static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
134 | int where, int size, u32 val) | ||
135 | { | ||
136 | void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where); | ||
137 | |||
138 | if (!reg) | ||
139 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
140 | |||
141 | switch (size) { | ||
142 | case 1: | ||
143 | iowrite8(val, reg); | ||
144 | break; | ||
145 | case 2: | ||
146 | iowrite16(val, reg); | ||
147 | break; | ||
148 | default: | ||
149 | iowrite32(val, reg); | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | return PCIBIOS_SUCCESSFUL; | ||
154 | } | ||
155 | |||
156 | /* PCI interrupt mapping */ | ||
157 | static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
158 | { | ||
159 | struct pci_sys_data *sys = dev->bus->sysdata; | ||
160 | struct rcar_pci_priv *priv = sys->private_data; | ||
161 | |||
162 | return priv->irq; | ||
163 | } | ||
164 | |||
165 | /* PCI host controller setup */ | ||
166 | static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) | ||
167 | { | ||
168 | struct rcar_pci_priv *priv = sys->private_data; | ||
169 | void __iomem *reg = priv->reg; | ||
170 | u32 val; | ||
171 | |||
172 | val = ioread32(reg + RCAR_PCI_UNIT_REV_REG); | ||
173 | pr_info("PCI: bus%u revision %x\n", sys->busnr, val); | ||
174 | |||
175 | /* Disable Direct Power Down State and assert reset */ | ||
176 | val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD; | ||
177 | val |= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST; | ||
178 | iowrite32(val, reg + RCAR_USBCTR_REG); | ||
179 | udelay(4); | ||
180 | |||
181 | /* De-assert reset and set PCIAHB window1 size to 1GB */ | ||
182 | val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK | | ||
183 | RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST); | ||
184 | iowrite32(val | RCAR_USBCTR_PCIAHB_WIN1_1G, reg + RCAR_USBCTR_REG); | ||
185 | |||
186 | /* Configure AHB master and slave modes */ | ||
187 | iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG); | ||
188 | |||
189 | /* Configure PCI arbiter */ | ||
190 | val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG); | ||
191 | val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 | | ||
192 | RCAR_PCI_ARBITER_PCIBP_MODE; | ||
193 | iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); | ||
194 | |||
195 | /* PCI-AHB mapping: 0x40000000-0x80000000 */ | ||
196 | iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16, | ||
197 | reg + RCAR_PCIAHB_WIN1_CTR_REG); | ||
198 | |||
199 | /* AHB-PCI mapping: OHCI/EHCI registers */ | ||
200 | val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM; | ||
201 | iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG); | ||
202 | |||
203 | /* Enable AHB-PCI bridge PCI configuration access */ | ||
204 | iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, | ||
205 | reg + RCAR_AHBPCI_WIN1_CTR_REG); | ||
206 | /* Set PCI-AHB Window1 address */ | ||
207 | iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH, | ||
208 | reg + PCI_BASE_ADDRESS_1); | ||
209 | /* Set AHB-PCI bridge PCI communication area address */ | ||
210 | val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; | ||
211 | iowrite32(val, reg + PCI_BASE_ADDRESS_0); | ||
212 | |||
213 | val = ioread32(reg + PCI_COMMAND); | ||
214 | val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | | ||
215 | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
216 | iowrite32(val, reg + PCI_COMMAND); | ||
217 | |||
218 | /* Enable PCI interrupts */ | ||
219 | iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, | ||
220 | reg + RCAR_PCI_INT_ENABLE_REG); | ||
221 | |||
222 | /* Add PCI resources */ | ||
223 | pci_add_resource(&sys->resources, &priv->io_res); | ||
224 | pci_add_resource(&sys->resources, &priv->mem_res); | ||
225 | |||
226 | return 1; | ||
227 | } | ||
228 | |||
229 | static struct pci_ops rcar_pci_ops = { | ||
230 | .read = rcar_pci_read_config, | ||
231 | .write = rcar_pci_write_config, | ||
232 | }; | ||
233 | |||
234 | static struct hw_pci rcar_hw_pci __initdata = { | ||
235 | .map_irq = rcar_pci_map_irq, | ||
236 | .ops = &rcar_pci_ops, | ||
237 | .setup = rcar_pci_setup, | ||
238 | }; | ||
239 | |||
240 | static int rcar_pci_count __initdata; | ||
241 | |||
242 | static int __init rcar_pci_add_controller(struct rcar_pci_priv *priv) | ||
243 | { | ||
244 | void **private_data; | ||
245 | int count; | ||
246 | |||
247 | if (rcar_hw_pci.nr_controllers < rcar_pci_count) | ||
248 | goto add_priv; | ||
249 | |||
250 | /* (Re)allocate private data pointer array if needed */ | ||
251 | count = rcar_pci_count + RCAR_PCI_NR_CONTROLLERS; | ||
252 | private_data = kzalloc(count * sizeof(void *), GFP_KERNEL); | ||
253 | if (!private_data) | ||
254 | return -ENOMEM; | ||
255 | |||
256 | rcar_pci_count = count; | ||
257 | if (rcar_hw_pci.private_data) { | ||
258 | memcpy(private_data, rcar_hw_pci.private_data, | ||
259 | rcar_hw_pci.nr_controllers * sizeof(void *)); | ||
260 | kfree(rcar_hw_pci.private_data); | ||
261 | } | ||
262 | |||
263 | rcar_hw_pci.private_data = private_data; | ||
264 | |||
265 | add_priv: | ||
266 | /* Add private data pointer to the array */ | ||
267 | rcar_hw_pci.private_data[rcar_hw_pci.nr_controllers++] = priv; | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int __init rcar_pci_probe(struct platform_device *pdev) | ||
272 | { | ||
273 | struct resource *cfg_res, *mem_res; | ||
274 | struct rcar_pci_priv *priv; | ||
275 | void __iomem *reg; | ||
276 | |||
277 | cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
278 | reg = devm_ioremap_resource(&pdev->dev, cfg_res); | ||
279 | if (!reg) | ||
280 | return -ENODEV; | ||
281 | |||
282 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
283 | if (!mem_res || !mem_res->start) | ||
284 | return -ENODEV; | ||
285 | |||
286 | priv = devm_kzalloc(&pdev->dev, | ||
287 | sizeof(struct rcar_pci_priv), GFP_KERNEL); | ||
288 | if (!priv) | ||
289 | return -ENOMEM; | ||
290 | |||
291 | priv->mem_res = *mem_res; | ||
292 | /* | ||
293 | * The controller does not support/use port I/O, | ||
294 | * so setup a dummy port I/O region here. | ||
295 | */ | ||
296 | priv->io_res.start = priv->mem_res.start; | ||
297 | priv->io_res.end = priv->mem_res.end; | ||
298 | priv->io_res.flags = IORESOURCE_IO; | ||
299 | |||
300 | priv->cfg_res = cfg_res; | ||
301 | |||
302 | priv->irq = platform_get_irq(pdev, 0); | ||
303 | priv->reg = reg; | ||
304 | |||
305 | return rcar_pci_add_controller(priv); | ||
306 | } | ||
307 | |||
308 | static struct platform_driver rcar_pci_driver = { | ||
309 | .driver = { | ||
310 | .name = "pci-rcar-gen2", | ||
311 | }, | ||
312 | }; | ||
313 | |||
314 | static int __init rcar_pci_init(void) | ||
315 | { | ||
316 | int retval; | ||
317 | |||
318 | retval = platform_driver_probe(&rcar_pci_driver, rcar_pci_probe); | ||
319 | if (!retval) | ||
320 | pci_common_init(&rcar_hw_pci); | ||
321 | |||
322 | /* Private data pointer array is not needed any more */ | ||
323 | kfree(rcar_hw_pci.private_data); | ||
324 | rcar_hw_pci.private_data = NULL; | ||
325 | |||
326 | return retval; | ||
327 | } | ||
328 | |||
329 | subsys_initcall(rcar_pci_init); | ||
330 | |||
331 | MODULE_LICENSE("GPL v2"); | ||
332 | MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI"); | ||
333 | MODULE_AUTHOR("Valentine Barshak <valentine.barshak@cogentembedded.com>"); | ||
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 2e9888a0635a..7c4f38dd42ba 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -408,7 +408,7 @@ static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie, | |||
408 | 408 | ||
409 | list_for_each_entry(bus, &pcie->busses, list) | 409 | list_for_each_entry(bus, &pcie->busses, list) |
410 | if (bus->nr == busnr) | 410 | if (bus->nr == busnr) |
411 | return bus->area->addr; | 411 | return (void __iomem *)bus->area->addr; |
412 | 412 | ||
413 | bus = tegra_pcie_bus_alloc(pcie, busnr); | 413 | bus = tegra_pcie_bus_alloc(pcie, busnr); |
414 | if (IS_ERR(bus)) | 414 | if (IS_ERR(bus)) |
@@ -416,7 +416,7 @@ static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie, | |||
416 | 416 | ||
417 | list_add_tail(&bus->list, &pcie->busses); | 417 | list_add_tail(&bus->list, &pcie->busses); |
418 | 418 | ||
419 | return bus->area->addr; | 419 | return (void __iomem *)bus->area->addr; |
420 | } | 420 | } |
421 | 421 | ||
422 | static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, | 422 | static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, |
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index c10e9ac9bbbc..1e1fea4d959b 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -11,8 +11,11 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/irqdomain.h> | ||
14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/msi.h> | ||
16 | #include <linux/of_address.h> | 19 | #include <linux/of_address.h> |
17 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
18 | #include <linux/pci_regs.h> | 21 | #include <linux/pci_regs.h> |
@@ -64,7 +67,7 @@ | |||
64 | 67 | ||
65 | static struct hw_pci dw_pci; | 68 | static struct hw_pci dw_pci; |
66 | 69 | ||
67 | unsigned long global_io_offset; | 70 | static unsigned long global_io_offset; |
68 | 71 | ||
69 | static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) | 72 | static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) |
70 | { | 73 | { |
@@ -115,8 +118,8 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg) | |||
115 | writel(val, pp->dbi_base + reg); | 118 | writel(val, pp->dbi_base + reg); |
116 | } | 119 | } |
117 | 120 | ||
118 | int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | 121 | static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
119 | u32 *val) | 122 | u32 *val) |
120 | { | 123 | { |
121 | int ret; | 124 | int ret; |
122 | 125 | ||
@@ -128,8 +131,8 @@ int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | |||
128 | return ret; | 131 | return ret; |
129 | } | 132 | } |
130 | 133 | ||
131 | int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | 134 | static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, |
132 | u32 val) | 135 | u32 val) |
133 | { | 136 | { |
134 | int ret; | 137 | int ret; |
135 | 138 | ||
@@ -142,6 +145,205 @@ int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | |||
142 | return ret; | 145 | return ret; |
143 | } | 146 | } |
144 | 147 | ||
148 | static struct irq_chip dw_msi_irq_chip = { | ||
149 | .name = "PCI-MSI", | ||
150 | .irq_enable = unmask_msi_irq, | ||
151 | .irq_disable = mask_msi_irq, | ||
152 | .irq_mask = mask_msi_irq, | ||
153 | .irq_unmask = unmask_msi_irq, | ||
154 | }; | ||
155 | |||
156 | /* MSI int handler */ | ||
157 | void dw_handle_msi_irq(struct pcie_port *pp) | ||
158 | { | ||
159 | unsigned long val; | ||
160 | int i, pos, irq; | ||
161 | |||
162 | for (i = 0; i < MAX_MSI_CTRLS; i++) { | ||
163 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, | ||
164 | (u32 *)&val); | ||
165 | if (val) { | ||
166 | pos = 0; | ||
167 | while ((pos = find_next_bit(&val, 32, pos)) != 32) { | ||
168 | irq = irq_find_mapping(pp->irq_domain, | ||
169 | i * 32 + pos); | ||
170 | generic_handle_irq(irq); | ||
171 | pos++; | ||
172 | } | ||
173 | } | ||
174 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, val); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | void dw_pcie_msi_init(struct pcie_port *pp) | ||
179 | { | ||
180 | pp->msi_data = __get_free_pages(GFP_KERNEL, 0); | ||
181 | |||
182 | /* program the msi_data */ | ||
183 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, | ||
184 | virt_to_phys((void *)pp->msi_data)); | ||
185 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0); | ||
186 | } | ||
187 | |||
188 | static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0) | ||
189 | { | ||
190 | int flag = 1; | ||
191 | |||
192 | do { | ||
193 | pos = find_next_zero_bit(pp->msi_irq_in_use, | ||
194 | MAX_MSI_IRQS, pos); | ||
195 | /*if you have reached to the end then get out from here.*/ | ||
196 | if (pos == MAX_MSI_IRQS) | ||
197 | return -ENOSPC; | ||
198 | /* | ||
199 | * Check if this position is at correct offset.nvec is always a | ||
200 | * power of two. pos0 must be nvec bit alligned. | ||
201 | */ | ||
202 | if (pos % msgvec) | ||
203 | pos += msgvec - (pos % msgvec); | ||
204 | else | ||
205 | flag = 0; | ||
206 | } while (flag); | ||
207 | |||
208 | *pos0 = pos; | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) | ||
213 | { | ||
214 | int res, bit, irq, pos0, pos1, i; | ||
215 | u32 val; | ||
216 | struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata); | ||
217 | |||
218 | if (!pp) { | ||
219 | BUG(); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | pos0 = find_first_zero_bit(pp->msi_irq_in_use, | ||
224 | MAX_MSI_IRQS); | ||
225 | if (pos0 % no_irqs) { | ||
226 | if (find_valid_pos0(pp, no_irqs, pos0, &pos0)) | ||
227 | goto no_valid_irq; | ||
228 | } | ||
229 | if (no_irqs > 1) { | ||
230 | pos1 = find_next_bit(pp->msi_irq_in_use, | ||
231 | MAX_MSI_IRQS, pos0); | ||
232 | /* there must be nvec number of consecutive free bits */ | ||
233 | while ((pos1 - pos0) < no_irqs) { | ||
234 | if (find_valid_pos0(pp, no_irqs, pos1, &pos0)) | ||
235 | goto no_valid_irq; | ||
236 | pos1 = find_next_bit(pp->msi_irq_in_use, | ||
237 | MAX_MSI_IRQS, pos0); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | irq = irq_find_mapping(pp->irq_domain, pos0); | ||
242 | if (!irq) | ||
243 | goto no_valid_irq; | ||
244 | |||
245 | i = 0; | ||
246 | while (i < no_irqs) { | ||
247 | set_bit(pos0 + i, pp->msi_irq_in_use); | ||
248 | irq_alloc_descs((irq + i), (irq + i), 1, 0); | ||
249 | irq_set_msi_desc(irq + i, desc); | ||
250 | /*Enable corresponding interrupt in MSI interrupt controller */ | ||
251 | res = ((pos0 + i) / 32) * 12; | ||
252 | bit = (pos0 + i) % 32; | ||
253 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | ||
254 | val |= 1 << bit; | ||
255 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
256 | i++; | ||
257 | } | ||
258 | |||
259 | *pos = pos0; | ||
260 | return irq; | ||
261 | |||
262 | no_valid_irq: | ||
263 | *pos = pos0; | ||
264 | return -ENOSPC; | ||
265 | } | ||
266 | |||
267 | static void clear_irq(unsigned int irq) | ||
268 | { | ||
269 | int res, bit, val, pos; | ||
270 | struct irq_desc *desc; | ||
271 | struct msi_desc *msi; | ||
272 | struct pcie_port *pp; | ||
273 | struct irq_data *data = irq_get_irq_data(irq); | ||
274 | |||
275 | /* get the port structure */ | ||
276 | desc = irq_to_desc(irq); | ||
277 | msi = irq_desc_get_msi_desc(desc); | ||
278 | pp = sys_to_pcie(msi->dev->bus->sysdata); | ||
279 | if (!pp) { | ||
280 | BUG(); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | pos = data->hwirq; | ||
285 | |||
286 | irq_free_desc(irq); | ||
287 | |||
288 | clear_bit(pos, pp->msi_irq_in_use); | ||
289 | |||
290 | /* Disable corresponding interrupt on MSI interrupt controller */ | ||
291 | res = (pos / 32) * 12; | ||
292 | bit = pos % 32; | ||
293 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); | ||
294 | val &= ~(1 << bit); | ||
295 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); | ||
296 | } | ||
297 | |||
298 | static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, | ||
299 | struct msi_desc *desc) | ||
300 | { | ||
301 | int irq, pos, msgvec; | ||
302 | u16 msg_ctr; | ||
303 | struct msi_msg msg; | ||
304 | struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata); | ||
305 | |||
306 | if (!pp) { | ||
307 | BUG(); | ||
308 | return -EINVAL; | ||
309 | } | ||
310 | |||
311 | pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS, | ||
312 | &msg_ctr); | ||
313 | msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4; | ||
314 | if (msgvec == 0) | ||
315 | msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1; | ||
316 | if (msgvec > 5) | ||
317 | msgvec = 0; | ||
318 | |||
319 | irq = assign_irq((1 << msgvec), desc, &pos); | ||
320 | if (irq < 0) | ||
321 | return irq; | ||
322 | |||
323 | msg_ctr &= ~PCI_MSI_FLAGS_QSIZE; | ||
324 | msg_ctr |= msgvec << 4; | ||
325 | pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS, | ||
326 | msg_ctr); | ||
327 | desc->msi_attrib.multiple = msgvec; | ||
328 | |||
329 | msg.address_lo = virt_to_phys((void *)pp->msi_data); | ||
330 | msg.address_hi = 0x0; | ||
331 | msg.data = pos; | ||
332 | write_msi_msg(irq, &msg); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) | ||
338 | { | ||
339 | clear_irq(irq); | ||
340 | } | ||
341 | |||
342 | static struct msi_chip dw_pcie_msi_chip = { | ||
343 | .setup_irq = dw_msi_setup_irq, | ||
344 | .teardown_irq = dw_msi_teardown_irq, | ||
345 | }; | ||
346 | |||
145 | int dw_pcie_link_up(struct pcie_port *pp) | 347 | int dw_pcie_link_up(struct pcie_port *pp) |
146 | { | 348 | { |
147 | if (pp->ops->link_up) | 349 | if (pp->ops->link_up) |
@@ -150,12 +352,27 @@ int dw_pcie_link_up(struct pcie_port *pp) | |||
150 | return 0; | 352 | return 0; |
151 | } | 353 | } |
152 | 354 | ||
355 | static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, | ||
356 | irq_hw_number_t hwirq) | ||
357 | { | ||
358 | irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq); | ||
359 | irq_set_chip_data(irq, domain->host_data); | ||
360 | set_irq_flags(irq, IRQF_VALID); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static const struct irq_domain_ops msi_domain_ops = { | ||
366 | .map = dw_pcie_msi_map, | ||
367 | }; | ||
368 | |||
153 | int __init dw_pcie_host_init(struct pcie_port *pp) | 369 | int __init dw_pcie_host_init(struct pcie_port *pp) |
154 | { | 370 | { |
155 | struct device_node *np = pp->dev->of_node; | 371 | struct device_node *np = pp->dev->of_node; |
156 | struct of_pci_range range; | 372 | struct of_pci_range range; |
157 | struct of_pci_range_parser parser; | 373 | struct of_pci_range_parser parser; |
158 | u32 val; | 374 | u32 val; |
375 | int i; | ||
159 | 376 | ||
160 | if (of_pci_range_parser_init(&parser, np)) { | 377 | if (of_pci_range_parser_init(&parser, np)) { |
161 | dev_err(pp->dev, "missing ranges property\n"); | 378 | dev_err(pp->dev, "missing ranges property\n"); |
@@ -223,6 +440,19 @@ int __init dw_pcie_host_init(struct pcie_port *pp) | |||
223 | return -EINVAL; | 440 | return -EINVAL; |
224 | } | 441 | } |
225 | 442 | ||
443 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
444 | pp->irq_domain = irq_domain_add_linear(pp->dev->of_node, | ||
445 | MAX_MSI_IRQS, &msi_domain_ops, | ||
446 | &dw_pcie_msi_chip); | ||
447 | if (!pp->irq_domain) { | ||
448 | dev_err(pp->dev, "irq domain init failed\n"); | ||
449 | return -ENXIO; | ||
450 | } | ||
451 | |||
452 | for (i = 0; i < MAX_MSI_IRQS; i++) | ||
453 | irq_create_mapping(pp->irq_domain, i); | ||
454 | } | ||
455 | |||
226 | if (pp->ops->host_init) | 456 | if (pp->ops->host_init) |
227 | pp->ops->host_init(pp); | 457 | pp->ops->host_init(pp); |
228 | 458 | ||
@@ -438,7 +668,7 @@ static struct pci_ops dw_pcie_ops = { | |||
438 | .write = dw_pcie_wr_conf, | 668 | .write = dw_pcie_wr_conf, |
439 | }; | 669 | }; |
440 | 670 | ||
441 | int dw_pcie_setup(int nr, struct pci_sys_data *sys) | 671 | static int dw_pcie_setup(int nr, struct pci_sys_data *sys) |
442 | { | 672 | { |
443 | struct pcie_port *pp; | 673 | struct pcie_port *pp; |
444 | 674 | ||
@@ -461,7 +691,7 @@ int dw_pcie_setup(int nr, struct pci_sys_data *sys) | |||
461 | return 1; | 691 | return 1; |
462 | } | 692 | } |
463 | 693 | ||
464 | struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) | 694 | static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) |
465 | { | 695 | { |
466 | struct pci_bus *bus; | 696 | struct pci_bus *bus; |
467 | struct pcie_port *pp = sys_to_pcie(sys); | 697 | struct pcie_port *pp = sys_to_pcie(sys); |
@@ -478,17 +708,28 @@ struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) | |||
478 | return bus; | 708 | return bus; |
479 | } | 709 | } |
480 | 710 | ||
481 | int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 711 | static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
482 | { | 712 | { |
483 | struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); | 713 | struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); |
484 | 714 | ||
485 | return pp->irq; | 715 | return pp->irq; |
486 | } | 716 | } |
487 | 717 | ||
718 | static void dw_pcie_add_bus(struct pci_bus *bus) | ||
719 | { | ||
720 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
721 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); | ||
722 | |||
723 | dw_pcie_msi_chip.dev = pp->dev; | ||
724 | bus->msi = &dw_pcie_msi_chip; | ||
725 | } | ||
726 | } | ||
727 | |||
488 | static struct hw_pci dw_pci = { | 728 | static struct hw_pci dw_pci = { |
489 | .setup = dw_pcie_setup, | 729 | .setup = dw_pcie_setup, |
490 | .scan = dw_pcie_scan_bus, | 730 | .scan = dw_pcie_scan_bus, |
491 | .map_irq = dw_pcie_map_irq, | 731 | .map_irq = dw_pcie_map_irq, |
732 | .add_bus = dw_pcie_add_bus, | ||
492 | }; | 733 | }; |
493 | 734 | ||
494 | void dw_pcie_setup_rc(struct pcie_port *pp) | 735 | void dw_pcie_setup_rc(struct pcie_port *pp) |
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index 133820f1da97..c15379be2372 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h | |||
@@ -11,6 +11,9 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef _PCIE_DESIGNWARE_H | ||
15 | #define _PCIE_DESIGNWARE_H | ||
16 | |||
14 | struct pcie_port_info { | 17 | struct pcie_port_info { |
15 | u32 cfg0_size; | 18 | u32 cfg0_size; |
16 | u32 cfg1_size; | 19 | u32 cfg1_size; |
@@ -20,6 +23,14 @@ struct pcie_port_info { | |||
20 | phys_addr_t mem_bus_addr; | 23 | phys_addr_t mem_bus_addr; |
21 | }; | 24 | }; |
22 | 25 | ||
26 | /* | ||
27 | * Maximum number of MSI IRQs can be 256 per controller. But keep | ||
28 | * it 32 as of now. Probably we will never need more than 32. If needed, | ||
29 | * then increment it in multiple of 32. | ||
30 | */ | ||
31 | #define MAX_MSI_IRQS 32 | ||
32 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) | ||
33 | |||
23 | struct pcie_port { | 34 | struct pcie_port { |
24 | struct device *dev; | 35 | struct device *dev; |
25 | u8 root_bus_nr; | 36 | u8 root_bus_nr; |
@@ -38,6 +49,10 @@ struct pcie_port { | |||
38 | int irq; | 49 | int irq; |
39 | u32 lanes; | 50 | u32 lanes; |
40 | struct pcie_host_ops *ops; | 51 | struct pcie_host_ops *ops; |
52 | int msi_irq; | ||
53 | struct irq_domain *irq_domain; | ||
54 | unsigned long msi_data; | ||
55 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); | ||
41 | }; | 56 | }; |
42 | 57 | ||
43 | struct pcie_host_ops { | 58 | struct pcie_host_ops { |
@@ -51,15 +66,12 @@ struct pcie_host_ops { | |||
51 | void (*host_init)(struct pcie_port *pp); | 66 | void (*host_init)(struct pcie_port *pp); |
52 | }; | 67 | }; |
53 | 68 | ||
54 | extern unsigned long global_io_offset; | ||
55 | |||
56 | int cfg_read(void __iomem *addr, int where, int size, u32 *val); | 69 | int cfg_read(void __iomem *addr, int where, int size, u32 *val); |
57 | int cfg_write(void __iomem *addr, int where, int size, u32 val); | 70 | int cfg_write(void __iomem *addr, int where, int size, u32 val); |
58 | int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, u32 val); | 71 | void dw_handle_msi_irq(struct pcie_port *pp); |
59 | int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val); | 72 | void dw_pcie_msi_init(struct pcie_port *pp); |
60 | int dw_pcie_link_up(struct pcie_port *pp); | 73 | int dw_pcie_link_up(struct pcie_port *pp); |
61 | void dw_pcie_setup_rc(struct pcie_port *pp); | 74 | void dw_pcie_setup_rc(struct pcie_port *pp); |
62 | int dw_pcie_host_init(struct pcie_port *pp); | 75 | int dw_pcie_host_init(struct pcie_port *pp); |
63 | int dw_pcie_setup(int nr, struct pci_sys_data *sys); | 76 | |
64 | struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys); | 77 | #endif /* _PCIE_DESIGNWARE_H */ |
65 | int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); | ||
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 2a47e82821da..f8140164ec0b 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -338,7 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) | |||
338 | acpi_handle chandle, handle; | 338 | acpi_handle chandle, handle; |
339 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 339 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
340 | 340 | ||
341 | flags &= OSC_SHPC_NATIVE_HP_CONTROL; | 341 | flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL; |
342 | if (!flags) { | 342 | if (!flags) { |
343 | err("Invalid flags %u specified!\n", flags); | 343 | err("Invalid flags %u specified!\n", flags); |
344 | return -EINVAL; | 344 | return -EINVAL; |
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index e260f207a90e..d876e4b3c6a9 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -191,7 +191,7 @@ static inline const char *slot_name(struct slot *slot) | |||
191 | #include <linux/pci-acpi.h> | 191 | #include <linux/pci-acpi.h> |
192 | static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev) | 192 | static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev) |
193 | { | 193 | { |
194 | u32 flags = OSC_SHPC_NATIVE_HP_CONTROL; | 194 | u32 flags = OSC_PCI_SHPC_NATIVE_HP_CONTROL; |
195 | return acpi_get_hp_hw_control_from_firmware(dev, flags); | 195 | return acpi_get_hp_hw_control_from_firmware(dev, flags); |
196 | } | 196 | } |
197 | #else | 197 | #else |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b60fe6737f78..840fdc5ba0d8 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -135,6 +135,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
135 | return retval; | 135 | return retval; |
136 | return count; | 136 | return count; |
137 | } | 137 | } |
138 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | ||
138 | 139 | ||
139 | /** | 140 | /** |
140 | * store_remove_id - remove a PCI device ID from this driver | 141 | * store_remove_id - remove a PCI device ID from this driver |
@@ -180,12 +181,14 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) | |||
180 | return retval; | 181 | return retval; |
181 | return count; | 182 | return count; |
182 | } | 183 | } |
184 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | ||
183 | 185 | ||
184 | static struct driver_attribute pci_drv_attrs[] = { | 186 | static struct attribute *pci_drv_attrs[] = { |
185 | __ATTR(new_id, S_IWUSR, NULL, store_new_id), | 187 | &driver_attr_new_id.attr, |
186 | __ATTR(remove_id, S_IWUSR, NULL, store_remove_id), | 188 | &driver_attr_remove_id.attr, |
187 | __ATTR_NULL, | 189 | NULL, |
188 | }; | 190 | }; |
191 | ATTRIBUTE_GROUPS(pci_drv); | ||
189 | 192 | ||
190 | /** | 193 | /** |
191 | * pci_match_id - See if a pci device matches a given pci_id table | 194 | * pci_match_id - See if a pci device matches a given pci_id table |
@@ -1307,9 +1310,9 @@ struct bus_type pci_bus_type = { | |||
1307 | .probe = pci_device_probe, | 1310 | .probe = pci_device_probe, |
1308 | .remove = pci_device_remove, | 1311 | .remove = pci_device_remove, |
1309 | .shutdown = pci_device_shutdown, | 1312 | .shutdown = pci_device_shutdown, |
1310 | .dev_attrs = pci_dev_attrs, | 1313 | .dev_groups = pci_dev_groups, |
1311 | .bus_attrs = pci_bus_attrs, | 1314 | .bus_groups = pci_bus_groups, |
1312 | .drv_attrs = pci_drv_attrs, | 1315 | .drv_groups = pci_drv_groups, |
1313 | .pm = PCI_PM_OPS_PTR, | 1316 | .pm = PCI_PM_OPS_PTR, |
1314 | }; | 1317 | }; |
1315 | 1318 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index d9252dd89ea9..2aaa83c85a4e 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -42,7 +42,8 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ | |||
42 | \ | 42 | \ |
43 | pdev = to_pci_dev (dev); \ | 43 | pdev = to_pci_dev (dev); \ |
44 | return sprintf (buf, format_string, pdev->field); \ | 44 | return sprintf (buf, format_string, pdev->field); \ |
45 | } | 45 | } \ |
46 | static DEVICE_ATTR_RO(field) | ||
46 | 47 | ||
47 | pci_config_attr(vendor, "0x%04x\n"); | 48 | pci_config_attr(vendor, "0x%04x\n"); |
48 | pci_config_attr(device, "0x%04x\n"); | 49 | pci_config_attr(device, "0x%04x\n"); |
@@ -73,6 +74,7 @@ static ssize_t broken_parity_status_store(struct device *dev, | |||
73 | 74 | ||
74 | return count; | 75 | return count; |
75 | } | 76 | } |
77 | static DEVICE_ATTR_RW(broken_parity_status); | ||
76 | 78 | ||
77 | static ssize_t pci_dev_show_local_cpu(struct device *dev, | 79 | static ssize_t pci_dev_show_local_cpu(struct device *dev, |
78 | int type, | 80 | int type, |
@@ -102,12 +104,14 @@ static ssize_t local_cpus_show(struct device *dev, | |||
102 | { | 104 | { |
103 | return pci_dev_show_local_cpu(dev, 1, attr, buf); | 105 | return pci_dev_show_local_cpu(dev, 1, attr, buf); |
104 | } | 106 | } |
107 | static DEVICE_ATTR_RO(local_cpus); | ||
105 | 108 | ||
106 | static ssize_t local_cpulist_show(struct device *dev, | 109 | static ssize_t local_cpulist_show(struct device *dev, |
107 | struct device_attribute *attr, char *buf) | 110 | struct device_attribute *attr, char *buf) |
108 | { | 111 | { |
109 | return pci_dev_show_local_cpu(dev, 0, attr, buf); | 112 | return pci_dev_show_local_cpu(dev, 0, attr, buf); |
110 | } | 113 | } |
114 | static DEVICE_ATTR_RO(local_cpulist); | ||
111 | 115 | ||
112 | /* | 116 | /* |
113 | * PCI Bus Class Devices | 117 | * PCI Bus Class Devices |
@@ -168,6 +172,7 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf) | |||
168 | } | 172 | } |
169 | return (str - buf); | 173 | return (str - buf); |
170 | } | 174 | } |
175 | static DEVICE_ATTR_RO(resource); | ||
171 | 176 | ||
172 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) | 177 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) |
173 | { | 178 | { |
@@ -179,10 +184,11 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | |||
179 | (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), | 184 | (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), |
180 | (u8)(pci_dev->class)); | 185 | (u8)(pci_dev->class)); |
181 | } | 186 | } |
187 | static DEVICE_ATTR_RO(modalias); | ||
182 | 188 | ||
183 | static ssize_t is_enabled_store(struct device *dev, | 189 | static ssize_t enabled_store(struct device *dev, |
184 | struct device_attribute *attr, const char *buf, | 190 | struct device_attribute *attr, const char *buf, |
185 | size_t count) | 191 | size_t count) |
186 | { | 192 | { |
187 | struct pci_dev *pdev = to_pci_dev(dev); | 193 | struct pci_dev *pdev = to_pci_dev(dev); |
188 | unsigned long val; | 194 | unsigned long val; |
@@ -206,14 +212,15 @@ static ssize_t is_enabled_store(struct device *dev, | |||
206 | return result < 0 ? result : count; | 212 | return result < 0 ? result : count; |
207 | } | 213 | } |
208 | 214 | ||
209 | static ssize_t is_enabled_show(struct device *dev, | 215 | static ssize_t enabled_show(struct device *dev, |
210 | struct device_attribute *attr, char *buf) | 216 | struct device_attribute *attr, char *buf) |
211 | { | 217 | { |
212 | struct pci_dev *pdev; | 218 | struct pci_dev *pdev; |
213 | 219 | ||
214 | pdev = to_pci_dev (dev); | 220 | pdev = to_pci_dev (dev); |
215 | return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt)); | 221 | return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt)); |
216 | } | 222 | } |
223 | static DEVICE_ATTR_RW(enabled); | ||
217 | 224 | ||
218 | #ifdef CONFIG_NUMA | 225 | #ifdef CONFIG_NUMA |
219 | static ssize_t | 226 | static ssize_t |
@@ -221,6 +228,7 @@ numa_node_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
221 | { | 228 | { |
222 | return sprintf (buf, "%d\n", dev->numa_node); | 229 | return sprintf (buf, "%d\n", dev->numa_node); |
223 | } | 230 | } |
231 | static DEVICE_ATTR_RO(numa_node); | ||
224 | #endif | 232 | #endif |
225 | 233 | ||
226 | static ssize_t | 234 | static ssize_t |
@@ -230,6 +238,7 @@ dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
230 | 238 | ||
231 | return sprintf (buf, "%d\n", fls64(pdev->dma_mask)); | 239 | return sprintf (buf, "%d\n", fls64(pdev->dma_mask)); |
232 | } | 240 | } |
241 | static DEVICE_ATTR_RO(dma_mask_bits); | ||
233 | 242 | ||
234 | static ssize_t | 243 | static ssize_t |
235 | consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr, | 244 | consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr, |
@@ -237,6 +246,7 @@ consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr, | |||
237 | { | 246 | { |
238 | return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask)); | 247 | return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask)); |
239 | } | 248 | } |
249 | static DEVICE_ATTR_RO(consistent_dma_mask_bits); | ||
240 | 250 | ||
241 | static ssize_t | 251 | static ssize_t |
242 | msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf) | 252 | msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -281,6 +291,7 @@ msi_bus_store(struct device *dev, struct device_attribute *attr, | |||
281 | 291 | ||
282 | return count; | 292 | return count; |
283 | } | 293 | } |
294 | static DEVICE_ATTR_RW(msi_bus); | ||
284 | 295 | ||
285 | static DEFINE_MUTEX(pci_remove_rescan_mutex); | 296 | static DEFINE_MUTEX(pci_remove_rescan_mutex); |
286 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | 297 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, |
@@ -300,10 +311,20 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | |||
300 | } | 311 | } |
301 | return count; | 312 | return count; |
302 | } | 313 | } |
314 | static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store); | ||
315 | |||
316 | static struct attribute *pci_bus_attrs[] = { | ||
317 | &bus_attr_rescan.attr, | ||
318 | NULL, | ||
319 | }; | ||
320 | |||
321 | static const struct attribute_group pci_bus_group = { | ||
322 | .attrs = pci_bus_attrs, | ||
323 | }; | ||
303 | 324 | ||
304 | struct bus_attribute pci_bus_attrs[] = { | 325 | const struct attribute_group *pci_bus_groups[] = { |
305 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store), | 326 | &pci_bus_group, |
306 | __ATTR_NULL | 327 | NULL, |
307 | }; | 328 | }; |
308 | 329 | ||
309 | static ssize_t | 330 | static ssize_t |
@@ -323,8 +344,9 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr, | |||
323 | } | 344 | } |
324 | return count; | 345 | return count; |
325 | } | 346 | } |
326 | struct device_attribute dev_rescan_attr = __ATTR(rescan, (S_IWUSR|S_IWGRP), | 347 | static struct device_attribute dev_rescan_attr = __ATTR(rescan, |
327 | NULL, dev_rescan_store); | 348 | (S_IWUSR|S_IWGRP), |
349 | NULL, dev_rescan_store); | ||
328 | 350 | ||
329 | static void remove_callback(struct device *dev) | 351 | static void remove_callback(struct device *dev) |
330 | { | 352 | { |
@@ -354,8 +376,9 @@ remove_store(struct device *dev, struct device_attribute *dummy, | |||
354 | count = ret; | 376 | count = ret; |
355 | return count; | 377 | return count; |
356 | } | 378 | } |
357 | struct device_attribute dev_remove_attr = __ATTR(remove, (S_IWUSR|S_IWGRP), | 379 | static struct device_attribute dev_remove_attr = __ATTR(remove, |
358 | NULL, remove_store); | 380 | (S_IWUSR|S_IWGRP), |
381 | NULL, remove_store); | ||
359 | 382 | ||
360 | static ssize_t | 383 | static ssize_t |
361 | dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, | 384 | dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, |
@@ -402,6 +425,7 @@ static ssize_t d3cold_allowed_show(struct device *dev, | |||
402 | struct pci_dev *pdev = to_pci_dev(dev); | 425 | struct pci_dev *pdev = to_pci_dev(dev); |
403 | return sprintf (buf, "%u\n", pdev->d3cold_allowed); | 426 | return sprintf (buf, "%u\n", pdev->d3cold_allowed); |
404 | } | 427 | } |
428 | static DEVICE_ATTR_RW(d3cold_allowed); | ||
405 | #endif | 429 | #endif |
406 | 430 | ||
407 | #ifdef CONFIG_PCI_IOV | 431 | #ifdef CONFIG_PCI_IOV |
@@ -487,30 +511,38 @@ static struct device_attribute sriov_numvfs_attr = | |||
487 | sriov_numvfs_show, sriov_numvfs_store); | 511 | sriov_numvfs_show, sriov_numvfs_store); |
488 | #endif /* CONFIG_PCI_IOV */ | 512 | #endif /* CONFIG_PCI_IOV */ |
489 | 513 | ||
490 | struct device_attribute pci_dev_attrs[] = { | 514 | static struct attribute *pci_dev_attrs[] = { |
491 | __ATTR_RO(resource), | 515 | &dev_attr_resource.attr, |
492 | __ATTR_RO(vendor), | 516 | &dev_attr_vendor.attr, |
493 | __ATTR_RO(device), | 517 | &dev_attr_device.attr, |
494 | __ATTR_RO(subsystem_vendor), | 518 | &dev_attr_subsystem_vendor.attr, |
495 | __ATTR_RO(subsystem_device), | 519 | &dev_attr_subsystem_device.attr, |
496 | __ATTR_RO(class), | 520 | &dev_attr_class.attr, |
497 | __ATTR_RO(irq), | 521 | &dev_attr_irq.attr, |
498 | __ATTR_RO(local_cpus), | 522 | &dev_attr_local_cpus.attr, |
499 | __ATTR_RO(local_cpulist), | 523 | &dev_attr_local_cpulist.attr, |
500 | __ATTR_RO(modalias), | 524 | &dev_attr_modalias.attr, |
501 | #ifdef CONFIG_NUMA | 525 | #ifdef CONFIG_NUMA |
502 | __ATTR_RO(numa_node), | 526 | &dev_attr_numa_node.attr, |
503 | #endif | 527 | #endif |
504 | __ATTR_RO(dma_mask_bits), | 528 | &dev_attr_dma_mask_bits.attr, |
505 | __ATTR_RO(consistent_dma_mask_bits), | 529 | &dev_attr_consistent_dma_mask_bits.attr, |
506 | __ATTR(enable, 0600, is_enabled_show, is_enabled_store), | 530 | &dev_attr_enabled.attr, |
507 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), | 531 | &dev_attr_broken_parity_status.attr, |
508 | broken_parity_status_show,broken_parity_status_store), | 532 | &dev_attr_msi_bus.attr, |
509 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), | ||
510 | #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) | 533 | #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) |
511 | __ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store), | 534 | &dev_attr_d3cold_allowed.attr, |
512 | #endif | 535 | #endif |
513 | __ATTR_NULL, | 536 | NULL, |
537 | }; | ||
538 | |||
539 | static const struct attribute_group pci_dev_group = { | ||
540 | .attrs = pci_dev_attrs, | ||
541 | }; | ||
542 | |||
543 | const struct attribute_group *pci_dev_groups[] = { | ||
544 | &pci_dev_group, | ||
545 | NULL, | ||
514 | }; | 546 | }; |
515 | 547 | ||
516 | static struct attribute *pcibus_attrs[] = { | 548 | static struct attribute *pcibus_attrs[] = { |
@@ -542,7 +574,7 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
542 | !!(pdev->resource[PCI_ROM_RESOURCE].flags & | 574 | !!(pdev->resource[PCI_ROM_RESOURCE].flags & |
543 | IORESOURCE_ROM_SHADOW)); | 575 | IORESOURCE_ROM_SHADOW)); |
544 | } | 576 | } |
545 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); | 577 | static struct device_attribute vga_attr = __ATTR_RO(boot_vga); |
546 | 578 | ||
547 | static ssize_t | 579 | static ssize_t |
548 | pci_read_config(struct file *filp, struct kobject *kobj, | 580 | pci_read_config(struct file *filp, struct kobject *kobj, |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 36cc8d5ae8b2..457f801fc49d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -3973,6 +3973,7 @@ int pcie_get_mps(struct pci_dev *dev) | |||
3973 | 3973 | ||
3974 | return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); | 3974 | return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); |
3975 | } | 3975 | } |
3976 | EXPORT_SYMBOL(pcie_get_mps); | ||
3976 | 3977 | ||
3977 | /** | 3978 | /** |
3978 | * pcie_set_mps - set PCI Express maximum payload size | 3979 | * pcie_set_mps - set PCI Express maximum payload size |
@@ -3997,6 +3998,7 @@ int pcie_set_mps(struct pci_dev *dev, int mps) | |||
3997 | return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, | 3998 | return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL, |
3998 | PCI_EXP_DEVCTL_PAYLOAD, v); | 3999 | PCI_EXP_DEVCTL_PAYLOAD, v); |
3999 | } | 4000 | } |
4001 | EXPORT_SYMBOL(pcie_set_mps); | ||
4000 | 4002 | ||
4001 | /** | 4003 | /** |
4002 | * pcie_get_minimum_link - determine minimum link settings of a PCI device | 4004 | * pcie_get_minimum_link - determine minimum link settings of a PCI device |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 8a00c063d7bc..9c91ecc1301b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -153,10 +153,10 @@ static inline int pci_no_d1d2(struct pci_dev *dev) | |||
153 | return (dev->no_d1d2 || parent_dstates); | 153 | return (dev->no_d1d2 || parent_dstates); |
154 | 154 | ||
155 | } | 155 | } |
156 | extern struct device_attribute pci_dev_attrs[]; | 156 | extern const struct attribute_group *pci_dev_groups[]; |
157 | extern const struct attribute_group *pcibus_groups[]; | 157 | extern const struct attribute_group *pcibus_groups[]; |
158 | extern struct device_type pci_dev_type; | 158 | extern struct device_type pci_dev_type; |
159 | extern struct bus_attribute pci_bus_attrs[]; | 159 | extern const struct attribute_group *pci_bus_groups[]; |
160 | 160 | ||
161 | 161 | ||
162 | /** | 162 | /** |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2372babe2fc5..5e14f5a51357 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -641,8 +641,7 @@ static void pci_set_bus_speed(struct pci_bus *bus) | |||
641 | return; | 641 | return; |
642 | } | 642 | } |
643 | 643 | ||
644 | pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); | 644 | if (pci_is_pcie(bridge)) { |
645 | if (pos) { | ||
646 | u32 linkcap; | 645 | u32 linkcap; |
647 | u16 linksta; | 646 | u16 linksta; |
648 | 647 | ||