diff options
61 files changed, 2510 insertions, 766 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 05c33b50b218..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, |
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-hyperv.c b/drivers/pci/host/pci-hyperv.c index 6955ffdb89f3..763ff8745828 100644 --- a/drivers/pci/host/pci-hyperv.c +++ b/drivers/pci/host/pci-hyperv.c | |||
| @@ -200,11 +200,11 @@ struct tran_int_desc { | |||
| 200 | */ | 200 | */ |
| 201 | 201 | ||
| 202 | struct pci_message { | 202 | struct pci_message { |
| 203 | u32 message_type; | 203 | u32 type; |
| 204 | } __packed; | 204 | } __packed; |
| 205 | 205 | ||
| 206 | struct pci_child_message { | 206 | struct pci_child_message { |
| 207 | u32 message_type; | 207 | struct pci_message message_type; |
| 208 | union win_slot_encoding wslot; | 208 | union win_slot_encoding wslot; |
| 209 | } __packed; | 209 | } __packed; |
| 210 | 210 | ||
| @@ -222,7 +222,8 @@ struct pci_packet { | |||
| 222 | void (*completion_func)(void *context, struct pci_response *resp, | 222 | void (*completion_func)(void *context, struct pci_response *resp, |
| 223 | int resp_packet_size); | 223 | int resp_packet_size); |
| 224 | void *compl_ctxt; | 224 | void *compl_ctxt; |
| 225 | struct pci_message message; | 225 | |
| 226 | struct pci_message message[0]; | ||
| 226 | }; | 227 | }; |
| 227 | 228 | ||
| 228 | /* | 229 | /* |
| @@ -258,7 +259,7 @@ struct pci_bus_d0_entry { | |||
| 258 | struct pci_bus_relations { | 259 | struct pci_bus_relations { |
| 259 | struct pci_incoming_message incoming; | 260 | struct pci_incoming_message incoming; |
| 260 | u32 device_count; | 261 | u32 device_count; |
| 261 | struct pci_function_description func[1]; | 262 | struct pci_function_description func[0]; |
| 262 | } __packed; | 263 | } __packed; |
| 263 | 264 | ||
| 264 | struct pci_q_res_req_response { | 265 | struct pci_q_res_req_response { |
| @@ -314,7 +315,7 @@ struct pci_dev_incoming { | |||
| 314 | } __packed; | 315 | } __packed; |
| 315 | 316 | ||
| 316 | struct pci_eject_response { | 317 | struct pci_eject_response { |
| 317 | u32 message_type; | 318 | struct pci_message message_type; |
| 318 | union win_slot_encoding wslot; | 319 | union win_slot_encoding wslot; |
| 319 | u32 status; | 320 | u32 status; |
| 320 | } __packed; | 321 | } __packed; |
| @@ -373,7 +374,6 @@ struct hv_pcibus_device { | |||
| 373 | 374 | ||
| 374 | struct list_head children; | 375 | struct list_head children; |
| 375 | struct list_head dr_list; | 376 | struct list_head dr_list; |
| 376 | struct work_struct wrk; | ||
| 377 | 377 | ||
| 378 | struct msi_domain_info msi_info; | 378 | struct msi_domain_info msi_info; |
| 379 | struct msi_controller msi_chip; | 379 | struct msi_controller msi_chip; |
| @@ -393,7 +393,7 @@ struct hv_dr_work { | |||
| 393 | struct hv_dr_state { | 393 | struct hv_dr_state { |
| 394 | struct list_head list_entry; | 394 | struct list_head list_entry; |
| 395 | u32 device_count; | 395 | u32 device_count; |
| 396 | struct pci_function_description func[1]; | 396 | struct pci_function_description func[0]; |
| 397 | }; | 397 | }; |
| 398 | 398 | ||
| 399 | enum hv_pcichild_state { | 399 | enum hv_pcichild_state { |
| @@ -447,15 +447,16 @@ struct hv_pci_compl { | |||
| 447 | * for any message for which the completion packet contains a | 447 | * for any message for which the completion packet contains a |
| 448 | * status and nothing else. | 448 | * status and nothing else. |
| 449 | */ | 449 | */ |
| 450 | static | 450 | static void hv_pci_generic_compl(void *context, struct pci_response *resp, |
| 451 | void | 451 | int resp_packet_size) |
| 452 | hv_pci_generic_compl(void *context, struct pci_response *resp, | ||
| 453 | int resp_packet_size) | ||
| 454 | { | 452 | { |
| 455 | struct hv_pci_compl *comp_pkt = context; | 453 | struct hv_pci_compl *comp_pkt = context; |
| 456 | 454 | ||
| 457 | if (resp_packet_size >= offsetofend(struct pci_response, status)) | 455 | if (resp_packet_size >= offsetofend(struct pci_response, status)) |
| 458 | comp_pkt->completion_status = resp->status; | 456 | comp_pkt->completion_status = resp->status; |
| 457 | else | ||
| 458 | comp_pkt->completion_status = -1; | ||
| 459 | |||
| 459 | complete(&comp_pkt->host_event); | 460 | complete(&comp_pkt->host_event); |
| 460 | } | 461 | } |
| 461 | 462 | ||
| @@ -694,13 +695,12 @@ static void hv_int_desc_free(struct hv_pci_dev *hpdev, | |||
| 694 | struct pci_delete_interrupt *int_pkt; | 695 | struct pci_delete_interrupt *int_pkt; |
| 695 | struct { | 696 | struct { |
| 696 | struct pci_packet pkt; | 697 | struct pci_packet pkt; |
| 697 | u8 buffer[sizeof(struct pci_delete_interrupt) - | 698 | u8 buffer[sizeof(struct pci_delete_interrupt)]; |
| 698 | sizeof(struct pci_message)]; | ||
| 699 | } ctxt; | 699 | } ctxt; |
| 700 | 700 | ||
| 701 | memset(&ctxt, 0, sizeof(ctxt)); | 701 | memset(&ctxt, 0, sizeof(ctxt)); |
| 702 | int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message; | 702 | int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message; |
| 703 | int_pkt->message_type.message_type = | 703 | int_pkt->message_type.type = |
| 704 | PCI_DELETE_INTERRUPT_MESSAGE; | 704 | PCI_DELETE_INTERRUPT_MESSAGE; |
| 705 | int_pkt->wslot.slot = hpdev->desc.win_slot.slot; | 705 | int_pkt->wslot.slot = hpdev->desc.win_slot.slot; |
| 706 | int_pkt->int_desc = *int_desc; | 706 | int_pkt->int_desc = *int_desc; |
| @@ -847,8 +847,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 847 | struct cpumask *affinity; | 847 | struct cpumask *affinity; |
| 848 | struct { | 848 | struct { |
| 849 | struct pci_packet pkt; | 849 | struct pci_packet pkt; |
| 850 | u8 buffer[sizeof(struct pci_create_interrupt) - | 850 | u8 buffer[sizeof(struct pci_create_interrupt)]; |
| 851 | sizeof(struct pci_message)]; | ||
| 852 | } ctxt; | 851 | } ctxt; |
| 853 | int cpu; | 852 | int cpu; |
| 854 | int ret; | 853 | int ret; |
| @@ -876,7 +875,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 876 | ctxt.pkt.completion_func = hv_pci_compose_compl; | 875 | ctxt.pkt.completion_func = hv_pci_compose_compl; |
| 877 | ctxt.pkt.compl_ctxt = ∁ | 876 | ctxt.pkt.compl_ctxt = ∁ |
| 878 | int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message; | 877 | int_pkt = (struct pci_create_interrupt *)&ctxt.pkt.message; |
| 879 | int_pkt->message_type.message_type = PCI_CREATE_INTERRUPT_MESSAGE; | 878 | int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; |
| 880 | int_pkt->wslot.slot = hpdev->desc.win_slot.slot; | 879 | int_pkt->wslot.slot = hpdev->desc.win_slot.slot; |
| 881 | int_pkt->int_desc.vector = cfg->vector; | 880 | int_pkt->int_desc.vector = cfg->vector; |
| 882 | int_pkt->int_desc.vector_count = 1; | 881 | int_pkt->int_desc.vector_count = 1; |
| @@ -897,8 +896,10 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | |||
| 897 | sizeof(*int_pkt), (unsigned long)&ctxt.pkt, | 896 | sizeof(*int_pkt), (unsigned long)&ctxt.pkt, |
| 898 | VM_PKT_DATA_INBAND, | 897 | VM_PKT_DATA_INBAND, |
| 899 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 898 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
| 900 | if (!ret) | 899 | if (ret) |
| 901 | wait_for_completion(&comp.comp_pkt.host_event); | 900 | goto free_int_desc; |
| 901 | |||
| 902 | wait_for_completion(&comp.comp_pkt.host_event); | ||
| 902 | 903 | ||
| 903 | if (comp.comp_pkt.completion_status < 0) { | 904 | if (comp.comp_pkt.completion_status < 0) { |
| 904 | dev_err(&hbus->hdev->device, | 905 | dev_err(&hbus->hdev->device, |
| @@ -1289,7 +1290,7 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus, | |||
| 1289 | pkt.init_packet.compl_ctxt = &comp_pkt; | 1290 | pkt.init_packet.compl_ctxt = &comp_pkt; |
| 1290 | pkt.init_packet.completion_func = q_resource_requirements; | 1291 | pkt.init_packet.completion_func = q_resource_requirements; |
| 1291 | res_req = (struct pci_child_message *)&pkt.init_packet.message; | 1292 | res_req = (struct pci_child_message *)&pkt.init_packet.message; |
| 1292 | res_req->message_type = PCI_QUERY_RESOURCE_REQUIREMENTS; | 1293 | res_req->message_type.type = PCI_QUERY_RESOURCE_REQUIREMENTS; |
| 1293 | res_req->wslot.slot = desc->win_slot.slot; | 1294 | res_req->wslot.slot = desc->win_slot.slot; |
| 1294 | 1295 | ||
| 1295 | ret = vmbus_sendpacket(hbus->hdev->channel, res_req, | 1296 | ret = vmbus_sendpacket(hbus->hdev->channel, res_req, |
| @@ -1466,8 +1467,7 @@ static void pci_devices_present_work(struct work_struct *work) | |||
| 1466 | if (hpdev->reported_missing) { | 1467 | if (hpdev->reported_missing) { |
| 1467 | found = true; | 1468 | found = true; |
| 1468 | put_pcichild(hpdev, hv_pcidev_ref_childlist); | 1469 | put_pcichild(hpdev, hv_pcidev_ref_childlist); |
| 1469 | list_del(&hpdev->list_entry); | 1470 | list_move_tail(&hpdev->list_entry, &removed); |
| 1470 | list_add_tail(&hpdev->list_entry, &removed); | ||
| 1471 | break; | 1471 | break; |
| 1472 | } | 1472 | } |
| 1473 | } | 1473 | } |
| @@ -1558,8 +1558,7 @@ static void hv_eject_device_work(struct work_struct *work) | |||
| 1558 | int wslot; | 1558 | int wslot; |
| 1559 | struct { | 1559 | struct { |
| 1560 | struct pci_packet pkt; | 1560 | struct pci_packet pkt; |
| 1561 | u8 buffer[sizeof(struct pci_eject_response) - | 1561 | u8 buffer[sizeof(struct pci_eject_response)]; |
| 1562 | sizeof(struct pci_message)]; | ||
| 1563 | } ctxt; | 1562 | } ctxt; |
| 1564 | 1563 | ||
| 1565 | hpdev = container_of(work, struct hv_pci_dev, wrk); | 1564 | hpdev = container_of(work, struct hv_pci_dev, wrk); |
| @@ -1585,7 +1584,7 @@ static void hv_eject_device_work(struct work_struct *work) | |||
| 1585 | 1584 | ||
| 1586 | memset(&ctxt, 0, sizeof(ctxt)); | 1585 | memset(&ctxt, 0, sizeof(ctxt)); |
| 1587 | ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; | 1586 | ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; |
| 1588 | ejct_pkt->message_type = PCI_EJECTION_COMPLETE; | 1587 | ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; |
| 1589 | ejct_pkt->wslot.slot = hpdev->desc.win_slot.slot; | 1588 | ejct_pkt->wslot.slot = hpdev->desc.win_slot.slot; |
| 1590 | vmbus_sendpacket(hpdev->hbus->hdev->channel, ejct_pkt, | 1589 | vmbus_sendpacket(hpdev->hbus->hdev->channel, ejct_pkt, |
| 1591 | sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt, | 1590 | sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt, |
| @@ -1688,7 +1687,7 @@ static void hv_pci_onchannelcallback(void *context) | |||
| 1688 | case VM_PKT_DATA_INBAND: | 1687 | case VM_PKT_DATA_INBAND: |
| 1689 | 1688 | ||
| 1690 | new_message = (struct pci_incoming_message *)buffer; | 1689 | new_message = (struct pci_incoming_message *)buffer; |
| 1691 | switch (new_message->message_type.message_type) { | 1690 | switch (new_message->message_type.type) { |
| 1692 | case PCI_BUS_RELATIONS: | 1691 | case PCI_BUS_RELATIONS: |
| 1693 | 1692 | ||
| 1694 | bus_rel = (struct pci_bus_relations *)buffer; | 1693 | bus_rel = (struct pci_bus_relations *)buffer; |
| @@ -1719,7 +1718,7 @@ static void hv_pci_onchannelcallback(void *context) | |||
| 1719 | default: | 1718 | default: |
| 1720 | dev_warn(&hbus->hdev->device, | 1719 | dev_warn(&hbus->hdev->device, |
| 1721 | "Unimplemented protocol message %x\n", | 1720 | "Unimplemented protocol message %x\n", |
| 1722 | new_message->message_type.message_type); | 1721 | new_message->message_type.type); |
| 1723 | break; | 1722 | break; |
| 1724 | } | 1723 | } |
| 1725 | break; | 1724 | break; |
| @@ -1772,7 +1771,7 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev) | |||
| 1772 | pkt->completion_func = hv_pci_generic_compl; | 1771 | pkt->completion_func = hv_pci_generic_compl; |
| 1773 | pkt->compl_ctxt = &comp_pkt; | 1772 | pkt->compl_ctxt = &comp_pkt; |
| 1774 | version_req = (struct pci_version_request *)&pkt->message; | 1773 | version_req = (struct pci_version_request *)&pkt->message; |
| 1775 | version_req->message_type.message_type = PCI_QUERY_PROTOCOL_VERSION; | 1774 | version_req->message_type.type = PCI_QUERY_PROTOCOL_VERSION; |
| 1776 | version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT; | 1775 | version_req->protocol_version = PCI_PROTOCOL_VERSION_CURRENT; |
| 1777 | 1776 | ||
| 1778 | ret = vmbus_sendpacket(hdev->channel, version_req, | 1777 | ret = vmbus_sendpacket(hdev->channel, version_req, |
| @@ -1973,7 +1972,7 @@ static int hv_pci_enter_d0(struct hv_device *hdev) | |||
| 1973 | pkt->completion_func = hv_pci_generic_compl; | 1972 | pkt->completion_func = hv_pci_generic_compl; |
| 1974 | pkt->compl_ctxt = &comp_pkt; | 1973 | pkt->compl_ctxt = &comp_pkt; |
| 1975 | d0_entry = (struct pci_bus_d0_entry *)&pkt->message; | 1974 | d0_entry = (struct pci_bus_d0_entry *)&pkt->message; |
| 1976 | d0_entry->message_type.message_type = PCI_BUS_D0ENTRY; | 1975 | d0_entry->message_type.type = PCI_BUS_D0ENTRY; |
| 1977 | d0_entry->mmio_base = hbus->mem_config->start; | 1976 | d0_entry->mmio_base = hbus->mem_config->start; |
| 1978 | 1977 | ||
| 1979 | ret = vmbus_sendpacket(hdev->channel, d0_entry, sizeof(*d0_entry), | 1978 | ret = vmbus_sendpacket(hdev->channel, d0_entry, sizeof(*d0_entry), |
| @@ -2019,7 +2018,7 @@ static int hv_pci_query_relations(struct hv_device *hdev) | |||
| 2019 | return -ENOTEMPTY; | 2018 | return -ENOTEMPTY; |
| 2020 | 2019 | ||
| 2021 | memset(&message, 0, sizeof(message)); | 2020 | memset(&message, 0, sizeof(message)); |
| 2022 | message.message_type = PCI_QUERY_BUS_RELATIONS; | 2021 | message.type = PCI_QUERY_BUS_RELATIONS; |
| 2023 | 2022 | ||
| 2024 | ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message), | 2023 | ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message), |
| 2025 | 0, VM_PKT_DATA_INBAND, 0); | 2024 | 0, VM_PKT_DATA_INBAND, 0); |
| @@ -2072,8 +2071,8 @@ static int hv_send_resources_allocated(struct hv_device *hdev) | |||
| 2072 | init_completion(&comp_pkt.host_event); | 2071 | init_completion(&comp_pkt.host_event); |
| 2073 | pkt->completion_func = hv_pci_generic_compl; | 2072 | pkt->completion_func = hv_pci_generic_compl; |
| 2074 | pkt->compl_ctxt = &comp_pkt; | 2073 | pkt->compl_ctxt = &comp_pkt; |
| 2075 | pkt->message.message_type = PCI_RESOURCES_ASSIGNED; | ||
| 2076 | res_assigned = (struct pci_resources_assigned *)&pkt->message; | 2074 | res_assigned = (struct pci_resources_assigned *)&pkt->message; |
| 2075 | res_assigned->message_type.type = PCI_RESOURCES_ASSIGNED; | ||
| 2077 | res_assigned->wslot.slot = hpdev->desc.win_slot.slot; | 2076 | res_assigned->wslot.slot = hpdev->desc.win_slot.slot; |
| 2078 | 2077 | ||
| 2079 | put_pcichild(hpdev, hv_pcidev_ref_by_slot); | 2078 | put_pcichild(hpdev, hv_pcidev_ref_by_slot); |
| @@ -2123,7 +2122,7 @@ static int hv_send_resources_released(struct hv_device *hdev) | |||
| 2123 | continue; | 2122 | continue; |
| 2124 | 2123 | ||
| 2125 | memset(&pkt, 0, sizeof(pkt)); | 2124 | memset(&pkt, 0, sizeof(pkt)); |
| 2126 | pkt.message_type = PCI_RESOURCES_RELEASED; | 2125 | pkt.message_type.type = PCI_RESOURCES_RELEASED; |
| 2127 | pkt.wslot.slot = hpdev->desc.win_slot.slot; | 2126 | pkt.wslot.slot = hpdev->desc.win_slot.slot; |
| 2128 | 2127 | ||
| 2129 | put_pcichild(hpdev, hv_pcidev_ref_by_slot); | 2128 | put_pcichild(hpdev, hv_pcidev_ref_by_slot); |
| @@ -2290,7 +2289,7 @@ static int hv_pci_remove(struct hv_device *hdev) | |||
| 2290 | init_completion(&comp_pkt.host_event); | 2289 | init_completion(&comp_pkt.host_event); |
| 2291 | pkt.teardown_packet.completion_func = hv_pci_generic_compl; | 2290 | pkt.teardown_packet.completion_func = hv_pci_generic_compl; |
| 2292 | pkt.teardown_packet.compl_ctxt = &comp_pkt; | 2291 | pkt.teardown_packet.compl_ctxt = &comp_pkt; |
| 2293 | pkt.teardown_packet.message.message_type = PCI_BUS_D0EXIT; | 2292 | pkt.teardown_packet.message[0].type = PCI_BUS_D0EXIT; |
| 2294 | 2293 | ||
| 2295 | ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message, | 2294 | ret = vmbus_sendpacket(hdev->channel, &pkt.teardown_packet.message, |
| 2296 | sizeof(struct pci_message), | 2295 | sizeof(struct pci_message), |
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 */ |
