Commit 0d519f2d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pci-v4.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI updates from Bjorn Helgaas:

 - add enhanced Downstream Port Containment support, which prints more
   details about Root Port Programmed I/O errors (Dongdong Liu)

 - add Layerscape ls1088a and ls2088a support (Hou Zhiqiang)

 - add MediaTek MT2712 and MT7622 support (Ryder Lee)

 - add MediaTek MT2712 and MT7622 MSI support (Honghui Zhang)

 - add Qualcom IPQ8074 support (Varadarajan Narayanan)

 - add R-Car r8a7743/5 device tree support (Biju Das)

 - add Rockchip per-lane PHY support for better power management (Shawn
   Lin)

 - fix IRQ mapping for hot-added devices by replacing the
   pci_fixup_irqs() boot-time design with a host bridge hook called at
   probe-time (Lorenzo Pieralisi, Matthew Minter)

 - fix race when enabling two devices that results in upstream bridge
   not being enabled correctly (Srinath Mannam)

 - fix pciehp power fault infinite loop (Keith Busch)

 - fix SHPC bridge MSI hotplug events by enabling bus mastering
   (Aleksandr Bezzubikov)

 - fix a VFIO issue by correcting PCIe capability sizes (Alex
   Williamson)

 - fix an INTD issue on Xilinx and possibly other drivers by unifying
   INTx IRQ domain support (Paul Burton)

 - avoid IOMMU stalls by marking AMD Stoney GPU ATS as broken (Joerg
   Roedel)

 - allow APM X-Gene device assignment to guests by adding an ACS quirk
   (Feng Kan)

 - fix driver crashes by disabling Extended Tags on Broadcom HT2100
   (Extended Tags support is required for PCIe Receivers but not
   Requesters, and we now enable them by default when Requesters support
   them) (Sinan Kaya)

 - fix MSIs for devices that use phantom RIDs for DMA by assuming MSIs
   use the real Requester ID (not a phantom RID) (Robin Murphy)

 - prevent assignment of Intel VMD children to guests (which may be
   supported eventually, but isn't yet) by not associating an IOMMU with
   them (Jon Derrick)

 - fix Intel VMD suspend/resume by releasing IRQs on suspend (Scott
   Bauer)

 - fix a Function-Level Reset issue with Intel 750 NVMe by waiting
   longer (up to 60sec instead of 1sec) for device to become ready
   (Sinan Kaya)

 - fix a Function-Level Reset issue on iProc Stingray by working around
   hardware defects in the CRS implementation (Oza Pawandeep)

 - fix an issue with Intel NVMe P3700 after an iProc reset by adding a
   delay during shutdown (Oza Pawandeep)

 - fix a Microsoft Hyper-V lockdep issue by polling instead of blocking
   in compose_msi_msg() (Stephen Hemminger)

 - fix a wireless LAN driver timeout by clearing DesignWare MSI
   interrupt status after it is handled, not before (Faiz Abbas)

 - fix DesignWare ATU enable checking (Jisheng Zhang)

 - reduce Layerscape dependencies on the bootloader by doing more
   initialization in the driver (Hou Zhiqiang)

 - improve Intel VMD performance allowing allocation of more IRQ vectors
   than present CPUs (Keith Busch)

 - improve endpoint framework support for initial DMA mask, different
   BAR sizes, configurable page sizes, MSI, test driver, etc (Kishon
   Vijay Abraham I, Stan Drozd)

 - rework CRS support to add periodic messages while we poll during
   enumeration and after Function-Level Reset and prepare for possible
   other uses of CRS (Sinan Kaya)

 - clean up Root Port AER handling by removing unnecessary code and
   moving error handler methods to struct pcie_port_service_driver
   (Christoph Hellwig)

 - clean up error handling paths in various drivers (Bjorn Andersson,
   Fabio Estevam, Gustavo A. R. Silva, Harunobu Kurokawa, Jeffy Chen,
   Lorenzo Pieralisi, Sergei Shtylyov)

 - clean up SR-IOV resource handling by disabling VF decoding before
   updating the corresponding resource structs (Gavin Shan)

 - clean up DesignWare-based drivers by unifying quirks to update Class
   Code and Interrupt Pin and related handling of write-protected
   registers (Hou Zhiqiang)

 - clean up by adding empty generic pcibios_align_resource() and
   pcibios_fixup_bus() and removing empty arch-specific implementations
   (Palmer Dabbelt)

 - request exclusive reset control for several drivers to allow cleanup
   elsewhere (Philipp Zabel)

 - constify various structures (Arvind Yadav, Bhumika Goyal)

 - convert from full_name() to %pOF (Rob Herring)

 - remove unused variables from iProc, HiSi, Altera, Keystone (Shawn
   Lin)

* tag 'pci-v4.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (170 commits)
  PCI: xgene: Clean up whitespace
  PCI: xgene: Define XGENE_PCI_EXP_CAP and use generic PCI_EXP_RTCTL offset
  PCI: xgene: Fix platform_get_irq() error handling
  PCI: xilinx-nwl: Fix platform_get_irq() error handling
  PCI: rockchip: Fix platform_get_irq() error handling
  PCI: altera: Fix platform_get_irq() error handling
  PCI: spear13xx: Fix platform_get_irq() error handling
  PCI: artpec6: Fix platform_get_irq() error handling
  PCI: armada8k: Fix platform_get_irq() error handling
  PCI: dra7xx: Fix platform_get_irq() error handling
  PCI: exynos: Fix platform_get_irq() error handling
  PCI: iproc: Clean up whitespace
  PCI: iproc: Rename PCI_EXP_CAP to IPROC_PCI_EXP_CAP
  PCI: iproc: Add 500ms delay during device shutdown
  PCI: Fix typos and whitespace errors
  PCI: Remove unused "res" variable from pci_resource_io()
  PCI: Correct kernel-doc of pci_vpd_srdt_size(), pci_vpd_srdt_tag()
  PCI/AER: Reformat AER register definitions
  iommu/vt-d: Prevent VMD child devices from being remapping targets
  x86/PCI: Use is_vmd() rather than relying on the domain number
  ...
parents 0756b7fb cf2d8041
......@@ -2090,7 +2090,7 @@ S: Kuala Lumpur, Malaysia
N: Mohit Kumar
D: ST Microelectronics SPEAr13xx PCI host bridge driver
D: Synopsys Designware PCI host bridge driver
D: Synopsys DesignWare PCI host bridge driver
N: Gabor Kuti
E: seasons@falcon.sch.bme.hu
......
* Freescale 83xx and 512x PCI bridges
Freescale 83xx and 512x SOCs include the same pci bridge core.
Freescale 83xx and 512x SOCs include the same PCI bridge core.
83xx/512x specific notes:
- reg: should contain two address length tuples
The first is for the internal pci bridge registers
The second is for the pci config space access registers
The first is for the internal PCI bridge registers
The second is for the PCI config space access registers
Example (MPC8313ERDB)
pci0: pci@e0008500 {
......
......@@ -7,21 +7,21 @@ Required properties:
"Txs": TX slave port region
"Cra": Control register access region
- interrupt-parent: interrupt source phandle.
- interrupts: specifies the interrupt source of the parent interrupt controller.
The format of the interrupt specifier depends on the parent interrupt
controller.
- interrupts: specifies the interrupt source of the parent interrupt
controller. The format of the interrupt specifier depends
on the parent interrupt controller.
- device_type: must be "pci"
- #address-cells: set to <3>
- #size-cells: set to <2>
- #size-cells: set to <2>
- #interrupt-cells: set to <1>
- ranges: describes the translation of addresses for root ports and standard
PCI regions.
- ranges: describes the translation of addresses for root ports and
standard PCI regions.
- interrupt-map-mask and interrupt-map: standard PCI properties to define the
mapping of the PCIe interface to interrupt numbers.
Optional properties:
- msi-parent: Link to the hardware entity that serves as the MSI controller for this PCIe
controller.
- msi-parent: Link to the hardware entity that serves as the MSI controller
for this PCIe controller.
- bus-range: PCI bus numbers covered
Example
......@@ -45,5 +45,5 @@ Example
<0 0 0 3 &pcie_0 3>,
<0 0 0 4 &pcie_0 4>;
ranges = <0x82000000 0x00000000 0x00000000 0xc0000000 0x00000000 0x10000000
0x82000000 0x00000000 0x10000000 0xd0000000 0x00000000 0x10000000>;
0x82000000 0x00000000 0x10000000 0xd0000000 0x00000000 0x10000000>;
};
......@@ -6,7 +6,7 @@ and thus inherits all the common properties defined in designware-pcie.txt.
Required properties:
- compatible: "axis,artpec6-pcie", "snps,dw-pcie"
- reg: base addresses and lengths of the PCIe controller (DBI),
the phy controller, and configuration address space.
the PHY controller, and configuration address space.
- reg-names: Must include the following entries:
- "dbi"
- "phy"
......
* Synopsys Designware PCIe interface
* Synopsys DesignWare PCIe interface
Required properties:
- compatible: should contain "snps,dw-pcie" to identify the core.
......@@ -17,29 +17,27 @@ RC mode:
properties to define the mapping of the PCIe interface to interrupt
numbers.
EP mode:
- num-ib-windows: number of inbound address translation
windows
- num-ob-windows: number of outbound address translation
windows
- num-ib-windows: number of inbound address translation windows
- num-ob-windows: number of outbound address translation windows
Optional properties:
- num-lanes: number of lanes to use (this property should be specified unless
the link is brought already up in BIOS)
- reset-gpio: gpio pin number of power good signal
- reset-gpio: GPIO pin number of power good signal
- clocks: Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names: Must include the following entries:
- "pcie"
- "pcie_bus"
RC mode:
- num-viewport: number of view ports configured in
hardware. If a platform does not specify it, the driver assumes 2.
- bus-range: PCI bus numbers covered (it is recommended
for new devicetrees to specify this property, to keep backwards
compatibility a range of 0x00-0xff is assumed if not present)
- num-viewport: number of view ports configured in hardware. If a platform
does not specify it, the driver assumes 2.
- bus-range: PCI bus numbers covered (it is recommended for new devicetrees
to specify this property, to keep backwards compatibility a range of
0x00-0xff is assumed if not present)
EP mode:
- max-functions: maximum number of functions that can be
configured
- max-functions: maximum number of functions that can be configured
Example configuration:
......
* Freescale i.MX6 PCIe interface
This PCIe host controller is based on the Synopsis Designware PCIe IP
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.
Required properties:
......
HiSilicon Hip05 and Hip06 PCIe host bridge DT description
HiSilicon PCIe host controller is based on Designware PCI core.
It shares common functions with PCIe Designware core driver and inherits
HiSilicon PCIe host controller is based on the Synopsys DesignWare PCI core.
It shares common functions with the PCIe DesignWare core driver and inherits
common properties defined in
Documentation/devicetree/bindings/pci/designware-pci.txt.
......
HiSilicon Kirin SoCs PCIe host DT description
Kirin PCIe host controller is based on Designware PCI core.
It shares common functions with PCIe Designware core driver
and inherits common properties defined in
Kirin PCIe host controller is based on the Synopsys DesignWare PCI core.
It shares common functions with the PCIe DesignWare core driver and
inherits common properties defined in
Documentation/devicetree/bindings/pci/designware-pci.txt.
Additional properties are described here:
......@@ -16,7 +16,7 @@ Required properties
"apb": apb Ctrl register defined by Kirin;
"phy": apb PHY register defined by Kirin;
"config": PCIe configuration space registers.
- reset-gpios: The gpio to generate PCIe perst assert and deassert signal.
- reset-gpios: The GPIO to generate PCIe PERST# assert and deassert signal.
Optional properties:
......
......@@ -15,8 +15,10 @@ Required properties:
- compatible: should contain the platform identifier such as:
"fsl,ls1021a-pcie", "snps,dw-pcie"
"fsl,ls2080a-pcie", "fsl,ls2085a-pcie", "snps,dw-pcie"
"fsl,ls2088a-pcie"
"fsl,ls1088a-pcie"
"fsl,ls1046a-pcie"
- reg: base addresses and lengths of the PCIe controller
- reg: base addresses and lengths of the PCIe controller register blocks.
- interrupts: A list of interrupt outputs of the controller. Must contain an
entry for each entry in the interrupt-names property.
- interrupt-names: Must include the following entries:
......
MediaTek Gen2 PCIe controller which is available on MT7623 series SoCs
PCIe subsys supports single root complex (RC) with 3 Root Ports. Each root
ports supports a Gen2 1-lane Link and has PIPE interface to PHY.
MediaTek Gen2 PCIe controller
Required properties:
- compatible: Should contain "mediatek,mt7623-pcie".
- compatible: Should contain one of the following strings:
"mediatek,mt2701-pcie"
"mediatek,mt2712-pcie"
"mediatek,mt7622-pcie"
"mediatek,mt7623-pcie"
- device_type: Must be "pci"
- reg: Base addresses and lengths of the PCIe controller.
- reg: Base addresses and lengths of the PCIe subsys and root ports.
- reg-names: Names of the above areas to use during resource lookup.
- #address-cells: Address representation for root ports (must be 3)
- #size-cells: Size representation for root ports (must be 2)
- #interrupt-cells: Size representation for interrupts (must be 1)
- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
Please refer to the standard PCI bus binding document for a more detailed
explanation.
- clocks: Must contain an entry for each entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names: Must include the following entries:
- free_ck :for reference clock of PCIe subsys
- sys_ck0 :for clock of Port0
- sys_ck1 :for clock of Port1
- sys_ck2 :for clock of Port2
- resets: Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names: Must include the following entries:
- pcie-rst0 :port0 reset
- pcie-rst1 :port1 reset
- pcie-rst2 :port2 reset
- clock-names:
Mandatory entries:
- sys_ckN :transaction layer and data link layer clock
Required entries for MT2701/MT7623:
- free_ck :for reference clock of PCIe subsys
Required entries for MT2712/MT7622:
- ahb_ckN :AHB slave interface operating clock for CSR access and RC
initiated MMIO access
Required entries for MT7622:
- axi_ckN :application layer MMIO channel operating clock
- aux_ckN :pe2_mac_bridge and pe2_mac_core operating clock when
pcie_mac_ck/pcie_pipe_ck is turned off
- obff_ckN :OBFF functional block operating clock
- pipe_ckN :LTSSM and PHY/MAC layer operating clock
where N starting from 0 to one less than the number of root ports.
- phys: List of PHY specifiers (used by generic PHY framework).
- phy-names : Must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
number of PHYs as specified in *phys* property.
......@@ -34,6 +36,20 @@ Required properties:
- bus-range: Range of bus numbers associated with this controller.
- ranges: Ranges for the PCI memory and I/O regions.
Required properties for MT7623/MT2701:
- #interrupt-cells: Size representation for interrupts (must be 1)
- interrupt-map-mask and interrupt-map: Standard PCI IRQ mapping properties
Please refer to the standard PCI bus binding document for a more detailed
explanation.
- resets: Must contain an entry for each entry in reset-names.
See ../reset/reset.txt for details.
- reset-names: Must be "pcie-rst0", "pcie-rst1", "pcie-rstN".. based on the
number of root ports.
Required properties for MT2712/MT7622:
-interrupts: A list of interrupt outputs of the controller, must have one
entry for each PCIe port
In addition, the device tree node must have sub-nodes describing each
PCIe port interface, having the following mandatory properties:
......@@ -51,7 +67,7 @@ Required properties:
property is sufficient.
- num-lanes: Number of lanes to use for this port.
Examples:
Examples for MT7623:
hifsys: syscon@1a000000 {
compatible = "mediatek,mt7623-hifsys",
......@@ -69,6 +85,7 @@ Examples:
<0 0x1a142000 0 0x1000>, /* Port0 registers */
<0 0x1a143000 0 0x1000>, /* Port1 registers */
<0 0x1a144000 0 0x1000>; /* Port2 registers */
reg-names = "subsys", "port0", "port1", "port2";
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
......@@ -85,7 +102,8 @@ Examples:
<&hifsys MT2701_HIFSYS_PCIE1_RST>,
<&hifsys MT2701_HIFSYS_PCIE2_RST>;
reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2";
phys = <&pcie0_phy>, <&pcie1_phy>, <&pcie2_phy>;
phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>,
<&pcie2_phy PHY_TYPE_PCIE>;
phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>;
bus-range = <0x00 0xff>;
......@@ -128,3 +146,139 @@ Examples:
num-lanes = <1>;
};
};
Examples for MT2712:
pcie: pcie@11700000 {
compatible = "mediatek,mt2712-pcie";
device_type = "pci";
reg = <0 0x11700000 0 0x1000>,
<0 0x112ff000 0 0x1000>;
reg-names = "port0", "port1";
#address-cells = <3>;
#size-cells = <2>;
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_PE2_MAC_P0_SEL>,
<&topckgen CLK_TOP_PE2_MAC_P1_SEL>,
<&pericfg CLK_PERI_PCIE0>,
<&pericfg CLK_PERI_PCIE1>;
clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1";
phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
phy-names = "pcie-phy0", "pcie-phy1";
bus-range = <0x00 0xff>;
ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
pcie0: pcie@0,0 {
device_type = "pci";
reg = <0x0000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges;
num-lanes = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
<0 0 0 2 &pcie_intc0 1>,
<0 0 0 3 &pcie_intc0 2>,
<0 0 0 4 &pcie_intc0 3>;
pcie_intc0: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
pcie1: pcie@1,0 {
device_type = "pci";
reg = <0x0800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges;
num-lanes = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc1 0>,
<0 0 0 2 &pcie_intc1 1>,
<0 0 0 3 &pcie_intc1 2>,
<0 0 0 4 &pcie_intc1 3>;
pcie_intc1: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
};
Examples for MT7622:
pcie: pcie@1a140000 {
compatible = "mediatek,mt7622-pcie";
device_type = "pci";
reg = <0 0x1a140000 0 0x1000>,
<0 0x1a143000 0 0x1000>,
<0 0x1a145000 0 0x1000>;
reg-names = "subsys", "port0", "port1";
#address-cells = <3>;
#size-cells = <2>;
interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_LOW>,
<GIC_SPI 229 IRQ_TYPE_LEVEL_LOW>;
clocks = <&pciesys CLK_PCIE_P0_MAC_EN>,
<&pciesys CLK_PCIE_P1_MAC_EN>,
<&pciesys CLK_PCIE_P0_AHB_EN>,
<&pciesys CLK_PCIE_P1_AHB_EN>,
<&pciesys CLK_PCIE_P0_AUX_EN>,
<&pciesys CLK_PCIE_P1_AUX_EN>,
<&pciesys CLK_PCIE_P0_AXI_EN>,
<&pciesys CLK_PCIE_P1_AXI_EN>,
<&pciesys CLK_PCIE_P0_OBFF_EN>,
<&pciesys CLK_PCIE_P1_OBFF_EN>,
<&pciesys CLK_PCIE_P0_PIPE_EN>,
<&pciesys CLK_PCIE_P1_PIPE_EN>;
clock-names = "sys_ck0", "sys_ck1", "ahb_ck0", "ahb_ck1",
"aux_ck0", "aux_ck1", "axi_ck0", "axi_ck1",
"obff_ck0", "obff_ck1", "pipe_ck0", "pipe_ck1";
phys = <&pcie0_phy PHY_TYPE_PCIE>, <&pcie1_phy PHY_TYPE_PCIE>;
phy-names = "pcie-phy0", "pcie-phy1";
power-domains = <&scpsys MT7622_POWER_DOMAIN_HIF0>;
bus-range = <0x00 0xff>;
ranges = <0x82000000 0 0x20000000 0x0 0x20000000 0 0x10000000>;
pcie0: pcie@0,0 {
device_type = "pci";
reg = <0x0000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges;
num-lanes = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
<0 0 0 2 &pcie_intc0 1>,
<0 0 0 3 &pcie_intc0 2>,
<0 0 0 4 &pcie_intc0 3>;
pcie_intc0: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
pcie1: pcie@1,0 {
device_type = "pci";
reg = <0x0800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
ranges;
num-lanes = <1>;
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc1 0>,
<0 0 0 2 &pcie_intc1 1>,
<0 0 0 3 &pcie_intc1 2>,
<0 0 0 4 &pcie_intc1 3>;
pcie_intc1: interrupt-controller {
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
};
};
};
......@@ -77,7 +77,7 @@ and the following optional properties:
- marvell,pcie-lane: the physical PCIe lane number, for ports having
multiple lanes. If this property is not found, we assume that the
value is 0.
- reset-gpios: optional gpio to PERST#
- reset-gpios: optional GPIO to PERST#
- reset-delay-us: delay in us to wait after reset de-assertion, if not
specified will default to 100ms, as required by the PCIe specification.
......
* Marvell Armada 7K/8K PCIe interface
This PCIe host controller is based on the Synopsis Designware PCIe IP
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.
Required properties:
......
TI Keystone PCIe interface
Keystone PCI host Controller is based on Designware PCI h/w version 3.65.
It shares common functions with PCIe Designware core driver and inherit
common properties defined in
Keystone PCI host Controller is based on the Synopsys DesignWare PCI
hardware version 3.65. It shares common functions with the PCIe DesignWare
core driver and inherits common properties defined in
Documentation/devicetree/bindings/pci/designware-pci.txt
Please refer to Documentation/devicetree/bindings/pci/designware-pci.txt
for the details of Designware DT bindings. Additional properties are
for the details of DesignWare DT bindings. Additional properties are
described here as well as properties that are not applicable.
Required Properties:-
......@@ -52,13 +52,12 @@ pcie_intc: Interrupt controller device node for Legacy IRQ chip
};
Optional properties:-
phys: phandle to Generic Keystone SerDes phy for PCI
phy-names: name of the Generic Keystine SerDes phy for PCI
phys: phandle to generic Keystone SerDes PHY for PCI
phy-names: name of the generic Keystone SerDes PHY for PCI
- If boot loader already does PCI link establishment, then phys and
phy-names shouldn't be present.
interrupts: platform interrupt for error interrupts.
Designware DT Properties not applicable for Keystone PCI
DesignWare DT Properties not applicable for Keystone PCI
1. pcie_bus clock-names not used. Instead, a phandle to phys is used.
......@@ -6,11 +6,14 @@ AHB. There is one bridge instance per USB port connected to the internal
OHCI and EHCI controllers.
Required properties:
- compatible: "renesas,pci-r8a7790" for the R8A7790 SoC;
- compatible: "renesas,pci-r8a7743" for the R8A7743 SoC;
"renesas,pci-r8a7745" for the R8A7745 SoC;
"renesas,pci-r8a7790" for the R8A7790 SoC;
"renesas,pci-r8a7791" for the R8A7791 SoC;
"renesas,pci-r8a7793" for the R8A7793 SoC;
"renesas,pci-r8a7794" for the R8A7794 SoC;
"renesas,pci-rcar-gen2" for a generic R-Car Gen2 compatible device
"renesas,pci-rcar-gen2" for a generic R-Car Gen2 or
RZ/G1 compatible device.
When compatible with the generic version, nodes must list the
......
......@@ -9,6 +9,7 @@
- "qcom,pcie-apq8084" for apq8084
- "qcom,pcie-msm8996" for msm8996 or apq8096
- "qcom,pcie-ipq4019" for ipq4019
- "qcom,pcie-ipq8074" for ipq8074
- reg:
Usage: required
......@@ -20,7 +21,7 @@
Value type: <stringlist>
Definition: Must include the following entries
- "parf" Qualcomm specific registers
- "dbi" Designware PCIe registers
- "dbi" DesignWare PCIe registers
- "elbi" External local bus interface registers
- "config" PCIe configuration space
......@@ -105,6 +106,16 @@
- "bus_master" Master AXI clock
- "bus_slave" Slave AXI clock
- clock-names:
Usage: required for ipq8074
Value type: <stringlist>
Definition: Should contain the following entries
- "iface" PCIe to SysNOC BIU clock
- "axi_m" AXI Master clock
- "axi_s" AXI Slave clock
- "ahb" AHB clock
- "aux" Auxiliary clock
- resets:
Usage: required
Value type: <prop-encoded-array>
......@@ -144,6 +155,18 @@
- "ahb" AHB reset
- "phy_ahb" PHY AHB reset
- reset-names:
Usage: required for ipq8074
Value type: <stringlist>
Definition: Should contain the following entries
- "pipe" PIPE reset
- "sleep" Sleep reset
- "sticky" Core Sticky reset
- "axi_m" AXI Master reset
- "axi_s" AXI Slave reset
- "ahb" AHB Reset
- "axi_m_sticky" AXI Master Sticky reset
- power-domains:
Usage: required for apq8084 and msm8996/apq8096
Value type: <prop-encoded-array>
......@@ -180,7 +203,7 @@
- <name>-gpios:
Usage: optional
Value type: <prop-encoded-array>
Definition: List of phandle and gpio specifier pairs. Should contain
Definition: List of phandle and GPIO specifier pairs. Should contain
- "perst-gpios" PCIe endpoint reset signal line
- "wake-gpios" PCIe endpoint wake signal line
......
......@@ -71,7 +71,7 @@
- interrupt-map: standard PCI properties to define the mapping of the
PCI interface to interrupt numbers.
The PCI host bridge node migh have additional sub-nodes representing
The PCI host bridge node might have additional sub-nodes representing
the onboard PCI devices/PCI slots. Each such sub-node must have the
following mandatory properties:
......
......@@ -14,7 +14,7 @@ compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC;
SoC-specific version corresponding to the platform first
followed by the generic version.
- reg: base address and length of the pcie controller registers.
- reg: base address and length of the PCIe controller registers.
- #address-cells: set to <3>
- #size-cells: set to <2>
- bus-range: PCI bus numbers covered
......@@ -25,15 +25,14 @@ compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC;
source for hardware related interrupts (e.g. link speed change).
- #interrupt-cells: set to <1>
- interrupt-map-mask and interrupt-map: standard PCI properties
to define the mapping of the PCIe interface to interrupt
numbers.
to define the mapping of the PCIe interface to interrupt numbers.
- clocks: from common clock binding: clock specifiers for the PCIe controller
and PCIe bus clocks.
- clock-names: from common clock binding: should be "pcie" and "pcie_bus".
Example:
SoC specific DT Entry:
SoC-specific DT Entry:
pcie: pcie@fe000000 {
compatible = "renesas,pcie-r8a7791", "renesas,pcie-rcar-gen2";
......
......@@ -19,8 +19,6 @@ Required properties:
- "pm"
- msi-map: Maps a Requester ID to an MSI controller and associated
msi-specifier data. See ./pci-msi.txt
- phys: From PHY bindings: Phandle for the Generic PHY for PCIe.
- phy-names: MUST be "pcie-phy".
- interrupts: Three interrupt entries must be specified.
- interrupt-names: Must include the following names
- "sys"
......@@ -42,11 +40,24 @@ Required properties:
interrupt source. The value must be 1.
- interrupt-map-mask and interrupt-map: standard PCI properties
Required properties for legacy PHY model (deprecated):
- phys: From PHY bindings: Phandle for the Generic PHY for PCIe.
- phy-names: MUST be "pcie-phy".
Required properties for per-lane PHY model (preferred):
- phys: Must contain an phandle to a PHY for each entry in phy-names.
- phy-names: Must include 4 entries for all 4 lanes even if some of
them won't be used for your cases. Entries are of the form "pcie-phy-N":
where N ranges from 0 to 3.
(see example below and you MUST also refer to ../phy/rockchip-pcie-phy.txt
for changing the #phy-cells of phy node to support it)
Optional Property:
- aspm-no-l0s: RC won't support ASPM L0s. This property is needed if
using 24MHz OSC for RC's PHY.
- ep-gpios: contain the entry for pre-reset gpio
- ep-gpios: contain the entry for pre-reset GPIO
- num-lanes: number of lanes to use
- vpcie12v-supply: The phandle to the 12v regulator to use for PCIe.
- vpcie3v3-supply: The phandle to the 3.3v regulator to use for PCIe.
- vpcie1v8-supply: The phandle to the 1.8v regulator to use for PCIe.
- vpcie0v9-supply: The phandle to the 0.9v regulator to use for PCIe.
......@@ -95,6 +106,7 @@ pcie0: pcie@f8000000 {
<&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>, <&cru SRST_A_PCIE>;
reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
"pm", "pclk", "aclk";
/* deprecated legacy PHY model */
phys = <&pcie_phy>;
phy-names = "pcie-phy";
pinctrl-names = "default";
......@@ -111,3 +123,13 @@ pcie0: pcie@f8000000 {
#interrupt-cells = <1>;
};
};
pcie0: pcie@f8000000 {
...
/* preferred per-lane PHY model */
phys = <&pcie_phy 0>, <&pcie_phy 1>, <&pcie_phy 2>, <&pcie_phy 3>;
phy-names = "pcie-phy-0", "pcie-phy-1", "pcie-phy-2", "pcie-phy-3";
...
};
* Samsung Exynos 5440 PCIe interface
This PCIe host controller is based on the Synopsis Designware PCIe IP
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.
Required properties:
- compatible: "samsung,exynos5440-pcie"
- reg: base addresses and lengths of the pcie controller,
the phy controller, additional register for the phy controller.
(Registers for the phy controller are DEPRECATED.
- reg: base addresses and lengths of the PCIe controller,
the PHY controller, additional register for the PHY controller.
(Registers for the PHY controller are DEPRECATED.
Use the PHY framework.)
- reg-names : First name should be set to "elbi".
And use the "config" instead of getting the confgiruation address space
And use the "config" instead of getting the configuration address space
from "ranges".
NOTE: When use the "config" property, reg-names must be set.
NOTE: When using the "config" property, reg-names must be set.
- interrupts: A list of interrupt outputs for level interrupt,
pulse interrupt, special interrupt.
- phys: From PHY binding. Phandle for the Generic PHY.
- phys: From PHY binding. Phandle for the generic PHY.
Refer to Documentation/devicetree/bindings/phy/samsung-phy.txt
Other common properties refer to
Documentation/devicetree/binding/pci/designware-pcie.txt
For other common properties, refer to
Documentation/devicetree/bindings/pci/designware-pcie.txt
Example:
SoC specific DT Entry:
SoC-specific DT Entry:
pcie@290000 {
compatible = "samsung,exynos5440-pcie", "snps,dw-pcie";
......@@ -83,7 +83,7 @@ With using PHY framework:
...
};
Board specific DT Entry:
Board-specific DT Entry:
pcie@290000 {
reset-gpio = <&pin_ctrl 5 0>;
......
SPEAr13XX PCIe DT detail:
================================
SPEAr13XX uses synopsis designware PCIe controller and ST MiPHY as phy
SPEAr13XX uses the Synopsys DesignWare PCIe controller and ST MiPHY as PHY
controller.
Required properties:
- compatible : should be "st,spear1340-pcie", "snps,dw-pcie".
- phys : phandle to phy node associated with pcie controller
- compatible : should be "st,spear1340-pcie", "snps,dw-pcie".
- phys : phandle to PHY node associated with PCIe controller
- phy-names : must be "pcie-phy"
- All other definitions as per generic PCI bindings
......
TI PCI Controllers
PCIe Designware Controller
PCIe DesignWare Controller
- compatible: Should be "ti,dra7-pcie" for RC
Should be "ti,dra7-pcie-ep" for EP
- phys : list of PHY specifiers (used by generic PHY framework)
......@@ -13,7 +13,7 @@ PCIe Designware Controller
HOST MODE
=========
- reg : Two register ranges as listed in the reg-names property
- reg-names : The first entry must be "ti-conf" for the TI specific registers
- reg-names : The first entry must be "ti-conf" for the TI-specific registers
The second entry must be "rc-dbics" for the DesignWare PCIe
registers
The third entry must be "config" for the PCIe configuration space
......@@ -30,7 +30,7 @@ HOST MODE
DEVICE MODE
===========
- reg : Four register ranges as listed in the reg-names property
- reg-names : "ti-conf" for the TI specific registers
- reg-names : "ti-conf" for the TI-specific registers
"ep_dbics" for the standard configuration registers as
they are locally accessed within the DIF CS space
"ep_dbics2" for the standard configuration registers as
......@@ -46,7 +46,7 @@ DEVICE MODE
access.
Optional Property:
- gpios : Should be added if a gpio line is required to drive PERST# line
- gpios : Should be added if a GPIO line is required to drive PERST# line
NOTE: Two DT nodes may be added for each PCI controller; one for host
mode and another for device mode. So in order for PCI to
......
......@@ -5,7 +5,7 @@ PCI host controller found on the ARM Versatile PB board's FPGA.
Required properties:
- compatible: should contain "arm,versatile-pci" to identify the Versatile PCI
controller.
- reg: base addresses and lengths of the pci controller. There must be 3
- reg: base addresses and lengths of the PCI controller. There must be 3
entries:
- Versatile-specific registers
- Self Config space
......
......@@ -4,7 +4,7 @@ Required properties:
- compatible: should be "apm,xgene1-msi" to identify
X-Gene v1 PCIe MSI controller block.
- msi-controller: indicates that this is X-Gene v1 PCIe MSI controller node
- msi-controller: indicates that this is an X-Gene v1 PCIe MSI controller node
- reg: physical base address (0x79000000) and length (0x900000) for controller
registers. These registers include the MSI termination address and data
registers as well as the MSI interrupt status registers.
......@@ -13,7 +13,8 @@ Required properties:
interrupt number 0x10 to 0x1f.
- interrupt-names: not required
Each PCIe node needs to have property msi-parent that points to msi controller node
Each PCIe node needs to have property msi-parent that points to an MSI
controller node
Examples:
......
......@@ -8,7 +8,7 @@ Required properties:
property.
- reg-names: Must include the following entries:
"csr": controller configuration registers.
"cfg": pcie configuration space registers.
"cfg": PCIe configuration space registers.
- #address-cells: set to <3>
- #size-cells: set to <2>
- ranges: ranges for the outbound memory, I/O regions.
......@@ -21,11 +21,11 @@ Required properties:
Optional properties:
- status: Either "ok" or "disabled".
- dma-coherent: Present if dma operations are coherent
- dma-coherent: Present if DMA operations are coherent
Example:
SoC specific DT Entry:
SoC-specific DT Entry:
pcie0: pcie@1f2b0000 {
status = "disabled";
......@@ -51,7 +51,7 @@ SoC specific DT Entry:
};
Board specific DT Entry:
Board-specific DT Entry:
&pcie0 {
status = "ok";
};
......@@ -15,9 +15,9 @@ Required properties:
- device_type: must be "pci"
- interrupts: Should contain NWL PCIe interrupt
- interrupt-names: Must include the following entries:
"msi1, msi0": interrupt asserted when MSI is received
"msi1, msi0": interrupt asserted when an MSI is received
"intx": interrupt asserted when a legacy interrupt is received
"misc": interrupt asserted when miscellaneous is received
"misc": interrupt asserted when miscellaneous interrupt is received
- interrupt-map-mask and interrupt-map: standard PCI properties to define the
mapping of the PCI interface to interrupt numbers.
- ranges: ranges for the PCI memory regions (I/O space region is not
......@@ -26,7 +26,8 @@ Required properties:
detailed explanation
- msi-controller: indicates that this is MSI controller node
- msi-parent: MSI parent of the root complex itself
- legacy-interrupt-controller: Interrupt controller device node for Legacy interrupts
- legacy-interrupt-controller: Interrupt controller device node for Legacy
interrupts
- interrupt-controller: identifies the node as an interrupt controller
- #interrupt-cells: should be set to 1
- #address-cells: specifies the number of cells needed to encode an
......
......@@ -3,7 +3,6 @@ Rockchip PCIE PHY
Required properties:
- compatible: rockchip,rk3399-pcie-phy
- #phy-cells: must be 0
- clocks: Must contain an entry in clock-names.
See ../clocks/clock-bindings.txt for details.
- clock-names: Must be "refclk"
......@@ -11,6 +10,12 @@ Required properties:
See ../reset/reset.txt for details.
- reset-names: Must be "phy"
Required properties for legacy PHY mode (deprecated):
- #phy-cells: must be 0
Required properties for per-lane PHY mode (preferred):
- #phy-cells: must be 1
Example:
grf: syscon@ff770000 {
......
......@@ -10244,6 +10244,7 @@ F: drivers/pci/dwc/*imx6*
PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
M: Keith Busch <keith.busch@intel.com>
M: Jonathan Derrick <jonathan.derrick@intel.com>
L: linux-pci@vger.kernel.org
S: Supported
F: drivers/pci/host/vmd.c
......@@ -10290,7 +10291,7 @@ L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
F: drivers/pci/dwc/pci-exynos.c
PCI DRIVER FOR SYNOPSIS DESIGNWARE
PCI DRIVER FOR SYNOPSYS DESIGNWARE
M: Jingoo Han <jingoohan1@gmail.com>
M: Joao Pinto <Joao.Pinto@synopsys.com>
L: linux-pci@vger.kernel.org
......
......@@ -312,8 +312,9 @@ common_init_pci(void)
{
struct pci_controller *hose;
struct list_head resources;
struct pci_host_bridge *bridge;
struct pci_bus *bus;
int next_busno;
int ret, next_busno;
int need_domain_info = 0;
u32 pci_mem_end;
u32 sg_base;
......@@ -336,11 +337,25 @@ common_init_pci(void)
pci_add_resource_offset(&resources, hose->mem_space,
hose->mem_space->start);
bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops,
hose, &resources);
if (!bus)
bridge = pci_alloc_host_bridge(0);
if (!bridge)
continue;
hose->bus = bus;
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = hose;
bridge->busnr = next_busno;
bridge->ops = alpha_mv.pci_ops;
bridge->swizzle_irq = alpha_mv.pci_swizzle;
bridge->map_irq = alpha_mv.pci_map_irq;
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
continue;
}
bus = hose->bus = bridge->bus;
hose->need_domain_info = need_domain_info;
next_busno = bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose -
......@@ -354,7 +369,6 @@ common_init_pci(void)
pcibios_claim_console_setup();
pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
for (hose = hose_head; hose; hose = hose->next) {
bus = hose->bus;
if (bus)
......@@ -362,7 +376,6 @@ common_init_pci(void)
}
}
struct pci_controller * __init
alloc_pci_controller(void)
{
......
......@@ -194,22 +194,46 @@ static struct resource irongate_mem = {
.name = "Irongate PCI MEM",
.flags = IORESOURCE_MEM,
};
static struct resource busn_resource = {
.name = "PCI busn",
.start = 0,
.end = 255,
.flags = IORESOURCE_BUS,
};
void __init
nautilus_init_pci(void)
{
struct pci_controller *hose = hose_head;
struct pci_host_bridge *bridge;
struct pci_bus *bus;
struct pci_dev *irongate;
unsigned long bus_align, bus_size, pci_mem;
unsigned long memtop = max_low_pfn << PAGE_SHIFT;
int ret;
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return;
pci_add_resource(&bridge->windows, &ioport_resource);
pci_add_resource(&bridge->windows, &iomem_resource);
pci_add_resource(&bridge->windows, &busn_resource);
bridge->dev.parent = NULL;
bridge->sysdata = hose;
bridge->busnr = 0;
bridge->ops = alpha_mv.pci_ops;
bridge->swizzle_irq = alpha_mv.pci_swizzle;
bridge->map_irq = alpha_mv.pci_map_irq;
/* Scan our single hose. */
bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
if (!bus)
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
return;
}
hose->bus = bus;
bus = hose->bus = bridge->bus;
pcibios_claim_one_bus(bus);
irongate = pci_get_bus_and_slot(0, 0);
......@@ -254,7 +278,6 @@ nautilus_init_pci(void)
/* pci_common_swizzle() relies on bus->self being NULL
for the root bus, so just clear it. */
bus->self = NULL;
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
pci_bus_add_devices(bus);
}
......
......@@ -12,7 +12,6 @@ obj-y := arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o
obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o
obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o
obj-$(CONFIG_PCI) += pcibios.o
obj-$(CONFIG_MODULES) += arcksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
......
/*
* Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/pci.h>
/*
* We don't have to worry about legacy ISA devices, so nothing to do here
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
void pcibios_fixup_bus(struct pci_bus *bus)
{
}
......@@ -238,8 +238,10 @@ pcie0: pcie@f8000000 {
linux,pci-domain = <0>;
max-link-speed = <1>;
msi-map = <0x0 &its 0x0 0x1000>;
phys = <&pcie_phy>;
phy-names = "pcie-phy";
phys = <&pcie_phy 0>, <&pcie_phy 1>,
<&pcie_phy 2>, <&pcie_phy 3>;
phy-names = "pcie-phy-0", "pcie-phy-1",
"pcie-phy-2", "pcie-phy-3";
ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x1e00000
0x81000000 0x0 0xfbe00000 0x0 0xfbe00000 0x0 0x100000>;
resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
......@@ -1295,7 +1297,7 @@ pcie_phy: pcie-phy {
compatible = "rockchip,rk3399-pcie-phy";
clocks = <&cru SCLK_PCIEPHY_REF>;
clock-names = "refclk";
#phy-cells = <0>;
#phy-cells = <1>;
resets = <&cru SRST_PCIEPHY>;
reset-names = "phy";
status = "disabled";
......
......@@ -22,23 +22,6 @@
#include <linux/pci-ecam.h>
#include <linux/slab.h>
/*
* Called after each bus is probed, but before its children are examined
*/
void pcibios_fixup_bus(struct pci_bus *bus)
{
/* nothing to do, expected to be removed in the future */
}
/*
* We don't have to worry about legacy ISA devices, so nothing to do here
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
#ifdef CONFIG_ACPI
/*
* Try to assign the IRQ number when probing a new device
......
......@@ -2,10 +2,6 @@
#include <linux/kernel.h>
#include <hwregs/intr_vect.h>
void pcibios_fixup_bus(struct pci_bus *b)
{
}
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
......
......@@ -411,13 +411,6 @@ pcibios_disable_device (struct pci_dev *dev)
acpi_pci_irq_disable(dev);
}
resource_size_t
pcibios_align_resource (void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
/**
* ia64_pci_get_legacy_mem - generic legacy mem routine
* @bus: bus to get legacy memory base address for
......
......@@ -243,6 +243,13 @@ static struct resource mcf_pci_io = {
.flags = IORESOURCE_IO,
};
static struct resource busn_resource = {
.name = "PCI busn",
.start = 0,
.end = 255,
.flags = IORESOURCE_BUS,
};
/*
* Interrupt mapping and setting.
*/
......@@ -258,6 +265,13 @@ static int mcf_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static int __init mcf_pci_init(void)
{
struct pci_host_bridge *bridge;
int ret;
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return -ENOMEM;
pr_info("ColdFire: PCI bus initialization...\n");
/* Reset the external PCI bus */
......@@ -312,14 +326,28 @@ static int __init mcf_pci_init(void)
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(msecs_to_jiffies(200));
rootbus = pci_scan_bus(0, &mcf_pci_ops, NULL);
if (!rootbus)
return -ENODEV;
pci_add_resource(&bridge->windows, &ioport_resource);
pci_add_resource(&bridge->windows, &iomem_resource);
pci_add_resource(&bridge->windows, &busn_resource);
bridge->dev.parent = NULL;
bridge->sysdata = NULL;
bridge->busnr = 0;
bridge->ops = &mcf_pci_ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = mcf_pci_map_irq;
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
return ret;
}
rootbus = bridge->bus;
rootbus->resource[0] = &mcf_pci_io;
rootbus->resource[1] = &mcf_pci_mem;
pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
pci_bus_size_bridges(rootbus);
pci_bus_assign_resources(rootbus);
pci_bus_add_devices(rootbus);
......
......@@ -81,9 +81,6 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file,
#define HAVE_ARCH_PCI_RESOURCE_TO_USER
extern void pcibios_setup_bus_devices(struct pci_bus *bus);
extern void pcibios_setup_bus_self(struct pci_bus *bus);
/* This part of code was originally in xilinx-pci.h */
#ifdef CONFIG_PCI_XILINX
extern void __init xilinx_pci_init(void);
......
......@@ -678,144 +678,6 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
/* This function tries to figure out if a bridge resource has been initialized
* by the firmware or not. It doesn't have to be absolutely bullet proof, but
* things go more smoothly when it gets it right. It should covers cases such
* as Apple "closed" bridge resources and bare-metal pSeries unassigned bridges
*/
static int pcibios_uninitialized_bridge_resource(struct pci_bus *bus,
struct resource *res)
{
struct pci_controller *hose = pci_bus_to_host(bus);
struct pci_dev *dev = bus->self;
resource_size_t offset;
u16 command;
int i;
/* Job is a bit different between memory and IO */
if (res->flags & IORESOURCE_MEM) {
/* If the BAR is non-0 (res != pci_mem_offset) then it's
* probably been initialized by somebody
*/
if (res->start != hose->pci_mem_offset)
return 0;
/* The BAR is 0, let's check if memory decoding is enabled on
* the bridge. If not, we consider it unassigned
*/
pci_read_config_word(dev, PCI_COMMAND, &command);
if ((command & PCI_COMMAND_MEMORY) == 0)
return 1;
/* Memory decoding is enabled and the BAR is 0. If any of
* the bridge resources covers that starting address (0 then
* it's good enough for us for memory
*/
for (i = 0; i < 3; i++) {
if ((hose->mem_resources[i].flags & IORESOURCE_MEM) &&
hose->mem_resources[i].start == hose->pci_mem_offset)
return 0;
}
/* Well, it starts at 0 and we know it will collide so we may as
* well consider it as unassigned. That covers the Apple case.
*/
return 1;
} else {
/* If the BAR is non-0, then we consider it assigned */
offset = (unsigned long)hose->io_base_virt - _IO_BASE;
if (((res->start - offset) & 0xfffffffful) != 0)
return 0;
/* Here, we are a bit different than memory as typically IO
* space starting at low addresses -is- valid. What we do
* instead if that we consider as unassigned anything that
* doesn't have IO enabled in the PCI command register,
* and that's it.
*/
pci_read_config_word(dev, PCI_COMMAND, &command);
if (command & PCI_COMMAND_IO)
return 0;
/* It's starting at 0 and IO is disabled in the bridge, consider
* it unassigned
*/
return 1;
}
}
/* Fixup resources of a PCI<->PCI bridge */
static void pcibios_fixup_bridge(struct pci_bus *bus)
{
struct resource *res;
int i;
struct pci_dev *dev = bus->self;
pci_bus_for_each_resource(bus, res, i) {
if (!res)
continue;
if (!res->flags)
continue;
if (i >= 3 && bus->self->transparent)
continue;
pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n",
pci_name(dev), i,
(unsigned long long)res->start,
(unsigned long long)res->end,
(unsigned int)res->flags);
/* Try to detect uninitialized P2P bridge resources,
* and clear them out so they get re-assigned later
*/
if (pcibios_uninitialized_bridge_resource(bus, res)) {
res->flags = 0;
pr_debug("PCI:%s (unassigned)\n",
pci_name(dev));
} else {
pr_debug("PCI:%s %016llx-%016llx\n",
pci_name(dev),
(unsigned long long)res->start,
(unsigned long long)res->end);
}
}
}
void pcibios_setup_bus_self(struct pci_bus *bus)
{
/* Fix up the bus resources for P2P bridges */
if (bus->self != NULL)
pcibios_fixup_bridge(bus);
}
void pcibios_setup_bus_devices(struct pci_bus *bus)
{
struct pci_dev *dev;
pr_debug("PCI: Fixup bus devices %d (%s)\n",
bus->number, bus->self ? pci_name(bus->self) : "PHB");
list_for_each_entry(dev, &bus->devices, bus_list) {
/* Setup OF node pointer in archdata */
dev->dev.of_node = pci_device_to_OF_node(dev);
/* Fixup NUMA node as it may not be setup yet by the generic
* code and is needed by the DMA init
*/
set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
/* Read default IRQs and fixup if necessary */
dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
}
}
void pcibios_fixup_bus(struct pci_bus *bus)
{
/* nothing to do */
}
EXPORT_SYMBOL(pcibios_fixup_bus);
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
......@@ -829,13 +691,6 @@ EXPORT_SYMBOL(pcibios_fixup_bus);
* but we want to try to avoid allocating at 0x2900-0x2bff
* which might have be mirrored at 0x0100-0x03ff..
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
EXPORT_SYMBOL(pcibios_align_resource);
int pcibios_add_device(struct pci_dev *dev)
{
dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
......
......@@ -78,6 +78,12 @@ static void pcibios_scanbus(struct pci_controller *hose)
static int need_domain_info;
LIST_HEAD(resources);
struct pci_bus *bus;
struct pci_host_bridge *bridge;
int ret;
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return;
if (hose->get_busno && pci_has_flag(PCI_PROBE_ONLY))
next_busno = (*hose->get_busno)();
......@@ -87,18 +93,24 @@ static void pcibios_scanbus(struct pci_controller *hose)
pci_add_resource_offset(&resources,
hose->io_resource, hose->io_offset);
pci_add_resource(&resources, hose->busn_resource);
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
hose->bus = bus;
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = hose;
bridge->busnr = next_busno;
bridge->ops = hose->pci_ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = pcibios_map_irq;
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
return;
}
hose->bus = bus = bridge->bus;
need_domain_info = need_domain_info || pci_domain_nr(bus);
set_pci_need_domain_info(hose, need_domain_info);
if (!bus) {
pci_free_resource_list(&resources);
return;
}
next_busno = bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */
......@@ -224,8 +236,6 @@ static int __init pcibios_init(void)
list_for_each_entry(hose, &controllers, list)
pcibios_scanbus(hose);
pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq);
pci_initialized = 1;
return 0;
......
......@@ -262,10 +262,6 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
return rc;
}
void pcibios_fixup_bus(struct pci_bus *bus)
{
}
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size,
resource_size_t align)
......
......@@ -5,7 +5,7 @@
#include <cpu/irq.h>
#include "pci-sh5.h"
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int result = -1;
......
......@@ -76,7 +76,7 @@ static void gapspci_fixup_resources(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
/*
* The interrupt routing semantics here are quite trivial.
......
......@@ -15,7 +15,7 @@
#include <linux/sh_intc.h>
#include "pci-sh4.h"
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
return evt2irq(0xa20) + slot;
}
......@@ -20,18 +20,18 @@
#define PCIMCR_MRSET_OFF 0xBFFFFFFF
#define PCIMCR_RFSH_OFF 0xFFFFFFFB
static u8 rts7751r2d_irq_tab[] __initdata = {
static u8 rts7751r2d_irq_tab[] = {
IRQ_PCI_INTA,
IRQ_PCI_INTB,
IRQ_PCI_INTC,
IRQ_PCI_INTD,
};
static char lboxre2_irq_tab[] __initdata = {
static char lboxre2_irq_tab[] = {
IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
};
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
if (mach_is_lboxre2())
return lboxre2_irq_tab[slot];
......
......@@ -22,7 +22,7 @@
#define IRQ_INTD evt2irq(0xa80)
/* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
static char sdk7780_irq_tab[4][16] __initdata = {
static char sdk7780_irq_tab[4][16] = {
/* INTA */
{ IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1 },
......@@ -37,7 +37,7 @@ static char sdk7780_irq_tab[4][16] __initdata = {
-1, -1, -1 },
};
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
return sdk7780_irq_tab[pin-1][slot];
}
......@@ -7,7 +7,7 @@
#include <linux/sh_intc.h>
#include "pci-sh4.h"
int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
{
switch (slot) {
case 0: return evt2irq(0x3a0);
......
......@@ -4,7 +4,7 @@
#include <linux/pci.h>
#include <linux/sh_intc.h>
int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
int irq;
......
......@@ -19,7 +19,7 @@
#include <linux/sh_intc.h>
#include "pci-sh4.h"
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
int irq = -1;
......
......@@ -19,7 +19,7 @@
#include <mach/titan.h>
#include "pci-sh4.h"
static char titan_irq_tab[] __initdata = {
static char titan_irq_tab[] = {
TITAN_IRQ_WAN,
TITAN_IRQ_LAN,
TITAN_IRQ_MPCIA,
......@@ -27,7 +27,7 @@ static char titan_irq_tab[] __initdata = {
TITAN_IRQ_USB,
};
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
int irq = titan_irq_tab[slot];
......
......@@ -39,8 +39,12 @@ static void pcibios_scanbus(struct pci_channel *hose)
LIST_HEAD(resources);
struct resource *res;
resource_size_t offset;
int i;
struct pci_bus *bus;
int i, ret;
struct pci_host_bridge *bridge;
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return;
for (i = 0; i < hose->nr_resources; i++) {
res = hose->resources + i;
......@@ -52,19 +56,26 @@ static void pcibios_scanbus(struct pci_channel *hose)
pci_add_resource_offset(&resources, res, offset);
}
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
hose->bus = bus;
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = hose;
bridge->busnr = next_busno;
bridge->ops = hose->pci_ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = pcibios_map_platform_irq;
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
return;
}
hose->bus = bridge->bus;
need_domain_info = need_domain_info || hose->index;
hose->need_domain_info = need_domain_info;
if (!bus) {
pci_free_resource_list(&resources);
return;
}
next_busno = bus->busn_res.end + 1;
next_busno = hose->bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */
if (next_busno > 224) {
......@@ -72,9 +83,9 @@ static void pcibios_scanbus(struct pci_channel *hose)
need_domain_info = 1;
}
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
pci_bus_add_devices(bus);
pci_bus_size_bridges(hose->bus);
pci_bus_assign_resources(hose->bus);
pci_bus_add_devices(hose->bus);
}
/*
......@@ -144,8 +155,6 @@ static int __init pcibios_init(void)
for (hose = hose_head; hose; hose = hose->next)
pcibios_scanbus(hose);
pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
dma_debug_add_bus(&pci_bus_type);
pci_initialized = 1;
......@@ -154,14 +163,6 @@ static int __init pcibios_init(void)
}
subsys_initcall(pcibios_init);
/*
* Called after each bus is probed, but before its children
* are examined.
*/
void pcibios_fixup_bus(struct pci_bus *bus)
{
}
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
......
......@@ -467,7 +467,7 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
return 0;
}
int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
{
return evt2irq(0xae0);
}
......
......@@ -25,6 +25,12 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
{
LIST_HEAD(resources);
struct pci_bus *root_bus;
struct pci_host_bridge *bridge;
int ret;
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return;
pci_add_resource_offset(&resources, &info->io_space,
info->io_space.start - 0x1000);
......@@ -32,15 +38,21 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
info->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &info->busn);
root_bus = pci_scan_root_bus(&ofdev->dev, 0, info->ops, info,
&resources);
if (!root_bus) {
pci_free_resource_list(&resources);
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = &ofdev->dev;
bridge->sysdata = info;
bridge->busnr = 0;
bridge->ops = info->ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = info->map_irq;
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
return;
}
/* Setup IRQs of all devices using custom routines */
pci_fixup_irqs(pci_common_swizzle, info->map_irq);
root_bus = bridge->bus;
/* Assign devices with resources */
pci_assign_unassigned_resources();
......@@ -94,9 +106,3 @@ void pcibios_fixup_bus(struct pci_bus *pbus)
}
}
}
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
......@@ -690,16 +690,6 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
return bus;
}
void pcibios_fixup_bus(struct pci_bus *pbus)
{
}
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, oldcmd;
......
......@@ -746,12 +746,6 @@ static void watchdog_reset() {
}
#endif
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
int pcibios_enable_device(struct pci_dev *pdev, int mask)
{
return 0;
......
......@@ -66,16 +66,6 @@ static int pci_scan_flags[TILE_NUM_PCIE];
static struct pci_ops tile_cfg_ops;
/*
* We don't need to worry about the alignment of resources.
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
return res->start;
}
EXPORT_SYMBOL(pcibios_align_resource);
/*
* Open a FD to the hypervisor PCI device.
*
......@@ -274,6 +264,7 @@ static void fixup_read_and_payload_sizes(void)
*/
int __init pcibios_init(void)
{
struct pci_host_bridge *bridge;
int i;
pr_info("PCI: Probing PCI hardware\n");
......@@ -306,16 +297,26 @@ int __init pcibios_init(void)
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
bus = pci_scan_root_bus(NULL, 0, controller->ops,
controller, &resources);
bridge = pci_alloc_host_bridge(0);
if (!bridge)
break;
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = controller;
bridge->busnr = 0;
bridge->ops = controller->ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = tile_map_irq;
pci_scan_root_bus_bridge(bridge);
bus = bridge->bus;
controller->root_bus = bus;
controller->last_busno = bus->busn_res.end;
}
}
/* Do machine dependent PCI interrupt routing */
pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
/*
* This comes from the generic Linux PCI driver.
*
......@@ -369,14 +370,6 @@ int __init pcibios_init(void)
}
subsys_initcall(pcibios_init);
/*
* No bus fixups needed.
*/
void pcibios_fixup_bus(struct pci_bus *bus)
{
/* Nothing needs to be done. */
}
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling. */
......
......@@ -108,15 +108,6 @@ static struct pci_ops tile_cfg_ops;
/* Mask of CPUs that should receive PCIe interrupts. */
static struct cpumask intr_cpus_map;
/* We don't need to worry about the alignment of resources. */
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size,
resource_size_t align)
{
return res->start;
}
EXPORT_SYMBOL(pcibios_align_resource);
/*
* Pick a CPU to receive and handle the PCIe interrupts, based on the IRQ #.
* For now, we simply send interrupts to non-dataplane CPUs.
......@@ -669,6 +660,7 @@ int __init pcibios_init(void)
resource_size_t offset;
LIST_HEAD(resources);
int next_busno;
struct pci_host_bridge *bridge;
int i;
tile_pci_init();
......@@ -881,15 +873,25 @@ int __init pcibios_init(void)
controller->mem_offset);
pci_add_resource(&resources, &controller->io_space);
controller->first_busno = next_busno;
bus = pci_scan_root_bus(NULL, next_busno, controller->ops,
controller, &resources);
bridge = pci_alloc_host_bridge(0);
if (!bridge)
break;
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = controller;
bridge->busnr = next_busno;
bridge->ops = controller->ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = tile_map_irq;
pci_scan_root_bus_bridge(bridge);
bus = bridge->bus;
controller->root_bus = bus;
next_busno = bus->busn_res.end + 1;
}
/* Do machine dependent PCI interrupt routing */
pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
/*
* This comes from the generic Linux PCI driver.
*
......@@ -1038,11 +1040,6 @@ int __init pcibios_init(void)
}
subsys_initcall(pcibios_init);
/* No bus fixups needed. */
void pcibios_fixup_bus(struct pci_bus *bus)
{
}
/* Process any "pci=" kernel boot arguments. */
char *__init pcibios_setup(char *str)
{
......
......@@ -101,7 +101,7 @@ void pci_puv3_preinit(void)
writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD);
}
static int __init pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
static int pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
if (dev->bus->number == 0) {
#ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
......@@ -252,19 +252,46 @@ void pcibios_fixup_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL(pcibios_fixup_bus);
static struct resource busn_resource = {
.name = "PCI busn",
.start = 0,
.end = 255,
.flags = IORESOURCE_BUS,
};
static int __init pci_common_init(void)
{
struct pci_bus *puv3_bus;
struct pci_host_bridge *bridge;
int ret;
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return -ENOMEM;
pci_puv3_preinit();
puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
pci_add_resource(&bridge->windows, &ioport_resource);
pci_add_resource(&bridge->windows, &iomem_resource);
pci_add_resource(&bridge->windows, &busn_resource);
bridge->sysdata = NULL;
bridge->busnr = 0;
bridge->ops = &pci_puv3_ops;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = pci_puv3_map_irq;
/* Scan our single hose. */
ret = pci_scan_root_bus_bridge(bridge);
if (ret) {
pci_free_host_bridge(bridge);
return;
}
puv3_bus = bridge->bus;
if (!puv3_bus)
panic("PCI: unable to scan bus!");
pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
pci_bus_size_bridges(puv3_bus);
pci_bus_assign_resources(puv3_bus);
pci_bus_add_devices(puv3_bus);
......
......@@ -618,3 +618,20 @@ static void quirk_apple_mbp_poweroff(struct pci_dev *pdev)
dev_info(dev, "can't work around MacBook Pro poweroff issue\n");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8c10, quirk_apple_mbp_poweroff);
/*
* VMD-enabled root ports will change the source ID for all messages
* to the VMD device. Rather than doing device matching with the source
* ID, the AER driver should traverse the child device tree, reading
* AER registers to find the faulting device.
*/
static void quirk_no_aersid(struct pci_dev *pdev)
{
/* VMD Domain */
if (is_vmd(pdev->bus))
pdev->bus->bus_flags |= PCI_BUS_FLAGS_NO_AERSID;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid);
......@@ -901,6 +901,13 @@ static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devf
struct pci_dev *pf_pdev;
pdev = to_pci_dev(dev);
#ifdef CONFIG_X86
/* VMD child devices currently cannot be handled individually */
if (is_vmd(pdev->bus))
return NULL;
#endif
/* VFs aren't listed in scope tables; we need to look up
* the PF instead to find the IOMMU. */
pf_pdev = pci_physfn(pdev);
......
......@@ -72,6 +72,11 @@ static DEFINE_IDA(pci_endpoint_test_ida);
#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
miscdev)
static bool no_msi;
module_param(no_msi, bool, 0444);
MODULE_PARM_DESC(no_msi, "Disable MSI interrupt in pci_endpoint_test");
enum pci_barno {
BAR_0,
BAR_1,
......@@ -90,9 +95,15 @@ struct pci_endpoint_test {
/* mutex to protect the ioctls */
struct mutex mutex;
struct miscdevice miscdev;
enum pci_barno test_reg_bar;
size_t alignment;
};
static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 };
struct pci_endpoint_test_data {
enum pci_barno test_reg_bar;
size_t alignment;
bool no_msi;
};
static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
u32 offset)
......@@ -141,11 +152,15 @@ static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
int j;
u32 val;
int size;
struct pci_dev *pdev = test->pdev;
if (!test->bar[barno])
return false;
size = bar_size[barno];
size = pci_resource_len(pdev, barno);
if (barno == test->test_reg_bar)
size = 0x4;
for (j = 0; j < size; j += 4)
pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
......@@ -202,16 +217,32 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
dma_addr_t dst_phys_addr;
struct pci_dev *pdev = test->pdev;
struct device *dev = &pdev->dev;
void *orig_src_addr;
dma_addr_t orig_src_phys_addr;
void *orig_dst_addr;
dma_addr_t orig_dst_phys_addr;
size_t offset;
size_t alignment = test->alignment;
u32 src_crc32;
u32 dst_crc32;
src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL);
if (!src_addr) {
orig_src_addr = dma_alloc_coherent(dev, size + alignment,
&orig_src_phys_addr, GFP_KERNEL);
if (!orig_src_addr) {
dev_err(dev, "failed to allocate source buffer\n");
ret = false;
goto err;
}
if (alignment && !IS_ALIGNED(orig_src_phys_addr, alignment)) {
src_phys_addr = PTR_ALIGN(orig_src_phys_addr, alignment);
offset = src_phys_addr - orig_src_phys_addr;
src_addr = orig_src_addr + offset;
} else {
src_phys_addr = orig_src_phys_addr;
src_addr = orig_src_addr;
}
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
lower_32_bits(src_phys_addr));
......@@ -221,11 +252,21 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
get_random_bytes(src_addr, size);
src_crc32 = crc32_le(~0, src_addr, size);
dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL);
if (!dst_addr) {
orig_dst_addr = dma_alloc_coherent(dev, size + alignment,
&orig_dst_phys_addr, GFP_KERNEL);
if (!orig_dst_addr) {
dev_err(dev, "failed to allocate destination address\n");
ret = false;
goto err_src_addr;
goto err_orig_src_addr;
}
if (alignment && !IS_ALIGNED(orig_dst_phys_addr, alignment)) {
dst_phys_addr = PTR_ALIGN(orig_dst_phys_addr, alignment);
offset = dst_phys_addr - orig_dst_phys_addr;
dst_addr = orig_dst_addr + offset;
} else {
dst_phys_addr = orig_dst_phys_addr;
dst_addr = orig_dst_addr;
}
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
......@@ -245,10 +286,12 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
if (dst_crc32 == src_crc32)
ret = true;
dma_free_coherent(dev, size, dst_addr, dst_phys_addr);
dma_free_coherent(dev, size + alignment, orig_dst_addr,
orig_dst_phys_addr);
err_src_addr:
dma_free_coherent(dev, size, src_addr, src_phys_addr);
err_orig_src_addr:
dma_free_coherent(dev, size + alignment, orig_src_addr,
orig_src_phys_addr);
err:
return ret;
......@@ -262,15 +305,29 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
dma_addr_t phys_addr;
struct pci_dev *pdev = test->pdev;
struct device *dev = &pdev->dev;
void *orig_addr;
dma_addr_t orig_phys_addr;
size_t offset;
size_t alignment = test->alignment;
u32 crc32;
addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
if (!addr) {
orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
GFP_KERNEL);
if (!orig_addr) {
dev_err(dev, "failed to allocate address\n");
ret = false;
goto err;
}
if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
offset = phys_addr - orig_phys_addr;
addr = orig_addr + offset;
} else {
phys_addr = orig_phys_addr;
addr = orig_addr;
}
get_random_bytes(addr, size);
crc32 = crc32_le(~0, addr, size);
......@@ -293,7 +350,7 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
if (reg & STATUS_READ_SUCCESS)
ret = true;
dma_free_coherent(dev, size, addr, phys_addr);
dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
err:
return ret;
......@@ -306,15 +363,29 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
dma_addr_t phys_addr;
struct pci_dev *pdev = test->pdev;
struct device *dev = &pdev->dev;
void *orig_addr;
dma_addr_t orig_phys_addr;
size_t offset;
size_t alignment = test->alignment;
u32 crc32;
addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
if (!addr) {
orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr,
GFP_KERNEL);
if (!orig_addr) {
dev_err(dev, "failed to allocate destination address\n");
ret = false;
goto err;
}
if (alignment && !IS_ALIGNED(orig_phys_addr, alignment)) {
phys_addr = PTR_ALIGN(orig_phys_addr, alignment);
offset = phys_addr - orig_phys_addr;
addr = orig_addr + offset;
} else {
phys_addr = orig_phys_addr;
addr = orig_addr;
}
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
lower_32_bits(phys_addr));
pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
......@@ -331,7 +402,7 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
ret = true;
dma_free_coherent(dev, size, addr, phys_addr);
dma_free_coherent(dev, size + alignment, orig_addr, orig_phys_addr);
err:
return ret;
}
......@@ -383,13 +454,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
{
int i;
int err;
int irq;
int irq = 0;
int id;
char name[20];
enum pci_barno bar;
void __iomem *base;
struct device *dev = &pdev->dev;
struct pci_endpoint_test *test;
struct pci_endpoint_test_data *data;
enum pci_barno test_reg_bar = BAR_0;
struct miscdevice *misc_device;
if (pci_is_bridge(pdev))
......@@ -399,7 +472,17 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
if (!test)
return -ENOMEM;
test->test_reg_bar = 0;
test->alignment = 0;
test->pdev = pdev;
data = (struct pci_endpoint_test_data *)ent->driver_data;
if (data) {
test_reg_bar = data->test_reg_bar;
test->alignment = data->alignment;
no_msi = data->no_msi;
}
init_completion(&test->irq_raised);
mutex_init(&test->mutex);
......@@ -417,9 +500,11 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
pci_set_master(pdev);
irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
if (irq < 0)
dev_err(dev, "failed to get MSI interrupts\n");
if (!no_msi) {
irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
if (irq < 0)
dev_err(dev, "failed to get MSI interrupts\n");
}
err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
IRQF_SHARED, DRV_MODULE_NAME, test);
......@@ -441,14 +526,15 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev,
base = pci_ioremap_bar(pdev, bar);
if (!base) {
dev_err(dev, "failed to read BAR%d\n", bar);
WARN_ON(bar == BAR_0);
WARN_ON(bar == test_reg_bar);
}
test->bar[bar] = base;
}
test->base = test->bar[0];
test->base = test->bar[test_reg_bar];
if (!test->base) {
dev_err(dev, "Cannot perform PCI test without BAR0\n");
dev_err(dev, "Cannot perform PCI test without BAR%d\n",
test_reg_bar);
goto err_iounmap;
}
......
......@@ -25,7 +25,7 @@ config PCI_DRA7XX
work either as EP or RC. In order to enable host-specific features
PCI_DRA7XX_HOST must be selected and in order to enable device-
specific features PCI_DRA7XX_EP must be selected. This uses
the Designware core.
the DesignWare core.
if PCI_DRA7XX
......@@ -97,8 +97,8 @@ config PCI_KEYSTONE
select PCIE_DW_HOST
help
Say Y here if you want to enable PCI controller support on Keystone
SoCs. The PCI controller on Keystone is based on Designware hardware
and therefore the driver re-uses the Designware core functions to
SoCs. The PCI controller on Keystone is based on DesignWare hardware
and therefore the driver re-uses the DesignWare core functions to
implement the driver.
config PCI_LAYERSCAPE
......@@ -132,7 +132,7 @@ config PCIE_QCOM
select PCIE_DW_HOST
help
Say Y here to enable PCIe controller support on Qualcomm SoCs. The
PCIe controller uses the Designware core plus Qualcomm-specific
PCIe controller uses the DesignWare core plus Qualcomm-specific
hardware wrappers.
config PCIE_ARMADA_8K
......@@ -145,8 +145,8 @@ config PCIE_ARMADA_8K
help
Say Y here if you want to enable PCIe controller support on
Armada-8K SoCs. The PCIe controller on Armada-8K is based on
Designware hardware and therefore the driver re-uses the
Designware core functions to implement the driver.
DesignWare hardware and therefore the driver re-uses the
DesignWare core functions to implement the driver.
config PCIE_ARTPEC6
bool "Axis ARTPEC-6 PCIe controller"
......
......@@ -195,7 +195,7 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
dra7xx_pcie_enable_msi_interrupts(dra7xx);
}
static void dra7xx_pcie_host_init(struct pcie_port *pp)
static int dra7xx_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
......@@ -206,6 +206,8 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
dw_pcie_wait_for_link(pci);
dw_pcie_msi_init(pp);
dra7xx_pcie_enable_interrupts(dra7xx);
return 0;
}
static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = {
......@@ -238,7 +240,7 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
return -ENODEV;
}
dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, 4,
dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
&intx_domain_ops, pp);
if (!dra7xx->irq_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n");
......@@ -275,7 +277,6 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
{
struct dra7xx_pcie *dra7xx = arg;
......@@ -335,10 +336,23 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
static void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
{
u32 reg;
reg = PCI_BASE_ADDRESS_0 + (4 * bar);
dw_pcie_writel_dbi2(pci, reg, 0x0);
dw_pcie_writel_dbi(pci, reg, 0x0);
}
static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep)
{
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
enum pci_barno bar;
for (bar = BAR_0; bar <= BAR_5; bar++)
dw_pcie_ep_reset_bar(pci, bar);
dra7xx_pcie_enable_wrapper_interrupts(dra7xx);
}
......@@ -435,7 +449,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
pp->irq = platform_get_irq(pdev, 1);
if (pp->irq < 0) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
return pp->irq;
}
ret = devm_request_irq(dev, pp->irq, dra7xx_pcie_msi_irq_handler,
......@@ -616,8 +630,8 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
dev_err(dev, "missing IRQ resource: %d\n", irq);
return irq;
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf");
......
......@@ -581,13 +581,15 @@ static int exynos_pcie_link_up(struct dw_pcie *pci)
return 0;
}
static void exynos_pcie_host_init(struct pcie_port *pp)
static int exynos_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct exynos_pcie *ep = to_exynos_pcie(pci);
exynos_pcie_establish_link(ep);
exynos_pcie_enable_interrupts(ep);
return 0;
}
static const struct dw_pcie_host_ops exynos_pcie_host_ops = {
......@@ -605,9 +607,9 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,
int ret;
pp->irq = platform_get_irq(pdev, 1);
if (!pp->irq) {
if (pp->irq < 0) {
dev_err(dev, "failed to get irq\n");
return -ENODEV;
return pp->irq;
}
ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler,
IRQF_SHARED, "exynos-pcie", ep);
......@@ -618,9 +620,9 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,
if (IS_ENABLED(CONFIG_PCI_MSI)) {
pp->msi_irq = platform_get_irq(pdev, 0);
if (!pp->msi_irq) {
if (pp->msi_irq < 0) {
dev_err(dev, "failed to get msi irq\n");
return -ENODEV;
return pp->msi_irq;
}
ret = devm_request_irq(dev, pp->msi_irq,
......
......@@ -636,7 +636,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
return ret;
}
static void imx6_pcie_host_init(struct pcie_port *pp)
static int imx6_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
......@@ -649,6 +649,8 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
return 0;
}
static int imx6_pcie_link_up(struct dw_pcie *pci)
......@@ -778,14 +780,15 @@ static int imx6_pcie_probe(struct platform_device *pdev)
}
break;
case IMX7D:
imx6_pcie->pciephy_reset = devm_reset_control_get(dev,
"pciephy");
imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev,
"pciephy");
if (IS_ERR(imx6_pcie->pciephy_reset)) {
dev_err(dev, "Failed to get PCIEPHY reset control\n");
return PTR_ERR(imx6_pcie->pciephy_reset);
}
imx6_pcie->apps_reset = devm_reset_control_get(dev, "apps");
imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
"apps");
if (IS_ERR(imx6_pcie->apps_reset)) {
dev_err(dev, "Failed to get PCIE APPS reset control\n");
return PTR_ERR(imx6_pcie->apps_reset);
......
/*
* Designware application register space functions for Keystone PCI controller
* DesignWare application register space functions for Keystone PCI controller
*
* Copyright (C) 2013-2014 Texas Instruments., Ltd.
* http://www.ti.com
......@@ -168,16 +168,12 @@ void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
{
struct keystone_pcie *ks_pcie;
struct msi_desc *msi;
struct pcie_port *pp;
struct dw_pcie *pci;
u32 offset;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
......@@ -191,16 +187,12 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
{
struct keystone_pcie *ks_pcie;
struct msi_desc *msi;
struct pcie_port *pp;
struct dw_pcie *pci;
u32 offset;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
......@@ -259,7 +251,7 @@ void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
{
int i;
for (i = 0; i < MAX_LEGACY_IRQS; i++)
for (i = 0; i < PCI_NUM_INTX; i++)
ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
}
......@@ -565,7 +557,7 @@ int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
/* Create legacy IRQ domain */
ks_pcie->legacy_irq_domain =
irq_domain_add_linear(ks_pcie->legacy_intc_np,
MAX_LEGACY_IRQS,
PCI_NUM_INTX,
&ks_dw_pcie_legacy_irq_domain_ops,
NULL);
if (!ks_pcie->legacy_irq_domain) {
......
......@@ -32,10 +32,6 @@
#define DRIVER_NAME "keystone-pcie"
/* driver specific constants */
#define MAX_MSI_HOST_IRQS 8
#define MAX_LEGACY_HOST_IRQS 4
/* DEV_STAT_CTRL */
#define PCIE_CAP_BASE 0x70
......@@ -173,7 +169,7 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
if (legacy) {
np_temp = &ks_pcie->legacy_intc_np;
max_host_irqs = MAX_LEGACY_HOST_IRQS;
max_host_irqs = PCI_NUM_INTX;
host_irqs = &ks_pcie->legacy_host_irqs[0];
} else {
np_temp = &ks_pcie->msi_intc_np;
......@@ -261,7 +257,7 @@ static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
return 0;
}
static void __init ks_pcie_host_init(struct pcie_port *pp)
static int __init ks_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
......@@ -289,6 +285,8 @@ static void __init ks_pcie_host_init(struct pcie_port *pp)
*/
hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
"Asynchronous external abort");
return 0;
}
static const struct dw_pcie_host_ops keystone_pcie_host_ops = {
......
......@@ -12,9 +12,7 @@
* published by the Free Software Foundation.
*/
#define MAX_LEGACY_IRQS 4
#define MAX_MSI_HOST_IRQS 8
#define MAX_LEGACY_HOST_IRQS 4
struct keystone_pcie {
struct dw_pcie *pci;
......@@ -22,7 +20,7 @@ struct keystone_pcie {
/* PCI Device ID */
u32 device_id;
int num_legacy_host_irqs;
int legacy_host_irqs[MAX_LEGACY_HOST_IRQS];
int legacy_host_irqs[PCI_NUM_INTX];
struct device_node *legacy_intc_np;
int num_msi_host_irqs;
......
......@@ -33,7 +33,8 @@
/* PEX Internal Configuration Registers */
#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */
#define PCIE_DBI_RO_WR_EN 0x8bc /* DBI Read-Only Write Enable Register */
#define PCIE_IATU_NUM 6
struct ls_pcie_drvdata {
u32 lut_offset;
......@@ -72,14 +73,6 @@ static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
}
/* Fix class value */
static void ls_pcie_fix_class(struct ls_pcie *pcie)
{
struct dw_pcie *pci = pcie->pci;
iowrite16(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE);
}
/* Drop MSG TLP except for Vendor MSG */
static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
{
......@@ -91,6 +84,14 @@ static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
}
static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)
{
int i;
for (i = 0; i < PCIE_IATU_NUM; i++)
dw_pcie_disable_atu(pcie->pci, DW_PCIE_REGION_OUTBOUND, i);
}
static int ls1021_pcie_link_up(struct dw_pcie *pci)
{
u32 state;
......@@ -108,33 +109,6 @@ static int ls1021_pcie_link_up(struct dw_pcie *pci)
return 1;
}
static void ls1021_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
struct device *dev = pci->dev;
u32 index[2];
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
"fsl,pcie-scfg");
if (IS_ERR(pcie->scfg)) {
dev_err(dev, "No syscfg phandle specified\n");
pcie->scfg = NULL;
return;
}
if (of_property_read_u32_array(dev->of_node,
"fsl,pcie-scfg", index, 2)) {
pcie->scfg = NULL;
return;
}
pcie->index = index[1];
dw_pcie_setup_rc(pp);
ls_pcie_drop_msg_tlp(pcie);
}
static int ls_pcie_link_up(struct dw_pcie *pci)
{
struct ls_pcie *pcie = to_ls_pcie(pci);
......@@ -150,16 +124,54 @@ static int ls_pcie_link_up(struct dw_pcie *pci)
return 1;
}
static void ls_pcie_host_init(struct pcie_port *pp)
static int ls_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
iowrite32(1, pci->dbi_base + PCIE_DBI_RO_WR_EN);
ls_pcie_fix_class(pcie);
/*
* Disable outbound windows configured by the bootloader to avoid
* one transaction hitting multiple outbound windows.
* dw_pcie_setup_rc() will reconfigure the outbound windows.
*/
ls_pcie_disable_outbound_atus(pcie);
dw_pcie_dbi_ro_wr_en(pci);
ls_pcie_clear_multifunction(pcie);
dw_pcie_dbi_ro_wr_dis(pci);
ls_pcie_drop_msg_tlp(pcie);
iowrite32(0, pci->dbi_base + PCIE_DBI_RO_WR_EN);
dw_pcie_setup_rc(pp);
return 0;
}
static int ls1021_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
struct device *dev = pci->dev;
u32 index[2];
int ret;
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
"fsl,pcie-scfg");
if (IS_ERR(pcie->scfg)) {
ret = PTR_ERR(pcie->scfg);
dev_err(dev, "No syscfg phandle specified\n");
pcie->scfg = NULL;
return ret;
}
if (of_property_read_u32_array(dev->of_node,
"fsl,pcie-scfg", index, 2)) {
pcie->scfg = NULL;
return -EINVAL;
}
pcie->index = index[1];
return ls_pcie_host_init(pp);
}
static int ls_pcie_msi_host_init(struct pcie_port *pp,
......@@ -232,12 +244,22 @@ static struct ls_pcie_drvdata ls2080_drvdata = {
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static struct ls_pcie_drvdata ls2088_drvdata = {
.lut_offset = 0x80000,
.ltssm_shift = 0,
.lut_dbg = 0x407fc,
.ops = &ls_pcie_host_ops,
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
{ .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
{ .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
{ .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
{ .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
{ .compatible = "fsl,ls2088a-pcie", .data = &ls2088_drvdata },
{ .compatible = "fsl,ls1088a-pcie", .data = &ls2088_drvdata },
{ },
};
......
......@@ -134,13 +134,15 @@ static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
dev_err(pci->dev, "Link not up after reconfiguration\n");
}
static void armada8k_pcie_host_init(struct pcie_port *pp)
static int armada8k_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
dw_pcie_setup_rc(pp);
armada8k_pcie_establish_link(pcie);
return 0;
}
static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
......@@ -176,9 +178,9 @@ static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
pp->ops = &armada8k_pcie_host_ops;
pp->irq = platform_get_irq(pdev, 0);
if (!pp->irq) {
if (pp->irq < 0) {
dev_err(dev, "failed to get irq for port\n");
return -ENODEV;
return pp->irq;
}
ret = devm_request_irq(dev, pp->irq, armada8k_pcie_irq_handler,
......@@ -226,7 +228,9 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
if (IS_ERR(pcie->clk))
return PTR_ERR(pcie->clk);
clk_prepare_enable(pcie->clk);
ret = clk_prepare_enable(pcie->clk);
if (ret)
return ret;
/* Get the dw-pcie unit configuration/control registers base. */
base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
......
......@@ -141,12 +141,6 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
usleep_range(100, 200);
/*
* Enable writing to config regs. This is required as the Synopsys
* driver changes the class code. That register needs DBI write enable.
*/
dw_pcie_writel_dbi(pci, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
/* setup root complex */
dw_pcie_setup_rc(pp);
......@@ -175,13 +169,15 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
dw_pcie_msi_init(pp);
}
static void artpec6_pcie_host_init(struct pcie_port *pp)
static int artpec6_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
artpec6_pcie_establish_link(artpec6_pcie);
artpec6_pcie_enable_interrupts(artpec6_pcie);
return 0;
}
static const struct dw_pcie_host_ops artpec6_pcie_host_ops = {
......@@ -207,9 +203,9 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
if (IS_ENABLED(CONFIG_PCI_MSI)) {
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
if (pp->msi_irq <= 0) {
if (pp->msi_irq < 0) {
dev_err(dev, "failed to get MSI irq\n");
return -ENODEV;
return pp->msi_irq;
}
ret = devm_request_irq(dev, pp->msi_irq,
......
/**
* Synopsys Designware PCIe Endpoint controller driver
* Synopsys DesignWare PCIe Endpoint controller driver
*
* Copyright (C) 2017 Texas Instruments
* Author: Kishon Vijay Abraham I <kishon@ti.com>
......@@ -283,7 +283,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
{
int ret;
void *addr;
enum pci_barno bar;
struct pci_epc *epc;
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct device *dev = pci->dev;
......@@ -312,9 +311,6 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
return -ENOMEM;
ep->outbound_addr = addr;
for (bar = BAR_0; bar <= BAR_5; bar++)
dw_pcie_ep_reset_bar(pci, bar);
if (ep->ops->ep_init)
ep->ops->ep_init(ep);
......@@ -328,7 +324,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
if (ret < 0)
epc->max_functions = 1;
ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size);
ret = __pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
ep->page_size);
if (ret < 0) {
dev_err(dev, "Failed to initialize address space\n");
return ret;
......
/*
* Synopsys Designware PCIe host controller driver
* Synopsys DesignWare PCIe host controller driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
......@@ -71,9 +71,9 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
while ((pos = find_next_bit((unsigned long *) &val, 32,
pos)) != 32) {
irq = irq_find_mapping(pp->irq_domain, i * 32 + pos);
generic_handle_irq(irq);
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12,
4, 1 << pos);
generic_handle_irq(irq);
pos++;
}
}
......@@ -401,8 +401,11 @@ int dw_pcie_host_init(struct pcie_port *pp)
}
}
if (pp->ops->host_init)
pp->ops->host_init(pp);
if (pp->ops->host_init) {
ret = pp->ops->host_init(pp);
if (ret)
goto error;
}
pp->root_bus_nr = pp->busn->start;
......@@ -594,10 +597,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
/* setup interrupt pins */
dw_pcie_dbi_ro_wr_en(pci);
val = dw_pcie_readl_dbi(pci, PCI_INTERRUPT_LINE);
val &= 0xffff00ff;
val |= 0x00000100;
dw_pcie_writel_dbi(pci, PCI_INTERRUPT_LINE, val);
dw_pcie_dbi_ro_wr_dis(pci);
/* setup bus numbers */
val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS);
......@@ -634,8 +639,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
/* Enable write permission for the DBI read-only register */
dw_pcie_dbi_ro_wr_en(pci);
/* program correct class for RC */
dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
/* Better disable write permission right after the update */
dw_pcie_dbi_ro_wr_dis(pci);
dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
val |= PORT_LOGIC_SPEED_CHANGE;
......
......@@ -35,7 +35,7 @@ static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
return dw_handle_msi_irq(pp);
}
static void dw_plat_pcie_host_init(struct pcie_port *pp)
static int dw_plat_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
......@@ -44,6 +44,8 @@ static void dw_plat_pcie_host_init(struct pcie_port *pp)
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
return 0;
}
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
......
/*
* Synopsys Designware PCIe host controller driver
* Synopsys DesignWare PCIe host controller driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
......@@ -107,8 +107,9 @@ static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
dw_pcie_writel_dbi(pci, offset + reg, val);
}
void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index, int type,
u64 cpu_addr, u64 pci_addr, u32 size)
static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
int type, u64 cpu_addr,
u64 pci_addr, u32 size)
{
u32 retries, val;
......@@ -177,7 +178,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
*/
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
if (val == PCIE_ATU_ENABLE)
if (val & PCIE_ATU_ENABLE)
return;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
......@@ -200,8 +201,9 @@ static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
dw_pcie_writel_dbi(pci, offset + reg, val);
}
int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index, int bar,
u64 cpu_addr, enum dw_pcie_as_type as_type)
static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
int bar, u64 cpu_addr,
enum dw_pcie_as_type as_type)
{
int type;
u32 retries, val;
......
/*
* Synopsys Designware PCIe host controller driver
* Synopsys DesignWare PCIe host controller driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
......@@ -76,6 +76,9 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
#define PCIE_MISC_CONTROL_1_OFF 0x8BC
#define PCIE_DBI_RO_WR_EN (0x1 << 0)
/*
* iATU Unroll-specific register definitions
* From 4.80 core version the address translation will be made by unroll
......@@ -134,7 +137,7 @@ struct dw_pcie_host_ops {
unsigned int devfn, int where, int size, u32 *val);
int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val);
void (*host_init)(struct pcie_port *pp);
int (*host_init)(struct pcie_port *pp);
void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq);
phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
......@@ -186,6 +189,7 @@ struct dw_pcie_ep {
struct dw_pcie_ep_ops *ops;
phys_addr_t phys_base;
size_t addr_size;
size_t page_size;
u8 bar_to_atu[6];
phys_addr_t *outbound_addr;
unsigned long ib_window_map;
......@@ -279,6 +283,28 @@ static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)
return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4);
}
static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci)
{
u32 reg;
u32 val;
reg = PCIE_MISC_CONTROL_1_OFF;
val = dw_pcie_readl_dbi(pci, reg);
val |= PCIE_DBI_RO_WR_EN;
dw_pcie_writel_dbi(pci, reg, val);
}
static inline void dw_pcie_dbi_ro_wr_dis(struct dw_pcie *pci)
{
u32 reg;
u32 val;
reg = PCIE_MISC_CONTROL_1_OFF;
val = dw_pcie_readl_dbi(pci, reg);
val &= ~PCIE_DBI_RO_WR_EN;
dw_pcie_writel_dbi(pci, reg, val);
}
#ifdef CONFIG_PCIE_DW_HOST
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);
......
......@@ -223,7 +223,7 @@ static int hisi_pcie_link_up(struct dw_pcie *pci)
return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie);
}
static struct dw_pcie_host_ops hisi_pcie_host_ops = {
static const struct dw_pcie_host_ops hisi_pcie_host_ops = {
.rd_own_conf = hisi_pcie_cfg_read,
.wr_own_conf = hisi_pcie_cfg_write,
};
......@@ -268,7 +268,6 @@ static int hisi_pcie_probe(struct platform_device *pdev)
struct dw_pcie *pci;
struct hisi_pcie *hisi_pcie;
struct resource *reg;
struct device_driver *driver;
int ret;
hisi_pcie = devm_kzalloc(dev, sizeof(*hisi_pcie), GFP_KERNEL);
......@@ -282,8 +281,6 @@ static int hisi_pcie_probe(struct platform_device *pdev)
pci->dev = dev;
pci->ops = &dw_pcie_ops;
driver = dev->driver;
hisi_pcie->pci = pci;
hisi_pcie->soc_ops = of_device_get_match_data(dev);
......
......@@ -430,9 +430,11 @@ static int kirin_pcie_establish_link(struct pcie_port *pp)
return 0;
}
static void kirin_pcie_host_init(struct pcie_port *pp)
static int kirin_pcie_host_init(struct pcie_port *pp)
{
kirin_pcie_establish_link(pp);
return 0;
}
static struct dw_pcie_ops kirin_dw_pcie_ops = {
......@@ -441,7 +443,7 @@ static struct dw_pcie_ops kirin_dw_pcie_ops = {
.link_up = kirin_pcie_link_up,
};
static struct dw_pcie_host_ops kirin_pcie_host_ops = {
static const struct dw_pcie_host_ops kirin_pcie_host_ops = {
.rd_own_conf = kirin_pcie_rd_own_conf,
.wr_own_conf = kirin_pcie_wr_own_conf,
.host_init = kirin_pcie_host_init,
......
This diff is collapsed.
......@@ -177,13 +177,15 @@ static int spear13xx_pcie_link_up(struct dw_pcie *pci)
return 0;
}
static void spear13xx_pcie_host_init(struct pcie_port *pp)
static int spear13xx_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
spear13xx_pcie_establish_link(spear13xx_pcie);
spear13xx_pcie_enable_interrupts(spear13xx_pcie);
return 0;
}
static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
......@@ -199,9 +201,9 @@ static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
int ret;
pp->irq = platform_get_irq(pdev, 0);
if (!pp->irq) {
if (pp->irq < 0) {
dev_err(dev, "failed to get irq\n");
return -ENODEV;
return pp->irq;
}
ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
IRQF_SHARED | IRQF_NO_THREAD,
......
......@@ -54,6 +54,8 @@ static struct workqueue_struct *kpcitest_workqueue;
struct pci_epf_test {
void *reg[6];
struct pci_epf *epf;
enum pci_barno test_reg_bar;
bool linkup_notifier;
struct delayed_work cmd_handler;
};
......@@ -74,7 +76,12 @@ static struct pci_epf_header test_header = {
.interrupt_pin = PCI_INTERRUPT_INTA,
};
static int bar_size[] = { 512, 1024, 16384, 131072, 1048576 };
struct pci_epf_test_data {
enum pci_barno test_reg_bar;
bool linkup_notifier;
};
static int bar_size[] = { 512, 512, 1024, 16384, 131072, 1048576 };
static int pci_epf_test_copy(struct pci_epf_test *epf_test)
{
......@@ -86,7 +93,8 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
struct pci_epf *epf = epf_test->epf;
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
struct pci_epf_test_reg *reg = epf_test->reg[0];
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
if (!src_addr) {
......@@ -145,7 +153,8 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
struct pci_epf *epf = epf_test->epf;
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
struct pci_epf_test_reg *reg = epf_test->reg[0];
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
if (!src_addr) {
......@@ -195,7 +204,8 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
struct pci_epf *epf = epf_test->epf;
struct device *dev = &epf->dev;
struct pci_epc *epc = epf->epc;
struct pci_epf_test_reg *reg = epf_test->reg[0];
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
if (!dst_addr) {
......@@ -247,7 +257,8 @@ static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test)
u8 msi_count;
struct pci_epf *epf = epf_test->epf;
struct pci_epc *epc = epf->epc;
struct pci_epf_test_reg *reg = epf_test->reg[0];
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
reg->status |= STATUS_IRQ_RAISED;
msi_count = pci_epc_get_msi(epc);
......@@ -263,22 +274,28 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
int ret;
u8 irq;
u8 msi_count;
u32 command;
struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test,
cmd_handler.work);
struct pci_epf *epf = epf_test->epf;
struct pci_epc *epc = epf->epc;
struct pci_epf_test_reg *reg = epf_test->reg[0];
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
struct pci_epf_test_reg *reg = epf_test->reg[test_reg_bar];
if (!reg->command)
command = reg->command;
if (!command)
goto reset_handler;
if (reg->command & COMMAND_RAISE_LEGACY_IRQ) {
reg->command = 0;
reg->status = 0;
if (command & COMMAND_RAISE_LEGACY_IRQ) {
reg->status = STATUS_IRQ_RAISED;
pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0);
goto reset_handler;
}
if (reg->command & COMMAND_WRITE) {
if (command & COMMAND_WRITE) {
ret = pci_epf_test_write(epf_test);
if (ret)
reg->status |= STATUS_WRITE_FAIL;
......@@ -288,7 +305,7 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
goto reset_handler;
}
if (reg->command & COMMAND_READ) {
if (command & COMMAND_READ) {
ret = pci_epf_test_read(epf_test);
if (!ret)
reg->status |= STATUS_READ_SUCCESS;
......@@ -298,7 +315,7 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
goto reset_handler;
}
if (reg->command & COMMAND_COPY) {
if (command & COMMAND_COPY) {
ret = pci_epf_test_copy(epf_test);
if (!ret)
reg->status |= STATUS_COPY_SUCCESS;
......@@ -308,9 +325,9 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
goto reset_handler;
}
if (reg->command & COMMAND_RAISE_MSI_IRQ) {
if (command & COMMAND_RAISE_MSI_IRQ) {
msi_count = pci_epc_get_msi(epc);
irq = (reg->command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
irq = (command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
if (irq > msi_count || msi_count <= 0)
goto reset_handler;
reg->status = STATUS_IRQ_RAISED;
......@@ -319,8 +336,6 @@ static void pci_epf_test_cmd_handler(struct work_struct *work)
}
reset_handler:
reg->command = 0;
queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler,
msecs_to_jiffies(1));
}
......@@ -358,6 +373,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
struct pci_epc *epc = epf->epc;
struct device *dev = &epf->dev;
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32;
if (sizeof(dma_addr_t) == 0x8)
......@@ -370,7 +386,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
if (ret) {
pci_epf_free_space(epf, epf_test->reg[bar], bar);
dev_err(dev, "failed to set BAR%d\n", bar);
if (bar == BAR_0)
if (bar == test_reg_bar)
return ret;
}
}
......@@ -384,17 +400,20 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
struct device *dev = &epf->dev;
void *base;
int bar;
enum pci_barno test_reg_bar = epf_test->test_reg_bar;
base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
BAR_0);
test_reg_bar);
if (!base) {
dev_err(dev, "failed to allocated register space\n");
return -ENOMEM;
}
epf_test->reg[0] = base;
epf_test->reg[test_reg_bar] = base;
for (bar = BAR_1; bar <= BAR_5; bar++) {
base = pci_epf_alloc_space(epf, bar_size[bar - 1], bar);
for (bar = BAR_0; bar <= BAR_5; bar++) {
if (bar == test_reg_bar)
continue;
base = pci_epf_alloc_space(epf, bar_size[bar], bar);
if (!base)
dev_err(dev, "failed to allocate space for BAR%d\n",
bar);
......@@ -407,6 +426,7 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
static int pci_epf_test_bind(struct pci_epf *epf)
{
int ret;
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
struct pci_epf_header *header = epf->header;
struct pci_epc *epc = epf->epc;
struct device *dev = &epf->dev;
......@@ -432,13 +452,34 @@ static int pci_epf_test_bind(struct pci_epf *epf)
if (ret)
return ret;
if (!epf_test->linkup_notifier)
queue_work(kpcitest_workqueue, &epf_test->cmd_handler.work);
return 0;
}
static const struct pci_epf_device_id pci_epf_test_ids[] = {
{
.name = "pci_epf_test",
},
{},
};
static int pci_epf_test_probe(struct pci_epf *epf)
{
struct pci_epf_test *epf_test;
struct device *dev = &epf->dev;
const struct pci_epf_device_id *match;
struct pci_epf_test_data *data;
enum pci_barno test_reg_bar = BAR_0;
bool linkup_notifier = true;
match = pci_epf_match_device(pci_epf_test_ids, epf);
data = (struct pci_epf_test_data *)match->driver_data;
if (data) {
test_reg_bar = data->test_reg_bar;
linkup_notifier = data->linkup_notifier;
}
epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
if (!epf_test)
......@@ -446,6 +487,8 @@ static int pci_epf_test_probe(struct pci_epf *epf)
epf->header = &test_header;
epf_test->epf = epf;
epf_test->test_reg_bar = test_reg_bar;
epf_test->linkup_notifier = linkup_notifier;
INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler);
......@@ -453,31 +496,15 @@ static int pci_epf_test_probe(struct pci_epf *epf)
return 0;
}
static int pci_epf_test_remove(struct pci_epf *epf)
{
struct pci_epf_test *epf_test = epf_get_drvdata(epf);
kfree(epf_test);
return 0;
}
static struct pci_epf_ops ops = {
.unbind = pci_epf_test_unbind,
.bind = pci_epf_test_bind,
.linkup = pci_epf_test_linkup,
};
static const struct pci_epf_device_id pci_epf_test_ids[] = {
{
.name = "pci_epf_test",
},
{},
};
static struct pci_epf_driver test_driver = {
.driver.name = "pci_epf_test",
.probe = pci_epf_test_probe,
.remove = pci_epf_test_remove,
.id_table = pci_epf_test_ids,
.ops = &ops,
.owner = THIS_MODULE,
......
......@@ -21,6 +21,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pci-epc.h>
#include <linux/pci-epf.h>
......@@ -370,6 +371,7 @@ EXPORT_SYMBOL_GPL(pci_epc_write_header);
int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf)
{
unsigned long flags;
struct device *dev = epc->dev.parent;
if (epf->epc)
return -EBUSY;
......@@ -381,8 +383,12 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf)
return -EINVAL;
epf->epc = epc;
dma_set_coherent_mask(&epf->dev, epc->dev.coherent_dma_mask);
epf->dev.dma_mask = epc->dev.dma_mask;
if (dev->of_node) {
of_dma_configure(&epf->dev, dev->of_node);
} else {
dma_set_coherent_mask(&epf->dev, epc->dev.coherent_dma_mask);
epf->dev.dma_mask = epc->dev.dma_mask;
}
spin_lock_irqsave(&epc->lock, flags);
list_add_tail(&epf->list, &epc->pci_epf);
......@@ -500,6 +506,7 @@ __pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
dma_set_coherent_mask(&epc->dev, dev->coherent_dma_mask);
epc->dev.class = pci_epc_class;
epc->dev.dma_mask = dev->dma_mask;
epc->dev.parent = dev;
epc->ops = ops;
ret = dev_set_name(&epc->dev, "%s", dev_name(dev));
......
......@@ -24,21 +24,54 @@
#include <linux/pci-epc.h>
/**
* pci_epc_mem_init() - initialize the pci_epc_mem structure
* pci_epc_mem_get_order() - determine the allocation order of a memory size
* @mem: address space of the endpoint controller
* @size: the size for which to get the order
*
* Reimplement get_order() for mem->page_size since the generic get_order
* always gets order with a constant PAGE_SIZE.
*/
static int pci_epc_mem_get_order(struct pci_epc_mem *mem, size_t size)
{
int order;
unsigned int page_shift = ilog2(mem->page_size);
size--;
size >>= page_shift;
#if BITS_PER_LONG == 32
order = fls(size);
#else
order = fls64(size);
#endif
return order;
}
/**
* __pci_epc_mem_init() - initialize the pci_epc_mem structure
* @epc: the EPC device that invoked pci_epc_mem_init
* @phys_base: the physical address of the base
* @size: the size of the address space
* @page_size: size of each page
*
* Invoke to initialize the pci_epc_mem structure used by the
* endpoint functions to allocate mapped PCI address.
*/
int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size,
size_t page_size)
{
int ret;
struct pci_epc_mem *mem;
unsigned long *bitmap;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
unsigned int page_shift;
int pages;
int bitmap_size;
if (page_size < PAGE_SIZE)
page_size = PAGE_SIZE;
page_shift = ilog2(page_size);
pages = size >> page_shift;
bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
if (!mem) {
......@@ -54,6 +87,7 @@ int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
mem->bitmap = bitmap;
mem->phys_base = phys_base;
mem->page_size = page_size;
mem->pages = pages;
mem->size = size;
......@@ -67,7 +101,7 @@ int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
err:
return ret;
}
EXPORT_SYMBOL_GPL(pci_epc_mem_init);
EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
/**
* pci_epc_mem_exit() - cleanup the pci_epc_mem structure
......@@ -101,13 +135,17 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
int pageno;
void __iomem *virt_addr;
struct pci_epc_mem *mem = epc->mem;
int order = get_order(size);
unsigned int page_shift = ilog2(mem->page_size);
int order;
size = ALIGN(size, mem->page_size);
order = pci_epc_mem_get_order(mem, size);
pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
if (pageno < 0)
return NULL;
*phys_addr = mem->phys_base + (pageno << PAGE_SHIFT);
*phys_addr = mem->phys_base + (pageno << page_shift);
virt_addr = ioremap(*phys_addr, size);
if (!virt_addr)
bitmap_release_region(mem->bitmap, pageno, order);
......@@ -129,11 +167,14 @@ void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
void __iomem *virt_addr, size_t size)
{
int pageno;
int order = get_order(size);
struct pci_epc_mem *mem = epc->mem;
unsigned int page_shift = ilog2(mem->page_size);
int order;
iounmap(virt_addr);
pageno = (phys_addr - mem->phys_base) >> PAGE_SHIFT;
pageno = (phys_addr - mem->phys_base) >> page_shift;
size = ALIGN(size, mem->page_size);
order = pci_epc_mem_get_order(mem, size);
bitmap_release_region(mem->bitmap, pageno, order);
}
EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
......
......@@ -27,7 +27,7 @@
#include <linux/pci-ep-cfs.h>
static struct bus_type pci_epf_bus_type;
static struct device_type pci_epf_type;
static const struct device_type pci_epf_type;
/**
* pci_epf_linkup() - Notify the function driver that EPC device has
......@@ -267,6 +267,22 @@ struct pci_epf *pci_epf_create(const char *name)
}
EXPORT_SYMBOL_GPL(pci_epf_create);
const struct pci_epf_device_id *
pci_epf_match_device(const struct pci_epf_device_id *id, struct pci_epf *epf)
{
if (!id || !epf)
return NULL;
while (*id->name) {
if (strcmp(epf->name, id->name) == 0)
return id;
id++;
}
return NULL;
}
EXPORT_SYMBOL_GPL(pci_epf_match_device);
static void pci_epf_dev_release(struct device *dev)
{
struct pci_epf *epf = to_pci_epf(dev);
......@@ -275,7 +291,7 @@ static void pci_epf_dev_release(struct device *dev)
kfree(epf);
}
static struct device_type pci_epf_type = {
static const struct device_type pci_epf_type = {
.release = pci_epf_dev_release,
};
......@@ -317,11 +333,12 @@ static int pci_epf_device_probe(struct device *dev)
static int pci_epf_device_remove(struct device *dev)
{
int ret;
int ret = 0;
struct pci_epf *epf = to_pci_epf(dev);
struct pci_epf_driver *driver = to_pci_epf_driver(dev->driver);
ret = driver->remove(epf);
if (driver->remove)
ret = driver->remove(epf);
epf->driver = NULL;
return ret;
......
......@@ -71,7 +71,7 @@ config PCI_HOST_GENERIC
config PCIE_XILINX
bool "Xilinx AXI PCIe host bridge support"
depends on ARCH_ZYNQ || MICROBLAZE
depends on ARCH_ZYNQ || MICROBLAZE || (MIPS && PCI_DRIVERS_GENERIC)
help
Say 'Y' here if you want kernel to support the Xilinx AXI PCIe
Host Bridge driver.
......@@ -182,14 +182,13 @@ config PCIE_ROCKCHIP
config PCIE_MEDIATEK
bool "MediaTek PCIe controller"
depends on ARM && (ARCH_MEDIATEK || COMPILE_TEST)
depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST)
depends on OF
depends on PCI
select PCIEPORTBUS
help
Say Y here if you want to enable PCIe controller support on
MT7623 series SoCs. There is one single root complex with 3 root
ports available. Each port supports Gen2 lane x1.
MediaTek SoCs.
config PCIE_TANGO_SMP8759
bool "Tango SMP8759 PCIe controller (DANGEROUS)"
......
......@@ -191,7 +191,6 @@
#define LINK_WAIT_USLEEP_MIN 90000
#define LINK_WAIT_USLEEP_MAX 100000
#define LEGACY_IRQ_NUM 4
#define MSI_IRQ_NUM 32
struct advk_pcie {
......@@ -729,7 +728,7 @@ static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
irq_chip->irq_unmask = advk_pcie_irq_unmask;
pcie->irq_domain =
irq_domain_add_linear(pcie_intc_node, LEGACY_IRQ_NUM,
irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
&advk_pcie_irq_domain_ops, pcie);
if (!pcie->irq_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n");
......@@ -786,7 +785,7 @@ static void advk_pcie_handle_int(struct advk_pcie *pcie)
advk_pcie_handle_msi(pcie);
/* Process legacy interrupts */
for (i = 0; i < LEGACY_IRQ_NUM; i++) {
for (i = 0; i < PCI_NUM_INTX; i++) {
if (!(status & PCIE_ISR0_INTX_ASSERT(i)))
continue;
......
......@@ -350,12 +350,12 @@ static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p)
/* All PCI IRQs cascade off this one */
irq = of_irq_get(intc, 0);
if (!irq) {
if (irq <= 0) {
dev_err(p->dev, "failed to get parent IRQ\n");
return -EINVAL;
return irq ?: -EINVAL;
}
p->irqdomain = irq_domain_add_linear(intc, 4,
p->irqdomain = irq_domain_add_linear(intc, PCI_NUM_INTX,
&faraday_pci_irqdomain_ops, p);
if (!p->irqdomain) {
dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n");
......
......@@ -50,6 +50,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/semaphore.h>
#include <linux/irqdomain.h>
#include <asm/irqdomain.h>
......@@ -1113,7 +1114,12 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
goto free_int_desc;
}
wait_for_completion(&comp.comp_pkt.host_event);
/*
* Since this function is called with IRQ locks held, can't
* do normal wait for completion; instead poll.
*/
while (!try_wait_for_completion(&comp.comp_pkt.host_event))
udelay(100);
if (comp.comp_pkt.completion_status < 0) {
dev_err(&hbus->hdev->device,
......
......@@ -1054,8 +1054,8 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
port->pcie = pcie;
if (of_property_read_u32(child, "marvell,pcie-port", &port->port)) {
dev_warn(dev, "ignoring %s, missing pcie-port property\n",
of_node_full_name(child));
dev_warn(dev, "ignoring %pOF, missing pcie-port property\n",
child);
goto skip;
}
......@@ -1106,8 +1106,8 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie,
}
if (flags & OF_GPIO_ACTIVE_LOW) {
dev_info(dev, "%s: reset gpio is active low\n",
of_node_full_name(child));
dev_info(dev, "%pOF: reset gpio is active low\n",
child);
gpio_flags = GPIOF_ACTIVE_LOW |
GPIOF_OUT_INIT_LOW;
} else {
......@@ -1186,8 +1186,7 @@ static int mvebu_pcie_powerup(struct mvebu_pcie_port *port)
*/
static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port)
{
if (port->reset_gpio)
gpiod_set_value_cansleep(port->reset_gpio, 1);
gpiod_set_value_cansleep(port->reset_gpio, 1);
clk_disable_unprepare(port->clk);
}
......
......@@ -1147,15 +1147,15 @@ static int tegra_pcie_resets_get(struct tegra_pcie *pcie)
{
struct device *dev = pcie->dev;
pcie->pex_rst = devm_reset_control_get(dev, "pex");
pcie->pex_rst = devm_reset_control_get_exclusive(dev, "pex");
if (IS_ERR(pcie->pex_rst))
return PTR_ERR(pcie->pex_rst);
pcie->afi_rst = devm_reset_control_get(dev, "afi");
pcie->afi_rst = devm_reset_control_get_exclusive(dev, "afi");
if (IS_ERR(pcie->afi_rst))
return PTR_ERR(pcie->afi_rst);
pcie->pcie_xrst = devm_reset_control_get(dev, "pcie_x");
pcie->pcie_xrst = devm_reset_control_get_exclusive(dev, "pcie_x");
if (IS_ERR(pcie->pcie_xrst))
return PTR_ERR(pcie->pcie_xrst);
......@@ -1703,8 +1703,7 @@ static int tegra_pcie_get_legacy_regulators(struct tegra_pcie *pcie)
pcie->num_supplies = 2;
if (pcie->num_supplies == 0) {
dev_err(dev, "device %s not supported in legacy mode\n",
np->full_name);
dev_err(dev, "device %pOF not supported in legacy mode\n", np);
return -ENODEV;
}
......
......@@ -489,7 +489,7 @@ static int xgene_msi_probe(struct platform_device *pdev)
if (virt_msir < 0) {
dev_err(&pdev->dev, "Cannot translate IRQ index %d\n",
irq_index);
rc = -EINVAL;
rc = virt_msir;
goto error;
}
xgene_msi->msi_groups[irq_index].gic_irq = virt_msir;
......
......@@ -61,7 +61,7 @@
#define SZ_1T (SZ_1G*1024ULL)
#define PIPE_PHY_RATE_RD(src) ((0xc000 & (u32)(src)) >> 0xe)
#define ROOT_CAP_AND_CTRL 0x5C
#define XGENE_V1_PCI_EXP_CAP 0x40
/* PCIe IP version */
#define XGENE_PCIE_IP_VER_UNKN 0
......@@ -160,7 +160,7 @@ static bool xgene_pcie_hide_rc_bars(struct pci_bus *bus, int offset)
}
static void __iomem *xgene_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
int offset)
int offset)
{
if ((pci_is_root_bus(bus) && devfn != 0) ||
xgene_pcie_hide_rc_bars(bus, offset))
......@@ -189,7 +189,7 @@ static int xgene_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
* Avoid this by not claiming to support CRS.
*/
if (pci_is_root_bus(bus) && (port->version == XGENE_PCIE_IP_VER_1) &&
((where & ~0x3) == ROOT_CAP_AND_CTRL))
((where & ~0x3) == XGENE_V1_PCI_EXP_CAP + PCI_EXP_RTCTL))
*val &= ~(PCI_EXP_RTCAP_CRSVIS << 16);
if (size <= 2)
......@@ -265,12 +265,12 @@ static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
}
struct pci_ecam_ops xgene_v1_pcie_ecam_ops = {
.bus_shift = 16,
.init = xgene_v1_pcie_ecam_init,
.pci_ops = {
.map_bus = xgene_pcie_map_bus,
.read = xgene_pcie_config_read32,
.write = pci_generic_config_write,
.bus_shift = 16,
.init = xgene_v1_pcie_ecam_init,
.pci_ops = {
.map_bus = xgene_pcie_map_bus,
.read = xgene_pcie_config_read32,
.write = pci_generic_config_write,
}
};
......@@ -280,12 +280,12 @@ static int xgene_v2_pcie_ecam_init(struct pci_config_window *cfg)
}
struct pci_ecam_ops xgene_v2_pcie_ecam_ops = {
.bus_shift = 16,
.init = xgene_v2_pcie_ecam_init,
.pci_ops = {
.map_bus = xgene_pcie_map_bus,
.read = xgene_pcie_config_read32,
.write = pci_generic_config_write,
.bus_shift = 16,
.init = xgene_v2_pcie_ecam_init,
.pci_ops = {
.map_bus = xgene_pcie_map_bus,
.read = xgene_pcie_config_read32,
.write = pci_generic_config_write,
}
};
#endif
......@@ -318,7 +318,7 @@ static u64 xgene_pcie_set_ib_mask(struct xgene_pcie_port *port, u32 addr,
}
static void xgene_pcie_linkup(struct xgene_pcie_port *port,
u32 *lanes, u32 *speed)
u32 *lanes, u32 *speed)
{
u32 val32;
......@@ -593,8 +593,7 @@ static void xgene_pcie_clear_config(struct xgene_pcie_port *port)
xgene_pcie_writel(port, i, 0);
}
static int xgene_pcie_setup(struct xgene_pcie_port *port,
struct list_head *res,
static int xgene_pcie_setup(struct xgene_pcie_port *port, struct list_head *res,
resource_size_t io_base)
{
struct device *dev = port->dev;
......@@ -706,9 +705,9 @@ static const struct of_device_id xgene_pcie_match_table[] = {
static struct platform_driver xgene_pcie_driver = {
.driver = {
.name = "xgene-pcie",
.of_match_table = of_match_ptr(xgene_pcie_match_table),
.suppress_bind_attrs = true,
.name = "xgene-pcie",
.of_match_table = of_match_ptr(xgene_pcie_match_table),
.suppress_bind_attrs = true,
},
.probe = xgene_pcie_probe_bridge,
};
......
......@@ -64,13 +64,11 @@ static void altera_msi_isr(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct altera_msi *msi;
unsigned long status;
u32 num_of_vectors;
u32 bit;
u32 virq;
chained_irq_enter(chip, desc);
msi = irq_desc_get_handler_data(desc);
num_of_vectors = msi->num_of_vectors;
while ((status = msi_readl(msi, MSI_STATUS)) != 0) {
for_each_set_bit(bit, &status, msi->num_of_vectors) {
......@@ -267,9 +265,9 @@ static int altera_msi_probe(struct platform_device *pdev)
return ret;
msi->irq = platform_get_irq(pdev, 0);
if (msi->irq <= 0) {
if (msi->irq < 0) {
dev_err(&pdev->dev, "failed to map IRQ: %d\n", msi->irq);
ret = -ENODEV;
ret = msi->irq;
goto err;
}
......
......@@ -76,8 +76,6 @@
#define LINK_UP_TIMEOUT HZ
#define LINK_RETRAIN_TIMEOUT HZ
#define INTX_NUM 4
#define DWORD_MASK 3
struct altera_pcie {
......@@ -464,6 +462,7 @@ static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
static const struct irq_domain_ops intx_domain_ops = {
.map = altera_pcie_intx_map,
.xlate = pci_irqd_intx_xlate,
};
static void altera_pcie_isr(struct irq_desc *desc)
......@@ -481,11 +480,11 @@ static void altera_pcie_isr(struct irq_desc *desc)
while ((status = cra_readl(pcie, P2A_INT_STATUS)
& P2A_INT_STS_ALL) != 0) {
for_each_set_bit(bit, &status, INTX_NUM) {
for_each_set_bit(bit, &status, PCI_NUM_INTX) {
/* clear interrupts */
cra_writel(pcie, 1 << bit, P2A_INT_STATUS);
virq = irq_find_mapping(pcie->irq_domain, bit + 1);
virq = irq_find_mapping(pcie->irq_domain, bit);
if (virq)
generic_handle_irq(virq);
else
......@@ -536,7 +535,7 @@ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
struct device_node *node = dev->of_node;
/* Setup INTx */
pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM + 1,
pcie->irq_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
&intx_domain_ops, pcie);
if (!pcie->irq_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n");
......@@ -559,9 +558,9 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie)
/* setup IRQ */
pcie->irq = platform_get_irq(pdev, 0);
if (pcie->irq <= 0) {
if (pcie->irq < 0) {
dev_err(dev, "failed to get IRQ: %d\n", pcie->irq);
return -EINVAL;
return pcie->irq;
}
irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie);
......
......@@ -317,7 +317,6 @@ static void iproc_msi_handler(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct iproc_msi_grp *grp;
struct iproc_msi *msi;
struct iproc_pcie *pcie;
u32 eq, head, tail, nr_events;
unsigned long hwirq;
int virq;
......@@ -326,7 +325,6 @@ static void iproc_msi_handler(struct irq_desc *desc)
grp = irq_desc_get_handler_data(desc);
msi = grp->msi;
pcie = msi->pcie;
eq = grp->eq;
/*
......
......@@ -134,6 +134,13 @@ static int iproc_pcie_pltfm_remove(struct platform_device *pdev)
return iproc_pcie_remove(pcie);
}
static void iproc_pcie_pltfm_shutdown(struct platform_device *pdev)
{
struct iproc_pcie *pcie = platform_get_drvdata(pdev);
iproc_pcie_shutdown(pcie);
}
static struct platform_driver iproc_pcie_pltfm_driver = {
.driver = {
.name = "iproc-pcie",
......@@ -141,6 +148,7 @@ static struct platform_driver iproc_pcie_pltfm_driver = {
},
.probe = iproc_pcie_pltfm_probe,
.remove = iproc_pcie_pltfm_remove,
.shutdown = iproc_pcie_pltfm_shutdown,
};
module_platform_driver(iproc_pcie_pltfm_driver);
......
This diff is collapsed.
......@@ -110,6 +110,7 @@ struct iproc_pcie {
int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res);
int iproc_pcie_remove(struct iproc_pcie *pcie);
int iproc_pcie_shutdown(struct iproc_pcie *pcie);
#ifdef CONFIG_PCIE_IPROC_MSI
int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node);
......
This diff is collapsed.
......@@ -471,10 +471,8 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie)
bridge->msi = &pcie->msi.chip;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0) {
kfree(bridge);
if (ret < 0)
return ret;
}
bus = bridge->bus;
......@@ -1190,14 +1188,16 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return 0;
err_free_bridge:
pci_free_host_bridge(bridge);
err_pm_put:
pm_runtime_put(dev);
err_pm_disable:
pm_runtime_disable(dev);
err_free_bridge:
pci_free_host_bridge(bridge);
pci_free_resource_list(&pcie->resources);
return err;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment