diff options
60 files changed, 2479 insertions, 736 deletions
diff --git a/Documentation/PCI/pcieaer-howto.txt b/Documentation/PCI/pcieaer-howto.txt index b4987c0bcb20..ea8cafba255c 100644 --- a/Documentation/PCI/pcieaer-howto.txt +++ b/Documentation/PCI/pcieaer-howto.txt | |||
@@ -49,25 +49,17 @@ depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and | |||
49 | CONFIG_PCIEAER = y. | 49 | CONFIG_PCIEAER = y. |
50 | 50 | ||
51 | 2.2 Load PCI Express AER Root Driver | 51 | 2.2 Load PCI Express AER Root Driver |
52 | There is a case where a system has AER support in BIOS. Enabling the AER | 52 | |
53 | Root driver and having AER support in BIOS may result unpredictable | 53 | Some systems have AER support in firmware. Enabling Linux AER support at |
54 | behavior. To avoid this conflict, a successful load of the AER Root driver | 54 | the same time the firmware handles AER may result in unpredictable |
55 | requires ACPI _OSC support in the BIOS to allow the AER Root driver to | 55 | behavior. Therefore, Linux does not handle AER events unless the firmware |
56 | request for native control of AER. See the PCI FW 3.0 Specification for | 56 | grants AER control to the OS via the ACPI _OSC method. See the PCI FW 3.0 |
57 | details regarding OSC usage. Currently, lots of firmwares don't provide | 57 | Specification for details regarding _OSC usage. |
58 | _OSC support while they use PCI Express. To support such firmwares, | ||
59 | forceload, a parameter of type bool, could enable AER to continue to | ||
60 | be initiated although firmwares have no _OSC support. To enable the | ||
61 | walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line | ||
62 | when booting kernel. Note that forceload=n by default. | ||
63 | |||
64 | nosourceid, another parameter of type bool, can be used when broken | ||
65 | hardware (mostly chipsets) has root ports that cannot obtain the reporting | ||
66 | source ID. nosourceid=n by default. | ||
67 | 58 | ||
68 | 2.3 AER error output | 59 | 2.3 AER error output |
69 | When a PCI-E AER error is captured, an error message will be outputted to | 60 | |
70 | console. If it's a correctable error, it is outputted as a warning. | 61 | When a PCIe AER error is captured, an error message will be output to |
62 | console. If it's a correctable error, it is output as a warning. | ||
71 | Otherwise, it is printed as an error. So users could choose different | 63 | Otherwise, it is printed as an error. So users could choose different |
72 | log level to filter out correctable error messages. | 64 | log level to filter out correctable error messages. |
73 | 65 | ||
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt index 6c5322c55411..1392c705ceca 100644 --- a/Documentation/devicetree/bindings/pci/designware-pcie.txt +++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt | |||
@@ -17,6 +17,8 @@ Required properties: | |||
17 | - num-lanes: number of lanes to use | 17 | - num-lanes: number of lanes to use |
18 | 18 | ||
19 | Optional properties: | 19 | Optional properties: |
20 | - num-viewport: number of view ports configured in hardware. If a platform | ||
21 | does not specify it, the driver assumes 2. | ||
20 | - num-lanes: number of lanes to use (this property should be specified unless | 22 | - num-lanes: number of lanes to use (this property should be specified unless |
21 | the link is brought already up in BIOS) | 23 | the link is brought already up in BIOS) |
22 | - reset-gpio: gpio pin number of power good signal | 24 | - reset-gpio: gpio pin number of power good signal |
@@ -44,4 +46,5 @@ Example configuration: | |||
44 | interrupts = <25>, <24>; | 46 | interrupts = <25>, <24>; |
45 | #interrupt-cells = <1>; | 47 | #interrupt-cells = <1>; |
46 | num-lanes = <1>; | 48 | num-lanes = <1>; |
49 | num-viewport = <3>; | ||
47 | }; | 50 | }; |
diff --git a/Documentation/devicetree/bindings/pci/rockchip-pcie.txt b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt new file mode 100644 index 000000000000..ba67b39939c1 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/rockchip-pcie.txt | |||
@@ -0,0 +1,106 @@ | |||
1 | * Rockchip AXI PCIe Root Port Bridge DT description | ||
2 | |||
3 | Required properties: | ||
4 | - #address-cells: Address representation for root ports, set to <3> | ||
5 | - #size-cells: Size representation for root ports, set to <2> | ||
6 | - #interrupt-cells: specifies the number of cells needed to encode an | ||
7 | interrupt source. The value must be 1. | ||
8 | - compatible: Should contain "rockchip,rk3399-pcie" | ||
9 | - reg: Two register ranges as listed in the reg-names property | ||
10 | - reg-names: Must include the following names | ||
11 | - "axi-base" | ||
12 | - "apb-base" | ||
13 | - clocks: Must contain an entry for each entry in clock-names. | ||
14 | See ../clocks/clock-bindings.txt for details. | ||
15 | - clock-names: Must include the following entries: | ||
16 | - "aclk" | ||
17 | - "aclk-perf" | ||
18 | - "hclk" | ||
19 | - "pm" | ||
20 | - msi-map: Maps a Requester ID to an MSI controller and associated | ||
21 | msi-specifier data. See ./pci-msi.txt | ||
22 | - phys: From PHY bindings: Phandle for the Generic PHY for PCIe. | ||
23 | - phy-names: MUST be "pcie-phy". | ||
24 | - interrupts: Three interrupt entries must be specified. | ||
25 | - interrupt-names: Must include the following names | ||
26 | - "sys" | ||
27 | - "legacy" | ||
28 | - "client" | ||
29 | - resets: Must contain five entries for each entry in reset-names. | ||
30 | See ../reset/reset.txt for details. | ||
31 | - reset-names: Must include the following names | ||
32 | - "core" | ||
33 | - "mgmt" | ||
34 | - "mgmt-sticky" | ||
35 | - "pipe" | ||
36 | - pinctrl-names : The pin control state names | ||
37 | - pinctrl-0: The "default" pinctrl state | ||
38 | - #interrupt-cells: specifies the number of cells needed to encode an | ||
39 | interrupt source. The value must be 1. | ||
40 | - interrupt-map-mask and interrupt-map: standard PCI properties | ||
41 | |||
42 | Optional Property: | ||
43 | - ep-gpios: contain the entry for pre-reset gpio | ||
44 | - num-lanes: number of lanes to use | ||
45 | - vpcie3v3-supply: The phandle to the 3.3v regulator to use for PCIe. | ||
46 | - vpcie1v8-supply: The phandle to the 1.8v regulator to use for PCIe. | ||
47 | - vpcie0v9-supply: The phandle to the 0.9v regulator to use for PCIe. | ||
48 | |||
49 | *Interrupt controller child node* | ||
50 | The core controller provides a single interrupt for legacy INTx. The PCIe node | ||
51 | should contain an interrupt controller node as a target for the PCI | ||
52 | 'interrupt-map' property. This node represents the domain at which the four | ||
53 | INTx interrupts are decoded and routed. | ||
54 | |||
55 | |||
56 | Required properties for Interrupt controller child node: | ||
57 | - interrupt-controller: identifies the node as an interrupt controller | ||
58 | - #address-cells: specifies the number of cells needed to encode an | ||
59 | address. The value must be 0. | ||
60 | - #interrupt-cells: specifies the number of cells needed to encode an | ||
61 | interrupt source. The value must be 1. | ||
62 | |||
63 | Example: | ||
64 | |||
65 | pcie0: pcie@f8000000 { | ||
66 | compatible = "rockchip,rk3399-pcie"; | ||
67 | #address-cells = <3>; | ||
68 | #size-cells = <2>; | ||
69 | clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>, | ||
70 | <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>; | ||
71 | clock-names = "aclk", "aclk-perf", | ||
72 | "hclk", "pm"; | ||
73 | bus-range = <0x0 0x1>; | ||
74 | interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>, | ||
75 | <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>, | ||
76 | <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>; | ||
77 | interrupt-names = "sys", "legacy", "client"; | ||
78 | assigned-clocks = <&cru SCLK_PCIEPHY_REF>; | ||
79 | assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>; | ||
80 | assigned-clock-rates = <100000000>; | ||
81 | ep-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>; | ||
82 | ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000 | ||
83 | 0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>; | ||
84 | num-lanes = <4>; | ||
85 | msi-map = <0x0 &its 0x0 0x1000>; | ||
86 | reg = <0x0 0xf8000000 0x0 0x2000000>, <0x0 0xfd000000 0x0 0x1000000>; | ||
87 | reg-names = "axi-base", "apb-base"; | ||
88 | resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>, | ||
89 | <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>; | ||
90 | reset-names = "core", "mgmt", "mgmt-sticky", "pipe"; | ||
91 | phys = <&pcie_phy>; | ||
92 | phy-names = "pcie-phy"; | ||
93 | pinctrl-names = "default"; | ||
94 | pinctrl-0 = <&pcie_clkreq>; | ||
95 | #interrupt-cells = <1>; | ||
96 | interrupt-map-mask = <0 0 0 7>; | ||
97 | interrupt-map = <0 0 0 1 &pcie0_intc 0>, | ||
98 | <0 0 0 2 &pcie0_intc 1>, | ||
99 | <0 0 0 3 &pcie0_intc 2>, | ||
100 | <0 0 0 4 &pcie0_intc 3>; | ||
101 | pcie0_intc: interrupt-controller { | ||
102 | interrupt-controller; | ||
103 | #address-cells = <0>; | ||
104 | #interrupt-cells = <1>; | ||
105 | }; | ||
106 | }; | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 20bb1d00098c..c0e623f57414 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -9083,6 +9083,15 @@ S: Maintained | |||
9083 | F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt | 9083 | F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt |
9084 | F: drivers/pci/host/pcie-hisi.c | 9084 | F: drivers/pci/host/pcie-hisi.c |
9085 | 9085 | ||
9086 | PCIE DRIVER FOR ROCKCHIP | ||
9087 | M: Shawn Lin <shawn.lin@rock-chips.com> | ||
9088 | M: Wenrui Li <wenrui.li@rock-chips.com> | ||
9089 | L: linux-pci@vger.kernel.org | ||
9090 | L: linux-rockchip@lists.infradead.org | ||
9091 | S: Maintained | ||
9092 | F: Documentation/devicetree/bindings/pci/rockchip-pcie.txt | ||
9093 | F: drivers/pci/host/pcie-rockchip.c | ||
9094 | |||
9086 | PCIE DRIVER FOR QUALCOMM MSM | 9095 | PCIE DRIVER FOR QUALCOMM MSM |
9087 | M: Stanimir Varbanov <svarbanov@mm-sol.com> | 9096 | M: Stanimir Varbanov <svarbanov@mm-sol.com> |
9088 | L: linux-pci@vger.kernel.org | 9097 | L: linux-pci@vger.kernel.org |
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 0b10ef2a4372..c332604606dd 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild | |||
@@ -25,6 +25,7 @@ generic-y += mcs_spinlock.h | |||
25 | generic-y += mm-arch-hooks.h | 25 | generic-y += mm-arch-hooks.h |
26 | generic-y += mman.h | 26 | generic-y += mman.h |
27 | generic-y += msgbuf.h | 27 | generic-y += msgbuf.h |
28 | generic-y += msi.h | ||
28 | generic-y += param.h | 29 | generic-y += param.h |
29 | generic-y += parport.h | 30 | generic-y += parport.h |
30 | generic-y += pci.h | 31 | generic-y += pci.h |
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 81556b843a8e..7f696f97f9dd 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c | |||
@@ -632,10 +632,10 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose, | |||
632 | } | 632 | } |
633 | } | 633 | } |
634 | 634 | ||
635 | /* Decide whether to display the domain number in /proc */ | 635 | /* Display the domain number in /proc */ |
636 | int pci_proc_domain(struct pci_bus *bus) | 636 | int pci_proc_domain(struct pci_bus *bus) |
637 | { | 637 | { |
638 | return 0; | 638 | return pci_domain_nr(bus); |
639 | } | 639 | } |
640 | 640 | ||
641 | /* This header fixup will do the resource fixup for all devices as they are | 641 | /* This header fixup will do the resource fixup for all devices as they are |
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 9ab7507ca1c2..1411dbed5e5e 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -23,6 +23,9 @@ struct pci_sysdata { | |||
23 | #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN | 23 | #ifdef CONFIG_PCI_MSI_IRQ_DOMAIN |
24 | void *fwnode; /* IRQ domain for MSI assignment */ | 24 | void *fwnode; /* IRQ domain for MSI assignment */ |
25 | #endif | 25 | #endif |
26 | #if IS_ENABLED(CONFIG_VMD) | ||
27 | bool vmd_domain; /* True if in Intel VMD domain */ | ||
28 | #endif | ||
26 | }; | 29 | }; |
27 | 30 | ||
28 | extern int pci_routeirq; | 31 | extern int pci_routeirq; |
@@ -56,6 +59,17 @@ static inline void *_pci_root_bus_fwnode(struct pci_bus *bus) | |||
56 | #define pci_root_bus_fwnode _pci_root_bus_fwnode | 59 | #define pci_root_bus_fwnode _pci_root_bus_fwnode |
57 | #endif | 60 | #endif |
58 | 61 | ||
62 | static inline bool is_vmd(struct pci_bus *bus) | ||
63 | { | ||
64 | #if IS_ENABLED(CONFIG_VMD) | ||
65 | struct pci_sysdata *sd = bus->sysdata; | ||
66 | |||
67 | return sd->vmd_domain; | ||
68 | #else | ||
69 | return false; | ||
70 | #endif | ||
71 | } | ||
72 | |||
59 | /* Can be used to override the logic in pci_scan_bus for skipping | 73 | /* Can be used to override the logic in pci_scan_bus for skipping |
60 | already-configured bus numbers - to be used for buggy BIOSes | 74 | already-configured bus numbers - to be used for buggy BIOSes |
61 | or architectures with incomplete PCI setup by the loader */ | 75 | or architectures with incomplete PCI setup by the loader */ |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 7b6a9d14c8c0..a4fdfa7dcc1b 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -677,6 +677,12 @@ static void set_dma_domain_ops(struct pci_dev *pdev) | |||
677 | static void set_dma_domain_ops(struct pci_dev *pdev) {} | 677 | static void set_dma_domain_ops(struct pci_dev *pdev) {} |
678 | #endif | 678 | #endif |
679 | 679 | ||
680 | static void set_dev_domain_options(struct pci_dev *pdev) | ||
681 | { | ||
682 | if (is_vmd(pdev->bus)) | ||
683 | pdev->hotplug_user_indicators = 1; | ||
684 | } | ||
685 | |||
680 | int pcibios_add_device(struct pci_dev *dev) | 686 | int pcibios_add_device(struct pci_dev *dev) |
681 | { | 687 | { |
682 | struct setup_data *data; | 688 | struct setup_data *data; |
@@ -707,6 +713,7 @@ int pcibios_add_device(struct pci_dev *dev) | |||
707 | iounmap(data); | 713 | iounmap(data); |
708 | } | 714 | } |
709 | set_dma_domain_ops(dev); | 715 | set_dma_domain_ops(dev); |
716 | set_dev_domain_options(dev); | ||
710 | return 0; | 717 | return 0; |
711 | } | 718 | } |
712 | 719 | ||
diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c index b814ca675131..a021b7b0eb69 100644 --- a/arch/x86/pci/vmd.c +++ b/arch/x86/pci/vmd.c | |||
@@ -596,6 +596,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd) | |||
596 | .parent = res, | 596 | .parent = res, |
597 | }; | 597 | }; |
598 | 598 | ||
599 | sd->vmd_domain = true; | ||
599 | sd->domain = vmd_find_free_domain(); | 600 | sd->domain = vmd_find_free_domain(); |
600 | if (sd->domain < 0) | 601 | if (sd->domain < 0) |
601 | return sd->domain; | 602 | return sd->domain; |
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 60746ef904e4..f0a029e68d3e 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -457,7 +457,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
457 | 457 | ||
458 | devfn = PCI_DEVFN(pcie_err->device_id.device, | 458 | devfn = PCI_DEVFN(pcie_err->device_id.device, |
459 | pcie_err->device_id.function); | 459 | pcie_err->device_id.function); |
460 | aer_severity = cper_severity_to_aer(sev); | 460 | aer_severity = cper_severity_to_aer(gdata->error_severity); |
461 | 461 | ||
462 | /* | 462 | /* |
463 | * If firmware reset the component to contain | 463 | * If firmware reset the component to contain |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 67f9916ff14d..6555eb78d91c 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -25,7 +25,7 @@ config PCI_MSI | |||
25 | If you don't know what to do here, say Y. | 25 | If you don't know what to do here, say Y. |
26 | 26 | ||
27 | config PCI_MSI_IRQ_DOMAIN | 27 | config PCI_MSI_IRQ_DOMAIN |
28 | def_bool ARM || ARM64 || X86 | 28 | def_bool ARC || ARM || ARM64 || X86 |
29 | depends on PCI_MSI | 29 | depends on PCI_MSI |
30 | select GENERIC_MSI_IRQ_DOMAIN | 30 | select GENERIC_MSI_IRQ_DOMAIN |
31 | 31 | ||
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 9b485d873b0d..90f5e89854be 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -274,4 +274,15 @@ config PCIE_ARTPEC6 | |||
274 | Say Y here to enable PCIe controller support on Axis ARTPEC-6 | 274 | Say Y here to enable PCIe controller support on Axis ARTPEC-6 |
275 | SoCs. This PCIe controller uses the DesignWare core. | 275 | SoCs. This PCIe controller uses the DesignWare core. |
276 | 276 | ||
277 | config PCIE_ROCKCHIP | ||
278 | bool "Rockchip PCIe controller" | ||
279 | depends on ARCH_ROCKCHIP | ||
280 | depends on OF | ||
281 | depends on PCI_MSI_IRQ_DOMAIN | ||
282 | select MFD_SYSCON | ||
283 | help | ||
284 | Say Y here if you want internal PCI support on Rockchip SoC. | ||
285 | There is 1 internal PCIe port available to support GEN2 with | ||
286 | 4 slots. | ||
287 | |||
277 | endmenu | 288 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 88434101e4c4..a8afc16b0299 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -31,3 +31,4 @@ obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o | |||
31 | obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o | 31 | obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o |
32 | obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o | 32 | obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o |
33 | obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o | 33 | obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o |
34 | obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o | ||
diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c index ef9893fa3176..e4a5b7ee90cf 100644 --- a/drivers/pci/host/pci-aardvark.c +++ b/drivers/pci/host/pci-aardvark.c | |||
@@ -848,7 +848,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) | |||
848 | int err, res_valid = 0; | 848 | int err, res_valid = 0; |
849 | struct device *dev = &pcie->pdev->dev; | 849 | struct device *dev = &pcie->pdev->dev; |
850 | struct device_node *np = dev->of_node; | 850 | struct device_node *np = dev->of_node; |
851 | struct resource_entry *win; | 851 | struct resource_entry *win, *tmp; |
852 | resource_size_t iobase; | 852 | resource_size_t iobase; |
853 | 853 | ||
854 | INIT_LIST_HEAD(&pcie->resources); | 854 | INIT_LIST_HEAD(&pcie->resources); |
@@ -862,7 +862,7 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) | |||
862 | if (err) | 862 | if (err) |
863 | goto out_release_res; | 863 | goto out_release_res; |
864 | 864 | ||
865 | resource_list_for_each_entry(win, &pcie->resources) { | 865 | resource_list_for_each_entry_safe(win, tmp, &pcie->resources) { |
866 | struct resource *res = win->res; | 866 | struct resource *res = win->res; |
867 | 867 | ||
868 | switch (resource_type(res)) { | 868 | switch (resource_type(res)) { |
@@ -874,9 +874,11 @@ static int advk_pcie_parse_request_of_pci_ranges(struct advk_pcie *pcie) | |||
874 | lower_32_bits(res->start), | 874 | lower_32_bits(res->start), |
875 | OB_PCIE_IO); | 875 | OB_PCIE_IO); |
876 | err = pci_remap_iospace(res, iobase); | 876 | err = pci_remap_iospace(res, iobase); |
877 | if (err) | 877 | if (err) { |
878 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 878 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
879 | err, res); | 879 | err, res); |
880 | resource_list_destroy_entry(win); | ||
881 | } | ||
880 | break; | 882 | break; |
881 | case IORESOURCE_MEM: | 883 | case IORESOURCE_MEM: |
882 | advk_pcie_set_ob_win(pcie, 0, | 884 | advk_pcie_set_ob_win(pcie, 0, |
@@ -925,10 +927,8 @@ static int advk_pcie_probe(struct platform_device *pdev) | |||
925 | 927 | ||
926 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 928 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
927 | pcie->base = devm_ioremap_resource(&pdev->dev, res); | 929 | pcie->base = devm_ioremap_resource(&pdev->dev, res); |
928 | if (IS_ERR(pcie->base)) { | 930 | if (IS_ERR(pcie->base)) |
929 | dev_err(&pdev->dev, "Failed to map registers\n"); | ||
930 | return PTR_ERR(pcie->base); | 931 | return PTR_ERR(pcie->base); |
931 | } | ||
932 | 932 | ||
933 | irq = platform_get_irq(pdev, 0); | 933 | irq = platform_get_irq(pdev, 0); |
934 | ret = devm_request_irq(&pdev->dev, irq, advk_pcie_irq_handler, | 934 | ret = devm_request_irq(&pdev->dev, irq, advk_pcie_irq_handler, |
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 81b3949a26db..19223ed2e619 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/init.h> |
19 | #include <linux/of_gpio.h> | 19 | #include <linux/of_gpio.h> |
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
@@ -443,25 +443,6 @@ err_phy: | |||
443 | return ret; | 443 | return ret; |
444 | } | 444 | } |
445 | 445 | ||
446 | static int __exit dra7xx_pcie_remove(struct platform_device *pdev) | ||
447 | { | ||
448 | struct dra7xx_pcie *dra7xx = platform_get_drvdata(pdev); | ||
449 | struct pcie_port *pp = &dra7xx->pp; | ||
450 | struct device *dev = &pdev->dev; | ||
451 | int count = dra7xx->phy_count; | ||
452 | |||
453 | if (pp->irq_domain) | ||
454 | irq_domain_remove(pp->irq_domain); | ||
455 | pm_runtime_put(dev); | ||
456 | pm_runtime_disable(dev); | ||
457 | while (count--) { | ||
458 | phy_power_off(dra7xx->phy[count]); | ||
459 | phy_exit(dra7xx->phy[count]); | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | #ifdef CONFIG_PM_SLEEP | 446 | #ifdef CONFIG_PM_SLEEP |
466 | static int dra7xx_pcie_suspend(struct device *dev) | 447 | static int dra7xx_pcie_suspend(struct device *dev) |
467 | { | 448 | { |
@@ -545,19 +526,13 @@ static const struct of_device_id of_dra7xx_pcie_match[] = { | |||
545 | { .compatible = "ti,dra7-pcie", }, | 526 | { .compatible = "ti,dra7-pcie", }, |
546 | {}, | 527 | {}, |
547 | }; | 528 | }; |
548 | MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match); | ||
549 | 529 | ||
550 | static struct platform_driver dra7xx_pcie_driver = { | 530 | static struct platform_driver dra7xx_pcie_driver = { |
551 | .remove = __exit_p(dra7xx_pcie_remove), | ||
552 | .driver = { | 531 | .driver = { |
553 | .name = "dra7-pcie", | 532 | .name = "dra7-pcie", |
554 | .of_match_table = of_dra7xx_pcie_match, | 533 | .of_match_table = of_dra7xx_pcie_match, |
534 | .suppress_bind_attrs = true, | ||
555 | .pm = &dra7xx_pcie_pm_ops, | 535 | .pm = &dra7xx_pcie_pm_ops, |
556 | }, | 536 | }, |
557 | }; | 537 | }; |
558 | 538 | builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); | |
559 | module_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); | ||
560 | |||
561 | MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>"); | ||
562 | MODULE_DESCRIPTION("TI PCIe controller driver"); | ||
563 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 219976103efc..2e2d7f00b9e8 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 19 | #include <linux/init.h> |
20 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
@@ -425,12 +425,15 @@ static void exynos_pcie_enable_interrupts(struct pcie_port *pp) | |||
425 | exynos_pcie_msi_init(pp); | 425 | exynos_pcie_msi_init(pp); |
426 | } | 426 | } |
427 | 427 | ||
428 | static inline void exynos_pcie_readl_rc(struct pcie_port *pp, | 428 | static inline u32 exynos_pcie_readl_rc(struct pcie_port *pp, |
429 | void __iomem *dbi_base, u32 *val) | 429 | void __iomem *dbi_base) |
430 | { | 430 | { |
431 | u32 val; | ||
432 | |||
431 | exynos_pcie_sideband_dbi_r_mode(pp, true); | 433 | exynos_pcie_sideband_dbi_r_mode(pp, true); |
432 | *val = readl(dbi_base); | 434 | val = readl(dbi_base); |
433 | exynos_pcie_sideband_dbi_r_mode(pp, false); | 435 | exynos_pcie_sideband_dbi_r_mode(pp, false); |
436 | return val; | ||
434 | } | 437 | } |
435 | 438 | ||
436 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, | 439 | static inline void exynos_pcie_writel_rc(struct pcie_port *pp, |
@@ -624,7 +627,6 @@ static const struct of_device_id exynos_pcie_of_match[] = { | |||
624 | { .compatible = "samsung,exynos5440-pcie", }, | 627 | { .compatible = "samsung,exynos5440-pcie", }, |
625 | {}, | 628 | {}, |
626 | }; | 629 | }; |
627 | MODULE_DEVICE_TABLE(of, exynos_pcie_of_match); | ||
628 | 630 | ||
629 | static struct platform_driver exynos_pcie_driver = { | 631 | static struct platform_driver exynos_pcie_driver = { |
630 | .remove = __exit_p(exynos_pcie_remove), | 632 | .remove = __exit_p(exynos_pcie_remove), |
@@ -641,7 +643,3 @@ static int __init exynos_pcie_init(void) | |||
641 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); | 643 | return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe); |
642 | } | 644 | } |
643 | subsys_initcall(exynos_pcie_init); | 645 | subsys_initcall(exynos_pcie_init); |
644 | |||
645 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||
646 | MODULE_DESCRIPTION("Samsung PCIe host controller driver"); | ||
647 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c index 9d9d34e959b6..e3c48b5deb93 100644 --- a/drivers/pci/host/pci-host-common.c +++ b/drivers/pci/host/pci-host-common.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Generic PCI host driver common code | ||
3 | * | ||
2 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
4 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
@@ -17,7 +19,6 @@ | |||
17 | */ | 19 | */ |
18 | 20 | ||
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | ||
21 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
22 | #include <linux/of_pci.h> | 23 | #include <linux/of_pci.h> |
23 | #include <linux/pci-ecam.h> | 24 | #include <linux/pci-ecam.h> |
@@ -29,7 +30,7 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, | |||
29 | int err, res_valid = 0; | 30 | int err, res_valid = 0; |
30 | struct device_node *np = dev->of_node; | 31 | struct device_node *np = dev->of_node; |
31 | resource_size_t iobase; | 32 | resource_size_t iobase; |
32 | struct resource_entry *win; | 33 | struct resource_entry *win, *tmp; |
33 | 34 | ||
34 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); | 35 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, resources, &iobase); |
35 | if (err) | 36 | if (err) |
@@ -39,15 +40,17 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev, | |||
39 | if (err) | 40 | if (err) |
40 | return err; | 41 | return err; |
41 | 42 | ||
42 | resource_list_for_each_entry(win, resources) { | 43 | resource_list_for_each_entry_safe(win, tmp, resources) { |
43 | struct resource *res = win->res; | 44 | struct resource *res = win->res; |
44 | 45 | ||
45 | switch (resource_type(res)) { | 46 | switch (resource_type(res)) { |
46 | case IORESOURCE_IO: | 47 | case IORESOURCE_IO: |
47 | err = pci_remap_iospace(res, iobase); | 48 | err = pci_remap_iospace(res, iobase); |
48 | if (err) | 49 | if (err) { |
49 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 50 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
50 | err, res); | 51 | err, res); |
52 | resource_list_destroy_entry(win); | ||
53 | } | ||
51 | break; | 54 | break; |
52 | case IORESOURCE_MEM: | 55 | case IORESOURCE_MEM: |
53 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | 56 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); |
@@ -162,7 +165,3 @@ int pci_host_common_probe(struct platform_device *pdev, | |||
162 | pci_bus_add_devices(bus); | 165 | pci_bus_add_devices(bus); |
163 | return 0; | 166 | return 0; |
164 | } | 167 | } |
165 | |||
166 | MODULE_DESCRIPTION("Generic PCI host driver common code"); | ||
167 | MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); | ||
168 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index b741a36a67f3..ead4a5c3480b 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -739,7 +739,6 @@ static const struct of_device_id imx6_pcie_of_match[] = { | |||
739 | { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, | 739 | { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, |
740 | {}, | 740 | {}, |
741 | }; | 741 | }; |
742 | MODULE_DEVICE_TABLE(of, imx6_pcie_of_match); | ||
743 | 742 | ||
744 | static struct platform_driver imx6_pcie_driver = { | 743 | static struct platform_driver imx6_pcie_driver = { |
745 | .driver = { | 744 | .driver = { |
@@ -749,14 +748,8 @@ static struct platform_driver imx6_pcie_driver = { | |||
749 | .shutdown = imx6_pcie_shutdown, | 748 | .shutdown = imx6_pcie_shutdown, |
750 | }; | 749 | }; |
751 | 750 | ||
752 | /* Freescale PCIe driver does not allow module unload */ | ||
753 | |||
754 | static int __init imx6_pcie_init(void) | 751 | static int __init imx6_pcie_init(void) |
755 | { | 752 | { |
756 | return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); | 753 | return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); |
757 | } | 754 | } |
758 | module_init(imx6_pcie_init); | 755 | device_initcall(imx6_pcie_init); |
759 | |||
760 | MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); | ||
761 | MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver"); | ||
762 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c index 8ba28834d470..82b461b5b08a 100644 --- a/drivers/pci/host/pci-keystone.c +++ b/drivers/pci/host/pci-keystone.c | |||
@@ -334,8 +334,9 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie, | |||
334 | if (ks_pcie->error_irq <= 0) | 334 | if (ks_pcie->error_irq <= 0) |
335 | dev_info(&pdev->dev, "no error IRQ defined\n"); | 335 | dev_info(&pdev->dev, "no error IRQ defined\n"); |
336 | else { | 336 | else { |
337 | if (request_irq(ks_pcie->error_irq, pcie_err_irq_handler, | 337 | ret = request_irq(ks_pcie->error_irq, pcie_err_irq_handler, |
338 | IRQF_SHARED, "pcie-error-irq", ks_pcie) < 0) { | 338 | IRQF_SHARED, "pcie-error-irq", ks_pcie); |
339 | if (ret < 0) { | ||
339 | dev_err(&pdev->dev, "failed to request error IRQ %d\n", | 340 | dev_err(&pdev->dev, "failed to request error IRQ %d\n", |
340 | ks_pcie->error_irq); | 341 | ks_pcie->error_irq); |
341 | return ret; | 342 | return ret; |
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 6de0757b11e4..e2a8e4cab22e 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -240,7 +240,7 @@ struct tegra_msi { | |||
240 | }; | 240 | }; |
241 | 241 | ||
242 | /* used to differentiate between Tegra SoC generations */ | 242 | /* used to differentiate between Tegra SoC generations */ |
243 | struct tegra_pcie_soc_data { | 243 | struct tegra_pcie_soc { |
244 | unsigned int num_ports; | 244 | unsigned int num_ports; |
245 | unsigned int msi_base_shift; | 245 | unsigned int msi_base_shift; |
246 | u32 pads_pll_ctl; | 246 | u32 pads_pll_ctl; |
@@ -300,7 +300,7 @@ struct tegra_pcie { | |||
300 | struct regulator_bulk_data *supplies; | 300 | struct regulator_bulk_data *supplies; |
301 | unsigned int num_supplies; | 301 | unsigned int num_supplies; |
302 | 302 | ||
303 | const struct tegra_pcie_soc_data *soc_data; | 303 | const struct tegra_pcie_soc *soc; |
304 | struct dentry *debugfs; | 304 | struct dentry *debugfs; |
305 | }; | 305 | }; |
306 | 306 | ||
@@ -542,8 +542,8 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) | |||
542 | 542 | ||
543 | static void tegra_pcie_port_enable(struct tegra_pcie_port *port) | 543 | static void tegra_pcie_port_enable(struct tegra_pcie_port *port) |
544 | { | 544 | { |
545 | const struct tegra_pcie_soc_data *soc = port->pcie->soc_data; | ||
546 | unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); | 545 | unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); |
546 | const struct tegra_pcie_soc *soc = port->pcie->soc; | ||
547 | unsigned long value; | 547 | unsigned long value; |
548 | 548 | ||
549 | /* enable reference clock */ | 549 | /* enable reference clock */ |
@@ -562,8 +562,8 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port) | |||
562 | 562 | ||
563 | static void tegra_pcie_port_disable(struct tegra_pcie_port *port) | 563 | static void tegra_pcie_port_disable(struct tegra_pcie_port *port) |
564 | { | 564 | { |
565 | const struct tegra_pcie_soc_data *soc = port->pcie->soc_data; | ||
566 | unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); | 565 | unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); |
566 | const struct tegra_pcie_soc *soc = port->pcie->soc; | ||
567 | unsigned long value; | 567 | unsigned long value; |
568 | 568 | ||
569 | /* assert port reset */ | 569 | /* assert port reset */ |
@@ -621,7 +621,11 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) | |||
621 | if (err < 0) | 621 | if (err < 0) |
622 | return err; | 622 | return err; |
623 | 623 | ||
624 | pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset); | 624 | err = pci_remap_iospace(&pcie->pio, pcie->io.start); |
625 | if (!err) | ||
626 | pci_add_resource_offset(&sys->resources, &pcie->pio, | ||
627 | sys->io_offset); | ||
628 | |||
625 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); | 629 | pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset); |
626 | pci_add_resource_offset(&sys->resources, &pcie->prefetch, | 630 | pci_add_resource_offset(&sys->resources, &pcie->prefetch, |
627 | sys->mem_offset); | 631 | sys->mem_offset); |
@@ -631,7 +635,6 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) | |||
631 | if (err < 0) | 635 | if (err < 0) |
632 | return err; | 636 | return err; |
633 | 637 | ||
634 | pci_remap_iospace(&pcie->pio, pcie->io.start); | ||
635 | return 1; | 638 | return 1; |
636 | } | 639 | } |
637 | 640 | ||
@@ -774,7 +777,7 @@ static void tegra_pcie_setup_translations(struct tegra_pcie *pcie) | |||
774 | 777 | ||
775 | static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout) | 778 | static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout) |
776 | { | 779 | { |
777 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 780 | const struct tegra_pcie_soc *soc = pcie->soc; |
778 | u32 value; | 781 | u32 value; |
779 | 782 | ||
780 | timeout = jiffies + msecs_to_jiffies(timeout); | 783 | timeout = jiffies + msecs_to_jiffies(timeout); |
@@ -790,7 +793,7 @@ static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout) | |||
790 | 793 | ||
791 | static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) | 794 | static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) |
792 | { | 795 | { |
793 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 796 | const struct tegra_pcie_soc *soc = pcie->soc; |
794 | u32 value; | 797 | u32 value; |
795 | int err; | 798 | int err; |
796 | 799 | ||
@@ -845,7 +848,7 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) | |||
845 | 848 | ||
846 | static int tegra_pcie_phy_disable(struct tegra_pcie *pcie) | 849 | static int tegra_pcie_phy_disable(struct tegra_pcie *pcie) |
847 | { | 850 | { |
848 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 851 | const struct tegra_pcie_soc *soc = pcie->soc; |
849 | u32 value; | 852 | u32 value; |
850 | 853 | ||
851 | /* disable TX/RX data */ | 854 | /* disable TX/RX data */ |
@@ -906,7 +909,7 @@ static int tegra_pcie_port_phy_power_off(struct tegra_pcie_port *port) | |||
906 | 909 | ||
907 | static int tegra_pcie_phy_power_on(struct tegra_pcie *pcie) | 910 | static int tegra_pcie_phy_power_on(struct tegra_pcie *pcie) |
908 | { | 911 | { |
909 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 912 | const struct tegra_pcie_soc *soc = pcie->soc; |
910 | struct tegra_pcie_port *port; | 913 | struct tegra_pcie_port *port; |
911 | int err; | 914 | int err; |
912 | 915 | ||
@@ -974,7 +977,7 @@ static int tegra_pcie_phy_power_off(struct tegra_pcie *pcie) | |||
974 | 977 | ||
975 | static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | 978 | static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) |
976 | { | 979 | { |
977 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 980 | const struct tegra_pcie_soc *soc = pcie->soc; |
978 | struct tegra_pcie_port *port; | 981 | struct tegra_pcie_port *port; |
979 | unsigned long value; | 982 | unsigned long value; |
980 | int err; | 983 | int err; |
@@ -1067,7 +1070,7 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie) | |||
1067 | 1070 | ||
1068 | static int tegra_pcie_power_on(struct tegra_pcie *pcie) | 1071 | static int tegra_pcie_power_on(struct tegra_pcie *pcie) |
1069 | { | 1072 | { |
1070 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 1073 | const struct tegra_pcie_soc *soc = pcie->soc; |
1071 | int err; | 1074 | int err; |
1072 | 1075 | ||
1073 | reset_control_assert(pcie->pcie_xrst); | 1076 | reset_control_assert(pcie->pcie_xrst); |
@@ -1117,7 +1120,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) | |||
1117 | 1120 | ||
1118 | static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) | 1121 | static int tegra_pcie_clocks_get(struct tegra_pcie *pcie) |
1119 | { | 1122 | { |
1120 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 1123 | const struct tegra_pcie_soc *soc = pcie->soc; |
1121 | 1124 | ||
1122 | pcie->pex_clk = devm_clk_get(pcie->dev, "pex"); | 1125 | pcie->pex_clk = devm_clk_get(pcie->dev, "pex"); |
1123 | if (IS_ERR(pcie->pex_clk)) | 1126 | if (IS_ERR(pcie->pex_clk)) |
@@ -1234,7 +1237,7 @@ static int tegra_pcie_port_get_phys(struct tegra_pcie_port *port) | |||
1234 | 1237 | ||
1235 | static int tegra_pcie_phys_get(struct tegra_pcie *pcie) | 1238 | static int tegra_pcie_phys_get(struct tegra_pcie *pcie) |
1236 | { | 1239 | { |
1237 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 1240 | const struct tegra_pcie_soc *soc = pcie->soc; |
1238 | struct device_node *np = pcie->dev->of_node; | 1241 | struct device_node *np = pcie->dev->of_node; |
1239 | struct tegra_pcie_port *port; | 1242 | struct tegra_pcie_port *port; |
1240 | int err; | 1243 | int err; |
@@ -1486,7 +1489,7 @@ static const struct irq_domain_ops msi_domain_ops = { | |||
1486 | static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) | 1489 | static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) |
1487 | { | 1490 | { |
1488 | struct platform_device *pdev = to_platform_device(pcie->dev); | 1491 | struct platform_device *pdev = to_platform_device(pcie->dev); |
1489 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 1492 | const struct tegra_pcie_soc *soc = pcie->soc; |
1490 | struct tegra_msi *msi = &pcie->msi; | 1493 | struct tegra_msi *msi = &pcie->msi; |
1491 | unsigned long base; | 1494 | unsigned long base; |
1492 | int err; | 1495 | int err; |
@@ -1799,8 +1802,8 @@ static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask) | |||
1799 | 1802 | ||
1800 | static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) | 1803 | static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) |
1801 | { | 1804 | { |
1802 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
1803 | struct device_node *np = pcie->dev->of_node, *port; | 1805 | struct device_node *np = pcie->dev->of_node, *port; |
1806 | const struct tegra_pcie_soc *soc = pcie->soc; | ||
1804 | struct of_pci_range_parser parser; | 1807 | struct of_pci_range_parser parser; |
1805 | struct of_pci_range range; | 1808 | struct of_pci_range range; |
1806 | u32 lanes = 0, mask = 0; | 1809 | u32 lanes = 0, mask = 0; |
@@ -2043,7 +2046,7 @@ static int tegra_pcie_enable(struct tegra_pcie *pcie) | |||
2043 | return 0; | 2046 | return 0; |
2044 | } | 2047 | } |
2045 | 2048 | ||
2046 | static const struct tegra_pcie_soc_data tegra20_pcie_data = { | 2049 | static const struct tegra_pcie_soc tegra20_pcie = { |
2047 | .num_ports = 2, | 2050 | .num_ports = 2, |
2048 | .msi_base_shift = 0, | 2051 | .msi_base_shift = 0, |
2049 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, | 2052 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, |
@@ -2056,7 +2059,7 @@ static const struct tegra_pcie_soc_data tegra20_pcie_data = { | |||
2056 | .has_gen2 = false, | 2059 | .has_gen2 = false, |
2057 | }; | 2060 | }; |
2058 | 2061 | ||
2059 | static const struct tegra_pcie_soc_data tegra30_pcie_data = { | 2062 | static const struct tegra_pcie_soc tegra30_pcie = { |
2060 | .num_ports = 3, | 2063 | .num_ports = 3, |
2061 | .msi_base_shift = 8, | 2064 | .msi_base_shift = 8, |
2062 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, | 2065 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, |
@@ -2070,7 +2073,7 @@ static const struct tegra_pcie_soc_data tegra30_pcie_data = { | |||
2070 | .has_gen2 = false, | 2073 | .has_gen2 = false, |
2071 | }; | 2074 | }; |
2072 | 2075 | ||
2073 | static const struct tegra_pcie_soc_data tegra124_pcie_data = { | 2076 | static const struct tegra_pcie_soc tegra124_pcie = { |
2074 | .num_ports = 2, | 2077 | .num_ports = 2, |
2075 | .msi_base_shift = 8, | 2078 | .msi_base_shift = 8, |
2076 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, | 2079 | .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, |
@@ -2084,9 +2087,9 @@ static const struct tegra_pcie_soc_data tegra124_pcie_data = { | |||
2084 | }; | 2087 | }; |
2085 | 2088 | ||
2086 | static const struct of_device_id tegra_pcie_of_match[] = { | 2089 | static const struct of_device_id tegra_pcie_of_match[] = { |
2087 | { .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie_data }, | 2090 | { .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie }, |
2088 | { .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie_data }, | 2091 | { .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie }, |
2089 | { .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie_data }, | 2092 | { .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie }, |
2090 | { }, | 2093 | { }, |
2091 | }; | 2094 | }; |
2092 | 2095 | ||
@@ -2201,21 +2204,16 @@ remove: | |||
2201 | 2204 | ||
2202 | static int tegra_pcie_probe(struct platform_device *pdev) | 2205 | static int tegra_pcie_probe(struct platform_device *pdev) |
2203 | { | 2206 | { |
2204 | const struct of_device_id *match; | ||
2205 | struct tegra_pcie *pcie; | 2207 | struct tegra_pcie *pcie; |
2206 | int err; | 2208 | int err; |
2207 | 2209 | ||
2208 | match = of_match_device(tegra_pcie_of_match, &pdev->dev); | ||
2209 | if (!match) | ||
2210 | return -ENODEV; | ||
2211 | |||
2212 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | 2210 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); |
2213 | if (!pcie) | 2211 | if (!pcie) |
2214 | return -ENOMEM; | 2212 | return -ENOMEM; |
2215 | 2213 | ||
2214 | pcie->soc = of_device_get_match_data(&pdev->dev); | ||
2216 | INIT_LIST_HEAD(&pcie->buses); | 2215 | INIT_LIST_HEAD(&pcie->buses); |
2217 | INIT_LIST_HEAD(&pcie->ports); | 2216 | INIT_LIST_HEAD(&pcie->ports); |
2218 | pcie->soc_data = match->data; | ||
2219 | pcie->dev = &pdev->dev; | 2217 | pcie->dev = &pdev->dev; |
2220 | 2218 | ||
2221 | err = tegra_pcie_parse_dt(pcie); | 2219 | err = tegra_pcie_parse_dt(pcie); |
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c index f234405770ab..b7dc07002f13 100644 --- a/drivers/pci/host/pci-versatile.c +++ b/drivers/pci/host/pci-versatile.c | |||
@@ -74,7 +74,7 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, | |||
74 | int err, mem = 1, res_valid = 0; | 74 | int err, mem = 1, res_valid = 0; |
75 | struct device_node *np = dev->of_node; | 75 | struct device_node *np = dev->of_node; |
76 | resource_size_t iobase; | 76 | resource_size_t iobase; |
77 | struct resource_entry *win; | 77 | struct resource_entry *win, *tmp; |
78 | 78 | ||
79 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, res, &iobase); | 79 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, res, &iobase); |
80 | if (err) | 80 | if (err) |
@@ -84,15 +84,17 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev, | |||
84 | if (err) | 84 | if (err) |
85 | goto out_release_res; | 85 | goto out_release_res; |
86 | 86 | ||
87 | resource_list_for_each_entry(win, res) { | 87 | resource_list_for_each_entry_safe(win, tmp, res) { |
88 | struct resource *res = win->res; | 88 | struct resource *res = win->res; |
89 | 89 | ||
90 | switch (resource_type(res)) { | 90 | switch (resource_type(res)) { |
91 | case IORESOURCE_IO: | 91 | case IORESOURCE_IO: |
92 | err = pci_remap_iospace(res, iobase); | 92 | err = pci_remap_iospace(res, iobase); |
93 | if (err) | 93 | if (err) { |
94 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 94 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
95 | err, res); | 95 | err, res); |
96 | resource_list_destroy_entry(win); | ||
97 | } | ||
96 | break; | 98 | break; |
97 | case IORESOURCE_MEM: | 99 | case IORESOURCE_MEM: |
98 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | 100 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); |
diff --git a/drivers/pci/host/pcie-altera-msi.c b/drivers/pci/host/pcie-altera-msi.c index 99177f4ccde2..4e5d628e8cd4 100644 --- a/drivers/pci/host/pcie-altera-msi.c +++ b/drivers/pci/host/pcie-altera-msi.c | |||
@@ -1,4 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Altera PCIe MSI support | ||
3 | * | ||
4 | * Author: Ley Foon Tan <lftan@altera.com> | ||
5 | * | ||
2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved | 6 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved |
3 | * | 7 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -16,7 +20,7 @@ | |||
16 | 20 | ||
17 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
18 | #include <linux/irqchip/chained_irq.h> | 22 | #include <linux/irqchip/chained_irq.h> |
19 | #include <linux/module.h> | 23 | #include <linux/init.h> |
20 | #include <linux/msi.h> | 24 | #include <linux/msi.h> |
21 | #include <linux/of_address.h> | 25 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 26 | #include <linux/of_irq.h> |
@@ -237,11 +241,6 @@ static int altera_msi_probe(struct platform_device *pdev) | |||
237 | msi->pdev = pdev; | 241 | msi->pdev = pdev; |
238 | 242 | ||
239 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr"); | 243 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr"); |
240 | if (!res) { | ||
241 | dev_err(&pdev->dev, "no csr memory resource defined\n"); | ||
242 | return -ENODEV; | ||
243 | } | ||
244 | |||
245 | msi->csr_base = devm_ioremap_resource(&pdev->dev, res); | 244 | msi->csr_base = devm_ioremap_resource(&pdev->dev, res); |
246 | if (IS_ERR(msi->csr_base)) { | 245 | if (IS_ERR(msi->csr_base)) { |
247 | dev_err(&pdev->dev, "failed to map csr memory\n"); | 246 | dev_err(&pdev->dev, "failed to map csr memory\n"); |
@@ -250,11 +249,6 @@ static int altera_msi_probe(struct platform_device *pdev) | |||
250 | 249 | ||
251 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 250 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
252 | "vector_slave"); | 251 | "vector_slave"); |
253 | if (!res) { | ||
254 | dev_err(&pdev->dev, "no vector_slave memory resource defined\n"); | ||
255 | return -ENODEV; | ||
256 | } | ||
257 | |||
258 | msi->vector_base = devm_ioremap_resource(&pdev->dev, res); | 252 | msi->vector_base = devm_ioremap_resource(&pdev->dev, res); |
259 | if (IS_ERR(msi->vector_base)) { | 253 | if (IS_ERR(msi->vector_base)) { |
260 | dev_err(&pdev->dev, "failed to map vector_slave memory\n"); | 254 | dev_err(&pdev->dev, "failed to map vector_slave memory\n"); |
@@ -308,7 +302,3 @@ static int __init altera_msi_init(void) | |||
308 | return platform_driver_register(&altera_msi_driver); | 302 | return platform_driver_register(&altera_msi_driver); |
309 | } | 303 | } |
310 | subsys_initcall(altera_msi_init); | 304 | subsys_initcall(altera_msi_init); |
311 | |||
312 | MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); | ||
313 | MODULE_DESCRIPTION("Altera PCIe MSI support"); | ||
314 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index 2b7837650db8..c24e96559cbb 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c | |||
@@ -1,6 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved | 2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved |
3 | * | 3 | * |
4 | * Author: Ley Foon Tan <lftan@altera.com> | ||
5 | * Description: Altera PCIe host controller driver | ||
6 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 8 | * under the terms and conditions of the GNU General Public License, |
6 | * version 2, as published by the Free Software Foundation. | 9 | * version 2, as published by the Free Software Foundation. |
@@ -17,7 +20,7 @@ | |||
17 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
18 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
19 | #include <linux/irqchip/chained_irq.h> | 22 | #include <linux/irqchip/chained_irq.h> |
20 | #include <linux/module.h> | 23 | #include <linux/init.h> |
21 | #include <linux/of_address.h> | 24 | #include <linux/of_address.h> |
22 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
23 | #include <linux/of_pci.h> | 26 | #include <linux/of_pci.h> |
@@ -43,6 +46,7 @@ | |||
43 | #define RP_LTSSM_MASK 0x1f | 46 | #define RP_LTSSM_MASK 0x1f |
44 | #define LTSSM_L0 0xf | 47 | #define LTSSM_L0 0xf |
45 | 48 | ||
49 | #define PCIE_CAP_OFFSET 0x80 | ||
46 | /* TLP configuration type 0 and 1 */ | 50 | /* TLP configuration type 0 and 1 */ |
47 | #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ | 51 | #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ |
48 | #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ | 52 | #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ |
@@ -61,7 +65,8 @@ | |||
61 | #define TLP_LOOP 500 | 65 | #define TLP_LOOP 500 |
62 | #define RP_DEVFN 0 | 66 | #define RP_DEVFN 0 |
63 | 67 | ||
64 | #define LINK_UP_TIMEOUT 5000 | 68 | #define LINK_UP_TIMEOUT HZ |
69 | #define LINK_RETRAIN_TIMEOUT HZ | ||
65 | 70 | ||
66 | #define INTX_NUM 4 | 71 | #define INTX_NUM 4 |
67 | 72 | ||
@@ -99,38 +104,6 @@ static bool altera_pcie_link_is_up(struct altera_pcie *pcie) | |||
99 | return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); | 104 | return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); |
100 | } | 105 | } |
101 | 106 | ||
102 | static void altera_pcie_retrain(struct pci_dev *dev) | ||
103 | { | ||
104 | u16 linkcap, linkstat; | ||
105 | struct altera_pcie *pcie = dev->bus->sysdata; | ||
106 | int timeout = 0; | ||
107 | |||
108 | if (!altera_pcie_link_is_up(pcie)) | ||
109 | return; | ||
110 | |||
111 | /* | ||
112 | * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but | ||
113 | * current speed is 2.5 GB/s. | ||
114 | */ | ||
115 | pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap); | ||
116 | |||
117 | if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) | ||
118 | return; | ||
119 | |||
120 | pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat); | ||
121 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { | ||
122 | pcie_capability_set_word(dev, PCI_EXP_LNKCTL, | ||
123 | PCI_EXP_LNKCTL_RL); | ||
124 | while (!altera_pcie_link_is_up(pcie)) { | ||
125 | timeout++; | ||
126 | if (timeout > LINK_UP_TIMEOUT) | ||
127 | break; | ||
128 | udelay(5); | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain); | ||
133 | |||
134 | /* | 107 | /* |
135 | * Altera PCIe port uses BAR0 of RC's configuration space as the translation | 108 | * Altera PCIe port uses BAR0 of RC's configuration space as the translation |
136 | * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space | 109 | * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space |
@@ -171,13 +144,6 @@ static bool altera_pcie_valid_config(struct altera_pcie *pcie, | |||
171 | if (bus->number == pcie->root_bus_nr && dev > 0) | 144 | if (bus->number == pcie->root_bus_nr && dev > 0) |
172 | return false; | 145 | return false; |
173 | 146 | ||
174 | /* | ||
175 | * Do not read more than one device on the bus directly attached | ||
176 | * to root port, root port can only attach to one downstream port. | ||
177 | */ | ||
178 | if (bus->primary == pcie->root_bus_nr && dev > 0) | ||
179 | return false; | ||
180 | |||
181 | return true; | 147 | return true; |
182 | } | 148 | } |
183 | 149 | ||
@@ -301,22 +267,14 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, | |||
301 | return PCIBIOS_SUCCESSFUL; | 267 | return PCIBIOS_SUCCESSFUL; |
302 | } | 268 | } |
303 | 269 | ||
304 | static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, | 270 | static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, |
305 | int where, int size, u32 *value) | 271 | unsigned int devfn, int where, int size, |
272 | u32 *value) | ||
306 | { | 273 | { |
307 | struct altera_pcie *pcie = bus->sysdata; | ||
308 | int ret; | 274 | int ret; |
309 | u32 data; | 275 | u32 data; |
310 | u8 byte_en; | 276 | u8 byte_en; |
311 | 277 | ||
312 | if (altera_pcie_hide_rc_bar(bus, devfn, where)) | ||
313 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
314 | |||
315 | if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) { | ||
316 | *value = 0xffffffff; | ||
317 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
318 | } | ||
319 | |||
320 | switch (size) { | 278 | switch (size) { |
321 | case 1: | 279 | case 1: |
322 | byte_en = 1 << (where & 3); | 280 | byte_en = 1 << (where & 3); |
@@ -329,7 +287,7 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, | |||
329 | break; | 287 | break; |
330 | } | 288 | } |
331 | 289 | ||
332 | ret = tlp_cfg_dword_read(pcie, bus->number, devfn, | 290 | ret = tlp_cfg_dword_read(pcie, busno, devfn, |
333 | (where & ~DWORD_MASK), byte_en, &data); | 291 | (where & ~DWORD_MASK), byte_en, &data); |
334 | if (ret != PCIBIOS_SUCCESSFUL) | 292 | if (ret != PCIBIOS_SUCCESSFUL) |
335 | return ret; | 293 | return ret; |
@@ -349,20 +307,14 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, | |||
349 | return PCIBIOS_SUCCESSFUL; | 307 | return PCIBIOS_SUCCESSFUL; |
350 | } | 308 | } |
351 | 309 | ||
352 | static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, | 310 | static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, |
353 | int where, int size, u32 value) | 311 | unsigned int devfn, int where, int size, |
312 | u32 value) | ||
354 | { | 313 | { |
355 | struct altera_pcie *pcie = bus->sysdata; | ||
356 | u32 data32; | 314 | u32 data32; |
357 | u32 shift = 8 * (where & 3); | 315 | u32 shift = 8 * (where & 3); |
358 | u8 byte_en; | 316 | u8 byte_en; |
359 | 317 | ||
360 | if (altera_pcie_hide_rc_bar(bus, devfn, where)) | ||
361 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
362 | |||
363 | if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) | ||
364 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
365 | |||
366 | switch (size) { | 318 | switch (size) { |
367 | case 1: | 319 | case 1: |
368 | data32 = (value & 0xff) << shift; | 320 | data32 = (value & 0xff) << shift; |
@@ -378,8 +330,40 @@ static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, | |||
378 | break; | 330 | break; |
379 | } | 331 | } |
380 | 332 | ||
381 | return tlp_cfg_dword_write(pcie, bus->number, devfn, | 333 | return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), |
382 | (where & ~DWORD_MASK), byte_en, data32); | 334 | byte_en, data32); |
335 | } | ||
336 | |||
337 | static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, | ||
338 | int where, int size, u32 *value) | ||
339 | { | ||
340 | struct altera_pcie *pcie = bus->sysdata; | ||
341 | |||
342 | if (altera_pcie_hide_rc_bar(bus, devfn, where)) | ||
343 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
344 | |||
345 | if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) { | ||
346 | *value = 0xffffffff; | ||
347 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
348 | } | ||
349 | |||
350 | return _altera_pcie_cfg_read(pcie, bus->number, devfn, where, size, | ||
351 | value); | ||
352 | } | ||
353 | |||
354 | static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, | ||
355 | int where, int size, u32 value) | ||
356 | { | ||
357 | struct altera_pcie *pcie = bus->sysdata; | ||
358 | |||
359 | if (altera_pcie_hide_rc_bar(bus, devfn, where)) | ||
360 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
361 | |||
362 | if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) | ||
363 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
364 | |||
365 | return _altera_pcie_cfg_write(pcie, bus->number, devfn, where, size, | ||
366 | value); | ||
383 | } | 367 | } |
384 | 368 | ||
385 | static struct pci_ops altera_pcie_ops = { | 369 | static struct pci_ops altera_pcie_ops = { |
@@ -387,6 +371,90 @@ static struct pci_ops altera_pcie_ops = { | |||
387 | .write = altera_pcie_cfg_write, | 371 | .write = altera_pcie_cfg_write, |
388 | }; | 372 | }; |
389 | 373 | ||
374 | static int altera_read_cap_word(struct altera_pcie *pcie, u8 busno, | ||
375 | unsigned int devfn, int offset, u16 *value) | ||
376 | { | ||
377 | u32 data; | ||
378 | int ret; | ||
379 | |||
380 | ret = _altera_pcie_cfg_read(pcie, busno, devfn, | ||
381 | PCIE_CAP_OFFSET + offset, sizeof(*value), | ||
382 | &data); | ||
383 | *value = data; | ||
384 | return ret; | ||
385 | } | ||
386 | |||
387 | static int altera_write_cap_word(struct altera_pcie *pcie, u8 busno, | ||
388 | unsigned int devfn, int offset, u16 value) | ||
389 | { | ||
390 | return _altera_pcie_cfg_write(pcie, busno, devfn, | ||
391 | PCIE_CAP_OFFSET + offset, sizeof(value), | ||
392 | value); | ||
393 | } | ||
394 | |||
395 | static void altera_wait_link_retrain(struct altera_pcie *pcie) | ||
396 | { | ||
397 | u16 reg16; | ||
398 | unsigned long start_jiffies; | ||
399 | |||
400 | /* Wait for link training end. */ | ||
401 | start_jiffies = jiffies; | ||
402 | for (;;) { | ||
403 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, | ||
404 | PCI_EXP_LNKSTA, ®16); | ||
405 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | ||
406 | break; | ||
407 | |||
408 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) { | ||
409 | dev_err(&pcie->pdev->dev, "link retrain timeout\n"); | ||
410 | break; | ||
411 | } | ||
412 | udelay(100); | ||
413 | } | ||
414 | |||
415 | /* Wait for link is up */ | ||
416 | start_jiffies = jiffies; | ||
417 | for (;;) { | ||
418 | if (altera_pcie_link_is_up(pcie)) | ||
419 | break; | ||
420 | |||
421 | if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { | ||
422 | dev_err(&pcie->pdev->dev, "link up timeout\n"); | ||
423 | break; | ||
424 | } | ||
425 | udelay(100); | ||
426 | } | ||
427 | } | ||
428 | |||
429 | static void altera_pcie_retrain(struct altera_pcie *pcie) | ||
430 | { | ||
431 | u16 linkcap, linkstat, linkctl; | ||
432 | |||
433 | if (!altera_pcie_link_is_up(pcie)) | ||
434 | return; | ||
435 | |||
436 | /* | ||
437 | * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but | ||
438 | * current speed is 2.5 GB/s. | ||
439 | */ | ||
440 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKCAP, | ||
441 | &linkcap); | ||
442 | if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) | ||
443 | return; | ||
444 | |||
445 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKSTA, | ||
446 | &linkstat); | ||
447 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { | ||
448 | altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, | ||
449 | PCI_EXP_LNKCTL, &linkctl); | ||
450 | linkctl |= PCI_EXP_LNKCTL_RL; | ||
451 | altera_write_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, | ||
452 | PCI_EXP_LNKCTL, linkctl); | ||
453 | |||
454 | altera_wait_link_retrain(pcie); | ||
455 | } | ||
456 | } | ||
457 | |||
390 | static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq, | 458 | static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq, |
391 | irq_hw_number_t hwirq) | 459 | irq_hw_number_t hwirq) |
392 | { | 460 | { |
@@ -508,6 +576,11 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) | |||
508 | return 0; | 576 | return 0; |
509 | } | 577 | } |
510 | 578 | ||
579 | static void altera_pcie_host_init(struct altera_pcie *pcie) | ||
580 | { | ||
581 | altera_pcie_retrain(pcie); | ||
582 | } | ||
583 | |||
511 | static int altera_pcie_probe(struct platform_device *pdev) | 584 | static int altera_pcie_probe(struct platform_device *pdev) |
512 | { | 585 | { |
513 | struct altera_pcie *pcie; | 586 | struct altera_pcie *pcie; |
@@ -545,6 +618,7 @@ static int altera_pcie_probe(struct platform_device *pdev) | |||
545 | cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); | 618 | cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); |
546 | /* enable all interrupts */ | 619 | /* enable all interrupts */ |
547 | cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); | 620 | cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); |
621 | altera_pcie_host_init(pcie); | ||
548 | 622 | ||
549 | bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops, | 623 | bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops, |
550 | pcie, &pcie->resources); | 624 | pcie, &pcie->resources); |
@@ -568,7 +642,6 @@ static const struct of_device_id altera_pcie_of_match[] = { | |||
568 | { .compatible = "altr,pcie-root-port-1.0", }, | 642 | { .compatible = "altr,pcie-root-port-1.0", }, |
569 | {}, | 643 | {}, |
570 | }; | 644 | }; |
571 | MODULE_DEVICE_TABLE(of, altera_pcie_of_match); | ||
572 | 645 | ||
573 | static struct platform_driver altera_pcie_driver = { | 646 | static struct platform_driver altera_pcie_driver = { |
574 | .probe = altera_pcie_probe, | 647 | .probe = altera_pcie_probe, |
@@ -583,8 +656,4 @@ static int altera_pcie_init(void) | |||
583 | { | 656 | { |
584 | return platform_driver_register(&altera_pcie_driver); | 657 | return platform_driver_register(&altera_pcie_driver); |
585 | } | 658 | } |
586 | module_init(altera_pcie_init); | 659 | device_initcall(altera_pcie_init); |
587 | |||
588 | MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); | ||
589 | MODULE_DESCRIPTION("Altera PCIe host controller driver"); | ||
590 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-artpec6.c b/drivers/pci/host/pcie-artpec6.c index 16ba70b7ec65..39bf1a6df463 100644 --- a/drivers/pci/host/pcie-artpec6.c +++ b/drivers/pci/host/pcie-artpec6.c | |||
@@ -191,8 +191,8 @@ static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg) | |||
191 | return dw_handle_msi_irq(pp); | 191 | return dw_handle_msi_irq(pp); |
192 | } | 192 | } |
193 | 193 | ||
194 | static int __init artpec6_add_pcie_port(struct pcie_port *pp, | 194 | static int artpec6_add_pcie_port(struct pcie_port *pp, |
195 | struct platform_device *pdev) | 195 | struct platform_device *pdev) |
196 | { | 196 | { |
197 | int ret; | 197 | int ret; |
198 | 198 | ||
diff --git a/drivers/pci/host/pcie-designware-plat.c b/drivers/pci/host/pcie-designware-plat.c index c8079dc81c10..17da005497a5 100644 --- a/drivers/pci/host/pcie-designware-plat.c +++ b/drivers/pci/host/pcie-designware-plat.c | |||
@@ -100,9 +100,6 @@ static int dw_plat_pcie_probe(struct platform_device *pdev) | |||
100 | pp->dev = &pdev->dev; | 100 | pp->dev = &pdev->dev; |
101 | 101 | ||
102 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 102 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
103 | if (!res) | ||
104 | return -ENODEV; | ||
105 | |||
106 | dw_plat_pcie->mem_base = devm_ioremap_resource(&pdev->dev, res); | 103 | dw_plat_pcie->mem_base = devm_ioremap_resource(&pdev->dev, res); |
107 | if (IS_ERR(dw_plat_pcie->mem_base)) | 104 | if (IS_ERR(dw_plat_pcie->mem_base)) |
108 | return PTR_ERR(dw_plat_pcie->mem_base); | 105 | return PTR_ERR(dw_plat_pcie->mem_base); |
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 12afce19890b..74da71ea544a 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
15 | #include <linux/irqdomain.h> | 15 | #include <linux/irqdomain.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | ||
18 | #include <linux/msi.h> | 17 | #include <linux/msi.h> |
19 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
20 | #include <linux/of_pci.h> | 19 | #include <linux/of_pci.h> |
@@ -26,7 +25,17 @@ | |||
26 | 25 | ||
27 | #include "pcie-designware.h" | 26 | #include "pcie-designware.h" |
28 | 27 | ||
29 | /* Synopsis specific PCIE configuration registers */ | 28 | /* Parameters for the waiting for link up routine */ |
29 | #define LINK_WAIT_MAX_RETRIES 10 | ||
30 | #define LINK_WAIT_USLEEP_MIN 90000 | ||
31 | #define LINK_WAIT_USLEEP_MAX 100000 | ||
32 | |||
33 | /* Parameters for the waiting for iATU enabled routine */ | ||
34 | #define LINK_WAIT_MAX_IATU_RETRIES 5 | ||
35 | #define LINK_WAIT_IATU_MIN 9000 | ||
36 | #define LINK_WAIT_IATU_MAX 10000 | ||
37 | |||
38 | /* Synopsys-specific PCIe configuration registers */ | ||
30 | #define PCIE_PORT_LINK_CONTROL 0x710 | 39 | #define PCIE_PORT_LINK_CONTROL 0x710 |
31 | #define PORT_LINK_MODE_MASK (0x3f << 16) | 40 | #define PORT_LINK_MODE_MASK (0x3f << 16) |
32 | #define PORT_LINK_MODE_1_LANES (0x1 << 16) | 41 | #define PORT_LINK_MODE_1_LANES (0x1 << 16) |
@@ -51,6 +60,7 @@ | |||
51 | #define PCIE_ATU_VIEWPORT 0x900 | 60 | #define PCIE_ATU_VIEWPORT 0x900 |
52 | #define PCIE_ATU_REGION_INBOUND (0x1 << 31) | 61 | #define PCIE_ATU_REGION_INBOUND (0x1 << 31) |
53 | #define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) | 62 | #define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) |
63 | #define PCIE_ATU_REGION_INDEX2 (0x2 << 0) | ||
54 | #define PCIE_ATU_REGION_INDEX1 (0x1 << 0) | 64 | #define PCIE_ATU_REGION_INDEX1 (0x1 << 0) |
55 | #define PCIE_ATU_REGION_INDEX0 (0x0 << 0) | 65 | #define PCIE_ATU_REGION_INDEX0 (0x0 << 0) |
56 | #define PCIE_ATU_CR1 0x904 | 66 | #define PCIE_ATU_CR1 0x904 |
@@ -70,10 +80,26 @@ | |||
70 | #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) | 80 | #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) |
71 | #define PCIE_ATU_UPPER_TARGET 0x91C | 81 | #define PCIE_ATU_UPPER_TARGET 0x91C |
72 | 82 | ||
83 | /* | ||
84 | * iATU Unroll-specific register definitions | ||
85 | * From 4.80 core version the address translation will be made by unroll | ||
86 | */ | ||
87 | #define PCIE_ATU_UNR_REGION_CTRL1 0x00 | ||
88 | #define PCIE_ATU_UNR_REGION_CTRL2 0x04 | ||
89 | #define PCIE_ATU_UNR_LOWER_BASE 0x08 | ||
90 | #define PCIE_ATU_UNR_UPPER_BASE 0x0C | ||
91 | #define PCIE_ATU_UNR_LIMIT 0x10 | ||
92 | #define PCIE_ATU_UNR_LOWER_TARGET 0x14 | ||
93 | #define PCIE_ATU_UNR_UPPER_TARGET 0x18 | ||
94 | |||
95 | /* Register address builder */ | ||
96 | #define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((0x3 << 20) | (region << 9)) | ||
97 | |||
73 | /* PCIe Port Logic registers */ | 98 | /* PCIe Port Logic registers */ |
74 | #define PLR_OFFSET 0x700 | 99 | #define PLR_OFFSET 0x700 |
75 | #define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c) | 100 | #define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c) |
76 | #define PCIE_PHY_DEBUG_R1_LINK_UP 0x00000010 | 101 | #define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4) |
102 | #define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29) | ||
77 | 103 | ||
78 | static struct pci_ops dw_pcie_ops; | 104 | static struct pci_ops dw_pcie_ops; |
79 | 105 | ||
@@ -115,12 +141,12 @@ int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val) | |||
115 | return PCIBIOS_SUCCESSFUL; | 141 | return PCIBIOS_SUCCESSFUL; |
116 | } | 142 | } |
117 | 143 | ||
118 | static inline void dw_pcie_readl_rc(struct pcie_port *pp, u32 reg, u32 *val) | 144 | static inline u32 dw_pcie_readl_rc(struct pcie_port *pp, u32 reg) |
119 | { | 145 | { |
120 | if (pp->ops->readl_rc) | 146 | if (pp->ops->readl_rc) |
121 | pp->ops->readl_rc(pp, pp->dbi_base + reg, val); | 147 | return pp->ops->readl_rc(pp, pp->dbi_base + reg); |
122 | else | 148 | |
123 | *val = readl(pp->dbi_base + reg); | 149 | return readl(pp->dbi_base + reg); |
124 | } | 150 | } |
125 | 151 | ||
126 | static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg) | 152 | static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg) |
@@ -131,6 +157,27 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg) | |||
131 | writel(val, pp->dbi_base + reg); | 157 | writel(val, pp->dbi_base + reg); |
132 | } | 158 | } |
133 | 159 | ||
160 | static inline u32 dw_pcie_readl_unroll(struct pcie_port *pp, u32 index, u32 reg) | ||
161 | { | ||
162 | u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); | ||
163 | |||
164 | if (pp->ops->readl_rc) | ||
165 | return pp->ops->readl_rc(pp, pp->dbi_base + offset + reg); | ||
166 | |||
167 | return readl(pp->dbi_base + offset + reg); | ||
168 | } | ||
169 | |||
170 | static inline void dw_pcie_writel_unroll(struct pcie_port *pp, u32 index, | ||
171 | u32 val, u32 reg) | ||
172 | { | ||
173 | u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); | ||
174 | |||
175 | if (pp->ops->writel_rc) | ||
176 | pp->ops->writel_rc(pp, val, pp->dbi_base + offset + reg); | ||
177 | else | ||
178 | writel(val, pp->dbi_base + offset + reg); | ||
179 | } | ||
180 | |||
134 | static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | 181 | static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, |
135 | u32 *val) | 182 | u32 *val) |
136 | { | 183 | { |
@@ -152,24 +199,57 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | |||
152 | static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, | 199 | static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, |
153 | int type, u64 cpu_addr, u64 pci_addr, u32 size) | 200 | int type, u64 cpu_addr, u64 pci_addr, u32 size) |
154 | { | 201 | { |
155 | u32 val; | 202 | u32 retries, val; |
156 | 203 | ||
157 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index, | 204 | if (pp->iatu_unroll_enabled) { |
158 | PCIE_ATU_VIEWPORT); | 205 | dw_pcie_writel_unroll(pp, index, |
159 | dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE); | 206 | lower_32_bits(cpu_addr), PCIE_ATU_UNR_LOWER_BASE); |
160 | dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), PCIE_ATU_UPPER_BASE); | 207 | dw_pcie_writel_unroll(pp, index, |
161 | dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1), | 208 | upper_32_bits(cpu_addr), PCIE_ATU_UNR_UPPER_BASE); |
162 | PCIE_ATU_LIMIT); | 209 | dw_pcie_writel_unroll(pp, index, |
163 | dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), PCIE_ATU_LOWER_TARGET); | 210 | lower_32_bits(cpu_addr + size - 1), PCIE_ATU_UNR_LIMIT); |
164 | dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET); | 211 | dw_pcie_writel_unroll(pp, index, |
165 | dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1); | 212 | lower_32_bits(pci_addr), PCIE_ATU_UNR_LOWER_TARGET); |
166 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | 213 | dw_pcie_writel_unroll(pp, index, |
214 | upper_32_bits(pci_addr), PCIE_ATU_UNR_UPPER_TARGET); | ||
215 | dw_pcie_writel_unroll(pp, index, | ||
216 | type, PCIE_ATU_UNR_REGION_CTRL1); | ||
217 | dw_pcie_writel_unroll(pp, index, | ||
218 | PCIE_ATU_ENABLE, PCIE_ATU_UNR_REGION_CTRL2); | ||
219 | } else { | ||
220 | dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index, | ||
221 | PCIE_ATU_VIEWPORT); | ||
222 | dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), | ||
223 | PCIE_ATU_LOWER_BASE); | ||
224 | dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), | ||
225 | PCIE_ATU_UPPER_BASE); | ||
226 | dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1), | ||
227 | PCIE_ATU_LIMIT); | ||
228 | dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), | ||
229 | PCIE_ATU_LOWER_TARGET); | ||
230 | dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), | ||
231 | PCIE_ATU_UPPER_TARGET); | ||
232 | dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1); | ||
233 | dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); | ||
234 | } | ||
167 | 235 | ||
168 | /* | 236 | /* |
169 | * Make sure ATU enable takes effect before any subsequent config | 237 | * Make sure ATU enable takes effect before any subsequent config |
170 | * and I/O accesses. | 238 | * and I/O accesses. |
171 | */ | 239 | */ |
172 | dw_pcie_readl_rc(pp, PCIE_ATU_CR2, &val); | 240 | for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { |
241 | if (pp->iatu_unroll_enabled) | ||
242 | val = dw_pcie_readl_unroll(pp, index, | ||
243 | PCIE_ATU_UNR_REGION_CTRL2); | ||
244 | else | ||
245 | val = dw_pcie_readl_rc(pp, PCIE_ATU_CR2); | ||
246 | |||
247 | if (val == PCIE_ATU_ENABLE) | ||
248 | return; | ||
249 | |||
250 | usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX); | ||
251 | } | ||
252 | dev_err(pp->dev, "iATU is not being enabled\n"); | ||
173 | } | 253 | } |
174 | 254 | ||
175 | static struct irq_chip dw_msi_irq_chip = { | 255 | static struct irq_chip dw_msi_irq_chip = { |
@@ -412,7 +492,8 @@ int dw_pcie_link_up(struct pcie_port *pp) | |||
412 | return pp->ops->link_up(pp); | 492 | return pp->ops->link_up(pp); |
413 | 493 | ||
414 | val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); | 494 | val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); |
415 | return val & PCIE_PHY_DEBUG_R1_LINK_UP; | 495 | return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) && |
496 | (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING))); | ||
416 | } | 497 | } |
417 | 498 | ||
418 | static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, | 499 | static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, |
@@ -428,6 +509,17 @@ static const struct irq_domain_ops msi_domain_ops = { | |||
428 | .map = dw_pcie_msi_map, | 509 | .map = dw_pcie_msi_map, |
429 | }; | 510 | }; |
430 | 511 | ||
512 | static u8 dw_pcie_iatu_unroll_enabled(struct pcie_port *pp) | ||
513 | { | ||
514 | u32 val; | ||
515 | |||
516 | val = dw_pcie_readl_rc(pp, PCIE_ATU_VIEWPORT); | ||
517 | if (val == 0xffffffff) | ||
518 | return 1; | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
431 | int dw_pcie_host_init(struct pcie_port *pp) | 523 | int dw_pcie_host_init(struct pcie_port *pp) |
432 | { | 524 | { |
433 | struct device_node *np = pp->dev->of_node; | 525 | struct device_node *np = pp->dev->of_node; |
@@ -436,7 +528,7 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
436 | struct resource *cfg_res; | 528 | struct resource *cfg_res; |
437 | int i, ret; | 529 | int i, ret; |
438 | LIST_HEAD(res); | 530 | LIST_HEAD(res); |
439 | struct resource_entry *win; | 531 | struct resource_entry *win, *tmp; |
440 | 532 | ||
441 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); | 533 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); |
442 | if (cfg_res) { | 534 | if (cfg_res) { |
@@ -457,17 +549,20 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
457 | goto error; | 549 | goto error; |
458 | 550 | ||
459 | /* Get the I/O and memory ranges from DT */ | 551 | /* Get the I/O and memory ranges from DT */ |
460 | resource_list_for_each_entry(win, &res) { | 552 | resource_list_for_each_entry_safe(win, tmp, &res) { |
461 | switch (resource_type(win->res)) { | 553 | switch (resource_type(win->res)) { |
462 | case IORESOURCE_IO: | 554 | case IORESOURCE_IO: |
463 | pp->io = win->res; | 555 | ret = pci_remap_iospace(win->res, pp->io_base); |
464 | pp->io->name = "I/O"; | 556 | if (ret) { |
465 | pp->io_size = resource_size(pp->io); | ||
466 | pp->io_bus_addr = pp->io->start - win->offset; | ||
467 | ret = pci_remap_iospace(pp->io, pp->io_base); | ||
468 | if (ret) | ||
469 | dev_warn(pp->dev, "error %d: failed to map resource %pR\n", | 557 | dev_warn(pp->dev, "error %d: failed to map resource %pR\n", |
470 | ret, pp->io); | 558 | ret, win->res); |
559 | resource_list_destroy_entry(win); | ||
560 | } else { | ||
561 | pp->io = win->res; | ||
562 | pp->io->name = "I/O"; | ||
563 | pp->io_size = resource_size(pp->io); | ||
564 | pp->io_bus_addr = pp->io->start - win->offset; | ||
565 | } | ||
471 | break; | 566 | break; |
472 | case IORESOURCE_MEM: | 567 | case IORESOURCE_MEM: |
473 | pp->mem = win->res; | 568 | pp->mem = win->res; |
@@ -524,6 +619,10 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
524 | if (ret) | 619 | if (ret) |
525 | pp->lanes = 0; | 620 | pp->lanes = 0; |
526 | 621 | ||
622 | ret = of_property_read_u32(np, "num-viewport", &pp->num_viewport); | ||
623 | if (ret) | ||
624 | pp->num_viewport = 2; | ||
625 | |||
527 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | 626 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
528 | if (!pp->ops->msi_host_init) { | 627 | if (!pp->ops->msi_host_init) { |
529 | pp->irq_domain = irq_domain_add_linear(pp->dev->of_node, | 628 | pp->irq_domain = irq_domain_add_linear(pp->dev->of_node, |
@@ -544,6 +643,8 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
544 | } | 643 | } |
545 | } | 644 | } |
546 | 645 | ||
646 | pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp); | ||
647 | |||
547 | if (pp->ops->host_init) | 648 | if (pp->ops->host_init) |
548 | pp->ops->host_init(pp); | 649 | pp->ops->host_init(pp); |
549 | 650 | ||
@@ -609,13 +710,14 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
609 | va_cfg_base = pp->va_cfg1_base; | 710 | va_cfg_base = pp->va_cfg1_base; |
610 | } | 711 | } |
611 | 712 | ||
612 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 713 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, |
613 | type, cpu_addr, | 714 | type, cpu_addr, |
614 | busdev, cfg_size); | 715 | busdev, cfg_size); |
615 | ret = dw_pcie_cfg_read(va_cfg_base + where, size, val); | 716 | ret = dw_pcie_cfg_read(va_cfg_base + where, size, val); |
616 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 717 | if (pp->num_viewport <= 2) |
617 | PCIE_ATU_TYPE_IO, pp->io_base, | 718 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, |
618 | pp->io_bus_addr, pp->io_size); | 719 | PCIE_ATU_TYPE_IO, pp->io_base, |
720 | pp->io_bus_addr, pp->io_size); | ||
619 | 721 | ||
620 | return ret; | 722 | return ret; |
621 | } | 723 | } |
@@ -646,13 +748,14 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
646 | va_cfg_base = pp->va_cfg1_base; | 748 | va_cfg_base = pp->va_cfg1_base; |
647 | } | 749 | } |
648 | 750 | ||
649 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 751 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, |
650 | type, cpu_addr, | 752 | type, cpu_addr, |
651 | busdev, cfg_size); | 753 | busdev, cfg_size); |
652 | ret = dw_pcie_cfg_write(va_cfg_base + where, size, val); | 754 | ret = dw_pcie_cfg_write(va_cfg_base + where, size, val); |
653 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 755 | if (pp->num_viewport <= 2) |
654 | PCIE_ATU_TYPE_IO, pp->io_base, | 756 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, |
655 | pp->io_bus_addr, pp->io_size); | 757 | PCIE_ATU_TYPE_IO, pp->io_base, |
758 | pp->io_bus_addr, pp->io_size); | ||
656 | 759 | ||
657 | return ret; | 760 | return ret; |
658 | } | 761 | } |
@@ -670,13 +773,6 @@ static int dw_pcie_valid_config(struct pcie_port *pp, | |||
670 | if (bus->number == pp->root_bus_nr && dev > 0) | 773 | if (bus->number == pp->root_bus_nr && dev > 0) |
671 | return 0; | 774 | return 0; |
672 | 775 | ||
673 | /* | ||
674 | * do not read more than one device on the bus directly attached | ||
675 | * to RC's (Virtual Bridge's) DS side. | ||
676 | */ | ||
677 | if (bus->primary == pp->root_bus_nr && dev > 0) | ||
678 | return 0; | ||
679 | |||
680 | return 1; | 776 | return 1; |
681 | } | 777 | } |
682 | 778 | ||
@@ -720,7 +816,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
720 | u32 val; | 816 | u32 val; |
721 | 817 | ||
722 | /* set the number of lanes */ | 818 | /* set the number of lanes */ |
723 | dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); | 819 | val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL); |
724 | val &= ~PORT_LINK_MODE_MASK; | 820 | val &= ~PORT_LINK_MODE_MASK; |
725 | switch (pp->lanes) { | 821 | switch (pp->lanes) { |
726 | case 1: | 822 | case 1: |
@@ -742,7 +838,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
742 | dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); | 838 | dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); |
743 | 839 | ||
744 | /* set link width speed control register */ | 840 | /* set link width speed control register */ |
745 | dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, &val); | 841 | val = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL); |
746 | val &= ~PORT_LOGIC_LINK_WIDTH_MASK; | 842 | val &= ~PORT_LOGIC_LINK_WIDTH_MASK; |
747 | switch (pp->lanes) { | 843 | switch (pp->lanes) { |
748 | case 1: | 844 | case 1: |
@@ -765,19 +861,19 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
765 | dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1); | 861 | dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1); |
766 | 862 | ||
767 | /* setup interrupt pins */ | 863 | /* setup interrupt pins */ |
768 | dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val); | 864 | val = dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE); |
769 | val &= 0xffff00ff; | 865 | val &= 0xffff00ff; |
770 | val |= 0x00000100; | 866 | val |= 0x00000100; |
771 | dw_pcie_writel_rc(pp, val, PCI_INTERRUPT_LINE); | 867 | dw_pcie_writel_rc(pp, val, PCI_INTERRUPT_LINE); |
772 | 868 | ||
773 | /* setup bus numbers */ | 869 | /* setup bus numbers */ |
774 | dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS, &val); | 870 | val = dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS); |
775 | val &= 0xff000000; | 871 | val &= 0xff000000; |
776 | val |= 0x00010100; | 872 | val |= 0x00010100; |
777 | dw_pcie_writel_rc(pp, val, PCI_PRIMARY_BUS); | 873 | dw_pcie_writel_rc(pp, val, PCI_PRIMARY_BUS); |
778 | 874 | ||
779 | /* setup command register */ | 875 | /* setup command register */ |
780 | dw_pcie_readl_rc(pp, PCI_COMMAND, &val); | 876 | val = dw_pcie_readl_rc(pp, PCI_COMMAND); |
781 | val &= 0xffff0000; | 877 | val &= 0xffff0000; |
782 | val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | 878 | val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
783 | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; | 879 | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; |
@@ -788,10 +884,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
788 | * uses its own address translation component rather than ATU, so | 884 | * uses its own address translation component rather than ATU, so |
789 | * we should not program the ATU here. | 885 | * we should not program the ATU here. |
790 | */ | 886 | */ |
791 | if (!pp->ops->rd_other_conf) | 887 | if (!pp->ops->rd_other_conf) { |
792 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, | 888 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, |
793 | PCIE_ATU_TYPE_MEM, pp->mem_base, | 889 | PCIE_ATU_TYPE_MEM, pp->mem_base, |
794 | pp->mem_bus_addr, pp->mem_size); | 890 | pp->mem_bus_addr, pp->mem_size); |
891 | if (pp->num_viewport > 2) | ||
892 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX2, | ||
893 | PCIE_ATU_TYPE_IO, pp->io_base, | ||
894 | pp->io_bus_addr, pp->io_size); | ||
895 | } | ||
795 | 896 | ||
796 | dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); | 897 | dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); |
797 | 898 | ||
@@ -802,7 +903,3 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
802 | val |= PORT_LOGIC_SPEED_CHANGE; | 903 | val |= PORT_LOGIC_SPEED_CHANGE; |
803 | dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); | 904 | dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); |
804 | } | 905 | } |
805 | |||
806 | MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); | ||
807 | MODULE_DESCRIPTION("Designware PCIe host controller driver"); | ||
808 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index f437f9b5be04..c8e5bc647f49 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h | |||
@@ -22,11 +22,6 @@ | |||
22 | #define MAX_MSI_IRQS 32 | 22 | #define MAX_MSI_IRQS 32 |
23 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) | 23 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) |
24 | 24 | ||
25 | /* Parameters for the waiting for link up routine */ | ||
26 | #define LINK_WAIT_MAX_RETRIES 10 | ||
27 | #define LINK_WAIT_USLEEP_MIN 90000 | ||
28 | #define LINK_WAIT_USLEEP_MAX 100000 | ||
29 | |||
30 | struct pcie_port { | 25 | struct pcie_port { |
31 | struct device *dev; | 26 | struct device *dev; |
32 | u8 root_bus_nr; | 27 | u8 root_bus_nr; |
@@ -49,16 +44,17 @@ struct pcie_port { | |||
49 | struct resource *busn; | 44 | struct resource *busn; |
50 | int irq; | 45 | int irq; |
51 | u32 lanes; | 46 | u32 lanes; |
47 | u32 num_viewport; | ||
52 | struct pcie_host_ops *ops; | 48 | struct pcie_host_ops *ops; |
53 | int msi_irq; | 49 | int msi_irq; |
54 | struct irq_domain *irq_domain; | 50 | struct irq_domain *irq_domain; |
55 | unsigned long msi_data; | 51 | unsigned long msi_data; |
52 | u8 iatu_unroll_enabled; | ||
56 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); | 53 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); |
57 | }; | 54 | }; |
58 | 55 | ||
59 | struct pcie_host_ops { | 56 | struct pcie_host_ops { |
60 | void (*readl_rc)(struct pcie_port *pp, | 57 | u32 (*readl_rc)(struct pcie_port *pp, void __iomem *dbi_base); |
61 | void __iomem *dbi_base, u32 *val); | ||
62 | void (*writel_rc)(struct pcie_port *pp, | 58 | void (*writel_rc)(struct pcie_port *pp, |
63 | u32 val, void __iomem *dbi_base); | 59 | u32 val, void __iomem *dbi_base); |
64 | int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); | 60 | int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); |
diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c index f2f90c50f75d..5ec2d440a6b7 100644 --- a/drivers/pci/host/pcie-qcom.c +++ b/drivers/pci/host/pcie-qcom.c | |||
@@ -1,7 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Qualcomm PCIe root complex driver | ||
3 | * | ||
2 | * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. | 4 | * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. |
3 | * Copyright 2015 Linaro Limited. | 5 | * Copyright 2015 Linaro Limited. |
4 | * | 6 | * |
7 | * Author: Stanimir Varbanov <svarbanov@mm-sol.com> | ||
8 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 and | 10 | * it under the terms of the GNU General Public License version 2 and |
7 | * only version 2 as published by the Free Software Foundation. | 11 | * only version 2 as published by the Free Software Foundation. |
@@ -19,7 +23,7 @@ | |||
19 | #include <linux/io.h> | 23 | #include <linux/io.h> |
20 | #include <linux/iopoll.h> | 24 | #include <linux/iopoll.h> |
21 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 26 | #include <linux/init.h> |
23 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
24 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
25 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
@@ -570,37 +574,19 @@ static int qcom_pcie_probe(struct platform_device *pdev) | |||
570 | return 0; | 574 | return 0; |
571 | } | 575 | } |
572 | 576 | ||
573 | static int qcom_pcie_remove(struct platform_device *pdev) | ||
574 | { | ||
575 | struct qcom_pcie *pcie = platform_get_drvdata(pdev); | ||
576 | |||
577 | qcom_ep_reset_assert(pcie); | ||
578 | phy_power_off(pcie->phy); | ||
579 | phy_exit(pcie->phy); | ||
580 | pcie->ops->deinit(pcie); | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static const struct of_device_id qcom_pcie_match[] = { | 577 | static const struct of_device_id qcom_pcie_match[] = { |
586 | { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, | 578 | { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 }, |
587 | { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, | 579 | { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 }, |
588 | { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, | 580 | { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 }, |
589 | { } | 581 | { } |
590 | }; | 582 | }; |
591 | MODULE_DEVICE_TABLE(of, qcom_pcie_match); | ||
592 | 583 | ||
593 | static struct platform_driver qcom_pcie_driver = { | 584 | static struct platform_driver qcom_pcie_driver = { |
594 | .probe = qcom_pcie_probe, | 585 | .probe = qcom_pcie_probe, |
595 | .remove = qcom_pcie_remove, | ||
596 | .driver = { | 586 | .driver = { |
597 | .name = "qcom-pcie", | 587 | .name = "qcom-pcie", |
588 | .suppress_bind_attrs = true, | ||
598 | .of_match_table = qcom_pcie_match, | 589 | .of_match_table = qcom_pcie_match, |
599 | }, | 590 | }, |
600 | }; | 591 | }; |
601 | 592 | builtin_platform_driver(qcom_pcie_driver); | |
602 | module_platform_driver(qcom_pcie_driver); | ||
603 | |||
604 | MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>"); | ||
605 | MODULE_DESCRIPTION("Qualcomm PCIe root complex driver"); | ||
606 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 65db7a221509..e06b1d3b4dea 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c | |||
@@ -84,8 +84,18 @@ | |||
84 | #define IDSETR1 0x011004 | 84 | #define IDSETR1 0x011004 |
85 | #define TLCTLR 0x011048 | 85 | #define TLCTLR 0x011048 |
86 | #define MACSR 0x011054 | 86 | #define MACSR 0x011054 |
87 | #define SPCHGFIN (1 << 4) | ||
88 | #define SPCHGFAIL (1 << 6) | ||
89 | #define SPCHGSUC (1 << 7) | ||
90 | #define LINK_SPEED (0xf << 16) | ||
91 | #define LINK_SPEED_2_5GTS (1 << 16) | ||
92 | #define LINK_SPEED_5_0GTS (2 << 16) | ||
87 | #define MACCTLR 0x011058 | 93 | #define MACCTLR 0x011058 |
94 | #define SPEED_CHANGE (1 << 24) | ||
88 | #define SCRAMBLE_DISABLE (1 << 27) | 95 | #define SCRAMBLE_DISABLE (1 << 27) |
96 | #define MACS2R 0x011078 | ||
97 | #define MACCGSPSETR 0x011084 | ||
98 | #define SPCNGRSN (1 << 31) | ||
89 | 99 | ||
90 | /* R-Car H1 PHY */ | 100 | /* R-Car H1 PHY */ |
91 | #define H1_PCIEPHYADRR 0x04000c | 101 | #define H1_PCIEPHYADRR 0x04000c |
@@ -385,11 +395,67 @@ static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci) | |||
385 | return 1; | 395 | return 1; |
386 | } | 396 | } |
387 | 397 | ||
398 | static void rcar_pcie_force_speedup(struct rcar_pcie *pcie) | ||
399 | { | ||
400 | unsigned int timeout = 1000; | ||
401 | u32 macsr; | ||
402 | |||
403 | if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS) | ||
404 | return; | ||
405 | |||
406 | if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) { | ||
407 | dev_err(pcie->dev, "Speed change already in progress\n"); | ||
408 | return; | ||
409 | } | ||
410 | |||
411 | macsr = rcar_pci_read_reg(pcie, MACSR); | ||
412 | if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS) | ||
413 | goto done; | ||
414 | |||
415 | /* Set target link speed to 5.0 GT/s */ | ||
416 | rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS, | ||
417 | PCI_EXP_LNKSTA_CLS_5_0GB); | ||
418 | |||
419 | /* Set speed change reason as intentional factor */ | ||
420 | rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0); | ||
421 | |||
422 | /* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */ | ||
423 | if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL)) | ||
424 | rcar_pci_write_reg(pcie, macsr, MACSR); | ||
425 | |||
426 | /* Start link speed change */ | ||
427 | rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE); | ||
428 | |||
429 | while (timeout--) { | ||
430 | macsr = rcar_pci_read_reg(pcie, MACSR); | ||
431 | if (macsr & SPCHGFIN) { | ||
432 | /* Clear the interrupt bits */ | ||
433 | rcar_pci_write_reg(pcie, macsr, MACSR); | ||
434 | |||
435 | if (macsr & SPCHGFAIL) | ||
436 | dev_err(pcie->dev, "Speed change failed\n"); | ||
437 | |||
438 | goto done; | ||
439 | } | ||
440 | |||
441 | msleep(1); | ||
442 | }; | ||
443 | |||
444 | dev_err(pcie->dev, "Speed change timed out\n"); | ||
445 | |||
446 | done: | ||
447 | dev_info(pcie->dev, "Current link speed is %s GT/s\n", | ||
448 | (macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5"); | ||
449 | } | ||
450 | |||
388 | static int rcar_pcie_enable(struct rcar_pcie *pcie) | 451 | static int rcar_pcie_enable(struct rcar_pcie *pcie) |
389 | { | 452 | { |
390 | struct pci_bus *bus, *child; | 453 | struct pci_bus *bus, *child; |
391 | LIST_HEAD(res); | 454 | LIST_HEAD(res); |
392 | 455 | ||
456 | /* Try setting 5 GT/s link speed */ | ||
457 | rcar_pcie_force_speedup(pcie); | ||
458 | |||
393 | rcar_pcie_setup(&res, pcie); | 459 | rcar_pcie_setup(&res, pcie); |
394 | 460 | ||
395 | pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); | 461 | pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); |
@@ -608,6 +674,18 @@ static int rcar_msi_alloc(struct rcar_msi *chip) | |||
608 | return msi; | 674 | return msi; |
609 | } | 675 | } |
610 | 676 | ||
677 | static int rcar_msi_alloc_region(struct rcar_msi *chip, int no_irqs) | ||
678 | { | ||
679 | int msi; | ||
680 | |||
681 | mutex_lock(&chip->lock); | ||
682 | msi = bitmap_find_free_region(chip->used, INT_PCI_MSI_NR, | ||
683 | order_base_2(no_irqs)); | ||
684 | mutex_unlock(&chip->lock); | ||
685 | |||
686 | return msi; | ||
687 | } | ||
688 | |||
611 | static void rcar_msi_free(struct rcar_msi *chip, unsigned long irq) | 689 | static void rcar_msi_free(struct rcar_msi *chip, unsigned long irq) |
612 | { | 690 | { |
613 | mutex_lock(&chip->lock); | 691 | mutex_lock(&chip->lock); |
@@ -665,7 +743,7 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, | |||
665 | if (hwirq < 0) | 743 | if (hwirq < 0) |
666 | return hwirq; | 744 | return hwirq; |
667 | 745 | ||
668 | irq = irq_create_mapping(msi->domain, hwirq); | 746 | irq = irq_find_mapping(msi->domain, hwirq); |
669 | if (!irq) { | 747 | if (!irq) { |
670 | rcar_msi_free(msi, hwirq); | 748 | rcar_msi_free(msi, hwirq); |
671 | return -EINVAL; | 749 | return -EINVAL; |
@@ -682,6 +760,58 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, | |||
682 | return 0; | 760 | return 0; |
683 | } | 761 | } |
684 | 762 | ||
763 | static int rcar_msi_setup_irqs(struct msi_controller *chip, | ||
764 | struct pci_dev *pdev, int nvec, int type) | ||
765 | { | ||
766 | struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip); | ||
767 | struct rcar_msi *msi = to_rcar_msi(chip); | ||
768 | struct msi_desc *desc; | ||
769 | struct msi_msg msg; | ||
770 | unsigned int irq; | ||
771 | int hwirq; | ||
772 | int i; | ||
773 | |||
774 | /* MSI-X interrupts are not supported */ | ||
775 | if (type == PCI_CAP_ID_MSIX) | ||
776 | return -EINVAL; | ||
777 | |||
778 | WARN_ON(!list_is_singular(&pdev->dev.msi_list)); | ||
779 | desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list); | ||
780 | |||
781 | hwirq = rcar_msi_alloc_region(msi, nvec); | ||
782 | if (hwirq < 0) | ||
783 | return -ENOSPC; | ||
784 | |||
785 | irq = irq_find_mapping(msi->domain, hwirq); | ||
786 | if (!irq) | ||
787 | return -ENOSPC; | ||
788 | |||
789 | for (i = 0; i < nvec; i++) { | ||
790 | /* | ||
791 | * irq_create_mapping() called from rcar_pcie_probe() pre- | ||
792 | * allocates descs, so there is no need to allocate descs here. | ||
793 | * We can therefore assume that if irq_find_mapping() above | ||
794 | * returns non-zero, then the descs are also successfully | ||
795 | * allocated. | ||
796 | */ | ||
797 | if (irq_set_msi_desc_off(irq, i, desc)) { | ||
798 | /* TODO: clear */ | ||
799 | return -EINVAL; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | desc->nvec_used = nvec; | ||
804 | desc->msi_attrib.multiple = order_base_2(nvec); | ||
805 | |||
806 | msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE; | ||
807 | msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR); | ||
808 | msg.data = hwirq; | ||
809 | |||
810 | pci_write_msi_msg(irq, &msg); | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
685 | static void rcar_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) | 815 | static void rcar_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) |
686 | { | 816 | { |
687 | struct rcar_msi *msi = to_rcar_msi(chip); | 817 | struct rcar_msi *msi = to_rcar_msi(chip); |
@@ -716,12 +846,13 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie) | |||
716 | struct platform_device *pdev = to_platform_device(pcie->dev); | 846 | struct platform_device *pdev = to_platform_device(pcie->dev); |
717 | struct rcar_msi *msi = &pcie->msi; | 847 | struct rcar_msi *msi = &pcie->msi; |
718 | unsigned long base; | 848 | unsigned long base; |
719 | int err; | 849 | int err, i; |
720 | 850 | ||
721 | mutex_init(&msi->lock); | 851 | mutex_init(&msi->lock); |
722 | 852 | ||
723 | msi->chip.dev = pcie->dev; | 853 | msi->chip.dev = pcie->dev; |
724 | msi->chip.setup_irq = rcar_msi_setup_irq; | 854 | msi->chip.setup_irq = rcar_msi_setup_irq; |
855 | msi->chip.setup_irqs = rcar_msi_setup_irqs; | ||
725 | msi->chip.teardown_irq = rcar_msi_teardown_irq; | 856 | msi->chip.teardown_irq = rcar_msi_teardown_irq; |
726 | 857 | ||
727 | msi->domain = irq_domain_add_linear(pcie->dev->of_node, INT_PCI_MSI_NR, | 858 | msi->domain = irq_domain_add_linear(pcie->dev->of_node, INT_PCI_MSI_NR, |
@@ -731,6 +862,9 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie) | |||
731 | return -ENOMEM; | 862 | return -ENOMEM; |
732 | } | 863 | } |
733 | 864 | ||
865 | for (i = 0; i < INT_PCI_MSI_NR; i++) | ||
866 | irq_create_mapping(msi->domain, i); | ||
867 | |||
734 | /* Two irqs are for MSI, but they are also used for non-MSI irqs */ | 868 | /* Two irqs are for MSI, but they are also used for non-MSI irqs */ |
735 | err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq, | 869 | err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq, |
736 | IRQF_SHARED | IRQF_NO_THREAD, | 870 | IRQF_SHARED | IRQF_NO_THREAD, |
@@ -775,6 +909,10 @@ static int rcar_pcie_get_resources(struct platform_device *pdev, | |||
775 | if (err) | 909 | if (err) |
776 | return err; | 910 | return err; |
777 | 911 | ||
912 | pcie->base = devm_ioremap_resource(&pdev->dev, &res); | ||
913 | if (IS_ERR(pcie->base)) | ||
914 | return PTR_ERR(pcie->base); | ||
915 | |||
778 | pcie->clk = devm_clk_get(&pdev->dev, "pcie"); | 916 | pcie->clk = devm_clk_get(&pdev->dev, "pcie"); |
779 | if (IS_ERR(pcie->clk)) { | 917 | if (IS_ERR(pcie->clk)) { |
780 | dev_err(pcie->dev, "cannot get platform clock\n"); | 918 | dev_err(pcie->dev, "cannot get platform clock\n"); |
@@ -782,7 +920,7 @@ static int rcar_pcie_get_resources(struct platform_device *pdev, | |||
782 | } | 920 | } |
783 | err = clk_prepare_enable(pcie->clk); | 921 | err = clk_prepare_enable(pcie->clk); |
784 | if (err) | 922 | if (err) |
785 | goto fail_clk; | 923 | return err; |
786 | 924 | ||
787 | pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus"); | 925 | pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus"); |
788 | if (IS_ERR(pcie->bus_clk)) { | 926 | if (IS_ERR(pcie->bus_clk)) { |
@@ -792,7 +930,7 @@ static int rcar_pcie_get_resources(struct platform_device *pdev, | |||
792 | } | 930 | } |
793 | err = clk_prepare_enable(pcie->bus_clk); | 931 | err = clk_prepare_enable(pcie->bus_clk); |
794 | if (err) | 932 | if (err) |
795 | goto err_map_reg; | 933 | goto fail_clk; |
796 | 934 | ||
797 | i = irq_of_parse_and_map(pdev->dev.of_node, 0); | 935 | i = irq_of_parse_and_map(pdev->dev.of_node, 0); |
798 | if (!i) { | 936 | if (!i) { |
@@ -810,12 +948,6 @@ static int rcar_pcie_get_resources(struct platform_device *pdev, | |||
810 | } | 948 | } |
811 | pcie->msi.irq2 = i; | 949 | pcie->msi.irq2 = i; |
812 | 950 | ||
813 | pcie->base = devm_ioremap_resource(&pdev->dev, &res); | ||
814 | if (IS_ERR(pcie->base)) { | ||
815 | err = PTR_ERR(pcie->base); | ||
816 | goto err_map_reg; | ||
817 | } | ||
818 | |||
819 | return 0; | 951 | return 0; |
820 | 952 | ||
821 | err_map_reg: | 953 | err_map_reg: |
@@ -865,12 +997,16 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie, | |||
865 | * Set up 64-bit inbound regions as the range parser doesn't | 997 | * Set up 64-bit inbound regions as the range parser doesn't |
866 | * distinguish between 32 and 64-bit types. | 998 | * distinguish between 32 and 64-bit types. |
867 | */ | 999 | */ |
868 | rcar_pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx)); | 1000 | rcar_pci_write_reg(pcie, lower_32_bits(pci_addr), |
1001 | PCIEPRAR(idx)); | ||
869 | rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx)); | 1002 | rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx)); |
870 | rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx)); | 1003 | rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags, |
1004 | PCIELAMR(idx)); | ||
871 | 1005 | ||
872 | rcar_pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1)); | 1006 | rcar_pci_write_reg(pcie, upper_32_bits(pci_addr), |
873 | rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1)); | 1007 | PCIEPRAR(idx + 1)); |
1008 | rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr), | ||
1009 | PCIELAR(idx + 1)); | ||
874 | rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1)); | 1010 | rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1)); |
875 | 1011 | ||
876 | pci_addr += size; | 1012 | pci_addr += size; |
@@ -919,6 +1055,7 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, | |||
919 | /* Get the dma-ranges from DT */ | 1055 | /* Get the dma-ranges from DT */ |
920 | for_each_of_pci_range(&parser, &range) { | 1056 | for_each_of_pci_range(&parser, &range) { |
921 | u64 end = range.cpu_addr + range.size - 1; | 1057 | u64 end = range.cpu_addr + range.size - 1; |
1058 | |||
922 | dev_dbg(pcie->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n", | 1059 | dev_dbg(pcie->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n", |
923 | range.flags, range.cpu_addr, end, range.pci_addr); | 1060 | range.flags, range.cpu_addr, end, range.pci_addr); |
924 | 1061 | ||
@@ -932,9 +1069,12 @@ static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, | |||
932 | 1069 | ||
933 | static const struct of_device_id rcar_pcie_of_match[] = { | 1070 | static const struct of_device_id rcar_pcie_of_match[] = { |
934 | { .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 }, | 1071 | { .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 }, |
935 | { .compatible = "renesas,pcie-rcar-gen2", .data = rcar_pcie_hw_init_gen2 }, | 1072 | { .compatible = "renesas,pcie-rcar-gen2", |
936 | { .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init_gen2 }, | 1073 | .data = rcar_pcie_hw_init_gen2 }, |
937 | { .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init_gen2 }, | 1074 | { .compatible = "renesas,pcie-r8a7790", |
1075 | .data = rcar_pcie_hw_init_gen2 }, | ||
1076 | { .compatible = "renesas,pcie-r8a7791", | ||
1077 | .data = rcar_pcie_hw_init_gen2 }, | ||
938 | { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init }, | 1078 | { .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init }, |
939 | {}, | 1079 | {}, |
940 | }; | 1080 | }; |
@@ -945,9 +1085,10 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) | |||
945 | struct device *dev = pci->dev; | 1085 | struct device *dev = pci->dev; |
946 | struct device_node *np = dev->of_node; | 1086 | struct device_node *np = dev->of_node; |
947 | resource_size_t iobase; | 1087 | resource_size_t iobase; |
948 | struct resource_entry *win; | 1088 | struct resource_entry *win, *tmp; |
949 | 1089 | ||
950 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, &iobase); | 1090 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pci->resources, |
1091 | &iobase); | ||
951 | if (err) | 1092 | if (err) |
952 | return err; | 1093 | return err; |
953 | 1094 | ||
@@ -955,14 +1096,17 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci) | |||
955 | if (err) | 1096 | if (err) |
956 | goto out_release_res; | 1097 | goto out_release_res; |
957 | 1098 | ||
958 | resource_list_for_each_entry(win, &pci->resources) { | 1099 | resource_list_for_each_entry_safe(win, tmp, &pci->resources) { |
959 | struct resource *res = win->res; | 1100 | struct resource *res = win->res; |
960 | 1101 | ||
961 | if (resource_type(res) == IORESOURCE_IO) { | 1102 | if (resource_type(res) == IORESOURCE_IO) { |
962 | err = pci_remap_iospace(res, iobase); | 1103 | err = pci_remap_iospace(res, iobase); |
963 | if (err) | 1104 | if (err) { |
964 | dev_warn(dev, "error %d: failed to map resource %pR\n", | 1105 | dev_warn(dev, "error %d: failed to map resource %pR\n", |
965 | err, res); | 1106 | err, res); |
1107 | |||
1108 | resource_list_destroy_entry(win); | ||
1109 | } | ||
966 | } | 1110 | } |
967 | } | 1111 | } |
968 | 1112 | ||
@@ -998,8 +1142,8 @@ static int rcar_pcie_probe(struct platform_device *pdev) | |||
998 | return err; | 1142 | return err; |
999 | } | 1143 | } |
1000 | 1144 | ||
1001 | err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); | 1145 | err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); |
1002 | if (err) | 1146 | if (err) |
1003 | return err; | 1147 | return err; |
1004 | 1148 | ||
1005 | of_id = of_match_device(rcar_pcie_of_match, pcie->dev); | 1149 | of_id = of_match_device(rcar_pcie_of_match, pcie->dev); |
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c new file mode 100644 index 000000000000..b8c82fc812dc --- /dev/null +++ b/drivers/pci/host/pcie-rockchip.c | |||
@@ -0,0 +1,1229 @@ | |||
1 | /* | ||
2 | * Rockchip AXI PCIe host controller driver | ||
3 | * | ||
4 | * Copyright (c) 2016 Rockchip, Inc. | ||
5 | * | ||
6 | * Author: Shawn Lin <shawn.lin@rock-chips.com> | ||
7 | * Wenrui Li <wenrui.li@rock-chips.com> | ||
8 | * | ||
9 | * Bits taken from Synopsys Designware Host controller driver and | ||
10 | * ARM PCI Host generic driver. | ||
11 | * | ||
12 | * This program is free software: you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation, either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/gpio/consumer.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/irqchip/chained_irq.h> | ||
25 | #include <linux/irqdomain.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/mfd/syscon.h> | ||
28 | #include <linux/of_address.h> | ||
29 | #include <linux/of_device.h> | ||
30 | #include <linux/of_pci.h> | ||
31 | #include <linux/of_platform.h> | ||
32 | #include <linux/of_irq.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/pci_ids.h> | ||
35 | #include <linux/phy/phy.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/reset.h> | ||
38 | #include <linux/regmap.h> | ||
39 | |||
40 | /* | ||
41 | * The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16 | ||
42 | * bits. This allows atomic updates of the register without locking. | ||
43 | */ | ||
44 | #define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val)) | ||
45 | #define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) | ||
46 | |||
47 | #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) | ||
48 | |||
49 | #define PCIE_CLIENT_BASE 0x0 | ||
50 | #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) | ||
51 | #define PCIE_CLIENT_CONF_ENABLE HIWORD_UPDATE_BIT(0x0001) | ||
52 | #define PCIE_CLIENT_LINK_TRAIN_ENABLE HIWORD_UPDATE_BIT(0x0002) | ||
53 | #define PCIE_CLIENT_ARI_ENABLE HIWORD_UPDATE_BIT(0x0008) | ||
54 | #define PCIE_CLIENT_CONF_LANE_NUM(x) HIWORD_UPDATE(0x0030, ENCODE_LANES(x)) | ||
55 | #define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040) | ||
56 | #define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080) | ||
57 | #define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48) | ||
58 | #define PCIE_CLIENT_LINK_STATUS_UP 0x00300000 | ||
59 | #define PCIE_CLIENT_LINK_STATUS_MASK 0x00300000 | ||
60 | #define PCIE_CLIENT_INT_MASK (PCIE_CLIENT_BASE + 0x4c) | ||
61 | #define PCIE_CLIENT_INT_STATUS (PCIE_CLIENT_BASE + 0x50) | ||
62 | #define PCIE_CLIENT_INTR_MASK GENMASK(8, 5) | ||
63 | #define PCIE_CLIENT_INTR_SHIFT 5 | ||
64 | #define PCIE_CLIENT_INT_LEGACY_DONE BIT(15) | ||
65 | #define PCIE_CLIENT_INT_MSG BIT(14) | ||
66 | #define PCIE_CLIENT_INT_HOT_RST BIT(13) | ||
67 | #define PCIE_CLIENT_INT_DPA BIT(12) | ||
68 | #define PCIE_CLIENT_INT_FATAL_ERR BIT(11) | ||
69 | #define PCIE_CLIENT_INT_NFATAL_ERR BIT(10) | ||
70 | #define PCIE_CLIENT_INT_CORR_ERR BIT(9) | ||
71 | #define PCIE_CLIENT_INT_INTD BIT(8) | ||
72 | #define PCIE_CLIENT_INT_INTC BIT(7) | ||
73 | #define PCIE_CLIENT_INT_INTB BIT(6) | ||
74 | #define PCIE_CLIENT_INT_INTA BIT(5) | ||
75 | #define PCIE_CLIENT_INT_LOCAL BIT(4) | ||
76 | #define PCIE_CLIENT_INT_UDMA BIT(3) | ||
77 | #define PCIE_CLIENT_INT_PHY BIT(2) | ||
78 | #define PCIE_CLIENT_INT_HOT_PLUG BIT(1) | ||
79 | #define PCIE_CLIENT_INT_PWR_STCG BIT(0) | ||
80 | |||
81 | #define PCIE_CLIENT_INT_LEGACY \ | ||
82 | (PCIE_CLIENT_INT_INTA | PCIE_CLIENT_INT_INTB | \ | ||
83 | PCIE_CLIENT_INT_INTC | PCIE_CLIENT_INT_INTD) | ||
84 | |||
85 | #define PCIE_CLIENT_INT_CLI \ | ||
86 | (PCIE_CLIENT_INT_CORR_ERR | PCIE_CLIENT_INT_NFATAL_ERR | \ | ||
87 | PCIE_CLIENT_INT_FATAL_ERR | PCIE_CLIENT_INT_DPA | \ | ||
88 | PCIE_CLIENT_INT_HOT_RST | PCIE_CLIENT_INT_MSG | \ | ||
89 | PCIE_CLIENT_INT_LEGACY_DONE | PCIE_CLIENT_INT_LEGACY | \ | ||
90 | PCIE_CLIENT_INT_PHY) | ||
91 | |||
92 | #define PCIE_CORE_CTRL_MGMT_BASE 0x900000 | ||
93 | #define PCIE_CORE_CTRL (PCIE_CORE_CTRL_MGMT_BASE + 0x000) | ||
94 | #define PCIE_CORE_PL_CONF_SPEED_5G 0x00000008 | ||
95 | #define PCIE_CORE_PL_CONF_SPEED_MASK 0x00000018 | ||
96 | #define PCIE_CORE_PL_CONF_LANE_MASK 0x00000006 | ||
97 | #define PCIE_CORE_PL_CONF_LANE_SHIFT 1 | ||
98 | #define PCIE_CORE_CTRL_PLC1 (PCIE_CORE_CTRL_MGMT_BASE + 0x004) | ||
99 | #define PCIE_CORE_CTRL_PLC1_FTS_MASK GENMASK(23, 8) | ||
100 | #define PCIE_CORE_CTRL_PLC1_FTS_SHIFT 8 | ||
101 | #define PCIE_CORE_CTRL_PLC1_FTS_CNT 0xffff | ||
102 | #define PCIE_CORE_TXCREDIT_CFG1 (PCIE_CORE_CTRL_MGMT_BASE + 0x020) | ||
103 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_MASK 0xFFFF0000 | ||
104 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT 16 | ||
105 | #define PCIE_CORE_TXCREDIT_CFG1_MUI_ENCODE(x) \ | ||
106 | (((x) >> 3) << PCIE_CORE_TXCREDIT_CFG1_MUI_SHIFT) | ||
107 | #define PCIE_CORE_INT_STATUS (PCIE_CORE_CTRL_MGMT_BASE + 0x20c) | ||
108 | #define PCIE_CORE_INT_PRFPE BIT(0) | ||
109 | #define PCIE_CORE_INT_CRFPE BIT(1) | ||
110 | #define PCIE_CORE_INT_RRPE BIT(2) | ||
111 | #define PCIE_CORE_INT_PRFO BIT(3) | ||
112 | #define PCIE_CORE_INT_CRFO BIT(4) | ||
113 | #define PCIE_CORE_INT_RT BIT(5) | ||
114 | #define PCIE_CORE_INT_RTR BIT(6) | ||
115 | #define PCIE_CORE_INT_PE BIT(7) | ||
116 | #define PCIE_CORE_INT_MTR BIT(8) | ||
117 | #define PCIE_CORE_INT_UCR BIT(9) | ||
118 | #define PCIE_CORE_INT_FCE BIT(10) | ||
119 | #define PCIE_CORE_INT_CT BIT(11) | ||
120 | #define PCIE_CORE_INT_UTC BIT(18) | ||
121 | #define PCIE_CORE_INT_MMVC BIT(19) | ||
122 | #define PCIE_CORE_INT_MASK (PCIE_CORE_CTRL_MGMT_BASE + 0x210) | ||
123 | #define PCIE_RC_BAR_CONF (PCIE_CORE_CTRL_MGMT_BASE + 0x300) | ||
124 | |||
125 | #define PCIE_CORE_INT \ | ||
126 | (PCIE_CORE_INT_PRFPE | PCIE_CORE_INT_CRFPE | \ | ||
127 | PCIE_CORE_INT_RRPE | PCIE_CORE_INT_CRFO | \ | ||
128 | PCIE_CORE_INT_RT | PCIE_CORE_INT_RTR | \ | ||
129 | PCIE_CORE_INT_PE | PCIE_CORE_INT_MTR | \ | ||
130 | PCIE_CORE_INT_UCR | PCIE_CORE_INT_FCE | \ | ||
131 | PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \ | ||
132 | PCIE_CORE_INT_MMVC) | ||
133 | |||
134 | #define PCIE_RC_CONFIG_BASE 0xa00000 | ||
135 | #define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00) | ||
136 | #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) | ||
137 | #define PCIE_RC_CONFIG_SCC_SHIFT 16 | ||
138 | #define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0) | ||
139 | #define PCIE_RC_CONFIG_LCS_RETRAIN_LINK BIT(5) | ||
140 | #define PCIE_RC_CONFIG_LCS_LBMIE BIT(10) | ||
141 | #define PCIE_RC_CONFIG_LCS_LABIE BIT(11) | ||
142 | #define PCIE_RC_CONFIG_LCS_LBMS BIT(30) | ||
143 | #define PCIE_RC_CONFIG_LCS_LAMS BIT(31) | ||
144 | #define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c) | ||
145 | |||
146 | #define PCIE_CORE_AXI_CONF_BASE 0xc00000 | ||
147 | #define PCIE_CORE_OB_REGION_ADDR0 (PCIE_CORE_AXI_CONF_BASE + 0x0) | ||
148 | #define PCIE_CORE_OB_REGION_ADDR0_NUM_BITS 0x3f | ||
149 | #define PCIE_CORE_OB_REGION_ADDR0_LO_ADDR 0xffffff00 | ||
150 | #define PCIE_CORE_OB_REGION_ADDR1 (PCIE_CORE_AXI_CONF_BASE + 0x4) | ||
151 | #define PCIE_CORE_OB_REGION_DESC0 (PCIE_CORE_AXI_CONF_BASE + 0x8) | ||
152 | #define PCIE_CORE_OB_REGION_DESC1 (PCIE_CORE_AXI_CONF_BASE + 0xc) | ||
153 | |||
154 | #define PCIE_CORE_AXI_INBOUND_BASE 0xc00800 | ||
155 | #define PCIE_RP_IB_ADDR0 (PCIE_CORE_AXI_INBOUND_BASE + 0x0) | ||
156 | #define PCIE_CORE_IB_REGION_ADDR0_NUM_BITS 0x3f | ||
157 | #define PCIE_CORE_IB_REGION_ADDR0_LO_ADDR 0xffffff00 | ||
158 | #define PCIE_RP_IB_ADDR1 (PCIE_CORE_AXI_INBOUND_BASE + 0x4) | ||
159 | |||
160 | /* Size of one AXI Region (not Region 0) */ | ||
161 | #define AXI_REGION_SIZE BIT(20) | ||
162 | /* Size of Region 0, equal to sum of sizes of other regions */ | ||
163 | #define AXI_REGION_0_SIZE (32 * (0x1 << 20)) | ||
164 | #define OB_REG_SIZE_SHIFT 5 | ||
165 | #define IB_ROOT_PORT_REG_SIZE_SHIFT 3 | ||
166 | #define AXI_WRAPPER_IO_WRITE 0x6 | ||
167 | #define AXI_WRAPPER_MEM_WRITE 0x2 | ||
168 | |||
169 | #define MAX_AXI_IB_ROOTPORT_REGION_NUM 3 | ||
170 | #define MIN_AXI_ADDR_BITS_PASSED 8 | ||
171 | #define ROCKCHIP_VENDOR_ID 0x1d87 | ||
172 | #define PCIE_ECAM_BUS(x) (((x) & 0xff) << 20) | ||
173 | #define PCIE_ECAM_DEV(x) (((x) & 0x1f) << 15) | ||
174 | #define PCIE_ECAM_FUNC(x) (((x) & 0x7) << 12) | ||
175 | #define PCIE_ECAM_REG(x) (((x) & 0xfff) << 0) | ||
176 | #define PCIE_ECAM_ADDR(bus, dev, func, reg) \ | ||
177 | (PCIE_ECAM_BUS(bus) | PCIE_ECAM_DEV(dev) | \ | ||
178 | PCIE_ECAM_FUNC(func) | PCIE_ECAM_REG(reg)) | ||
179 | |||
180 | #define RC_REGION_0_ADDR_TRANS_H 0x00000000 | ||
181 | #define RC_REGION_0_ADDR_TRANS_L 0x00000000 | ||
182 | #define RC_REGION_0_PASS_BITS (25 - 1) | ||
183 | #define MAX_AXI_WRAPPER_REGION_NUM 33 | ||
184 | |||
185 | struct rockchip_pcie { | ||
186 | void __iomem *reg_base; /* DT axi-base */ | ||
187 | void __iomem *apb_base; /* DT apb-base */ | ||
188 | struct phy *phy; | ||
189 | struct reset_control *core_rst; | ||
190 | struct reset_control *mgmt_rst; | ||
191 | struct reset_control *mgmt_sticky_rst; | ||
192 | struct reset_control *pipe_rst; | ||
193 | struct clk *aclk_pcie; | ||
194 | struct clk *aclk_perf_pcie; | ||
195 | struct clk *hclk_pcie; | ||
196 | struct clk *clk_pcie_pm; | ||
197 | struct regulator *vpcie3v3; /* 3.3V power supply */ | ||
198 | struct regulator *vpcie1v8; /* 1.8V power supply */ | ||
199 | struct regulator *vpcie0v9; /* 0.9V power supply */ | ||
200 | struct gpio_desc *ep_gpio; | ||
201 | u32 lanes; | ||
202 | u8 root_bus_nr; | ||
203 | struct device *dev; | ||
204 | struct irq_domain *irq_domain; | ||
205 | }; | ||
206 | |||
207 | static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg) | ||
208 | { | ||
209 | return readl(rockchip->apb_base + reg); | ||
210 | } | ||
211 | |||
212 | static void rockchip_pcie_write(struct rockchip_pcie *rockchip, u32 val, | ||
213 | u32 reg) | ||
214 | { | ||
215 | writel(val, rockchip->apb_base + reg); | ||
216 | } | ||
217 | |||
218 | static void rockchip_pcie_enable_bw_int(struct rockchip_pcie *rockchip) | ||
219 | { | ||
220 | u32 status; | ||
221 | |||
222 | status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); | ||
223 | status |= (PCIE_RC_CONFIG_LCS_LBMIE | PCIE_RC_CONFIG_LCS_LABIE); | ||
224 | rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); | ||
225 | } | ||
226 | |||
227 | static void rockchip_pcie_clr_bw_int(struct rockchip_pcie *rockchip) | ||
228 | { | ||
229 | u32 status; | ||
230 | |||
231 | status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); | ||
232 | status |= (PCIE_RC_CONFIG_LCS_LBMS | PCIE_RC_CONFIG_LCS_LAMS); | ||
233 | rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); | ||
234 | } | ||
235 | |||
236 | static void rockchip_pcie_update_txcredit_mui(struct rockchip_pcie *rockchip) | ||
237 | { | ||
238 | u32 val; | ||
239 | |||
240 | /* Update Tx credit maximum update interval */ | ||
241 | val = rockchip_pcie_read(rockchip, PCIE_CORE_TXCREDIT_CFG1); | ||
242 | val &= ~PCIE_CORE_TXCREDIT_CFG1_MUI_MASK; | ||
243 | val |= PCIE_CORE_TXCREDIT_CFG1_MUI_ENCODE(24000); /* ns */ | ||
244 | rockchip_pcie_write(rockchip, val, PCIE_CORE_TXCREDIT_CFG1); | ||
245 | } | ||
246 | |||
247 | static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip, | ||
248 | struct pci_bus *bus, int dev) | ||
249 | { | ||
250 | /* access only one slot on each root port */ | ||
251 | if (bus->number == rockchip->root_bus_nr && dev > 0) | ||
252 | return 0; | ||
253 | |||
254 | /* | ||
255 | * do not read more than one device on the bus directly attached | ||
256 | * to RC's downstream side. | ||
257 | */ | ||
258 | if (bus->primary == rockchip->root_bus_nr && dev > 0) | ||
259 | return 0; | ||
260 | |||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip, | ||
265 | int where, int size, u32 *val) | ||
266 | { | ||
267 | void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where; | ||
268 | |||
269 | if (!IS_ALIGNED((uintptr_t)addr, size)) { | ||
270 | *val = 0; | ||
271 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
272 | } | ||
273 | |||
274 | if (size == 4) { | ||
275 | *val = readl(addr); | ||
276 | } else if (size == 2) { | ||
277 | *val = readw(addr); | ||
278 | } else if (size == 1) { | ||
279 | *val = readb(addr); | ||
280 | } else { | ||
281 | *val = 0; | ||
282 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
283 | } | ||
284 | return PCIBIOS_SUCCESSFUL; | ||
285 | } | ||
286 | |||
287 | static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip, | ||
288 | int where, int size, u32 val) | ||
289 | { | ||
290 | u32 mask, tmp, offset; | ||
291 | |||
292 | offset = where & ~0x3; | ||
293 | |||
294 | if (size == 4) { | ||
295 | writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset); | ||
296 | return PCIBIOS_SUCCESSFUL; | ||
297 | } | ||
298 | |||
299 | mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8)); | ||
300 | |||
301 | /* | ||
302 | * N.B. This read/modify/write isn't safe in general because it can | ||
303 | * corrupt RW1C bits in adjacent registers. But the hardware | ||
304 | * doesn't support smaller writes. | ||
305 | */ | ||
306 | tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask; | ||
307 | tmp |= val << ((where & 0x3) * 8); | ||
308 | writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset); | ||
309 | |||
310 | return PCIBIOS_SUCCESSFUL; | ||
311 | } | ||
312 | |||
313 | static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip, | ||
314 | struct pci_bus *bus, u32 devfn, | ||
315 | int where, int size, u32 *val) | ||
316 | { | ||
317 | u32 busdev; | ||
318 | |||
319 | busdev = PCIE_ECAM_ADDR(bus->number, PCI_SLOT(devfn), | ||
320 | PCI_FUNC(devfn), where); | ||
321 | |||
322 | if (!IS_ALIGNED(busdev, size)) { | ||
323 | *val = 0; | ||
324 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
325 | } | ||
326 | |||
327 | if (size == 4) { | ||
328 | *val = readl(rockchip->reg_base + busdev); | ||
329 | } else if (size == 2) { | ||
330 | *val = readw(rockchip->reg_base + busdev); | ||
331 | } else if (size == 1) { | ||
332 | *val = readb(rockchip->reg_base + busdev); | ||
333 | } else { | ||
334 | *val = 0; | ||
335 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
336 | } | ||
337 | return PCIBIOS_SUCCESSFUL; | ||
338 | } | ||
339 | |||
340 | static int rockchip_pcie_wr_other_conf(struct rockchip_pcie *rockchip, | ||
341 | struct pci_bus *bus, u32 devfn, | ||
342 | int where, int size, u32 val) | ||
343 | { | ||
344 | u32 busdev; | ||
345 | |||
346 | busdev = PCIE_ECAM_ADDR(bus->number, PCI_SLOT(devfn), | ||
347 | PCI_FUNC(devfn), where); | ||
348 | if (!IS_ALIGNED(busdev, size)) | ||
349 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
350 | |||
351 | if (size == 4) | ||
352 | writel(val, rockchip->reg_base + busdev); | ||
353 | else if (size == 2) | ||
354 | writew(val, rockchip->reg_base + busdev); | ||
355 | else if (size == 1) | ||
356 | writeb(val, rockchip->reg_base + busdev); | ||
357 | else | ||
358 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
359 | |||
360 | return PCIBIOS_SUCCESSFUL; | ||
361 | } | ||
362 | |||
363 | static int rockchip_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | ||
364 | int size, u32 *val) | ||
365 | { | ||
366 | struct rockchip_pcie *rockchip = bus->sysdata; | ||
367 | |||
368 | if (!rockchip_pcie_valid_device(rockchip, bus, PCI_SLOT(devfn))) { | ||
369 | *val = 0xffffffff; | ||
370 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
371 | } | ||
372 | |||
373 | if (bus->number == rockchip->root_bus_nr) | ||
374 | return rockchip_pcie_rd_own_conf(rockchip, where, size, val); | ||
375 | |||
376 | return rockchip_pcie_rd_other_conf(rockchip, bus, devfn, where, size, val); | ||
377 | } | ||
378 | |||
379 | static int rockchip_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | ||
380 | int where, int size, u32 val) | ||
381 | { | ||
382 | struct rockchip_pcie *rockchip = bus->sysdata; | ||
383 | |||
384 | if (!rockchip_pcie_valid_device(rockchip, bus, PCI_SLOT(devfn))) | ||
385 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
386 | |||
387 | if (bus->number == rockchip->root_bus_nr) | ||
388 | return rockchip_pcie_wr_own_conf(rockchip, where, size, val); | ||
389 | |||
390 | return rockchip_pcie_wr_other_conf(rockchip, bus, devfn, where, size, val); | ||
391 | } | ||
392 | |||
393 | static struct pci_ops rockchip_pcie_ops = { | ||
394 | .read = rockchip_pcie_rd_conf, | ||
395 | .write = rockchip_pcie_wr_conf, | ||
396 | }; | ||
397 | |||
398 | /** | ||
399 | * rockchip_pcie_init_port - Initialize hardware | ||
400 | * @rockchip: PCIe port information | ||
401 | */ | ||
402 | static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip) | ||
403 | { | ||
404 | struct device *dev = rockchip->dev; | ||
405 | int err; | ||
406 | u32 status; | ||
407 | unsigned long timeout; | ||
408 | |||
409 | gpiod_set_value(rockchip->ep_gpio, 0); | ||
410 | |||
411 | err = phy_init(rockchip->phy); | ||
412 | if (err < 0) { | ||
413 | dev_err(dev, "fail to init phy, err %d\n", err); | ||
414 | return err; | ||
415 | } | ||
416 | |||
417 | err = reset_control_assert(rockchip->core_rst); | ||
418 | if (err) { | ||
419 | dev_err(dev, "assert core_rst err %d\n", err); | ||
420 | return err; | ||
421 | } | ||
422 | |||
423 | err = reset_control_assert(rockchip->mgmt_rst); | ||
424 | if (err) { | ||
425 | dev_err(dev, "assert mgmt_rst err %d\n", err); | ||
426 | return err; | ||
427 | } | ||
428 | |||
429 | err = reset_control_assert(rockchip->mgmt_sticky_rst); | ||
430 | if (err) { | ||
431 | dev_err(dev, "assert mgmt_sticky_rst err %d\n", err); | ||
432 | return err; | ||
433 | } | ||
434 | |||
435 | err = reset_control_assert(rockchip->pipe_rst); | ||
436 | if (err) { | ||
437 | dev_err(dev, "assert pipe_rst err %d\n", err); | ||
438 | return err; | ||
439 | } | ||
440 | |||
441 | rockchip_pcie_write(rockchip, | ||
442 | PCIE_CLIENT_CONF_ENABLE | | ||
443 | PCIE_CLIENT_LINK_TRAIN_ENABLE | | ||
444 | PCIE_CLIENT_ARI_ENABLE | | ||
445 | PCIE_CLIENT_CONF_LANE_NUM(rockchip->lanes) | | ||
446 | PCIE_CLIENT_MODE_RC | | ||
447 | PCIE_CLIENT_GEN_SEL_2, | ||
448 | PCIE_CLIENT_CONFIG); | ||
449 | |||
450 | err = phy_power_on(rockchip->phy); | ||
451 | if (err) { | ||
452 | dev_err(dev, "fail to power on phy, err %d\n", err); | ||
453 | return err; | ||
454 | } | ||
455 | |||
456 | /* | ||
457 | * Please don't reorder the deassert sequence of the following | ||
458 | * four reset pins. | ||
459 | */ | ||
460 | err = reset_control_deassert(rockchip->mgmt_sticky_rst); | ||
461 | if (err) { | ||
462 | dev_err(dev, "deassert mgmt_sticky_rst err %d\n", err); | ||
463 | return err; | ||
464 | } | ||
465 | |||
466 | err = reset_control_deassert(rockchip->core_rst); | ||
467 | if (err) { | ||
468 | dev_err(dev, "deassert core_rst err %d\n", err); | ||
469 | return err; | ||
470 | } | ||
471 | |||
472 | err = reset_control_deassert(rockchip->mgmt_rst); | ||
473 | if (err) { | ||
474 | dev_err(dev, "deassert mgmt_rst err %d\n", err); | ||
475 | return err; | ||
476 | } | ||
477 | |||
478 | err = reset_control_deassert(rockchip->pipe_rst); | ||
479 | if (err) { | ||
480 | dev_err(dev, "deassert pipe_rst err %d\n", err); | ||
481 | return err; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * We need to read/write PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 before | ||
486 | * enabling ASPM. Otherwise L1PwrOnSc and L1PwrOnVal isn't | ||
487 | * reliable and enabling ASPM doesn't work. This is a controller | ||
488 | * bug we need to work around. | ||
489 | */ | ||
490 | status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2); | ||
491 | rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2); | ||
492 | |||
493 | /* Fix the transmitted FTS count desired to exit from L0s. */ | ||
494 | status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL_PLC1); | ||
495 | status = (status & PCIE_CORE_CTRL_PLC1_FTS_MASK) | | ||
496 | (PCIE_CORE_CTRL_PLC1_FTS_CNT << PCIE_CORE_CTRL_PLC1_FTS_SHIFT); | ||
497 | rockchip_pcie_write(rockchip, status, PCIE_CORE_CTRL_PLC1); | ||
498 | |||
499 | /* Enable Gen1 training */ | ||
500 | rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, | ||
501 | PCIE_CLIENT_CONFIG); | ||
502 | |||
503 | gpiod_set_value(rockchip->ep_gpio, 1); | ||
504 | |||
505 | /* 500ms timeout value should be enough for Gen1/2 training */ | ||
506 | timeout = jiffies + msecs_to_jiffies(500); | ||
507 | |||
508 | for (;;) { | ||
509 | status = rockchip_pcie_read(rockchip, | ||
510 | PCIE_CLIENT_BASIC_STATUS1); | ||
511 | if ((status & PCIE_CLIENT_LINK_STATUS_MASK) == | ||
512 | PCIE_CLIENT_LINK_STATUS_UP) { | ||
513 | dev_dbg(dev, "PCIe link training gen1 pass!\n"); | ||
514 | break; | ||
515 | } | ||
516 | |||
517 | if (time_after(jiffies, timeout)) { | ||
518 | dev_err(dev, "PCIe link training gen1 timeout!\n"); | ||
519 | return -ETIMEDOUT; | ||
520 | } | ||
521 | |||
522 | msleep(20); | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * Enable retrain for gen2. This should be configured only after | ||
527 | * gen1 finished. | ||
528 | */ | ||
529 | status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS); | ||
530 | status |= PCIE_RC_CONFIG_LCS_RETRAIN_LINK; | ||
531 | rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS); | ||
532 | |||
533 | timeout = jiffies + msecs_to_jiffies(500); | ||
534 | for (;;) { | ||
535 | status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL); | ||
536 | if ((status & PCIE_CORE_PL_CONF_SPEED_MASK) == | ||
537 | PCIE_CORE_PL_CONF_SPEED_5G) { | ||
538 | dev_dbg(dev, "PCIe link training gen2 pass!\n"); | ||
539 | break; | ||
540 | } | ||
541 | |||
542 | if (time_after(jiffies, timeout)) { | ||
543 | dev_dbg(dev, "PCIe link training gen2 timeout, fall back to gen1!\n"); | ||
544 | break; | ||
545 | } | ||
546 | |||
547 | msleep(20); | ||
548 | } | ||
549 | |||
550 | /* Check the final link width from negotiated lane counter from MGMT */ | ||
551 | status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL); | ||
552 | status = 0x1 << ((status & PCIE_CORE_PL_CONF_LANE_MASK) >> | ||
553 | PCIE_CORE_PL_CONF_LANE_MASK); | ||
554 | dev_dbg(dev, "current link width is x%d\n", status); | ||
555 | |||
556 | rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID, | ||
557 | PCIE_RC_CONFIG_VENDOR); | ||
558 | rockchip_pcie_write(rockchip, | ||
559 | PCI_CLASS_BRIDGE_PCI << PCIE_RC_CONFIG_SCC_SHIFT, | ||
560 | PCIE_RC_CONFIG_RID_CCR); | ||
561 | rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF); | ||
562 | |||
563 | rockchip_pcie_write(rockchip, | ||
564 | (RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS), | ||
565 | PCIE_CORE_OB_REGION_ADDR0); | ||
566 | rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H, | ||
567 | PCIE_CORE_OB_REGION_ADDR1); | ||
568 | rockchip_pcie_write(rockchip, 0x0080000a, PCIE_CORE_OB_REGION_DESC0); | ||
569 | rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1); | ||
570 | |||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | static irqreturn_t rockchip_pcie_subsys_irq_handler(int irq, void *arg) | ||
575 | { | ||
576 | struct rockchip_pcie *rockchip = arg; | ||
577 | struct device *dev = rockchip->dev; | ||
578 | u32 reg; | ||
579 | u32 sub_reg; | ||
580 | |||
581 | reg = rockchip_pcie_read(rockchip, PCIE_CLIENT_INT_STATUS); | ||
582 | if (reg & PCIE_CLIENT_INT_LOCAL) { | ||
583 | dev_dbg(dev, "local interrupt received\n"); | ||
584 | sub_reg = rockchip_pcie_read(rockchip, PCIE_CORE_INT_STATUS); | ||
585 | if (sub_reg & PCIE_CORE_INT_PRFPE) | ||
586 | dev_dbg(dev, "parity error detected while reading from the PNP receive FIFO RAM\n"); | ||
587 | |||
588 | if (sub_reg & PCIE_CORE_INT_CRFPE) | ||
589 | dev_dbg(dev, "parity error detected while reading from the Completion Receive FIFO RAM\n"); | ||
590 | |||
591 | if (sub_reg & PCIE_CORE_INT_RRPE) | ||
592 | dev_dbg(dev, "parity error detected while reading from replay buffer RAM\n"); | ||
593 | |||
594 | if (sub_reg & PCIE_CORE_INT_PRFO) | ||
595 | dev_dbg(dev, "overflow occurred in the PNP receive FIFO\n"); | ||
596 | |||
597 | if (sub_reg & PCIE_CORE_INT_CRFO) | ||
598 | dev_dbg(dev, "overflow occurred in the completion receive FIFO\n"); | ||
599 | |||
600 | if (sub_reg & PCIE_CORE_INT_RT) | ||
601 | dev_dbg(dev, "replay timer timed out\n"); | ||
602 | |||
603 | if (sub_reg & PCIE_CORE_INT_RTR) | ||
604 | dev_dbg(dev, "replay timer rolled over after 4 transmissions of the same TLP\n"); | ||
605 | |||
606 | if (sub_reg & PCIE_CORE_INT_PE) | ||
607 | dev_dbg(dev, "phy error detected on receive side\n"); | ||
608 | |||
609 | if (sub_reg & PCIE_CORE_INT_MTR) | ||
610 | dev_dbg(dev, "malformed TLP received from the link\n"); | ||
611 | |||
612 | if (sub_reg & PCIE_CORE_INT_UCR) | ||
613 | dev_dbg(dev, "malformed TLP received from the link\n"); | ||
614 | |||
615 | if (sub_reg & PCIE_CORE_INT_FCE) | ||
616 | dev_dbg(dev, "an error was observed in the flow control advertisements from the other side\n"); | ||
617 | |||
618 | if (sub_reg & PCIE_CORE_INT_CT) | ||
619 | dev_dbg(dev, "a request timed out waiting for completion\n"); | ||
620 | |||
621 | if (sub_reg & PCIE_CORE_INT_UTC) | ||
622 | dev_dbg(dev, "unmapped TC error\n"); | ||
623 | |||
624 | if (sub_reg & PCIE_CORE_INT_MMVC) | ||
625 | dev_dbg(dev, "MSI mask register changes\n"); | ||
626 | |||
627 | rockchip_pcie_write(rockchip, sub_reg, PCIE_CORE_INT_STATUS); | ||
628 | } else if (reg & PCIE_CLIENT_INT_PHY) { | ||
629 | dev_dbg(dev, "phy link changes\n"); | ||
630 | rockchip_pcie_update_txcredit_mui(rockchip); | ||
631 | rockchip_pcie_clr_bw_int(rockchip); | ||
632 | } | ||
633 | |||
634 | rockchip_pcie_write(rockchip, reg & PCIE_CLIENT_INT_LOCAL, | ||
635 | PCIE_CLIENT_INT_STATUS); | ||
636 | |||
637 | return IRQ_HANDLED; | ||
638 | } | ||
639 | |||
640 | static irqreturn_t rockchip_pcie_client_irq_handler(int irq, void *arg) | ||
641 | { | ||
642 | struct rockchip_pcie *rockchip = arg; | ||
643 | struct device *dev = rockchip->dev; | ||
644 | u32 reg; | ||
645 | |||
646 | reg = rockchip_pcie_read(rockchip, PCIE_CLIENT_INT_STATUS); | ||
647 | if (reg & PCIE_CLIENT_INT_LEGACY_DONE) | ||
648 | dev_dbg(dev, "legacy done interrupt received\n"); | ||
649 | |||
650 | if (reg & PCIE_CLIENT_INT_MSG) | ||
651 | dev_dbg(dev, "message done interrupt received\n"); | ||
652 | |||
653 | if (reg & PCIE_CLIENT_INT_HOT_RST) | ||
654 | dev_dbg(dev, "hot reset interrupt received\n"); | ||
655 | |||
656 | if (reg & PCIE_CLIENT_INT_DPA) | ||
657 | dev_dbg(dev, "dpa interrupt received\n"); | ||
658 | |||
659 | if (reg & PCIE_CLIENT_INT_FATAL_ERR) | ||
660 | dev_dbg(dev, "fatal error interrupt received\n"); | ||
661 | |||
662 | if (reg & PCIE_CLIENT_INT_NFATAL_ERR) | ||
663 | dev_dbg(dev, "no fatal error interrupt received\n"); | ||
664 | |||
665 | if (reg & PCIE_CLIENT_INT_CORR_ERR) | ||
666 | dev_dbg(dev, "correctable error interrupt received\n"); | ||
667 | |||
668 | if (reg & PCIE_CLIENT_INT_PHY) | ||
669 | dev_dbg(dev, "phy interrupt received\n"); | ||
670 | |||
671 | rockchip_pcie_write(rockchip, reg & (PCIE_CLIENT_INT_LEGACY_DONE | | ||
672 | PCIE_CLIENT_INT_MSG | PCIE_CLIENT_INT_HOT_RST | | ||
673 | PCIE_CLIENT_INT_DPA | PCIE_CLIENT_INT_FATAL_ERR | | ||
674 | PCIE_CLIENT_INT_NFATAL_ERR | | ||
675 | PCIE_CLIENT_INT_CORR_ERR | | ||
676 | PCIE_CLIENT_INT_PHY), | ||
677 | PCIE_CLIENT_INT_STATUS); | ||
678 | |||
679 | return IRQ_HANDLED; | ||
680 | } | ||
681 | |||
682 | static void rockchip_pcie_legacy_int_handler(struct irq_desc *desc) | ||
683 | { | ||
684 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
685 | struct rockchip_pcie *rockchip = irq_desc_get_handler_data(desc); | ||
686 | struct device *dev = rockchip->dev; | ||
687 | u32 reg; | ||
688 | u32 hwirq; | ||
689 | u32 virq; | ||
690 | |||
691 | chained_irq_enter(chip, desc); | ||
692 | |||
693 | reg = rockchip_pcie_read(rockchip, PCIE_CLIENT_INT_STATUS); | ||
694 | reg = (reg & PCIE_CLIENT_INTR_MASK) >> PCIE_CLIENT_INTR_SHIFT; | ||
695 | |||
696 | while (reg) { | ||
697 | hwirq = ffs(reg) - 1; | ||
698 | reg &= ~BIT(hwirq); | ||
699 | |||
700 | virq = irq_find_mapping(rockchip->irq_domain, hwirq); | ||
701 | if (virq) | ||
702 | generic_handle_irq(virq); | ||
703 | else | ||
704 | dev_err(dev, "unexpected IRQ, INT%d\n", hwirq); | ||
705 | } | ||
706 | |||
707 | chained_irq_exit(chip, desc); | ||
708 | } | ||
709 | |||
710 | |||
711 | /** | ||
712 | * rockchip_pcie_parse_dt - Parse Device Tree | ||
713 | * @rockchip: PCIe port information | ||
714 | * | ||
715 | * Return: '0' on success and error value on failure | ||
716 | */ | ||
717 | static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | ||
718 | { | ||
719 | struct device *dev = rockchip->dev; | ||
720 | struct platform_device *pdev = to_platform_device(dev); | ||
721 | struct device_node *node = dev->of_node; | ||
722 | struct resource *regs; | ||
723 | int irq; | ||
724 | int err; | ||
725 | |||
726 | regs = platform_get_resource_byname(pdev, | ||
727 | IORESOURCE_MEM, | ||
728 | "axi-base"); | ||
729 | rockchip->reg_base = devm_ioremap_resource(dev, regs); | ||
730 | if (IS_ERR(rockchip->reg_base)) | ||
731 | return PTR_ERR(rockchip->reg_base); | ||
732 | |||
733 | regs = platform_get_resource_byname(pdev, | ||
734 | IORESOURCE_MEM, | ||
735 | "apb-base"); | ||
736 | rockchip->apb_base = devm_ioremap_resource(dev, regs); | ||
737 | if (IS_ERR(rockchip->apb_base)) | ||
738 | return PTR_ERR(rockchip->apb_base); | ||
739 | |||
740 | rockchip->phy = devm_phy_get(dev, "pcie-phy"); | ||
741 | if (IS_ERR(rockchip->phy)) { | ||
742 | if (PTR_ERR(rockchip->phy) != -EPROBE_DEFER) | ||
743 | dev_err(dev, "missing phy\n"); | ||
744 | return PTR_ERR(rockchip->phy); | ||
745 | } | ||
746 | |||
747 | rockchip->lanes = 1; | ||
748 | err = of_property_read_u32(node, "num-lanes", &rockchip->lanes); | ||
749 | if (!err && (rockchip->lanes == 0 || | ||
750 | rockchip->lanes == 3 || | ||
751 | rockchip->lanes > 4)) { | ||
752 | dev_warn(dev, "invalid num-lanes, default to use one lane\n"); | ||
753 | rockchip->lanes = 1; | ||
754 | } | ||
755 | |||
756 | rockchip->core_rst = devm_reset_control_get(dev, "core"); | ||
757 | if (IS_ERR(rockchip->core_rst)) { | ||
758 | if (PTR_ERR(rockchip->core_rst) != -EPROBE_DEFER) | ||
759 | dev_err(dev, "missing core reset property in node\n"); | ||
760 | return PTR_ERR(rockchip->core_rst); | ||
761 | } | ||
762 | |||
763 | rockchip->mgmt_rst = devm_reset_control_get(dev, "mgmt"); | ||
764 | if (IS_ERR(rockchip->mgmt_rst)) { | ||
765 | if (PTR_ERR(rockchip->mgmt_rst) != -EPROBE_DEFER) | ||
766 | dev_err(dev, "missing mgmt reset property in node\n"); | ||
767 | return PTR_ERR(rockchip->mgmt_rst); | ||
768 | } | ||
769 | |||
770 | rockchip->mgmt_sticky_rst = devm_reset_control_get(dev, "mgmt-sticky"); | ||
771 | if (IS_ERR(rockchip->mgmt_sticky_rst)) { | ||
772 | if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER) | ||
773 | dev_err(dev, "missing mgmt-sticky reset property in node\n"); | ||
774 | return PTR_ERR(rockchip->mgmt_sticky_rst); | ||
775 | } | ||
776 | |||
777 | rockchip->pipe_rst = devm_reset_control_get(dev, "pipe"); | ||
778 | if (IS_ERR(rockchip->pipe_rst)) { | ||
779 | if (PTR_ERR(rockchip->pipe_rst) != -EPROBE_DEFER) | ||
780 | dev_err(dev, "missing pipe reset property in node\n"); | ||
781 | return PTR_ERR(rockchip->pipe_rst); | ||
782 | } | ||
783 | |||
784 | rockchip->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH); | ||
785 | if (IS_ERR(rockchip->ep_gpio)) { | ||
786 | dev_err(dev, "missing ep-gpios property in node\n"); | ||
787 | return PTR_ERR(rockchip->ep_gpio); | ||
788 | } | ||
789 | |||
790 | rockchip->aclk_pcie = devm_clk_get(dev, "aclk"); | ||
791 | if (IS_ERR(rockchip->aclk_pcie)) { | ||
792 | dev_err(dev, "aclk clock not found\n"); | ||
793 | return PTR_ERR(rockchip->aclk_pcie); | ||
794 | } | ||
795 | |||
796 | rockchip->aclk_perf_pcie = devm_clk_get(dev, "aclk-perf"); | ||
797 | if (IS_ERR(rockchip->aclk_perf_pcie)) { | ||
798 | dev_err(dev, "aclk_perf clock not found\n"); | ||
799 | return PTR_ERR(rockchip->aclk_perf_pcie); | ||
800 | } | ||
801 | |||
802 | rockchip->hclk_pcie = devm_clk_get(dev, "hclk"); | ||
803 | if (IS_ERR(rockchip->hclk_pcie)) { | ||
804 | dev_err(dev, "hclk clock not found\n"); | ||
805 | return PTR_ERR(rockchip->hclk_pcie); | ||
806 | } | ||
807 | |||
808 | rockchip->clk_pcie_pm = devm_clk_get(dev, "pm"); | ||
809 | if (IS_ERR(rockchip->clk_pcie_pm)) { | ||
810 | dev_err(dev, "pm clock not found\n"); | ||
811 | return PTR_ERR(rockchip->clk_pcie_pm); | ||
812 | } | ||
813 | |||
814 | irq = platform_get_irq_byname(pdev, "sys"); | ||
815 | if (irq < 0) { | ||
816 | dev_err(dev, "missing sys IRQ resource\n"); | ||
817 | return -EINVAL; | ||
818 | } | ||
819 | |||
820 | err = devm_request_irq(dev, irq, rockchip_pcie_subsys_irq_handler, | ||
821 | IRQF_SHARED, "pcie-sys", rockchip); | ||
822 | if (err) { | ||
823 | dev_err(dev, "failed to request PCIe subsystem IRQ\n"); | ||
824 | return err; | ||
825 | } | ||
826 | |||
827 | irq = platform_get_irq_byname(pdev, "legacy"); | ||
828 | if (irq < 0) { | ||
829 | dev_err(dev, "missing legacy IRQ resource\n"); | ||
830 | return -EINVAL; | ||
831 | } | ||
832 | |||
833 | irq_set_chained_handler_and_data(irq, | ||
834 | rockchip_pcie_legacy_int_handler, | ||
835 | rockchip); | ||
836 | |||
837 | irq = platform_get_irq_byname(pdev, "client"); | ||
838 | if (irq < 0) { | ||
839 | dev_err(dev, "missing client IRQ resource\n"); | ||
840 | return -EINVAL; | ||
841 | } | ||
842 | |||
843 | err = devm_request_irq(dev, irq, rockchip_pcie_client_irq_handler, | ||
844 | IRQF_SHARED, "pcie-client", rockchip); | ||
845 | if (err) { | ||
846 | dev_err(dev, "failed to request PCIe client IRQ\n"); | ||
847 | return err; | ||
848 | } | ||
849 | |||
850 | rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3"); | ||
851 | if (IS_ERR(rockchip->vpcie3v3)) { | ||
852 | if (PTR_ERR(rockchip->vpcie3v3) == -EPROBE_DEFER) | ||
853 | return -EPROBE_DEFER; | ||
854 | dev_info(dev, "no vpcie3v3 regulator found\n"); | ||
855 | } | ||
856 | |||
857 | rockchip->vpcie1v8 = devm_regulator_get_optional(dev, "vpcie1v8"); | ||
858 | if (IS_ERR(rockchip->vpcie1v8)) { | ||
859 | if (PTR_ERR(rockchip->vpcie1v8) == -EPROBE_DEFER) | ||
860 | return -EPROBE_DEFER; | ||
861 | dev_info(dev, "no vpcie1v8 regulator found\n"); | ||
862 | } | ||
863 | |||
864 | rockchip->vpcie0v9 = devm_regulator_get_optional(dev, "vpcie0v9"); | ||
865 | if (IS_ERR(rockchip->vpcie0v9)) { | ||
866 | if (PTR_ERR(rockchip->vpcie0v9) == -EPROBE_DEFER) | ||
867 | return -EPROBE_DEFER; | ||
868 | dev_info(dev, "no vpcie0v9 regulator found\n"); | ||
869 | } | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | static int rockchip_pcie_set_vpcie(struct rockchip_pcie *rockchip) | ||
875 | { | ||
876 | struct device *dev = rockchip->dev; | ||
877 | int err; | ||
878 | |||
879 | if (!IS_ERR(rockchip->vpcie3v3)) { | ||
880 | err = regulator_enable(rockchip->vpcie3v3); | ||
881 | if (err) { | ||
882 | dev_err(dev, "fail to enable vpcie3v3 regulator\n"); | ||
883 | goto err_out; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | if (!IS_ERR(rockchip->vpcie1v8)) { | ||
888 | err = regulator_enable(rockchip->vpcie1v8); | ||
889 | if (err) { | ||
890 | dev_err(dev, "fail to enable vpcie1v8 regulator\n"); | ||
891 | goto err_disable_3v3; | ||
892 | } | ||
893 | } | ||
894 | |||
895 | if (!IS_ERR(rockchip->vpcie0v9)) { | ||
896 | err = regulator_enable(rockchip->vpcie0v9); | ||
897 | if (err) { | ||
898 | dev_err(dev, "fail to enable vpcie0v9 regulator\n"); | ||
899 | goto err_disable_1v8; | ||
900 | } | ||
901 | } | ||
902 | |||
903 | return 0; | ||
904 | |||
905 | err_disable_1v8: | ||
906 | if (!IS_ERR(rockchip->vpcie1v8)) | ||
907 | regulator_disable(rockchip->vpcie1v8); | ||
908 | err_disable_3v3: | ||
909 | if (!IS_ERR(rockchip->vpcie3v3)) | ||
910 | regulator_disable(rockchip->vpcie3v3); | ||
911 | err_out: | ||
912 | return err; | ||
913 | } | ||
914 | |||
915 | static void rockchip_pcie_enable_interrupts(struct rockchip_pcie *rockchip) | ||
916 | { | ||
917 | rockchip_pcie_write(rockchip, (PCIE_CLIENT_INT_CLI << 16) & | ||
918 | (~PCIE_CLIENT_INT_CLI), PCIE_CLIENT_INT_MASK); | ||
919 | rockchip_pcie_write(rockchip, (u32)(~PCIE_CORE_INT), | ||
920 | PCIE_CORE_INT_MASK); | ||
921 | |||
922 | rockchip_pcie_enable_bw_int(rockchip); | ||
923 | } | ||
924 | |||
925 | static int rockchip_pcie_intx_map(struct irq_domain *domain, unsigned int irq, | ||
926 | irq_hw_number_t hwirq) | ||
927 | { | ||
928 | irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq); | ||
929 | irq_set_chip_data(irq, domain->host_data); | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | static const struct irq_domain_ops intx_domain_ops = { | ||
935 | .map = rockchip_pcie_intx_map, | ||
936 | }; | ||
937 | |||
938 | static int rockchip_pcie_init_irq_domain(struct rockchip_pcie *rockchip) | ||
939 | { | ||
940 | struct device *dev = rockchip->dev; | ||
941 | struct device_node *intc = of_get_next_child(dev->of_node, NULL); | ||
942 | |||
943 | if (!intc) { | ||
944 | dev_err(dev, "missing child interrupt-controller node\n"); | ||
945 | return -EINVAL; | ||
946 | } | ||
947 | |||
948 | rockchip->irq_domain = irq_domain_add_linear(intc, 4, | ||
949 | &intx_domain_ops, rockchip); | ||
950 | if (!rockchip->irq_domain) { | ||
951 | dev_err(dev, "failed to get a INTx IRQ domain\n"); | ||
952 | return -EINVAL; | ||
953 | } | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int rockchip_pcie_prog_ob_atu(struct rockchip_pcie *rockchip, | ||
959 | int region_no, int type, u8 num_pass_bits, | ||
960 | u32 lower_addr, u32 upper_addr) | ||
961 | { | ||
962 | u32 ob_addr_0; | ||
963 | u32 ob_addr_1; | ||
964 | u32 ob_desc_0; | ||
965 | u32 aw_offset; | ||
966 | |||
967 | if (region_no >= MAX_AXI_WRAPPER_REGION_NUM) | ||
968 | return -EINVAL; | ||
969 | if (num_pass_bits + 1 < 8) | ||
970 | return -EINVAL; | ||
971 | if (num_pass_bits > 63) | ||
972 | return -EINVAL; | ||
973 | if (region_no == 0) { | ||
974 | if (AXI_REGION_0_SIZE < (2ULL << num_pass_bits)) | ||
975 | return -EINVAL; | ||
976 | } | ||
977 | if (region_no != 0) { | ||
978 | if (AXI_REGION_SIZE < (2ULL << num_pass_bits)) | ||
979 | return -EINVAL; | ||
980 | } | ||
981 | |||
982 | aw_offset = (region_no << OB_REG_SIZE_SHIFT); | ||
983 | |||
984 | ob_addr_0 = num_pass_bits & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS; | ||
985 | ob_addr_0 |= lower_addr & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR; | ||
986 | ob_addr_1 = upper_addr; | ||
987 | ob_desc_0 = (1 << 23 | type); | ||
988 | |||
989 | rockchip_pcie_write(rockchip, ob_addr_0, | ||
990 | PCIE_CORE_OB_REGION_ADDR0 + aw_offset); | ||
991 | rockchip_pcie_write(rockchip, ob_addr_1, | ||
992 | PCIE_CORE_OB_REGION_ADDR1 + aw_offset); | ||
993 | rockchip_pcie_write(rockchip, ob_desc_0, | ||
994 | PCIE_CORE_OB_REGION_DESC0 + aw_offset); | ||
995 | rockchip_pcie_write(rockchip, 0, | ||
996 | PCIE_CORE_OB_REGION_DESC1 + aw_offset); | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie *rockchip, | ||
1002 | int region_no, u8 num_pass_bits, | ||
1003 | u32 lower_addr, u32 upper_addr) | ||
1004 | { | ||
1005 | u32 ib_addr_0; | ||
1006 | u32 ib_addr_1; | ||
1007 | u32 aw_offset; | ||
1008 | |||
1009 | if (region_no > MAX_AXI_IB_ROOTPORT_REGION_NUM) | ||
1010 | return -EINVAL; | ||
1011 | if (num_pass_bits + 1 < MIN_AXI_ADDR_BITS_PASSED) | ||
1012 | return -EINVAL; | ||
1013 | if (num_pass_bits > 63) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | aw_offset = (region_no << IB_ROOT_PORT_REG_SIZE_SHIFT); | ||
1017 | |||
1018 | ib_addr_0 = num_pass_bits & PCIE_CORE_IB_REGION_ADDR0_NUM_BITS; | ||
1019 | ib_addr_0 |= (lower_addr << 8) & PCIE_CORE_IB_REGION_ADDR0_LO_ADDR; | ||
1020 | ib_addr_1 = upper_addr; | ||
1021 | |||
1022 | rockchip_pcie_write(rockchip, ib_addr_0, PCIE_RP_IB_ADDR0 + aw_offset); | ||
1023 | rockchip_pcie_write(rockchip, ib_addr_1, PCIE_RP_IB_ADDR1 + aw_offset); | ||
1024 | |||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | static int rockchip_pcie_probe(struct platform_device *pdev) | ||
1029 | { | ||
1030 | struct rockchip_pcie *rockchip; | ||
1031 | struct device *dev = &pdev->dev; | ||
1032 | struct pci_bus *bus, *child; | ||
1033 | struct resource_entry *win; | ||
1034 | resource_size_t io_base; | ||
1035 | struct resource *mem; | ||
1036 | struct resource *io; | ||
1037 | phys_addr_t io_bus_addr = 0; | ||
1038 | u32 io_size; | ||
1039 | phys_addr_t mem_bus_addr = 0; | ||
1040 | u32 mem_size = 0; | ||
1041 | int reg_no; | ||
1042 | int err; | ||
1043 | int offset; | ||
1044 | |||
1045 | LIST_HEAD(res); | ||
1046 | |||
1047 | if (!dev->of_node) | ||
1048 | return -ENODEV; | ||
1049 | |||
1050 | rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); | ||
1051 | if (!rockchip) | ||
1052 | return -ENOMEM; | ||
1053 | |||
1054 | rockchip->dev = dev; | ||
1055 | |||
1056 | err = rockchip_pcie_parse_dt(rockchip); | ||
1057 | if (err) | ||
1058 | return err; | ||
1059 | |||
1060 | err = clk_prepare_enable(rockchip->aclk_pcie); | ||
1061 | if (err) { | ||
1062 | dev_err(dev, "unable to enable aclk_pcie clock\n"); | ||
1063 | goto err_aclk_pcie; | ||
1064 | } | ||
1065 | |||
1066 | err = clk_prepare_enable(rockchip->aclk_perf_pcie); | ||
1067 | if (err) { | ||
1068 | dev_err(dev, "unable to enable aclk_perf_pcie clock\n"); | ||
1069 | goto err_aclk_perf_pcie; | ||
1070 | } | ||
1071 | |||
1072 | err = clk_prepare_enable(rockchip->hclk_pcie); | ||
1073 | if (err) { | ||
1074 | dev_err(dev, "unable to enable hclk_pcie clock\n"); | ||
1075 | goto err_hclk_pcie; | ||
1076 | } | ||
1077 | |||
1078 | err = clk_prepare_enable(rockchip->clk_pcie_pm); | ||
1079 | if (err) { | ||
1080 | dev_err(dev, "unable to enable hclk_pcie clock\n"); | ||
1081 | goto err_pcie_pm; | ||
1082 | } | ||
1083 | |||
1084 | err = rockchip_pcie_set_vpcie(rockchip); | ||
1085 | if (err) { | ||
1086 | dev_err(dev, "failed to set vpcie regulator\n"); | ||
1087 | goto err_set_vpcie; | ||
1088 | } | ||
1089 | |||
1090 | err = rockchip_pcie_init_port(rockchip); | ||
1091 | if (err) | ||
1092 | goto err_vpcie; | ||
1093 | |||
1094 | platform_set_drvdata(pdev, rockchip); | ||
1095 | |||
1096 | rockchip_pcie_enable_interrupts(rockchip); | ||
1097 | |||
1098 | err = rockchip_pcie_init_irq_domain(rockchip); | ||
1099 | if (err < 0) | ||
1100 | goto err_vpcie; | ||
1101 | |||
1102 | err = of_pci_get_host_bridge_resources(dev->of_node, 0, 0xff, | ||
1103 | &res, &io_base); | ||
1104 | if (err) | ||
1105 | goto err_vpcie; | ||
1106 | |||
1107 | err = devm_request_pci_bus_resources(dev, &res); | ||
1108 | if (err) | ||
1109 | goto err_vpcie; | ||
1110 | |||
1111 | /* Get the I/O and memory ranges from DT */ | ||
1112 | io_size = 0; | ||
1113 | resource_list_for_each_entry(win, &res) { | ||
1114 | switch (resource_type(win->res)) { | ||
1115 | case IORESOURCE_IO: | ||
1116 | io = win->res; | ||
1117 | io->name = "I/O"; | ||
1118 | io_size = resource_size(io); | ||
1119 | io_bus_addr = io->start - win->offset; | ||
1120 | err = pci_remap_iospace(io, io_base); | ||
1121 | if (err) { | ||
1122 | dev_warn(dev, "error %d: failed to map resource %pR\n", | ||
1123 | err, io); | ||
1124 | continue; | ||
1125 | } | ||
1126 | break; | ||
1127 | case IORESOURCE_MEM: | ||
1128 | mem = win->res; | ||
1129 | mem->name = "MEM"; | ||
1130 | mem_size = resource_size(mem); | ||
1131 | mem_bus_addr = mem->start - win->offset; | ||
1132 | break; | ||
1133 | case IORESOURCE_BUS: | ||
1134 | rockchip->root_bus_nr = win->res->start; | ||
1135 | break; | ||
1136 | default: | ||
1137 | continue; | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | if (mem_size) { | ||
1142 | for (reg_no = 0; reg_no < (mem_size >> 20); reg_no++) { | ||
1143 | err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1, | ||
1144 | AXI_WRAPPER_MEM_WRITE, | ||
1145 | 20 - 1, | ||
1146 | mem_bus_addr + | ||
1147 | (reg_no << 20), | ||
1148 | 0); | ||
1149 | if (err) { | ||
1150 | dev_err(dev, "program RC mem outbound ATU failed\n"); | ||
1151 | goto err_vpcie; | ||
1152 | } | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | err = rockchip_pcie_prog_ib_atu(rockchip, 2, 32 - 1, 0x0, 0); | ||
1157 | if (err) { | ||
1158 | dev_err(dev, "program RC mem inbound ATU failed\n"); | ||
1159 | goto err_vpcie; | ||
1160 | } | ||
1161 | |||
1162 | offset = mem_size >> 20; | ||
1163 | |||
1164 | if (io_size) { | ||
1165 | for (reg_no = 0; reg_no < (io_size >> 20); reg_no++) { | ||
1166 | err = rockchip_pcie_prog_ob_atu(rockchip, | ||
1167 | reg_no + 1 + offset, | ||
1168 | AXI_WRAPPER_IO_WRITE, | ||
1169 | 20 - 1, | ||
1170 | io_bus_addr + | ||
1171 | (reg_no << 20), | ||
1172 | 0); | ||
1173 | if (err) { | ||
1174 | dev_err(dev, "program RC io outbound ATU failed\n"); | ||
1175 | goto err_vpcie; | ||
1176 | } | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1180 | bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res); | ||
1181 | if (!bus) { | ||
1182 | err = -ENOMEM; | ||
1183 | goto err_vpcie; | ||
1184 | } | ||
1185 | |||
1186 | pci_bus_size_bridges(bus); | ||
1187 | pci_bus_assign_resources(bus); | ||
1188 | list_for_each_entry(child, &bus->children, node) | ||
1189 | pcie_bus_configure_settings(child); | ||
1190 | |||
1191 | pci_bus_add_devices(bus); | ||
1192 | |||
1193 | dev_warn(dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n"); | ||
1194 | |||
1195 | return err; | ||
1196 | |||
1197 | err_vpcie: | ||
1198 | if (!IS_ERR(rockchip->vpcie3v3)) | ||
1199 | regulator_disable(rockchip->vpcie3v3); | ||
1200 | if (!IS_ERR(rockchip->vpcie1v8)) | ||
1201 | regulator_disable(rockchip->vpcie1v8); | ||
1202 | if (!IS_ERR(rockchip->vpcie0v9)) | ||
1203 | regulator_disable(rockchip->vpcie0v9); | ||
1204 | err_set_vpcie: | ||
1205 | clk_disable_unprepare(rockchip->clk_pcie_pm); | ||
1206 | err_pcie_pm: | ||
1207 | clk_disable_unprepare(rockchip->hclk_pcie); | ||
1208 | err_hclk_pcie: | ||
1209 | clk_disable_unprepare(rockchip->aclk_perf_pcie); | ||
1210 | err_aclk_perf_pcie: | ||
1211 | clk_disable_unprepare(rockchip->aclk_pcie); | ||
1212 | err_aclk_pcie: | ||
1213 | return err; | ||
1214 | } | ||
1215 | |||
1216 | static const struct of_device_id rockchip_pcie_of_match[] = { | ||
1217 | { .compatible = "rockchip,rk3399-pcie", }, | ||
1218 | {} | ||
1219 | }; | ||
1220 | |||
1221 | static struct platform_driver rockchip_pcie_driver = { | ||
1222 | .driver = { | ||
1223 | .name = "rockchip-pcie", | ||
1224 | .of_match_table = rockchip_pcie_of_match, | ||
1225 | }, | ||
1226 | .probe = rockchip_pcie_probe, | ||
1227 | |||
1228 | }; | ||
1229 | builtin_platform_driver(rockchip_pcie_driver); | ||
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c index a4060b85ab23..09aed85f275a 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/host/pcie-spear13xx.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/init.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
@@ -355,7 +355,6 @@ static const struct of_device_id spear13xx_pcie_of_match[] = { | |||
355 | { .compatible = "st,spear1340-pcie", }, | 355 | { .compatible = "st,spear1340-pcie", }, |
356 | {}, | 356 | {}, |
357 | }; | 357 | }; |
358 | MODULE_DEVICE_TABLE(of, spear13xx_pcie_of_match); | ||
359 | 358 | ||
360 | static struct platform_driver spear13xx_pcie_driver = { | 359 | static struct platform_driver spear13xx_pcie_driver = { |
361 | .probe = spear13xx_pcie_probe, | 360 | .probe = spear13xx_pcie_probe, |
@@ -365,14 +364,8 @@ static struct platform_driver spear13xx_pcie_driver = { | |||
365 | }, | 364 | }, |
366 | }; | 365 | }; |
367 | 366 | ||
368 | /* SPEAr13xx PCIe driver does not allow module unload */ | ||
369 | |||
370 | static int __init spear13xx_pcie_init(void) | 367 | static int __init spear13xx_pcie_init(void) |
371 | { | 368 | { |
372 | return platform_driver_register(&spear13xx_pcie_driver); | 369 | return platform_driver_register(&spear13xx_pcie_driver); |
373 | } | 370 | } |
374 | module_init(spear13xx_pcie_init); | 371 | device_initcall(spear13xx_pcie_init); |
375 | |||
376 | MODULE_DESCRIPTION("ST Microelectronics SPEAr13xx PCIe host controller driver"); | ||
377 | MODULE_AUTHOR("Pratyush Anand <pratyush.anand@gmail.com>"); | ||
378 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c index 0b597d9190b4..67eae4179290 100644 --- a/drivers/pci/host/pcie-xilinx-nwl.c +++ b/drivers/pci/host/pcie-xilinx-nwl.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/init.h> |
19 | #include <linux/msi.h> | 19 | #include <linux/msi.h> |
20 | #include <linux/of_address.h> | 20 | #include <linux/of_address.h> |
21 | #include <linux/of_pci.h> | 21 | #include <linux/of_pci.h> |
@@ -85,10 +85,15 @@ | |||
85 | #define MSGF_MISC_SR_MASTER_ERR BIT(5) | 85 | #define MSGF_MISC_SR_MASTER_ERR BIT(5) |
86 | #define MSGF_MISC_SR_I_ADDR_ERR BIT(6) | 86 | #define MSGF_MISC_SR_I_ADDR_ERR BIT(6) |
87 | #define MSGF_MISC_SR_E_ADDR_ERR BIT(7) | 87 | #define MSGF_MISC_SR_E_ADDR_ERR BIT(7) |
88 | #define MSGF_MISC_SR_UR_DETECT BIT(20) | 88 | #define MSGF_MISC_SR_FATAL_AER BIT(16) |
89 | 89 | #define MSGF_MISC_SR_NON_FATAL_AER BIT(17) | |
90 | #define MSGF_MISC_SR_PCIE_CORE GENMASK(18, 16) | 90 | #define MSGF_MISC_SR_CORR_AER BIT(18) |
91 | #define MSGF_MISC_SR_PCIE_CORE_ERR GENMASK(31, 22) | 91 | #define MSGF_MISC_SR_UR_DETECT BIT(20) |
92 | #define MSGF_MISC_SR_NON_FATAL_DEV BIT(22) | ||
93 | #define MSGF_MISC_SR_FATAL_DEV BIT(23) | ||
94 | #define MSGF_MISC_SR_LINK_DOWN BIT(24) | ||
95 | #define MSGF_MSIC_SR_LINK_AUTO_BWIDTH BIT(25) | ||
96 | #define MSGF_MSIC_SR_LINK_BWIDTH BIT(26) | ||
92 | 97 | ||
93 | #define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \ | 98 | #define MSGF_MISC_SR_MASKALL (MSGF_MISC_SR_RXMSG_AVAIL | \ |
94 | MSGF_MISC_SR_RXMSG_OVER | \ | 99 | MSGF_MISC_SR_RXMSG_OVER | \ |
@@ -96,9 +101,15 @@ | |||
96 | MSGF_MISC_SR_MASTER_ERR | \ | 101 | MSGF_MISC_SR_MASTER_ERR | \ |
97 | MSGF_MISC_SR_I_ADDR_ERR | \ | 102 | MSGF_MISC_SR_I_ADDR_ERR | \ |
98 | MSGF_MISC_SR_E_ADDR_ERR | \ | 103 | MSGF_MISC_SR_E_ADDR_ERR | \ |
104 | MSGF_MISC_SR_FATAL_AER | \ | ||
105 | MSGF_MISC_SR_NON_FATAL_AER | \ | ||
106 | MSGF_MISC_SR_CORR_AER | \ | ||
99 | MSGF_MISC_SR_UR_DETECT | \ | 107 | MSGF_MISC_SR_UR_DETECT | \ |
100 | MSGF_MISC_SR_PCIE_CORE | \ | 108 | MSGF_MISC_SR_NON_FATAL_DEV | \ |
101 | MSGF_MISC_SR_PCIE_CORE_ERR) | 109 | MSGF_MISC_SR_FATAL_DEV | \ |
110 | MSGF_MISC_SR_LINK_DOWN | \ | ||
111 | MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \ | ||
112 | MSGF_MSIC_SR_LINK_BWIDTH) | ||
102 | 113 | ||
103 | /* Legacy interrupt status mask bits */ | 114 | /* Legacy interrupt status mask bits */ |
104 | #define MSGF_LEG_SR_INTA BIT(0) | 115 | #define MSGF_LEG_SR_INTA BIT(0) |
@@ -109,8 +120,8 @@ | |||
109 | MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD) | 120 | MSGF_LEG_SR_INTC | MSGF_LEG_SR_INTD) |
110 | 121 | ||
111 | /* MSI interrupt status mask bits */ | 122 | /* MSI interrupt status mask bits */ |
112 | #define MSGF_MSI_SR_LO_MASK BIT(0) | 123 | #define MSGF_MSI_SR_LO_MASK GENMASK(31, 0) |
113 | #define MSGF_MSI_SR_HI_MASK BIT(0) | 124 | #define MSGF_MSI_SR_HI_MASK GENMASK(31, 0) |
114 | 125 | ||
115 | #define MSII_PRESENT BIT(0) | 126 | #define MSII_PRESENT BIT(0) |
116 | #define MSII_ENABLE BIT(0) | 127 | #define MSII_ENABLE BIT(0) |
@@ -291,8 +302,29 @@ static irqreturn_t nwl_pcie_misc_handler(int irq, void *data) | |||
291 | dev_err(pcie->dev, | 302 | dev_err(pcie->dev, |
292 | "In Misc Egress address translation error\n"); | 303 | "In Misc Egress address translation error\n"); |
293 | 304 | ||
294 | if (misc_stat & MSGF_MISC_SR_PCIE_CORE_ERR) | 305 | if (misc_stat & MSGF_MISC_SR_FATAL_AER) |
295 | dev_err(pcie->dev, "PCIe Core error\n"); | 306 | dev_err(pcie->dev, "Fatal Error in AER Capability\n"); |
307 | |||
308 | if (misc_stat & MSGF_MISC_SR_NON_FATAL_AER) | ||
309 | dev_err(pcie->dev, "Non-Fatal Error in AER Capability\n"); | ||
310 | |||
311 | if (misc_stat & MSGF_MISC_SR_CORR_AER) | ||
312 | dev_err(pcie->dev, "Correctable Error in AER Capability\n"); | ||
313 | |||
314 | if (misc_stat & MSGF_MISC_SR_UR_DETECT) | ||
315 | dev_err(pcie->dev, "Unsupported request Detected\n"); | ||
316 | |||
317 | if (misc_stat & MSGF_MISC_SR_NON_FATAL_DEV) | ||
318 | dev_err(pcie->dev, "Non-Fatal Error Detected\n"); | ||
319 | |||
320 | if (misc_stat & MSGF_MISC_SR_FATAL_DEV) | ||
321 | dev_err(pcie->dev, "Fatal Error Detected\n"); | ||
322 | |||
323 | if (misc_stat & MSGF_MSIC_SR_LINK_AUTO_BWIDTH) | ||
324 | dev_info(pcie->dev, "Link Autonomous Bandwidth Management Status bit set\n"); | ||
325 | |||
326 | if (misc_stat & MSGF_MSIC_SR_LINK_BWIDTH) | ||
327 | dev_info(pcie->dev, "Link Bandwidth Management Status bit set\n"); | ||
296 | 328 | ||
297 | /* Clear misc interrupt status */ | 329 | /* Clear misc interrupt status */ |
298 | nwl_bridge_writel(pcie, misc_stat, MSGF_MISC_STATUS); | 330 | nwl_bridge_writel(pcie, misc_stat, MSGF_MISC_STATUS); |
@@ -459,40 +491,6 @@ static const struct irq_domain_ops dev_msi_domain_ops = { | |||
459 | .free = nwl_irq_domain_free, | 491 | .free = nwl_irq_domain_free, |
460 | }; | 492 | }; |
461 | 493 | ||
462 | static void nwl_msi_free_irq_domain(struct nwl_pcie *pcie) | ||
463 | { | ||
464 | struct nwl_msi *msi = &pcie->msi; | ||
465 | |||
466 | if (msi->irq_msi0) | ||
467 | irq_set_chained_handler_and_data(msi->irq_msi0, NULL, NULL); | ||
468 | if (msi->irq_msi1) | ||
469 | irq_set_chained_handler_and_data(msi->irq_msi1, NULL, NULL); | ||
470 | |||
471 | if (msi->msi_domain) | ||
472 | irq_domain_remove(msi->msi_domain); | ||
473 | if (msi->dev_domain) | ||
474 | irq_domain_remove(msi->dev_domain); | ||
475 | |||
476 | kfree(msi->bitmap); | ||
477 | msi->bitmap = NULL; | ||
478 | } | ||
479 | |||
480 | static void nwl_pcie_free_irq_domain(struct nwl_pcie *pcie) | ||
481 | { | ||
482 | int i; | ||
483 | u32 irq; | ||
484 | |||
485 | for (i = 0; i < INTX_NUM; i++) { | ||
486 | irq = irq_find_mapping(pcie->legacy_irq_domain, i + 1); | ||
487 | if (irq > 0) | ||
488 | irq_dispose_mapping(irq); | ||
489 | } | ||
490 | if (pcie->legacy_irq_domain) | ||
491 | irq_domain_remove(pcie->legacy_irq_domain); | ||
492 | |||
493 | nwl_msi_free_irq_domain(pcie); | ||
494 | } | ||
495 | |||
496 | static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie) | 494 | static int nwl_pcie_init_msi_irq_domain(struct nwl_pcie *pcie) |
497 | { | 495 | { |
498 | #ifdef CONFIG_PCI_MSI | 496 | #ifdef CONFIG_PCI_MSI |
@@ -867,25 +865,12 @@ error: | |||
867 | return err; | 865 | return err; |
868 | } | 866 | } |
869 | 867 | ||
870 | static int nwl_pcie_remove(struct platform_device *pdev) | ||
871 | { | ||
872 | struct nwl_pcie *pcie = platform_get_drvdata(pdev); | ||
873 | |||
874 | nwl_pcie_free_irq_domain(pcie); | ||
875 | platform_set_drvdata(pdev, NULL); | ||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | static struct platform_driver nwl_pcie_driver = { | 868 | static struct platform_driver nwl_pcie_driver = { |
880 | .driver = { | 869 | .driver = { |
881 | .name = "nwl-pcie", | 870 | .name = "nwl-pcie", |
871 | .suppress_bind_attrs = true, | ||
882 | .of_match_table = nwl_pcie_of_match, | 872 | .of_match_table = nwl_pcie_of_match, |
883 | }, | 873 | }, |
884 | .probe = nwl_pcie_probe, | 874 | .probe = nwl_pcie_probe, |
885 | .remove = nwl_pcie_remove, | ||
886 | }; | 875 | }; |
887 | module_platform_driver(nwl_pcie_driver); | 876 | builtin_platform_driver(nwl_pcie_driver); |
888 | |||
889 | MODULE_AUTHOR("Xilinx, Inc"); | ||
890 | MODULE_DESCRIPTION("NWL PCIe driver"); | ||
891 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index a30e01639557..be568039d9d0 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/irqdomain.h> | 19 | #include <linux/irqdomain.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | 21 | #include <linux/init.h> |
22 | #include <linux/msi.h> | 22 | #include <linux/msi.h> |
23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
24 | #include <linux/of_pci.h> | 24 | #include <linux/of_pci.h> |
@@ -101,7 +101,8 @@ | |||
101 | * @msi_pages: MSI pages | 101 | * @msi_pages: MSI pages |
102 | * @root_busno: Root Bus number | 102 | * @root_busno: Root Bus number |
103 | * @dev: Device pointer | 103 | * @dev: Device pointer |
104 | * @irq_domain: IRQ domain pointer | 104 | * @msi_domain: MSI IRQ domain pointer |
105 | * @leg_domain: Legacy IRQ domain pointer | ||
105 | * @resources: Bus Resources | 106 | * @resources: Bus Resources |
106 | */ | 107 | */ |
107 | struct xilinx_pcie_port { | 108 | struct xilinx_pcie_port { |
@@ -110,7 +111,8 @@ struct xilinx_pcie_port { | |||
110 | unsigned long msi_pages; | 111 | unsigned long msi_pages; |
111 | u8 root_busno; | 112 | u8 root_busno; |
112 | struct device *dev; | 113 | struct device *dev; |
113 | struct irq_domain *irq_domain; | 114 | struct irq_domain *msi_domain; |
115 | struct irq_domain *leg_domain; | ||
114 | struct list_head resources; | 116 | struct list_head resources; |
115 | }; | 117 | }; |
116 | 118 | ||
@@ -168,13 +170,6 @@ static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn) | |||
168 | if (bus->number == port->root_busno && devfn > 0) | 170 | if (bus->number == port->root_busno && devfn > 0) |
169 | return false; | 171 | return false; |
170 | 172 | ||
171 | /* | ||
172 | * Do not read more than one device on the bus directly attached | ||
173 | * to RC. | ||
174 | */ | ||
175 | if (bus->primary == port->root_busno && devfn > 0) | ||
176 | return false; | ||
177 | |||
178 | return true; | 173 | return true; |
179 | } | 174 | } |
180 | 175 | ||
@@ -219,13 +214,15 @@ static void xilinx_pcie_destroy_msi(unsigned int irq) | |||
219 | { | 214 | { |
220 | struct msi_desc *msi; | 215 | struct msi_desc *msi; |
221 | struct xilinx_pcie_port *port; | 216 | struct xilinx_pcie_port *port; |
217 | struct irq_data *d = irq_get_irq_data(irq); | ||
218 | irq_hw_number_t hwirq = irqd_to_hwirq(d); | ||
222 | 219 | ||
223 | if (!test_bit(irq, msi_irq_in_use)) { | 220 | if (!test_bit(hwirq, msi_irq_in_use)) { |
224 | msi = irq_get_msi_desc(irq); | 221 | msi = irq_get_msi_desc(irq); |
225 | port = msi_desc_to_pci_sysdata(msi); | 222 | port = msi_desc_to_pci_sysdata(msi); |
226 | dev_err(port->dev, "Trying to free unused MSI#%d\n", irq); | 223 | dev_err(port->dev, "Trying to free unused MSI#%d\n", irq); |
227 | } else { | 224 | } else { |
228 | clear_bit(irq, msi_irq_in_use); | 225 | clear_bit(hwirq, msi_irq_in_use); |
229 | } | 226 | } |
230 | } | 227 | } |
231 | 228 | ||
@@ -257,6 +254,7 @@ static void xilinx_msi_teardown_irq(struct msi_controller *chip, | |||
257 | unsigned int irq) | 254 | unsigned int irq) |
258 | { | 255 | { |
259 | xilinx_pcie_destroy_msi(irq); | 256 | xilinx_pcie_destroy_msi(irq); |
257 | irq_dispose_mapping(irq); | ||
260 | } | 258 | } |
261 | 259 | ||
262 | /** | 260 | /** |
@@ -281,7 +279,7 @@ static int xilinx_pcie_msi_setup_irq(struct msi_controller *chip, | |||
281 | if (hwirq < 0) | 279 | if (hwirq < 0) |
282 | return hwirq; | 280 | return hwirq; |
283 | 281 | ||
284 | irq = irq_create_mapping(port->irq_domain, hwirq); | 282 | irq = irq_create_mapping(port->msi_domain, hwirq); |
285 | if (!irq) | 283 | if (!irq) |
286 | return -EINVAL; | 284 | return -EINVAL; |
287 | 285 | ||
@@ -432,7 +430,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) | |||
432 | /* Check whether interrupt valid */ | 430 | /* Check whether interrupt valid */ |
433 | if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) { | 431 | if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) { |
434 | dev_warn(port->dev, "RP Intr FIFO1 read error\n"); | 432 | dev_warn(port->dev, "RP Intr FIFO1 read error\n"); |
435 | return IRQ_HANDLED; | 433 | goto error; |
436 | } | 434 | } |
437 | 435 | ||
438 | if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) { | 436 | if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) { |
@@ -443,7 +441,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) | |||
443 | /* Handle INTx Interrupt */ | 441 | /* Handle INTx Interrupt */ |
444 | val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >> | 442 | val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >> |
445 | XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1; | 443 | XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1; |
446 | generic_handle_irq(irq_find_mapping(port->irq_domain, | 444 | generic_handle_irq(irq_find_mapping(port->leg_domain, |
447 | val)); | 445 | val)); |
448 | } | 446 | } |
449 | } | 447 | } |
@@ -454,7 +452,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) | |||
454 | 452 | ||
455 | if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) { | 453 | if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) { |
456 | dev_warn(port->dev, "RP Intr FIFO1 read error\n"); | 454 | dev_warn(port->dev, "RP Intr FIFO1 read error\n"); |
457 | return IRQ_HANDLED; | 455 | goto error; |
458 | } | 456 | } |
459 | 457 | ||
460 | if (val & XILINX_PCIE_RPIFR1_MSI_INTR) { | 458 | if (val & XILINX_PCIE_RPIFR1_MSI_INTR) { |
@@ -499,6 +497,7 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) | |||
499 | if (status & XILINX_PCIE_INTR_MST_ERRP) | 497 | if (status & XILINX_PCIE_INTR_MST_ERRP) |
500 | dev_warn(port->dev, "Master error poison\n"); | 498 | dev_warn(port->dev, "Master error poison\n"); |
501 | 499 | ||
500 | error: | ||
502 | /* Clear the Interrupt Decode register */ | 501 | /* Clear the Interrupt Decode register */ |
503 | pcie_write(port, status, XILINX_PCIE_REG_IDR); | 502 | pcie_write(port, status, XILINX_PCIE_REG_IDR); |
504 | 503 | ||
@@ -506,35 +505,6 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data) | |||
506 | } | 505 | } |
507 | 506 | ||
508 | /** | 507 | /** |
509 | * xilinx_pcie_free_irq_domain - Free IRQ domain | ||
510 | * @port: PCIe port information | ||
511 | */ | ||
512 | static void xilinx_pcie_free_irq_domain(struct xilinx_pcie_port *port) | ||
513 | { | ||
514 | int i; | ||
515 | u32 irq, num_irqs; | ||
516 | |||
517 | /* Free IRQ Domain */ | ||
518 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | ||
519 | |||
520 | free_pages(port->msi_pages, 0); | ||
521 | |||
522 | num_irqs = XILINX_NUM_MSI_IRQS; | ||
523 | } else { | ||
524 | /* INTx */ | ||
525 | num_irqs = 4; | ||
526 | } | ||
527 | |||
528 | for (i = 0; i < num_irqs; i++) { | ||
529 | irq = irq_find_mapping(port->irq_domain, i); | ||
530 | if (irq > 0) | ||
531 | irq_dispose_mapping(irq); | ||
532 | } | ||
533 | |||
534 | irq_domain_remove(port->irq_domain); | ||
535 | } | ||
536 | |||
537 | /** | ||
538 | * xilinx_pcie_init_irq_domain - Initialize IRQ domain | 508 | * xilinx_pcie_init_irq_domain - Initialize IRQ domain |
539 | * @port: PCIe port information | 509 | * @port: PCIe port information |
540 | * | 510 | * |
@@ -553,21 +523,21 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port) | |||
553 | return -ENODEV; | 523 | return -ENODEV; |
554 | } | 524 | } |
555 | 525 | ||
556 | port->irq_domain = irq_domain_add_linear(pcie_intc_node, 4, | 526 | port->leg_domain = irq_domain_add_linear(pcie_intc_node, 4, |
557 | &intx_domain_ops, | 527 | &intx_domain_ops, |
558 | port); | 528 | port); |
559 | if (!port->irq_domain) { | 529 | if (!port->leg_domain) { |
560 | dev_err(dev, "Failed to get a INTx IRQ domain\n"); | 530 | dev_err(dev, "Failed to get a INTx IRQ domain\n"); |
561 | return -ENODEV; | 531 | return -ENODEV; |
562 | } | 532 | } |
563 | 533 | ||
564 | /* Setup MSI */ | 534 | /* Setup MSI */ |
565 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | 535 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
566 | port->irq_domain = irq_domain_add_linear(node, | 536 | port->msi_domain = irq_domain_add_linear(node, |
567 | XILINX_NUM_MSI_IRQS, | 537 | XILINX_NUM_MSI_IRQS, |
568 | &msi_domain_ops, | 538 | &msi_domain_ops, |
569 | &xilinx_pcie_msi_chip); | 539 | &xilinx_pcie_msi_chip); |
570 | if (!port->irq_domain) { | 540 | if (!port->msi_domain) { |
571 | dev_err(dev, "Failed to get a MSI IRQ domain\n"); | 541 | dev_err(dev, "Failed to get a MSI IRQ domain\n"); |
572 | return -ENODEV; | 542 | return -ENODEV; |
573 | } | 543 | } |
@@ -724,21 +694,6 @@ error: | |||
724 | return err; | 694 | return err; |
725 | } | 695 | } |
726 | 696 | ||
727 | /** | ||
728 | * xilinx_pcie_remove - Remove function | ||
729 | * @pdev: Platform device pointer | ||
730 | * | ||
731 | * Return: '0' always | ||
732 | */ | ||
733 | static int xilinx_pcie_remove(struct platform_device *pdev) | ||
734 | { | ||
735 | struct xilinx_pcie_port *port = platform_get_drvdata(pdev); | ||
736 | |||
737 | xilinx_pcie_free_irq_domain(port); | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static struct of_device_id xilinx_pcie_of_match[] = { | 697 | static struct of_device_id xilinx_pcie_of_match[] = { |
743 | { .compatible = "xlnx,axi-pcie-host-1.00.a", }, | 698 | { .compatible = "xlnx,axi-pcie-host-1.00.a", }, |
744 | {} | 699 | {} |
@@ -751,10 +706,5 @@ static struct platform_driver xilinx_pcie_driver = { | |||
751 | .suppress_bind_attrs = true, | 706 | .suppress_bind_attrs = true, |
752 | }, | 707 | }, |
753 | .probe = xilinx_pcie_probe, | 708 | .probe = xilinx_pcie_probe, |
754 | .remove = xilinx_pcie_remove, | ||
755 | }; | 709 | }; |
756 | module_platform_driver(xilinx_pcie_driver); | 710 | builtin_platform_driver(xilinx_pcie_driver); |
757 | |||
758 | MODULE_AUTHOR("Xilinx Inc"); | ||
759 | MODULE_DESCRIPTION("Xilinx AXI PCIe driver"); | ||
760 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 555bcde3b196..60e66e027ebc 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h | |||
@@ -101,10 +101,8 @@ int cpci_unconfigure_slot(struct slot *slot); | |||
101 | 101 | ||
102 | #ifdef CONFIG_HOTPLUG_PCI_CPCI | 102 | #ifdef CONFIG_HOTPLUG_PCI_CPCI |
103 | int cpci_hotplug_init(int debug); | 103 | int cpci_hotplug_init(int debug); |
104 | void cpci_hotplug_exit(void); | ||
105 | #else | 104 | #else |
106 | static inline int cpci_hotplug_init(int debug) { return 0; } | 105 | static inline int cpci_hotplug_init(int debug) { return 0; } |
107 | static inline void cpci_hotplug_exit(void) { } | ||
108 | #endif | 106 | #endif |
109 | 107 | ||
110 | #endif /* _CPCI_HOTPLUG_H */ | 108 | #endif /* _CPCI_HOTPLUG_H */ |
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 7d3866c47312..7ec8a8f72c69 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c | |||
@@ -719,13 +719,3 @@ cpci_hotplug_init(int debug) | |||
719 | cpci_debug = debug; | 719 | cpci_debug = debug; |
720 | return 0; | 720 | return 0; |
721 | } | 721 | } |
722 | |||
723 | void __exit | ||
724 | cpci_hotplug_exit(void) | ||
725 | { | ||
726 | /* | ||
727 | * Clean everything up. | ||
728 | */ | ||
729 | cpci_hp_stop(); | ||
730 | cpci_hp_unregister_controller(controller); | ||
731 | } | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 9acd1997c6fe..fea0b8b33589 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> /* try_module_get & module_put */ |
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
@@ -537,17 +537,11 @@ static int __init pci_hotplug_init(void) | |||
537 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 537 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
538 | return result; | 538 | return result; |
539 | } | 539 | } |
540 | device_initcall(pci_hotplug_init); | ||
540 | 541 | ||
541 | static void __exit pci_hotplug_exit(void) | 542 | /* |
542 | { | 543 | * not really modular, but the easiest way to keep compat with existing |
543 | cpci_hotplug_exit(); | 544 | * bootargs behaviour is to continue using module_param here. |
544 | } | 545 | */ |
545 | |||
546 | module_init(pci_hotplug_init); | ||
547 | module_exit(pci_hotplug_exit); | ||
548 | |||
549 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
550 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
551 | MODULE_LICENSE("GPL"); | ||
552 | module_param(debug, bool, 0644); | 546 | module_param(debug, bool, 0644); |
553 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); | 547 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e764918641ae..37d70b5ad22f 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -152,6 +152,9 @@ bool pciehp_check_link_active(struct controller *ctrl); | |||
152 | void pciehp_release_ctrl(struct controller *ctrl); | 152 | void pciehp_release_ctrl(struct controller *ctrl); |
153 | int pciehp_reset_slot(struct slot *slot, int probe); | 153 | int pciehp_reset_slot(struct slot *slot, int probe); |
154 | 154 | ||
155 | int pciehp_set_raw_indicator_status(struct hotplug_slot *h_slot, u8 status); | ||
156 | int pciehp_get_raw_indicator_status(struct hotplug_slot *h_slot, u8 *status); | ||
157 | |||
155 | static inline const char *slot_name(struct slot *slot) | 158 | static inline const char *slot_name(struct slot *slot) |
156 | { | 159 | { |
157 | return hotplug_slot_name(slot->hotplug_slot); | 160 | return hotplug_slot_name(slot->hotplug_slot); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index ac531e674a05..7d32fa33dcef 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -27,7 +27,6 @@ | |||
27 | * | 27 | * |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
@@ -47,10 +46,10 @@ static bool pciehp_force; | |||
47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 46 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
48 | #define DRIVER_DESC "PCI Express Hot Plug Controller Driver" | 47 | #define DRIVER_DESC "PCI Express Hot Plug Controller Driver" |
49 | 48 | ||
50 | MODULE_AUTHOR(DRIVER_AUTHOR); | 49 | /* |
51 | MODULE_DESCRIPTION(DRIVER_DESC); | 50 | * not really modular, but the easiest way to keep compat with existing |
52 | MODULE_LICENSE("GPL"); | 51 | * bootargs behaviour is to continue using module_param here. |
53 | 52 | */ | |
54 | module_param(pciehp_debug, bool, 0644); | 53 | module_param(pciehp_debug, bool, 0644); |
55 | module_param(pciehp_poll_mode, bool, 0644); | 54 | module_param(pciehp_poll_mode, bool, 0644); |
56 | module_param(pciehp_poll_time, int, 0644); | 55 | module_param(pciehp_poll_time, int, 0644); |
@@ -114,6 +113,9 @@ static int init_slot(struct controller *ctrl) | |||
114 | if (ATTN_LED(ctrl)) { | 113 | if (ATTN_LED(ctrl)) { |
115 | ops->get_attention_status = get_attention_status; | 114 | ops->get_attention_status = get_attention_status; |
116 | ops->set_attention_status = set_attention_status; | 115 | ops->set_attention_status = set_attention_status; |
116 | } else if (ctrl->pcie->port->hotplug_user_indicators) { | ||
117 | ops->get_attention_status = pciehp_get_raw_indicator_status; | ||
118 | ops->set_attention_status = pciehp_set_raw_indicator_status; | ||
117 | } | 119 | } |
118 | 120 | ||
119 | /* register this slot with the hotplug pci core */ | 121 | /* register this slot with the hotplug pci core */ |
@@ -337,13 +339,4 @@ static int __init pcied_init(void) | |||
337 | 339 | ||
338 | return retval; | 340 | return retval; |
339 | } | 341 | } |
340 | 342 | device_initcall(pcied_init); | |
341 | static void __exit pcied_cleanup(void) | ||
342 | { | ||
343 | dbg("unload_pciehpd()\n"); | ||
344 | pcie_port_service_unregister(&hpdriver_portdrv); | ||
345 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | ||
346 | } | ||
347 | |||
348 | module_init(pcied_init); | ||
349 | module_exit(pcied_cleanup); | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 880978b6d534..efe69e879455 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -106,7 +106,7 @@ static int board_added(struct slot *p_slot) | |||
106 | 106 | ||
107 | /* Check for a power fault */ | 107 | /* Check for a power fault */ |
108 | if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { | 108 | if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) { |
109 | ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot)); | 109 | ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(p_slot)); |
110 | retval = -EIO; | 110 | retval = -EIO; |
111 | goto err_exit; | 111 | goto err_exit; |
112 | } | 112 | } |
@@ -120,6 +120,7 @@ static int board_added(struct slot *p_slot) | |||
120 | } | 120 | } |
121 | 121 | ||
122 | pciehp_green_led_on(p_slot); | 122 | pciehp_green_led_on(p_slot); |
123 | pciehp_set_attention_status(p_slot, 0); | ||
123 | return 0; | 124 | return 0; |
124 | 125 | ||
125 | err_exit: | 126 | err_exit: |
@@ -253,11 +254,11 @@ static void handle_button_press_event(struct slot *p_slot) | |||
253 | pciehp_get_power_status(p_slot, &getstatus); | 254 | pciehp_get_power_status(p_slot, &getstatus); |
254 | if (getstatus) { | 255 | if (getstatus) { |
255 | p_slot->state = BLINKINGOFF_STATE; | 256 | p_slot->state = BLINKINGOFF_STATE; |
256 | ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", | 257 | ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n", |
257 | slot_name(p_slot)); | 258 | slot_name(p_slot)); |
258 | } else { | 259 | } else { |
259 | p_slot->state = BLINKINGON_STATE; | 260 | p_slot->state = BLINKINGON_STATE; |
260 | ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", | 261 | ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n", |
261 | slot_name(p_slot)); | 262 | slot_name(p_slot)); |
262 | } | 263 | } |
263 | /* blink green LED and turn off amber */ | 264 | /* blink green LED and turn off amber */ |
@@ -272,14 +273,14 @@ static void handle_button_press_event(struct slot *p_slot) | |||
272 | * press the attention again before the 5 sec. limit | 273 | * press the attention again before the 5 sec. limit |
273 | * expires to cancel hot-add or hot-remove | 274 | * expires to cancel hot-add or hot-remove |
274 | */ | 275 | */ |
275 | ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); | 276 | ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(p_slot)); |
276 | cancel_delayed_work(&p_slot->work); | 277 | cancel_delayed_work(&p_slot->work); |
277 | if (p_slot->state == BLINKINGOFF_STATE) | 278 | if (p_slot->state == BLINKINGOFF_STATE) |
278 | pciehp_green_led_on(p_slot); | 279 | pciehp_green_led_on(p_slot); |
279 | else | 280 | else |
280 | pciehp_green_led_off(p_slot); | 281 | pciehp_green_led_off(p_slot); |
281 | pciehp_set_attention_status(p_slot, 0); | 282 | pciehp_set_attention_status(p_slot, 0); |
282 | ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", | 283 | ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n", |
283 | slot_name(p_slot)); | 284 | slot_name(p_slot)); |
284 | p_slot->state = STATIC_STATE; | 285 | p_slot->state = STATIC_STATE; |
285 | break; | 286 | break; |
@@ -290,10 +291,12 @@ static void handle_button_press_event(struct slot *p_slot) | |||
290 | * this means that the previous attention button action | 291 | * this means that the previous attention button action |
291 | * to hot-add or hot-remove is undergoing | 292 | * to hot-add or hot-remove is undergoing |
292 | */ | 293 | */ |
293 | ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot)); | 294 | ctrl_info(ctrl, "Slot(%s): Button ignored\n", |
295 | slot_name(p_slot)); | ||
294 | break; | 296 | break; |
295 | default: | 297 | default: |
296 | ctrl_warn(ctrl, "ignoring invalid state %#x\n", p_slot->state); | 298 | ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", |
299 | slot_name(p_slot), p_slot->state); | ||
297 | break; | 300 | break; |
298 | } | 301 | } |
299 | } | 302 | } |
@@ -301,20 +304,6 @@ static void handle_button_press_event(struct slot *p_slot) | |||
301 | /* | 304 | /* |
302 | * Note: This function must be called with slot->lock held | 305 | * Note: This function must be called with slot->lock held |
303 | */ | 306 | */ |
304 | static void handle_surprise_event(struct slot *p_slot) | ||
305 | { | ||
306 | u8 getstatus; | ||
307 | |||
308 | pciehp_get_adapter_status(p_slot, &getstatus); | ||
309 | if (!getstatus) | ||
310 | pciehp_queue_power_work(p_slot, DISABLE_REQ); | ||
311 | else | ||
312 | pciehp_queue_power_work(p_slot, ENABLE_REQ); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Note: This function must be called with slot->lock held | ||
317 | */ | ||
318 | static void handle_link_event(struct slot *p_slot, u32 event) | 307 | static void handle_link_event(struct slot *p_slot, u32 event) |
319 | { | 308 | { |
320 | struct controller *ctrl = p_slot->ctrl; | 309 | struct controller *ctrl = p_slot->ctrl; |
@@ -330,31 +319,27 @@ static void handle_link_event(struct slot *p_slot, u32 event) | |||
330 | break; | 319 | break; |
331 | case POWERON_STATE: | 320 | case POWERON_STATE: |
332 | if (event == INT_LINK_UP) { | 321 | if (event == INT_LINK_UP) { |
333 | ctrl_info(ctrl, | 322 | ctrl_info(ctrl, "Slot(%s): Link Up event ignored; already powering on\n", |
334 | "Link Up event ignored on slot(%s): already powering on\n", | ||
335 | slot_name(p_slot)); | 323 | slot_name(p_slot)); |
336 | } else { | 324 | } else { |
337 | ctrl_info(ctrl, | 325 | ctrl_info(ctrl, "Slot(%s): Link Down event queued; currently getting powered on\n", |
338 | "Link Down event queued on slot(%s): currently getting powered on\n", | ||
339 | slot_name(p_slot)); | 326 | slot_name(p_slot)); |
340 | pciehp_queue_power_work(p_slot, DISABLE_REQ); | 327 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
341 | } | 328 | } |
342 | break; | 329 | break; |
343 | case POWEROFF_STATE: | 330 | case POWEROFF_STATE: |
344 | if (event == INT_LINK_UP) { | 331 | if (event == INT_LINK_UP) { |
345 | ctrl_info(ctrl, | 332 | ctrl_info(ctrl, "Slot(%s): Link Up event queued; currently getting powered off\n", |
346 | "Link Up event queued on slot(%s): currently getting powered off\n", | ||
347 | slot_name(p_slot)); | 333 | slot_name(p_slot)); |
348 | pciehp_queue_power_work(p_slot, ENABLE_REQ); | 334 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
349 | } else { | 335 | } else { |
350 | ctrl_info(ctrl, | 336 | ctrl_info(ctrl, "Slot(%s): Link Down event ignored; already powering off\n", |
351 | "Link Down event ignored on slot(%s): already powering off\n", | ||
352 | slot_name(p_slot)); | 337 | slot_name(p_slot)); |
353 | } | 338 | } |
354 | break; | 339 | break; |
355 | default: | 340 | default: |
356 | ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n", | 341 | ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n", |
357 | p_slot->state, slot_name(p_slot)); | 342 | slot_name(p_slot), p_slot->state); |
358 | break; | 343 | break; |
359 | } | 344 | } |
360 | } | 345 | } |
@@ -377,14 +362,14 @@ static void interrupt_event_handler(struct work_struct *work) | |||
377 | pciehp_green_led_off(p_slot); | 362 | pciehp_green_led_off(p_slot); |
378 | break; | 363 | break; |
379 | case INT_PRESENCE_ON: | 364 | case INT_PRESENCE_ON: |
380 | handle_surprise_event(p_slot); | 365 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
381 | break; | 366 | break; |
382 | case INT_PRESENCE_OFF: | 367 | case INT_PRESENCE_OFF: |
383 | /* | 368 | /* |
384 | * Regardless of surprise capability, we need to | 369 | * Regardless of surprise capability, we need to |
385 | * definitely remove a card that has been pulled out! | 370 | * definitely remove a card that has been pulled out! |
386 | */ | 371 | */ |
387 | handle_surprise_event(p_slot); | 372 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
388 | break; | 373 | break; |
389 | case INT_LINK_UP: | 374 | case INT_LINK_UP: |
390 | case INT_LINK_DOWN: | 375 | case INT_LINK_DOWN: |
@@ -404,18 +389,17 @@ static void interrupt_event_handler(struct work_struct *work) | |||
404 | int pciehp_enable_slot(struct slot *p_slot) | 389 | int pciehp_enable_slot(struct slot *p_slot) |
405 | { | 390 | { |
406 | u8 getstatus = 0; | 391 | u8 getstatus = 0; |
407 | int rc; | ||
408 | struct controller *ctrl = p_slot->ctrl; | 392 | struct controller *ctrl = p_slot->ctrl; |
409 | 393 | ||
410 | pciehp_get_adapter_status(p_slot, &getstatus); | 394 | pciehp_get_adapter_status(p_slot, &getstatus); |
411 | if (!getstatus) { | 395 | if (!getstatus) { |
412 | ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); | 396 | ctrl_info(ctrl, "Slot(%s): No adapter\n", slot_name(p_slot)); |
413 | return -ENODEV; | 397 | return -ENODEV; |
414 | } | 398 | } |
415 | if (MRL_SENS(p_slot->ctrl)) { | 399 | if (MRL_SENS(p_slot->ctrl)) { |
416 | pciehp_get_latch_status(p_slot, &getstatus); | 400 | pciehp_get_latch_status(p_slot, &getstatus); |
417 | if (getstatus) { | 401 | if (getstatus) { |
418 | ctrl_info(ctrl, "Latch open on slot(%s)\n", | 402 | ctrl_info(ctrl, "Slot(%s): Latch open\n", |
419 | slot_name(p_slot)); | 403 | slot_name(p_slot)); |
420 | return -ENODEV; | 404 | return -ENODEV; |
421 | } | 405 | } |
@@ -424,19 +408,13 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
424 | if (POWER_CTRL(p_slot->ctrl)) { | 408 | if (POWER_CTRL(p_slot->ctrl)) { |
425 | pciehp_get_power_status(p_slot, &getstatus); | 409 | pciehp_get_power_status(p_slot, &getstatus); |
426 | if (getstatus) { | 410 | if (getstatus) { |
427 | ctrl_info(ctrl, "Already enabled on slot(%s)\n", | 411 | ctrl_info(ctrl, "Slot(%s): Already enabled\n", |
428 | slot_name(p_slot)); | 412 | slot_name(p_slot)); |
429 | return -EINVAL; | 413 | return -EINVAL; |
430 | } | 414 | } |
431 | } | 415 | } |
432 | 416 | ||
433 | pciehp_get_latch_status(p_slot, &getstatus); | 417 | return board_added(p_slot); |
434 | |||
435 | rc = board_added(p_slot); | ||
436 | if (rc) | ||
437 | pciehp_get_latch_status(p_slot, &getstatus); | ||
438 | |||
439 | return rc; | ||
440 | } | 418 | } |
441 | 419 | ||
442 | /* | 420 | /* |
@@ -453,7 +431,7 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
453 | if (POWER_CTRL(p_slot->ctrl)) { | 431 | if (POWER_CTRL(p_slot->ctrl)) { |
454 | pciehp_get_power_status(p_slot, &getstatus); | 432 | pciehp_get_power_status(p_slot, &getstatus); |
455 | if (!getstatus) { | 433 | if (!getstatus) { |
456 | ctrl_info(ctrl, "Already disabled on slot(%s)\n", | 434 | ctrl_info(ctrl, "Slot(%s): Already disabled\n", |
457 | slot_name(p_slot)); | 435 | slot_name(p_slot)); |
458 | return -EINVAL; | 436 | return -EINVAL; |
459 | } | 437 | } |
@@ -481,17 +459,17 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot) | |||
481 | p_slot->state = STATIC_STATE; | 459 | p_slot->state = STATIC_STATE; |
482 | break; | 460 | break; |
483 | case POWERON_STATE: | 461 | case POWERON_STATE: |
484 | ctrl_info(ctrl, "Slot %s is already in powering on state\n", | 462 | ctrl_info(ctrl, "Slot(%s): Already in powering on state\n", |
485 | slot_name(p_slot)); | 463 | slot_name(p_slot)); |
486 | break; | 464 | break; |
487 | case BLINKINGOFF_STATE: | 465 | case BLINKINGOFF_STATE: |
488 | case POWEROFF_STATE: | 466 | case POWEROFF_STATE: |
489 | ctrl_info(ctrl, "Already enabled on slot %s\n", | 467 | ctrl_info(ctrl, "Slot(%s): Already enabled\n", |
490 | slot_name(p_slot)); | 468 | slot_name(p_slot)); |
491 | break; | 469 | break; |
492 | default: | 470 | default: |
493 | ctrl_err(ctrl, "invalid state %#x on slot %s\n", | 471 | ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n", |
494 | p_slot->state, slot_name(p_slot)); | 472 | slot_name(p_slot), p_slot->state); |
495 | break; | 473 | break; |
496 | } | 474 | } |
497 | mutex_unlock(&p_slot->lock); | 475 | mutex_unlock(&p_slot->lock); |
@@ -518,17 +496,17 @@ int pciehp_sysfs_disable_slot(struct slot *p_slot) | |||
518 | p_slot->state = STATIC_STATE; | 496 | p_slot->state = STATIC_STATE; |
519 | break; | 497 | break; |
520 | case POWEROFF_STATE: | 498 | case POWEROFF_STATE: |
521 | ctrl_info(ctrl, "Slot %s is already in powering off state\n", | 499 | ctrl_info(ctrl, "Slot(%s): Already in powering off state\n", |
522 | slot_name(p_slot)); | 500 | slot_name(p_slot)); |
523 | break; | 501 | break; |
524 | case BLINKINGON_STATE: | 502 | case BLINKINGON_STATE: |
525 | case POWERON_STATE: | 503 | case POWERON_STATE: |
526 | ctrl_info(ctrl, "Already disabled on slot %s\n", | 504 | ctrl_info(ctrl, "Slot(%s): Already disabled\n", |
527 | slot_name(p_slot)); | 505 | slot_name(p_slot)); |
528 | break; | 506 | break; |
529 | default: | 507 | default: |
530 | ctrl_err(ctrl, "invalid state %#x on slot %s\n", | 508 | ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n", |
531 | p_slot->state, slot_name(p_slot)); | 509 | slot_name(p_slot), p_slot->state); |
532 | break; | 510 | break; |
533 | } | 511 | } |
534 | mutex_unlock(&p_slot->lock); | 512 | mutex_unlock(&p_slot->lock); |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 08e84d61874e..b57fc6d6e28a 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -355,6 +355,18 @@ static int pciehp_link_enable(struct controller *ctrl) | |||
355 | return __pciehp_link_set(ctrl, true); | 355 | return __pciehp_link_set(ctrl, true); |
356 | } | 356 | } |
357 | 357 | ||
358 | int pciehp_get_raw_indicator_status(struct hotplug_slot *hotplug_slot, | ||
359 | u8 *status) | ||
360 | { | ||
361 | struct slot *slot = hotplug_slot->private; | ||
362 | struct pci_dev *pdev = ctrl_dev(slot->ctrl); | ||
363 | u16 slot_ctrl; | ||
364 | |||
365 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); | ||
366 | *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; | ||
367 | return 0; | ||
368 | } | ||
369 | |||
358 | void pciehp_get_attention_status(struct slot *slot, u8 *status) | 370 | void pciehp_get_attention_status(struct slot *slot, u8 *status) |
359 | { | 371 | { |
360 | struct controller *ctrl = slot->ctrl; | 372 | struct controller *ctrl = slot->ctrl; |
@@ -431,6 +443,17 @@ int pciehp_query_power_fault(struct slot *slot) | |||
431 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); | 443 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); |
432 | } | 444 | } |
433 | 445 | ||
446 | int pciehp_set_raw_indicator_status(struct hotplug_slot *hotplug_slot, | ||
447 | u8 status) | ||
448 | { | ||
449 | struct slot *slot = hotplug_slot->private; | ||
450 | struct controller *ctrl = slot->ctrl; | ||
451 | |||
452 | pcie_write_cmd_nowait(ctrl, status << 6, | ||
453 | PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
434 | void pciehp_set_attention_status(struct slot *slot, u8 value) | 457 | void pciehp_set_attention_status(struct slot *slot, u8 value) |
435 | { | 458 | { |
436 | struct controller *ctrl = slot->ctrl; | 459 | struct controller *ctrl = slot->ctrl; |
@@ -535,14 +558,14 @@ void pciehp_power_off_slot(struct slot *slot) | |||
535 | PCI_EXP_SLTCTL_PWR_OFF); | 558 | PCI_EXP_SLTCTL_PWR_OFF); |
536 | } | 559 | } |
537 | 560 | ||
538 | static irqreturn_t pcie_isr(int irq, void *dev_id) | 561 | static irqreturn_t pciehp_isr(int irq, void *dev_id) |
539 | { | 562 | { |
540 | struct controller *ctrl = (struct controller *)dev_id; | 563 | struct controller *ctrl = (struct controller *)dev_id; |
541 | struct pci_dev *pdev = ctrl_dev(ctrl); | 564 | struct pci_dev *pdev = ctrl_dev(ctrl); |
542 | struct pci_bus *subordinate = pdev->subordinate; | 565 | struct pci_bus *subordinate = pdev->subordinate; |
543 | struct pci_dev *dev; | 566 | struct pci_dev *dev; |
544 | struct slot *slot = ctrl->slot; | 567 | struct slot *slot = ctrl->slot; |
545 | u16 detected, intr_loc; | 568 | u16 status, events; |
546 | u8 present; | 569 | u8 present; |
547 | bool link; | 570 | bool link; |
548 | 571 | ||
@@ -550,36 +573,31 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
550 | if (pdev->current_state == PCI_D3cold) | 573 | if (pdev->current_state == PCI_D3cold) |
551 | return IRQ_NONE; | 574 | return IRQ_NONE; |
552 | 575 | ||
576 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &status); | ||
577 | if (status == (u16) ~0) { | ||
578 | ctrl_info(ctrl, "%s: no response from device\n", __func__); | ||
579 | return IRQ_NONE; | ||
580 | } | ||
581 | |||
553 | /* | 582 | /* |
554 | * In order to guarantee that all interrupt events are | 583 | * Slot Status contains plain status bits as well as event |
555 | * serviced, we need to re-inspect Slot Status register after | 584 | * notification bits; right now we only want the event bits. |
556 | * clearing what is presumed to be the last pending interrupt. | ||
557 | */ | 585 | */ |
558 | intr_loc = 0; | 586 | events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
559 | do { | 587 | PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC | |
560 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected); | 588 | PCI_EXP_SLTSTA_DLLSC); |
561 | if (detected == (u16) ~0) { | 589 | if (!events) |
562 | ctrl_info(ctrl, "%s: no response from device\n", | 590 | return IRQ_NONE; |
563 | __func__); | ||
564 | return IRQ_HANDLED; | ||
565 | } | ||
566 | 591 | ||
567 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | | 592 | /* Capture link status before clearing interrupts */ |
568 | PCI_EXP_SLTSTA_PDC | | 593 | if (events & PCI_EXP_SLTSTA_DLLSC) |
569 | PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); | 594 | link = pciehp_check_link_active(ctrl); |
570 | detected &= ~intr_loc; | ||
571 | intr_loc |= detected; | ||
572 | if (!intr_loc) | ||
573 | return IRQ_NONE; | ||
574 | if (detected) | ||
575 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, | ||
576 | intr_loc); | ||
577 | } while (detected); | ||
578 | 595 | ||
579 | ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", intr_loc); | 596 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events); |
597 | ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", events); | ||
580 | 598 | ||
581 | /* Check Command Complete Interrupt Pending */ | 599 | /* Check Command Complete Interrupt Pending */ |
582 | if (intr_loc & PCI_EXP_SLTSTA_CC) { | 600 | if (events & PCI_EXP_SLTSTA_CC) { |
583 | ctrl->cmd_busy = 0; | 601 | ctrl->cmd_busy = 0; |
584 | smp_mb(); | 602 | smp_mb(); |
585 | wake_up(&ctrl->queue); | 603 | wake_up(&ctrl->queue); |
@@ -589,42 +607,38 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
589 | list_for_each_entry(dev, &subordinate->devices, bus_list) { | 607 | list_for_each_entry(dev, &subordinate->devices, bus_list) { |
590 | if (dev->ignore_hotplug) { | 608 | if (dev->ignore_hotplug) { |
591 | ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", | 609 | ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n", |
592 | intr_loc, pci_name(dev)); | 610 | events, pci_name(dev)); |
593 | return IRQ_HANDLED; | 611 | return IRQ_HANDLED; |
594 | } | 612 | } |
595 | } | 613 | } |
596 | } | 614 | } |
597 | 615 | ||
598 | if (!(intr_loc & ~PCI_EXP_SLTSTA_CC)) | ||
599 | return IRQ_HANDLED; | ||
600 | |||
601 | /* Check Attention Button Pressed */ | 616 | /* Check Attention Button Pressed */ |
602 | if (intr_loc & PCI_EXP_SLTSTA_ABP) { | 617 | if (events & PCI_EXP_SLTSTA_ABP) { |
603 | ctrl_info(ctrl, "Button pressed on Slot(%s)\n", | 618 | ctrl_info(ctrl, "Slot(%s): Attention button pressed\n", |
604 | slot_name(slot)); | 619 | slot_name(slot)); |
605 | pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS); | 620 | pciehp_queue_interrupt_event(slot, INT_BUTTON_PRESS); |
606 | } | 621 | } |
607 | 622 | ||
608 | /* Check Presence Detect Changed */ | 623 | /* Check Presence Detect Changed */ |
609 | if (intr_loc & PCI_EXP_SLTSTA_PDC) { | 624 | if (events & PCI_EXP_SLTSTA_PDC) { |
610 | pciehp_get_adapter_status(slot, &present); | 625 | present = !!(status & PCI_EXP_SLTSTA_PDS); |
611 | ctrl_info(ctrl, "Card %spresent on Slot(%s)\n", | 626 | ctrl_info(ctrl, "Slot(%s): Card %spresent\n", slot_name(slot), |
612 | present ? "" : "not ", slot_name(slot)); | 627 | present ? "" : "not "); |
613 | pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON : | 628 | pciehp_queue_interrupt_event(slot, present ? INT_PRESENCE_ON : |
614 | INT_PRESENCE_OFF); | 629 | INT_PRESENCE_OFF); |
615 | } | 630 | } |
616 | 631 | ||
617 | /* Check Power Fault Detected */ | 632 | /* Check Power Fault Detected */ |
618 | if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { | 633 | if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { |
619 | ctrl->power_fault_detected = 1; | 634 | ctrl->power_fault_detected = 1; |
620 | ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(slot)); | 635 | ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(slot)); |
621 | pciehp_queue_interrupt_event(slot, INT_POWER_FAULT); | 636 | pciehp_queue_interrupt_event(slot, INT_POWER_FAULT); |
622 | } | 637 | } |
623 | 638 | ||
624 | if (intr_loc & PCI_EXP_SLTSTA_DLLSC) { | 639 | if (events & PCI_EXP_SLTSTA_DLLSC) { |
625 | link = pciehp_check_link_active(ctrl); | 640 | ctrl_info(ctrl, "Slot(%s): Link %s\n", slot_name(slot), |
626 | ctrl_info(ctrl, "slot(%s): Link %s event\n", | 641 | link ? "Up" : "Down"); |
627 | slot_name(slot), link ? "Up" : "Down"); | ||
628 | pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP : | 642 | pciehp_queue_interrupt_event(slot, link ? INT_LINK_UP : |
629 | INT_LINK_DOWN); | 643 | INT_LINK_DOWN); |
630 | } | 644 | } |
@@ -632,6 +646,25 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
632 | return IRQ_HANDLED; | 646 | return IRQ_HANDLED; |
633 | } | 647 | } |
634 | 648 | ||
649 | static irqreturn_t pcie_isr(int irq, void *dev_id) | ||
650 | { | ||
651 | irqreturn_t rc, handled = IRQ_NONE; | ||
652 | |||
653 | /* | ||
654 | * To guarantee that all interrupt events are serviced, we need to | ||
655 | * re-inspect Slot Status register after clearing what is presumed | ||
656 | * to be the last pending interrupt. | ||
657 | */ | ||
658 | do { | ||
659 | rc = pciehp_isr(irq, dev_id); | ||
660 | if (rc == IRQ_HANDLED) | ||
661 | handled = IRQ_HANDLED; | ||
662 | } while (rc == IRQ_HANDLED); | ||
663 | |||
664 | /* Return IRQ_HANDLED if we handled one or more events */ | ||
665 | return handled; | ||
666 | } | ||
667 | |||
635 | void pcie_enable_notification(struct controller *ctrl) | 668 | void pcie_enable_notification(struct controller *ctrl) |
636 | { | 669 | { |
637 | u16 cmd, mask; | 670 | u16 cmd, mask; |
@@ -804,6 +837,10 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
804 | } | 837 | } |
805 | ctrl->pcie = dev; | 838 | ctrl->pcie = dev; |
806 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); | 839 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); |
840 | |||
841 | if (pdev->hotplug_user_indicators) | ||
842 | slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP); | ||
843 | |||
807 | ctrl->slot_cap = slot_cap; | 844 | ctrl->slot_cap = slot_cap; |
808 | mutex_init(&ctrl->ctrl_lock); | 845 | mutex_init(&ctrl->ctrl_lock); |
809 | init_waitqueue_head(&ctrl->queue); | 846 | init_waitqueue_head(&ctrl->queue); |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 2194b447201d..e30f05c8517f 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -136,7 +136,10 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset) | |||
136 | virtfn->devfn = pci_iov_virtfn_devfn(dev, id); | 136 | virtfn->devfn = pci_iov_virtfn_devfn(dev, id); |
137 | virtfn->vendor = dev->vendor; | 137 | virtfn->vendor = dev->vendor; |
138 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device); | 138 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device); |
139 | pci_setup_device(virtfn); | 139 | rc = pci_setup_device(virtfn); |
140 | if (rc) | ||
141 | goto failed0; | ||
142 | |||
140 | virtfn->dev.parent = dev->dev.parent; | 143 | virtfn->dev.parent = dev->dev.parent; |
141 | virtfn->physfn = pci_dev_get(dev); | 144 | virtfn->physfn = pci_dev_get(dev); |
142 | virtfn->is_virtfn = 1; | 145 | virtfn->is_virtfn = 1; |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 9a033e8ee9a4..d966d47c9e80 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -452,6 +452,27 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
452 | return error; | 452 | return error; |
453 | } | 453 | } |
454 | 454 | ||
455 | static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) | ||
456 | { | ||
457 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); | ||
458 | static const pci_power_t state_conv[] = { | ||
459 | [ACPI_STATE_D0] = PCI_D0, | ||
460 | [ACPI_STATE_D1] = PCI_D1, | ||
461 | [ACPI_STATE_D2] = PCI_D2, | ||
462 | [ACPI_STATE_D3_HOT] = PCI_D3hot, | ||
463 | [ACPI_STATE_D3_COLD] = PCI_D3cold, | ||
464 | }; | ||
465 | int state; | ||
466 | |||
467 | if (!adev || !acpi_device_power_manageable(adev)) | ||
468 | return PCI_UNKNOWN; | ||
469 | |||
470 | if (acpi_device_get_power(adev, &state) || state == ACPI_STATE_UNKNOWN) | ||
471 | return PCI_UNKNOWN; | ||
472 | |||
473 | return state_conv[state]; | ||
474 | } | ||
475 | |||
455 | static bool acpi_pci_can_wakeup(struct pci_dev *dev) | 476 | static bool acpi_pci_can_wakeup(struct pci_dev *dev) |
456 | { | 477 | { |
457 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); | 478 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); |
@@ -534,6 +555,7 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) | |||
534 | static const struct pci_platform_pm_ops acpi_pci_platform_pm = { | 555 | static const struct pci_platform_pm_ops acpi_pci_platform_pm = { |
535 | .is_manageable = acpi_pci_power_manageable, | 556 | .is_manageable = acpi_pci_power_manageable, |
536 | .set_state = acpi_pci_set_power_state, | 557 | .set_state = acpi_pci_set_power_state, |
558 | .get_state = acpi_pci_get_power_state, | ||
537 | .choose_state = acpi_pci_choose_state, | 559 | .choose_state = acpi_pci_choose_state, |
538 | .sleep_wake = acpi_pci_sleep_wake, | 560 | .sleep_wake = acpi_pci_sleep_wake, |
539 | .run_wake = acpi_pci_run_wake, | 561 | .run_wake = acpi_pci_run_wake, |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e39a67c8ef39..1ccce1cd6aca 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -466,7 +466,6 @@ static void pci_device_shutdown(struct device *dev) | |||
466 | pci_msi_shutdown(pci_dev); | 466 | pci_msi_shutdown(pci_dev); |
467 | pci_msix_shutdown(pci_dev); | 467 | pci_msix_shutdown(pci_dev); |
468 | 468 | ||
469 | #ifdef CONFIG_KEXEC_CORE | ||
470 | /* | 469 | /* |
471 | * If this is a kexec reboot, turn off Bus Master bit on the | 470 | * If this is a kexec reboot, turn off Bus Master bit on the |
472 | * device to tell it to not continue to do DMA. Don't touch | 471 | * device to tell it to not continue to do DMA. Don't touch |
@@ -476,7 +475,6 @@ static void pci_device_shutdown(struct device *dev) | |||
476 | */ | 475 | */ |
477 | if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) | 476 | if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot)) |
478 | pci_clear_master(pci_dev); | 477 | pci_clear_master(pci_dev); |
479 | #endif | ||
480 | } | 478 | } |
481 | 479 | ||
482 | #ifdef CONFIG_PM | 480 | #ifdef CONFIG_PM |
@@ -684,8 +682,19 @@ static int pci_pm_prepare(struct device *dev) | |||
684 | 682 | ||
685 | static void pci_pm_complete(struct device *dev) | 683 | static void pci_pm_complete(struct device *dev) |
686 | { | 684 | { |
687 | pci_dev_complete_resume(to_pci_dev(dev)); | 685 | struct pci_dev *pci_dev = to_pci_dev(dev); |
688 | pm_complete_with_resume_check(dev); | 686 | |
687 | pci_dev_complete_resume(pci_dev); | ||
688 | pm_generic_complete(dev); | ||
689 | |||
690 | /* Resume device if platform firmware has put it in reset-power-on */ | ||
691 | if (dev->power.direct_complete && pm_resume_via_firmware()) { | ||
692 | pci_power_t pre_sleep_state = pci_dev->current_state; | ||
693 | |||
694 | pci_update_current_state(pci_dev, pci_dev->current_state); | ||
695 | if (pci_dev->current_state < pre_sleep_state) | ||
696 | pm_request_resume(dev); | ||
697 | } | ||
689 | } | 698 | } |
690 | 699 | ||
691 | #else /* !CONFIG_PM_SLEEP */ | 700 | #else /* !CONFIG_PM_SLEEP */ |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index aab9d5115a5f..2537d86ad634 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -552,8 +552,9 @@ static const struct pci_platform_pm_ops *pci_platform_pm; | |||
552 | 552 | ||
553 | int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) | 553 | int pci_set_platform_pm(const struct pci_platform_pm_ops *ops) |
554 | { | 554 | { |
555 | if (!ops->is_manageable || !ops->set_state || !ops->choose_state || | 555 | if (!ops->is_manageable || !ops->set_state || !ops->get_state || |
556 | !ops->sleep_wake || !ops->run_wake || !ops->need_resume) | 556 | !ops->choose_state || !ops->sleep_wake || !ops->run_wake || |
557 | !ops->need_resume) | ||
557 | return -EINVAL; | 558 | return -EINVAL; |
558 | pci_platform_pm = ops; | 559 | pci_platform_pm = ops; |
559 | return 0; | 560 | return 0; |
@@ -570,6 +571,11 @@ static inline int platform_pci_set_power_state(struct pci_dev *dev, | |||
570 | return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS; | 571 | return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS; |
571 | } | 572 | } |
572 | 573 | ||
574 | static inline pci_power_t platform_pci_get_power_state(struct pci_dev *dev) | ||
575 | { | ||
576 | return pci_platform_pm ? pci_platform_pm->get_state(dev) : PCI_UNKNOWN; | ||
577 | } | ||
578 | |||
573 | static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) | 579 | static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev) |
574 | { | 580 | { |
575 | return pci_platform_pm ? | 581 | return pci_platform_pm ? |
@@ -701,26 +707,25 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
701 | } | 707 | } |
702 | 708 | ||
703 | /** | 709 | /** |
704 | * pci_update_current_state - Read PCI power state of given device from its | 710 | * pci_update_current_state - Read power state of given device and cache it |
705 | * PCI PM registers and cache it | ||
706 | * @dev: PCI device to handle. | 711 | * @dev: PCI device to handle. |
707 | * @state: State to cache in case the device doesn't have the PM capability | 712 | * @state: State to cache in case the device doesn't have the PM capability |
713 | * | ||
714 | * The power state is read from the PMCSR register, which however is | ||
715 | * inaccessible in D3cold. The platform firmware is therefore queried first | ||
716 | * to detect accessibility of the register. In case the platform firmware | ||
717 | * reports an incorrect state or the device isn't power manageable by the | ||
718 | * platform at all, we try to detect D3cold by testing accessibility of the | ||
719 | * vendor ID in config space. | ||
708 | */ | 720 | */ |
709 | void pci_update_current_state(struct pci_dev *dev, pci_power_t state) | 721 | void pci_update_current_state(struct pci_dev *dev, pci_power_t state) |
710 | { | 722 | { |
711 | if (dev->pm_cap) { | 723 | if (platform_pci_get_power_state(dev) == PCI_D3cold || |
724 | !pci_device_is_present(dev)) { | ||
725 | dev->current_state = PCI_D3cold; | ||
726 | } else if (dev->pm_cap) { | ||
712 | u16 pmcsr; | 727 | u16 pmcsr; |
713 | 728 | ||
714 | /* | ||
715 | * Configuration space is not accessible for device in | ||
716 | * D3cold, so just keep or set D3cold for safety | ||
717 | */ | ||
718 | if (dev->current_state == PCI_D3cold) | ||
719 | return; | ||
720 | if (state == PCI_D3cold) { | ||
721 | dev->current_state = PCI_D3cold; | ||
722 | return; | ||
723 | } | ||
724 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); | 729 | pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); |
725 | dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); | 730 | dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); |
726 | } else { | 731 | } else { |
@@ -1959,9 +1964,22 @@ static pci_power_t pci_target_state(struct pci_dev *dev) | |||
1959 | default: | 1964 | default: |
1960 | target_state = state; | 1965 | target_state = state; |
1961 | } | 1966 | } |
1962 | } else if (!dev->pm_cap) { | 1967 | |
1968 | return target_state; | ||
1969 | } | ||
1970 | |||
1971 | if (!dev->pm_cap) | ||
1963 | target_state = PCI_D0; | 1972 | target_state = PCI_D0; |
1964 | } else if (device_may_wakeup(&dev->dev)) { | 1973 | |
1974 | /* | ||
1975 | * If the device is in D3cold even though it's not power-manageable by | ||
1976 | * the platform, it may have been powered down by non-standard means. | ||
1977 | * Best to let it slumber. | ||
1978 | */ | ||
1979 | if (dev->current_state == PCI_D3cold) | ||
1980 | target_state = PCI_D3cold; | ||
1981 | |||
1982 | if (device_may_wakeup(&dev->dev)) { | ||
1965 | /* | 1983 | /* |
1966 | * Find the deepest state from which the device can generate | 1984 | * Find the deepest state from which the device can generate |
1967 | * wake-up events, make it the target state and enable device | 1985 | * wake-up events, make it the target state and enable device |
@@ -4959,6 +4977,13 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) | |||
4959 | 4977 | ||
4960 | spin_lock(&resource_alignment_lock); | 4978 | spin_lock(&resource_alignment_lock); |
4961 | p = resource_alignment_param; | 4979 | p = resource_alignment_param; |
4980 | if (!*p) | ||
4981 | goto out; | ||
4982 | if (pci_has_flag(PCI_PROBE_ONLY)) { | ||
4983 | pr_info_once("PCI: Ignoring requested alignments (PCI_PROBE_ONLY)\n"); | ||
4984 | goto out; | ||
4985 | } | ||
4986 | |||
4962 | while (*p) { | 4987 | while (*p) { |
4963 | count = 0; | 4988 | count = 0; |
4964 | if (sscanf(p, "%d%n", &align_order, &count) == 1 && | 4989 | if (sscanf(p, "%d%n", &align_order, &count) == 1 && |
@@ -5023,6 +5048,7 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) | |||
5023 | } | 5048 | } |
5024 | p++; | 5049 | p++; |
5025 | } | 5050 | } |
5051 | out: | ||
5026 | spin_unlock(&resource_alignment_lock); | 5052 | spin_unlock(&resource_alignment_lock); |
5027 | return align; | 5053 | return align; |
5028 | } | 5054 | } |
@@ -5041,6 +5067,15 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) | |||
5041 | resource_size_t align, size; | 5067 | resource_size_t align, size; |
5042 | u16 command; | 5068 | u16 command; |
5043 | 5069 | ||
5070 | /* | ||
5071 | * VF BARs are read-only zero according to SR-IOV spec r1.1, sec | ||
5072 | * 3.4.1.11. Their resources are allocated from the space | ||
5073 | * described by the VF BARx register in the PF's SR-IOV capability. | ||
5074 | * We can't influence their alignment here. | ||
5075 | */ | ||
5076 | if (dev->is_virtfn) | ||
5077 | return; | ||
5078 | |||
5044 | /* check if specified PCI is target device to reassign */ | 5079 | /* check if specified PCI is target device to reassign */ |
5045 | align = pci_specified_resource_alignment(dev); | 5080 | align = pci_specified_resource_alignment(dev); |
5046 | if (!align) | 5081 | if (!align) |
@@ -5063,6 +5098,12 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) | |||
5063 | r = &dev->resource[i]; | 5098 | r = &dev->resource[i]; |
5064 | if (!(r->flags & IORESOURCE_MEM)) | 5099 | if (!(r->flags & IORESOURCE_MEM)) |
5065 | continue; | 5100 | continue; |
5101 | if (r->flags & IORESOURCE_PCI_FIXED) { | ||
5102 | dev_info(&dev->dev, "Ignoring requested alignment for BAR%d: %pR\n", | ||
5103 | i, r); | ||
5104 | continue; | ||
5105 | } | ||
5106 | |||
5066 | size = resource_size(r); | 5107 | size = resource_size(r); |
5067 | if (size < align) { | 5108 | if (size < align) { |
5068 | size = align; | 5109 | size = align; |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 9730c474b016..451856210e18 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -42,6 +42,8 @@ int pci_probe_reset_function(struct pci_dev *dev); | |||
42 | * | 42 | * |
43 | * @set_state: invokes the platform firmware to set the device's power state | 43 | * @set_state: invokes the platform firmware to set the device's power state |
44 | * | 44 | * |
45 | * @get_state: queries the platform firmware for a device's current power state | ||
46 | * | ||
45 | * @choose_state: returns PCI power state of given device preferred by the | 47 | * @choose_state: returns PCI power state of given device preferred by the |
46 | * platform; to be used during system-wide transitions from a | 48 | * platform; to be used during system-wide transitions from a |
47 | * sleeping state to the working state and vice versa | 49 | * sleeping state to the working state and vice versa |
@@ -62,6 +64,7 @@ int pci_probe_reset_function(struct pci_dev *dev); | |||
62 | struct pci_platform_pm_ops { | 64 | struct pci_platform_pm_ops { |
63 | bool (*is_manageable)(struct pci_dev *dev); | 65 | bool (*is_manageable)(struct pci_dev *dev); |
64 | int (*set_state)(struct pci_dev *dev, pci_power_t state); | 66 | int (*set_state)(struct pci_dev *dev, pci_power_t state); |
67 | pci_power_t (*get_state)(struct pci_dev *dev); | ||
65 | pci_power_t (*choose_state)(struct pci_dev *dev); | 68 | pci_power_t (*choose_state)(struct pci_dev *dev); |
66 | int (*sleep_wake)(struct pci_dev *dev, bool enable); | 69 | int (*sleep_wake)(struct pci_dev *dev, bool enable); |
67 | int (*run_wake)(struct pci_dev *dev, bool enable); | 70 | int (*run_wake)(struct pci_dev *dev, bool enable); |
@@ -332,6 +335,12 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, | |||
332 | 335 | ||
333 | void pci_enable_acs(struct pci_dev *dev); | 336 | void pci_enable_acs(struct pci_dev *dev); |
334 | 337 | ||
338 | #ifdef CONFIG_PCIE_PTM | ||
339 | void pci_ptm_init(struct pci_dev *dev); | ||
340 | #else | ||
341 | static inline void pci_ptm_init(struct pci_dev *dev) { } | ||
342 | #endif | ||
343 | |||
335 | struct pci_dev_reset_methods { | 344 | struct pci_dev_reset_methods { |
336 | u16 vendor; | 345 | u16 vendor; |
337 | u16 device; | 346 | u16 device; |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 7fcea75afa4c..7ce77635e5ad 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -92,3 +92,14 @@ config PCIE_DPC | |||
92 | will be handled by the DPC driver. If your system doesn't | 92 | will be handled by the DPC driver. If your system doesn't |
93 | have this capability or you do not want to use this feature, | 93 | have this capability or you do not want to use this feature, |
94 | it is safe to answer N. | 94 | it is safe to answer N. |
95 | |||
96 | config PCIE_PTM | ||
97 | bool "PCIe Precision Time Measurement support" | ||
98 | default n | ||
99 | depends on PCIEPORTBUS | ||
100 | help | ||
101 | This enables PCI Express Precision Time Measurement (PTM) | ||
102 | support. | ||
103 | |||
104 | This is only useful if you have devices that support PTM, but it | ||
105 | is safe to enable even if you don't. | ||
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile index b24525b3dec1..36e35ea8fde7 100644 --- a/drivers/pci/pcie/Makefile +++ b/drivers/pci/pcie/Makefile | |||
@@ -16,3 +16,4 @@ obj-$(CONFIG_PCIEAER) += aer/ | |||
16 | obj-$(CONFIG_PCIE_PME) += pme.o | 16 | obj-$(CONFIG_PCIE_PME) += pme.o |
17 | 17 | ||
18 | obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o | 18 | obj-$(CONFIG_PCIE_DPC) += pcie-dpc.o |
19 | obj-$(CONFIG_PCIE_PTM) += ptm.o | ||
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 48d21e0edd56..139150b2bdfd 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
20 | #include <linux/pci-acpi.h> | 19 | #include <linux/pci-acpi.h> |
21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
@@ -37,9 +36,6 @@ | |||
37 | #define DRIVER_VERSION "v1.0" | 36 | #define DRIVER_VERSION "v1.0" |
38 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" | 37 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" |
39 | #define DRIVER_DESC "Root Port Advanced Error Reporting Driver" | 38 | #define DRIVER_DESC "Root Port Advanced Error Reporting Driver" |
40 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
41 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | 39 | ||
44 | static int aer_probe(struct pcie_device *dev); | 40 | static int aer_probe(struct pcie_device *dev); |
45 | static void aer_remove(struct pcie_device *dev); | 41 | static void aer_remove(struct pcie_device *dev); |
@@ -70,7 +66,7 @@ static int pcie_aer_disable; | |||
70 | 66 | ||
71 | void pci_no_aer(void) | 67 | void pci_no_aer(void) |
72 | { | 68 | { |
73 | pcie_aer_disable = 1; /* has priority over 'forceload' */ | 69 | pcie_aer_disable = 1; |
74 | } | 70 | } |
75 | 71 | ||
76 | bool pci_aer_available(void) | 72 | bool pci_aer_available(void) |
@@ -134,7 +130,7 @@ static void aer_enable_rootport(struct aer_rpc *rpc) | |||
134 | pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, | 130 | pcie_capability_clear_word(pdev, PCI_EXP_RTCTL, |
135 | SYSTEM_ERROR_INTR_ON_MESG_MASK); | 131 | SYSTEM_ERROR_INTR_ON_MESG_MASK); |
136 | 132 | ||
137 | aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 133 | aer_pos = pdev->aer_cap; |
138 | /* Clear error status */ | 134 | /* Clear error status */ |
139 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); | 135 | pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, ®32); |
140 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); | 136 | pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32); |
@@ -173,7 +169,7 @@ static void aer_disable_rootport(struct aer_rpc *rpc) | |||
173 | */ | 169 | */ |
174 | set_downstream_devices_error_reporting(pdev, false); | 170 | set_downstream_devices_error_reporting(pdev, false); |
175 | 171 | ||
176 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); | 172 | pos = pdev->aer_cap; |
177 | /* Disable Root's interrupt in response to error messages */ | 173 | /* Disable Root's interrupt in response to error messages */ |
178 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); | 174 | pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
179 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; | 175 | reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK; |
@@ -200,7 +196,7 @@ irqreturn_t aer_irq(int irq, void *context) | |||
200 | unsigned long flags; | 196 | unsigned long flags; |
201 | int pos; | 197 | int pos; |
202 | 198 | ||
203 | pos = pci_find_ext_capability(pdev->port, PCI_EXT_CAP_ID_ERR); | 199 | pos = pdev->port->aer_cap; |
204 | /* | 200 | /* |
205 | * Must lock access to Root Error Status Reg, Root Error ID Reg, | 201 | * Must lock access to Root Error Status Reg, Root Error ID Reg, |
206 | * and Root error producer/consumer index | 202 | * and Root error producer/consumer index |
@@ -294,7 +290,6 @@ static void aer_remove(struct pcie_device *dev) | |||
294 | /** | 290 | /** |
295 | * aer_probe - initialize resources | 291 | * aer_probe - initialize resources |
296 | * @dev: pointer to the pcie_dev data structure | 292 | * @dev: pointer to the pcie_dev data structure |
297 | * @id: pointer to the service id data structure | ||
298 | * | 293 | * |
299 | * Invoked when PCI Express bus loads AER service driver. | 294 | * Invoked when PCI Express bus loads AER service driver. |
300 | */ | 295 | */ |
@@ -304,11 +299,6 @@ static int aer_probe(struct pcie_device *dev) | |||
304 | struct aer_rpc *rpc; | 299 | struct aer_rpc *rpc; |
305 | struct device *device = &dev->device; | 300 | struct device *device = &dev->device; |
306 | 301 | ||
307 | /* Init */ | ||
308 | status = aer_init(dev); | ||
309 | if (status) | ||
310 | return status; | ||
311 | |||
312 | /* Alloc rpc data structure */ | 302 | /* Alloc rpc data structure */ |
313 | rpc = aer_alloc_rpc(dev); | 303 | rpc = aer_alloc_rpc(dev); |
314 | if (!rpc) { | 304 | if (!rpc) { |
@@ -343,7 +333,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) | |||
343 | u32 reg32; | 333 | u32 reg32; |
344 | int pos; | 334 | int pos; |
345 | 335 | ||
346 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 336 | pos = dev->aer_cap; |
347 | 337 | ||
348 | /* Disable Root's interrupt in response to error messages */ | 338 | /* Disable Root's interrupt in response to error messages */ |
349 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); | 339 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, ®32); |
@@ -396,7 +386,7 @@ static void aer_error_resume(struct pci_dev *dev) | |||
396 | pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); | 386 | pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16); |
397 | 387 | ||
398 | /* Clean AER Root Error Status */ | 388 | /* Clean AER Root Error Status */ |
399 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 389 | pos = dev->aer_cap; |
400 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); | 390 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); |
401 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); | 391 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); |
402 | if (dev->error_state == pci_channel_io_normal) | 392 | if (dev->error_state == pci_channel_io_normal) |
@@ -417,16 +407,4 @@ static int __init aer_service_init(void) | |||
417 | return -ENXIO; | 407 | return -ENXIO; |
418 | return pcie_port_service_register(&aerdriver); | 408 | return pcie_port_service_register(&aerdriver); |
419 | } | 409 | } |
420 | 410 | device_initcall(aer_service_init); | |
421 | /** | ||
422 | * aer_service_exit - unregister AER root service driver | ||
423 | * | ||
424 | * Invoked when AER root service driver is unloaded. | ||
425 | */ | ||
426 | static void __exit aer_service_exit(void) | ||
427 | { | ||
428 | pcie_port_service_unregister(&aerdriver); | ||
429 | } | ||
430 | |||
431 | module_init(aer_service_init); | ||
432 | module_exit(aer_service_exit); | ||
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 945c939a86c5..d51e4a57b190 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -60,6 +60,7 @@ struct aer_rpc { | |||
60 | struct pcie_device *rpd; /* Root Port device */ | 60 | struct pcie_device *rpd; /* Root Port device */ |
61 | struct work_struct dpc_handler; | 61 | struct work_struct dpc_handler; |
62 | struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; | 62 | struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX]; |
63 | struct aer_err_info e_info; | ||
63 | unsigned short prod_idx; /* Error Producer Index */ | 64 | unsigned short prod_idx; /* Error Producer Index */ |
64 | unsigned short cons_idx; /* Error Consumer Index */ | 65 | unsigned short cons_idx; /* Error Consumer Index */ |
65 | int isr; | 66 | int isr; |
@@ -105,7 +106,6 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, | |||
105 | } | 106 | } |
106 | 107 | ||
107 | extern struct bus_type pcie_port_bus_type; | 108 | extern struct bus_type pcie_port_bus_type; |
108 | int aer_init(struct pcie_device *dev); | ||
109 | void aer_isr(struct work_struct *work); | 109 | void aer_isr(struct work_struct *work); |
110 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); | 110 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); |
111 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); | 111 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); |
@@ -121,11 +121,4 @@ static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | |||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | #endif | 123 | #endif |
124 | |||
125 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, | ||
126 | int enable) | ||
127 | { | ||
128 | pci_dev->__aer_firmware_first = !!enable; | ||
129 | pci_dev->__aer_firmware_first_valid = 1; | ||
130 | } | ||
131 | #endif /* _AERDRV_H_ */ | 124 | #endif /* _AERDRV_H_ */ |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 521e39c1b66d..b1303b32053f 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -27,11 +27,6 @@ | |||
27 | #include <linux/kfifo.h> | 27 | #include <linux/kfifo.h> |
28 | #include "aerdrv.h" | 28 | #include "aerdrv.h" |
29 | 29 | ||
30 | static bool forceload; | ||
31 | static bool nosourceid; | ||
32 | module_param(forceload, bool, 0); | ||
33 | module_param(nosourceid, bool, 0); | ||
34 | |||
35 | #define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ | 30 | #define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \ |
36 | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) | 31 | PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE) |
37 | 32 | ||
@@ -40,7 +35,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) | |||
40 | if (pcie_aer_get_firmware_first(dev)) | 35 | if (pcie_aer_get_firmware_first(dev)) |
41 | return -EIO; | 36 | return -EIO; |
42 | 37 | ||
43 | if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) | 38 | if (!dev->aer_cap) |
44 | return -EIO; | 39 | return -EIO; |
45 | 40 | ||
46 | return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); | 41 | return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS); |
@@ -62,7 +57,7 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | |||
62 | int pos; | 57 | int pos; |
63 | u32 status; | 58 | u32 status; |
64 | 59 | ||
65 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 60 | pos = dev->aer_cap; |
66 | if (!pos) | 61 | if (!pos) |
67 | return -EIO; | 62 | return -EIO; |
68 | 63 | ||
@@ -83,7 +78,7 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
83 | if (!pci_is_pcie(dev)) | 78 | if (!pci_is_pcie(dev)) |
84 | return -ENODEV; | 79 | return -ENODEV; |
85 | 80 | ||
86 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 81 | pos = dev->aer_cap; |
87 | if (!pos) | 82 | if (!pos) |
88 | return -EIO; | 83 | return -EIO; |
89 | 84 | ||
@@ -102,6 +97,12 @@ int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
102 | return 0; | 97 | return 0; |
103 | } | 98 | } |
104 | 99 | ||
100 | int pci_aer_init(struct pci_dev *dev) | ||
101 | { | ||
102 | dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
103 | return pci_cleanup_aer_error_status_regs(dev); | ||
104 | } | ||
105 | |||
105 | /** | 106 | /** |
106 | * add_error_device - list device to be handled | 107 | * add_error_device - list device to be handled |
107 | * @e_info: pointer to error info | 108 | * @e_info: pointer to error info |
@@ -132,7 +133,8 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
132 | * When bus id is equal to 0, it might be a bad id | 133 | * When bus id is equal to 0, it might be a bad id |
133 | * reported by root port. | 134 | * reported by root port. |
134 | */ | 135 | */ |
135 | if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { | 136 | if ((PCI_BUS_NUM(e_info->id) != 0) && |
137 | !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) { | ||
136 | /* Device ID match? */ | 138 | /* Device ID match? */ |
137 | if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) | 139 | if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) |
138 | return true; | 140 | return true; |
@@ -144,10 +146,10 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
144 | 146 | ||
145 | /* | 147 | /* |
146 | * When either | 148 | * When either |
147 | * 1) nosourceid==y; | 149 | * 1) bus id is equal to 0. Some ports might lose the bus |
148 | * 2) bus id is equal to 0. Some ports might lose the bus | ||
149 | * id of error source id; | 150 | * id of error source id; |
150 | * 3) There are multiple errors and prior id comparing fails; | 151 | * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set |
152 | * 3) There are multiple errors and prior ID comparing fails; | ||
151 | * We check AER status registers to find possible reporter. | 153 | * We check AER status registers to find possible reporter. |
152 | */ | 154 | */ |
153 | if (atomic_read(&dev->enable_cnt) == 0) | 155 | if (atomic_read(&dev->enable_cnt) == 0) |
@@ -158,7 +160,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) | |||
158 | if (!(reg16 & PCI_EXP_AER_FLAGS)) | 160 | if (!(reg16 & PCI_EXP_AER_FLAGS)) |
159 | return false; | 161 | return false; |
160 | 162 | ||
161 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 163 | pos = dev->aer_cap; |
162 | if (!pos) | 164 | if (!pos) |
163 | return false; | 165 | return false; |
164 | 166 | ||
@@ -555,7 +557,7 @@ static void handle_error_source(struct pcie_device *aerdev, | |||
555 | * Correctable error does not need software intervention. | 557 | * Correctable error does not need software intervention. |
556 | * No need to go through error recovery process. | 558 | * No need to go through error recovery process. |
557 | */ | 559 | */ |
558 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 560 | pos = dev->aer_cap; |
559 | if (pos) | 561 | if (pos) |
560 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, | 562 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, |
561 | info->status); | 563 | info->status); |
@@ -647,7 +649,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info) | |||
647 | info->status = 0; | 649 | info->status = 0; |
648 | info->tlp_header_valid = 0; | 650 | info->tlp_header_valid = 0; |
649 | 651 | ||
650 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 652 | pos = dev->aer_cap; |
651 | 653 | ||
652 | /* The device might not support AER */ | 654 | /* The device might not support AER */ |
653 | if (!pos) | 655 | if (!pos) |
@@ -715,15 +717,8 @@ static inline void aer_process_err_devices(struct pcie_device *p_device, | |||
715 | static void aer_isr_one_error(struct pcie_device *p_device, | 717 | static void aer_isr_one_error(struct pcie_device *p_device, |
716 | struct aer_err_source *e_src) | 718 | struct aer_err_source *e_src) |
717 | { | 719 | { |
718 | struct aer_err_info *e_info; | 720 | struct aer_rpc *rpc = get_service_data(p_device); |
719 | 721 | struct aer_err_info *e_info = &rpc->e_info; | |
720 | /* struct aer_err_info might be big, so we allocate it with slab */ | ||
721 | e_info = kmalloc(sizeof(struct aer_err_info), GFP_KERNEL); | ||
722 | if (!e_info) { | ||
723 | dev_printk(KERN_DEBUG, &p_device->port->dev, | ||
724 | "Can't allocate mem when processing AER errors\n"); | ||
725 | return; | ||
726 | } | ||
727 | 722 | ||
728 | /* | 723 | /* |
729 | * There is a possibility that both correctable error and | 724 | * There is a possibility that both correctable error and |
@@ -762,8 +757,6 @@ static void aer_isr_one_error(struct pcie_device *p_device, | |||
762 | if (find_source_device(p_device->port, e_info)) | 757 | if (find_source_device(p_device->port, e_info)) |
763 | aer_process_err_devices(p_device, e_info); | 758 | aer_process_err_devices(p_device, e_info); |
764 | } | 759 | } |
765 | |||
766 | kfree(e_info); | ||
767 | } | 760 | } |
768 | 761 | ||
769 | /** | 762 | /** |
@@ -812,19 +805,3 @@ void aer_isr(struct work_struct *work) | |||
812 | aer_isr_one_error(p_device, &e_src); | 805 | aer_isr_one_error(p_device, &e_src); |
813 | mutex_unlock(&rpc->rpc_mutex); | 806 | mutex_unlock(&rpc->rpc_mutex); |
814 | } | 807 | } |
815 | |||
816 | /** | ||
817 | * aer_init - provide AER initialization | ||
818 | * @dev: pointer to AER pcie device | ||
819 | * | ||
820 | * Invoked when AER service driver is loaded. | ||
821 | */ | ||
822 | int aer_init(struct pcie_device *dev) | ||
823 | { | ||
824 | if (forceload) { | ||
825 | dev_printk(KERN_DEBUG, &dev->device, | ||
826 | "aerdrv forceload requested.\n"); | ||
827 | pcie_aer_force_firmware_first(dev->port, 0); | ||
828 | } | ||
829 | return 0; | ||
830 | } | ||
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 167fe411ce2e..54c4b691e51f 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c | |||
@@ -219,15 +219,13 @@ int cper_severity_to_aer(int cper_severity) | |||
219 | } | 219 | } |
220 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); | 220 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); |
221 | 221 | ||
222 | void cper_print_aer(struct pci_dev *dev, int cper_severity, | 222 | void cper_print_aer(struct pci_dev *dev, int aer_severity, |
223 | struct aer_capability_regs *aer) | 223 | struct aer_capability_regs *aer) |
224 | { | 224 | { |
225 | int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; | 225 | int layer, agent, status_strs_size, tlp_header_valid = 0; |
226 | u32 status, mask; | 226 | u32 status, mask; |
227 | const char **status_strs; | 227 | const char **status_strs; |
228 | 228 | ||
229 | aer_severity = cper_severity_to_aer(cper_severity); | ||
230 | |||
231 | if (aer_severity == AER_CORRECTABLE) { | 229 | if (aer_severity == AER_CORRECTABLE) { |
232 | status = aer->cor_status; | 230 | status = aer->cor_status; |
233 | mask = aer->cor_mask; | 231 | mask = aer->cor_mask; |
diff --git a/drivers/pci/pcie/pcie-dpc.c b/drivers/pci/pcie/pcie-dpc.c index 250f87861786..9811b14d9ad8 100644 --- a/drivers/pci/pcie/pcie-dpc.c +++ b/drivers/pci/pcie/pcie-dpc.c | |||
@@ -1,5 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * PCI Express Downstream Port Containment services driver | 2 | * PCI Express Downstream Port Containment services driver |
3 | * Author: Keith Busch <keith.busch@intel.com> | ||
4 | * | ||
3 | * Copyright (C) 2016 Intel Corp. | 5 | * Copyright (C) 2016 Intel Corp. |
4 | * | 6 | * |
5 | * This file is subject to the terms and conditions of the GNU General Public | 7 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -9,7 +11,7 @@ | |||
9 | 11 | ||
10 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
11 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
12 | #include <linux/module.h> | 14 | #include <linux/init.h> |
13 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
14 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
15 | 17 | ||
@@ -143,16 +145,4 @@ static int __init dpc_service_init(void) | |||
143 | { | 145 | { |
144 | return pcie_port_service_register(&dpcdriver); | 146 | return pcie_port_service_register(&dpcdriver); |
145 | } | 147 | } |
146 | 148 | device_initcall(dpc_service_init); | |
147 | static void __exit dpc_service_exit(void) | ||
148 | { | ||
149 | pcie_port_service_unregister(&dpcdriver); | ||
150 | } | ||
151 | |||
152 | MODULE_DESCRIPTION("PCI Express Downstream Port Containment driver"); | ||
153 | MODULE_AUTHOR("Keith Busch <keith.busch@intel.com>"); | ||
154 | MODULE_LICENSE("GPL"); | ||
155 | MODULE_VERSION("0.1"); | ||
156 | |||
157 | module_init(dpc_service_init); | ||
158 | module_exit(dpc_service_exit); | ||
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 1ae4c73e7a3c..884bad5320f8 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * for more details. | 10 | * for more details. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
15 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
16 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
@@ -449,17 +448,6 @@ static int pcie_pme_resume(struct pcie_device *srv) | |||
449 | return 0; | 448 | return 0; |
450 | } | 449 | } |
451 | 450 | ||
452 | /** | ||
453 | * pcie_pme_remove - Prepare PCIe PME service device for removal. | ||
454 | * @srv - PCIe service device to remove. | ||
455 | */ | ||
456 | static void pcie_pme_remove(struct pcie_device *srv) | ||
457 | { | ||
458 | pcie_pme_suspend(srv); | ||
459 | free_irq(srv->irq, srv); | ||
460 | kfree(get_service_data(srv)); | ||
461 | } | ||
462 | |||
463 | static struct pcie_port_service_driver pcie_pme_driver = { | 451 | static struct pcie_port_service_driver pcie_pme_driver = { |
464 | .name = "pcie_pme", | 452 | .name = "pcie_pme", |
465 | .port_type = PCI_EXP_TYPE_ROOT_PORT, | 453 | .port_type = PCI_EXP_TYPE_ROOT_PORT, |
@@ -468,7 +456,6 @@ static struct pcie_port_service_driver pcie_pme_driver = { | |||
468 | .probe = pcie_pme_probe, | 456 | .probe = pcie_pme_probe, |
469 | .suspend = pcie_pme_suspend, | 457 | .suspend = pcie_pme_suspend, |
470 | .resume = pcie_pme_resume, | 458 | .resume = pcie_pme_resume, |
471 | .remove = pcie_pme_remove, | ||
472 | }; | 459 | }; |
473 | 460 | ||
474 | /** | 461 | /** |
@@ -478,5 +465,4 @@ static int __init pcie_pme_service_init(void) | |||
478 | { | 465 | { |
479 | return pcie_port_service_register(&pcie_pme_driver); | 466 | return pcie_port_service_register(&pcie_pme_driver); |
480 | } | 467 | } |
481 | 468 | device_initcall(pcie_pme_service_init); | |
482 | module_init(pcie_pme_service_init); | ||
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 70d7ad8c6d17..79327cc14e7d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -1,12 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * File: portdrv_pci.c | 2 | * File: portdrv_pci.c |
3 | * Purpose: PCI Express Port Bus Driver | 3 | * Purpose: PCI Express Port Bus Driver |
4 | * Author: Tom Nguyen <tom.l.nguyen@intel.com> | ||
5 | * Version: v1.0 | ||
4 | * | 6 | * |
5 | * Copyright (C) 2004 Intel | 7 | * Copyright (C) 2004 Intel |
6 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) | 8 | * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) |
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
11 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
@@ -21,16 +22,6 @@ | |||
21 | #include "portdrv.h" | 22 | #include "portdrv.h" |
22 | #include "aer/aerdrv.h" | 23 | #include "aer/aerdrv.h" |
23 | 24 | ||
24 | /* | ||
25 | * Version Information | ||
26 | */ | ||
27 | #define DRIVER_VERSION "v1.0" | ||
28 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" | ||
29 | #define DRIVER_DESC "PCIe Port Bus Driver" | ||
30 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
31 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
32 | MODULE_LICENSE("GPL"); | ||
33 | |||
34 | /* If this switch is set, PCIe port native services should not be enabled. */ | 25 | /* If this switch is set, PCIe port native services should not be enabled. */ |
35 | bool pcie_ports_disabled; | 26 | bool pcie_ports_disabled; |
36 | 27 | ||
@@ -341,7 +332,6 @@ static const struct pci_device_id port_pci_ids[] = { { | |||
341 | PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), | 332 | PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), |
342 | }, { /* end: all zeroes */ } | 333 | }, { /* end: all zeroes */ } |
343 | }; | 334 | }; |
344 | MODULE_DEVICE_TABLE(pci, port_pci_ids); | ||
345 | 335 | ||
346 | static const struct pci_error_handlers pcie_portdrv_err_handler = { | 336 | static const struct pci_error_handlers pcie_portdrv_err_handler = { |
347 | .error_detected = pcie_portdrv_error_detected, | 337 | .error_detected = pcie_portdrv_error_detected, |
@@ -406,5 +396,4 @@ static int __init pcie_portdrv_init(void) | |||
406 | out: | 396 | out: |
407 | return retval; | 397 | return retval; |
408 | } | 398 | } |
409 | 399 | device_initcall(pcie_portdrv_init); | |
410 | module_init(pcie_portdrv_init); | ||
diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c new file mode 100644 index 000000000000..bab8ac63c4f3 --- /dev/null +++ b/drivers/pci/pcie/ptm.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * PCI Express Precision Time Measurement | ||
3 | * Copyright (c) 2016, Intel Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include "../pci.h" | ||
19 | |||
20 | static void pci_ptm_info(struct pci_dev *dev) | ||
21 | { | ||
22 | char clock_desc[8]; | ||
23 | |||
24 | switch (dev->ptm_granularity) { | ||
25 | case 0: | ||
26 | snprintf(clock_desc, sizeof(clock_desc), "unknown"); | ||
27 | break; | ||
28 | case 255: | ||
29 | snprintf(clock_desc, sizeof(clock_desc), ">254ns"); | ||
30 | break; | ||
31 | default: | ||
32 | snprintf(clock_desc, sizeof(clock_desc), "%udns", | ||
33 | dev->ptm_granularity); | ||
34 | break; | ||
35 | } | ||
36 | dev_info(&dev->dev, "PTM enabled%s, %s granularity\n", | ||
37 | dev->ptm_root ? " (root)" : "", clock_desc); | ||
38 | } | ||
39 | |||
40 | void pci_ptm_init(struct pci_dev *dev) | ||
41 | { | ||
42 | int pos; | ||
43 | u32 cap, ctrl; | ||
44 | u8 local_clock; | ||
45 | struct pci_dev *ups; | ||
46 | |||
47 | if (!pci_is_pcie(dev)) | ||
48 | return; | ||
49 | |||
50 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM); | ||
51 | if (!pos) | ||
52 | return; | ||
53 | |||
54 | /* | ||
55 | * Enable PTM only on interior devices (root ports, switch ports, | ||
56 | * etc.) on the assumption that it causes no link traffic until an | ||
57 | * endpoint enables it. | ||
58 | */ | ||
59 | if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT || | ||
60 | pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)) | ||
61 | return; | ||
62 | |||
63 | pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap); | ||
64 | local_clock = (cap & PCI_PTM_GRANULARITY_MASK) >> 8; | ||
65 | |||
66 | /* | ||
67 | * There's no point in enabling PTM unless it's enabled in the | ||
68 | * upstream device or this device can be a PTM Root itself. Per | ||
69 | * the spec recommendation (PCIe r3.1, sec 7.32.3), select the | ||
70 | * furthest upstream Time Source as the PTM Root. | ||
71 | */ | ||
72 | ups = pci_upstream_bridge(dev); | ||
73 | if (ups && ups->ptm_enabled) { | ||
74 | ctrl = PCI_PTM_CTRL_ENABLE; | ||
75 | if (ups->ptm_granularity == 0) | ||
76 | dev->ptm_granularity = 0; | ||
77 | else if (ups->ptm_granularity > local_clock) | ||
78 | dev->ptm_granularity = ups->ptm_granularity; | ||
79 | } else { | ||
80 | if (cap & PCI_PTM_CAP_ROOT) { | ||
81 | ctrl = PCI_PTM_CTRL_ENABLE | PCI_PTM_CTRL_ROOT; | ||
82 | dev->ptm_root = 1; | ||
83 | dev->ptm_granularity = local_clock; | ||
84 | } else | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | ctrl |= dev->ptm_granularity << 8; | ||
89 | pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl); | ||
90 | dev->ptm_enabled = 1; | ||
91 | |||
92 | pci_ptm_info(dev); | ||
93 | } | ||
94 | |||
95 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
96 | { | ||
97 | int pos; | ||
98 | u32 cap, ctrl; | ||
99 | struct pci_dev *ups; | ||
100 | |||
101 | if (!pci_is_pcie(dev)) | ||
102 | return -EINVAL; | ||
103 | |||
104 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM); | ||
105 | if (!pos) | ||
106 | return -EINVAL; | ||
107 | |||
108 | pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap); | ||
109 | if (!(cap & PCI_PTM_CAP_REQ)) | ||
110 | return -EINVAL; | ||
111 | |||
112 | /* | ||
113 | * For a PCIe Endpoint, PTM is only useful if the endpoint can | ||
114 | * issue PTM requests to upstream devices that have PTM enabled. | ||
115 | * | ||
116 | * For Root Complex Integrated Endpoints, there is no upstream | ||
117 | * device, so there must be some implementation-specific way to | ||
118 | * associate the endpoint with a time source. | ||
119 | */ | ||
120 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_ENDPOINT) { | ||
121 | ups = pci_upstream_bridge(dev); | ||
122 | if (!ups || !ups->ptm_enabled) | ||
123 | return -EINVAL; | ||
124 | |||
125 | dev->ptm_granularity = ups->ptm_granularity; | ||
126 | } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) { | ||
127 | dev->ptm_granularity = 0; | ||
128 | } else | ||
129 | return -EINVAL; | ||
130 | |||
131 | ctrl = PCI_PTM_CTRL_ENABLE; | ||
132 | ctrl |= dev->ptm_granularity << 8; | ||
133 | pci_write_config_dword(dev, pos + PCI_PTM_CTRL, ctrl); | ||
134 | dev->ptm_enabled = 1; | ||
135 | |||
136 | pci_ptm_info(dev); | ||
137 | |||
138 | if (granularity) | ||
139 | *granularity = dev->ptm_granularity; | ||
140 | return 0; | ||
141 | } | ||
142 | EXPORT_SYMBOL(pci_enable_ptm); | ||
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 93f280df3428..ab002671fa60 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -1666,7 +1666,11 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1666 | /* Enable ACS P2P upstream forwarding */ | 1666 | /* Enable ACS P2P upstream forwarding */ |
1667 | pci_enable_acs(dev); | 1667 | pci_enable_acs(dev); |
1668 | 1668 | ||
1669 | pci_cleanup_aer_error_status_regs(dev); | 1669 | /* Precision Time Measurement */ |
1670 | pci_ptm_init(dev); | ||
1671 | |||
1672 | /* Advanced Error Reporting */ | ||
1673 | pci_aer_init(dev); | ||
1670 | } | 1674 | } |
1671 | 1675 | ||
1672 | /* | 1676 | /* |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 37ff0158e45f..edc7f9600477 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -3198,6 +3198,7 @@ static void quirk_no_bus_reset(struct pci_dev *dev) | |||
3198 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset); | 3198 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset); |
3199 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset); | 3199 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset); |
3200 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); | 3200 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset); |
3201 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset); | ||
3201 | 3202 | ||
3202 | static void quirk_no_pm_reset(struct pci_dev *dev) | 3203 | static void quirk_no_pm_reset(struct pci_dev *dev) |
3203 | { | 3204 | { |
@@ -4428,3 +4429,20 @@ static void quirk_intel_qat_vf_cap(struct pci_dev *pdev) | |||
4428 | } | 4429 | } |
4429 | } | 4430 | } |
4430 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap); | 4431 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap); |
4432 | |||
4433 | /* | ||
4434 | * VMD-enabled root ports will change the source ID for all messages | ||
4435 | * to the VMD device. Rather than doing device matching with the source | ||
4436 | * ID, the AER driver should traverse the child device tree, reading | ||
4437 | * AER registers to find the faulting device. | ||
4438 | */ | ||
4439 | static void quirk_no_aersid(struct pci_dev *pdev) | ||
4440 | { | ||
4441 | /* VMD Domain */ | ||
4442 | if (pdev->bus->sysdata && pci_domain_nr(pdev->bus) >= 0x10000) | ||
4443 | pdev->bus->bus_flags |= PCI_BUS_FLAGS_NO_AERSID; | ||
4444 | } | ||
4445 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid); | ||
4446 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid); | ||
4447 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid); | ||
4448 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid); | ||
diff --git a/include/linux/aer.h b/include/linux/aer.h index 164049357e5c..04602cbe85dc 100644 --- a/include/linux/aer.h +++ b/include/linux/aer.h | |||
@@ -63,7 +63,7 @@ static inline int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | |||
63 | } | 63 | } |
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | void cper_print_aer(struct pci_dev *dev, int cper_severity, | 66 | void cper_print_aer(struct pci_dev *dev, int aer_severity, |
67 | struct aer_capability_regs *aer); | 67 | struct aer_capability_regs *aer); |
68 | int cper_severity_to_aer(int cper_severity); | 68 | int cper_severity_to_aer(int cper_severity); |
69 | void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, | 69 | void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn, |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 2599a980340f..b0e4ed19b315 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -187,8 +187,9 @@ enum pci_irq_reroute_variant { | |||
187 | 187 | ||
188 | typedef unsigned short __bitwise pci_bus_flags_t; | 188 | typedef unsigned short __bitwise pci_bus_flags_t; |
189 | enum pci_bus_flags { | 189 | enum pci_bus_flags { |
190 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, | 190 | PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1, |
191 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, | 191 | PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2, |
192 | PCI_BUS_FLAGS_NO_AERSID = (__force pci_bus_flags_t) 4, | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | /* These values come from the PCI Express Spec */ | 195 | /* These values come from the PCI Express Spec */ |
@@ -268,6 +269,9 @@ struct pci_dev { | |||
268 | unsigned int class; /* 3 bytes: (base,sub,prog-if) */ | 269 | unsigned int class; /* 3 bytes: (base,sub,prog-if) */ |
269 | u8 revision; /* PCI revision, low byte of class word */ | 270 | u8 revision; /* PCI revision, low byte of class word */ |
270 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ | 271 | u8 hdr_type; /* PCI header type (`multi' flag masked out) */ |
272 | #ifdef CONFIG_PCIEAER | ||
273 | u16 aer_cap; /* AER capability offset */ | ||
274 | #endif | ||
271 | u8 pcie_cap; /* PCIe capability offset */ | 275 | u8 pcie_cap; /* PCIe capability offset */ |
272 | u8 msi_cap; /* MSI capability offset */ | 276 | u8 msi_cap; /* MSI capability offset */ |
273 | u8 msix_cap; /* MSI-X capability offset */ | 277 | u8 msix_cap; /* MSI-X capability offset */ |
@@ -308,6 +312,9 @@ struct pci_dev { | |||
308 | powered on/off by the | 312 | powered on/off by the |
309 | corresponding bridge */ | 313 | corresponding bridge */ |
310 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ | 314 | unsigned int ignore_hotplug:1; /* Ignore hotplug events */ |
315 | unsigned int hotplug_user_indicators:1; /* SlotCtl indicators | ||
316 | controlled exclusively by | ||
317 | user sysfs */ | ||
311 | unsigned int d3_delay; /* D3->D0 transition time in ms */ | 318 | unsigned int d3_delay; /* D3->D0 transition time in ms */ |
312 | unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ | 319 | unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */ |
313 | 320 | ||
@@ -367,6 +374,12 @@ struct pci_dev { | |||
367 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ | 374 | int rom_attr_enabled; /* has display of the rom attribute been enabled? */ |
368 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ | 375 | struct bin_attribute *res_attr[DEVICE_COUNT_RESOURCE]; /* sysfs file for resources */ |
369 | struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ | 376 | struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ |
377 | |||
378 | #ifdef CONFIG_PCIE_PTM | ||
379 | unsigned int ptm_root:1; | ||
380 | unsigned int ptm_enabled:1; | ||
381 | u8 ptm_granularity; | ||
382 | #endif | ||
370 | #ifdef CONFIG_PCI_MSI | 383 | #ifdef CONFIG_PCI_MSI |
371 | const struct attribute_group **msi_irq_groups; | 384 | const struct attribute_group **msi_irq_groups; |
372 | #endif | 385 | #endif |
@@ -1368,9 +1381,11 @@ static inline bool pcie_aspm_support_enabled(void) { return false; } | |||
1368 | #ifdef CONFIG_PCIEAER | 1381 | #ifdef CONFIG_PCIEAER |
1369 | void pci_no_aer(void); | 1382 | void pci_no_aer(void); |
1370 | bool pci_aer_available(void); | 1383 | bool pci_aer_available(void); |
1384 | int pci_aer_init(struct pci_dev *dev); | ||
1371 | #else | 1385 | #else |
1372 | static inline void pci_no_aer(void) { } | 1386 | static inline void pci_no_aer(void) { } |
1373 | static inline bool pci_aer_available(void) { return false; } | 1387 | static inline bool pci_aer_available(void) { return false; } |
1388 | static inline int pci_aer_init(struct pci_dev *d) { return -ENODEV; } | ||
1374 | #endif | 1389 | #endif |
1375 | 1390 | ||
1376 | #ifdef CONFIG_PCIE_ECRC | 1391 | #ifdef CONFIG_PCIE_ECRC |
@@ -1402,6 +1417,13 @@ static inline void pci_disable_ats(struct pci_dev *d) { } | |||
1402 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } | 1417 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } |
1403 | #endif | 1418 | #endif |
1404 | 1419 | ||
1420 | #ifdef CONFIG_PCIE_PTM | ||
1421 | int pci_enable_ptm(struct pci_dev *dev, u8 *granularity); | ||
1422 | #else | ||
1423 | static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity) | ||
1424 | { return -EINVAL; } | ||
1425 | #endif | ||
1426 | |||
1405 | void pci_cfg_access_lock(struct pci_dev *dev); | 1427 | void pci_cfg_access_lock(struct pci_dev *dev); |
1406 | bool pci_cfg_access_trylock(struct pci_dev *dev); | 1428 | bool pci_cfg_access_trylock(struct pci_dev *dev); |
1407 | void pci_cfg_access_unlock(struct pci_dev *dev); | 1429 | void pci_cfg_access_unlock(struct pci_dev *dev); |
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index 404095124ae2..d812172d1d7b 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h | |||
@@ -671,7 +671,8 @@ | |||
671 | #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ | 671 | #define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */ |
672 | #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ | 672 | #define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ |
673 | #define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ | 673 | #define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */ |
674 | #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DPC | 674 | #define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */ |
675 | #define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM | ||
675 | 676 | ||
676 | #define PCI_EXT_CAP_DSN_SIZEOF 12 | 677 | #define PCI_EXT_CAP_DSN_SIZEOF 12 |
677 | #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 | 678 | #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 |
@@ -964,4 +965,13 @@ | |||
964 | 965 | ||
965 | #define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ | 966 | #define PCI_EXP_DPC_SOURCE_ID 10 /* DPC Source Identifier */ |
966 | 967 | ||
968 | /* Precision Time Measurement */ | ||
969 | #define PCI_PTM_CAP 0x04 /* PTM Capability */ | ||
970 | #define PCI_PTM_CAP_REQ 0x00000001 /* Requester capable */ | ||
971 | #define PCI_PTM_CAP_ROOT 0x00000004 /* Root capable */ | ||
972 | #define PCI_PTM_GRANULARITY_MASK 0x0000FF00 /* Clock granularity */ | ||
973 | #define PCI_PTM_CTRL 0x08 /* PTM Control */ | ||
974 | #define PCI_PTM_CTRL_ENABLE 0x00000001 /* PTM enable */ | ||
975 | #define PCI_PTM_CTRL_ROOT 0x00000002 /* Root select */ | ||
976 | |||
967 | #endif /* LINUX_PCI_REGS_H */ | 977 | #endif /* LINUX_PCI_REGS_H */ |