Commit f263fbb8 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull PCI updates from Bjorn Helgaas:

  - add sysfs max_link_speed/width, current_link_speed/width (Wong Vee
    Khee)

  - make host bridge IRQ mapping much more generic (Matthew Minter,
    Lorenzo Pieralisi)

  - convert most drivers to pci_scan_root_bus_bridge() (Lorenzo
    Pieralisi)

  - mutex sriov_configure() (Jakub Kicinski)

  - mutex pci_error_handlers callbacks (Christoph Hellwig)

  - split ->reset_notify() into ->reset_prepare()/reset_done()
    (Christoph Hellwig)

  - support multiple PCIe portdrv interrupts for MSI as well as MSI-X
    (Gabriele Paoloni)

  - allocate MSI/MSI-X vector for Downstream Port Containment (Gabriele
    Paoloni)

  - fix MSI IRQ affinity pre/post/min_vecs issue (Michael Hernandez)

  - test INTx masking during enumeration, not at run-time (Piotr Gregor)

  - avoid using device_may_wakeup() for runtime PM (Rafael J. Wysocki)

  - restore the status of PCI devices across hibernation (Chen Yu)

  - keep parent resources that start at 0x0 (Ard Biesheuvel)

  - enable ECRC only if device supports it (Bjorn Helgaas)

  - restore PRI and PASID state after Function-Level Reset (CQ Tang)

  - skip DPC event if device is not present (Keith Busch)

  - check domain when matching SMBIOS info (Sujith Pandel)

  - mark Intel XXV710 NIC INTx masking as broken (Alex Williamson)

  - avoid AMD SB7xx EHCI USB wakeup defect (Kai-Heng Feng)

  - work around long-standing Macbook Pro poweroff issue (Bjorn Helgaas)

  - add Switchtec "running" status flag (Logan Gunthorpe)

  - fix dra7xx incorrect RW1C IRQ register usage (Arvind Yadav)

  - modify xilinx-nwl IRQ chip for legacy interrupts (Bharat Kumar
    Gogada)

  - move VMD SRCU cleanup after bus, child device removal (Jon Derrick)

  - add Faraday clock handling (Linus Walleij)

  - configure Rockchip MPS and reorganize (Shawn Lin)

  - limit Qualcomm TLP size to 2K (hardware issue) (Srinivas Kandagatla)

  - support Tegra MSI 64-bit addressing (Thierry Reding)

  - use Rockchip normal (not privileged) register bank (Shawn Lin)

  - add HiSilicon Kirin SoC PCIe controller driver (Xiaowei Song)

  - add Sigma Designs Tango SMP8759 PCIe controller driver (Marc
    Gonzalez)

  - add MediaTek PCIe host controller support (Ryder Lee)

  - add Qualcomm IPQ4019 support (John Crispin)

  - add HyperV vPCI protocol v1.2 support (Jork Loeser)

  - add i.MX6 regulator support (Quentin Schulz)

* tag 'pci-v4.13-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (113 commits)
  PCI: tango: Add Sigma Designs Tango SMP8759 PCIe host bridge support
  PCI: Add DT binding for Sigma Designs Tango PCIe controller
  PCI: rockchip: Use normal register bank for config accessors
  dt-bindings: PCI: Add documentation for MediaTek PCIe
  PCI: Remove __pci_dev_reset() and pci_dev_reset()
  PCI: Split ->reset_notify() method into ->reset_prepare() and ->reset_done()
  PCI: xilinx: Make of_device_ids const
  PCI: xilinx-nwl: Modify IRQ chip for legacy interrupts
  PCI: vmd: Move SRCU cleanup after bus, child device removal
  PCI: vmd: Correct comment: VMD domains start at 0x10000, not 0x1000
  PCI: versatile: Add local struct device pointers
  PCI: tegra: Do not allocate MSI target memory
  PCI: tegra: Support MSI 64-bit addressing
  PCI: rockchip: Use local struct device pointer consistently
  PCI: rockchip: Check for clk_prepare_enable() errors during resume
  MAINTAINERS: Remove Wenrui Li as Rockchip PCIe driver maintainer
  PCI: rockchip: Configure RC's MPS setting
  PCI: rockchip: Reconfigure configuration space header type
  PCI: rockchip: Split out rockchip_pcie_cfg_configuration_accesses()
  PCI: rockchip: Move configuration accesses into rockchip_pcie_cfg_atu()
  ...
parents 026d15f6 6aed4684
......@@ -30,6 +30,13 @@ Mandatory properties:
128MB, 256MB, 512MB, 1GB or 2GB in size. The memory should be marked as
pre-fetchable.
Optional properties:
- clocks: when present, this should contain the peripheral clock (PCLK) and the
PCI clock (PCICLK). If these are not present, they are assumed to be
hard-wired enabled and always on. The PCI clock will be 33 or 66 MHz.
- clock-names: when present, this should contain "PCLK" for the peripheral
clock and "PCICLK" for the PCI-side clock.
Mandatory subnodes:
- For "faraday,ftpci100" a node representing the interrupt-controller inside the
host bridge is mandatory. It has the following mandatory properties:
......
......@@ -33,6 +33,10 @@ Optional properties:
- reset-gpio-active-high: If present then the reset sequence using the GPIO
specified in the "reset-gpio" property is reversed (H=reset state,
L=operation state).
- vpcie-supply: Should specify the regulator in charge of PCIe port power.
The regulator will be enabled when initializing the PCIe host and
disabled either as part of the init process or when shutting down the
host.
Additional required properties for imx6sx-pcie:
- clock names: Must include the following additional 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.
Required properties:
- compatible: Should contain "mediatek,mt7623-pcie".
- device_type: Must be "pci"
- reg: Base addresses and lengths of the PCIe controller.
- #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
- 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.
- power-domains: A phandle and power domain specifier pair to the power domain
which is responsible for collapsing and restoring power to the peripheral.
- bus-range: Range of bus numbers associated with this controller.
- ranges: Ranges for the PCI memory and I/O regions.
In addition, the device tree node must have sub-nodes describing each
PCIe port interface, having the following mandatory properties:
Required properties:
- device_type: Must be "pci"
- reg: Only the first four bytes are used to refer to the correct bus number
and device number.
- #address-cells: Must be 3
- #size-cells: Must be 2
- #interrupt-cells: 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.
- ranges: Sub-ranges distributed from the PCIe controller node. An empty
property is sufficient.
- num-lanes: Number of lanes to use for this port.
Examples:
hifsys: syscon@1a000000 {
compatible = "mediatek,mt7623-hifsys",
"mediatek,mt2701-hifsys",
"syscon";
reg = <0 0x1a000000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
pcie: pcie-controller@1a140000 {
compatible = "mediatek,mt7623-pcie";
device_type = "pci";
reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */
<0 0x1a142000 0 0x1000>, /* Port0 registers */
<0 0x1a143000 0 0x1000>, /* Port1 registers */
<0 0x1a144000 0 0x1000>; /* Port2 registers */
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0xf800 0 0 0>;
interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>,
<0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>,
<0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>;
clocks = <&topckgen CLK_TOP_ETHIF_SEL>,
<&hifsys CLK_HIFSYS_PCIE0>,
<&hifsys CLK_HIFSYS_PCIE1>,
<&hifsys CLK_HIFSYS_PCIE2>;
clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2";
resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>,
<&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>;
phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2";
power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>;
bus-range = <0x00 0xff>;
ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 /* I/O space */
0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; /* memory space */
pcie@0,0 {
device_type = "pci";
reg = <0x0000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>;
ranges;
num-lanes = <1>;
};
pcie@1,0 {
device_type = "pci";
reg = <0x0800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>;
ranges;
num-lanes = <1>;
};
pcie@2,0 {
device_type = "pci";
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>;
ranges;
num-lanes = <1>;
};
};
......@@ -8,6 +8,7 @@
- "qcom,pcie-apq8064" for apq8064
- "qcom,pcie-apq8084" for apq8084
- "qcom,pcie-msm8996" for msm8996 or apq8096
- "qcom,pcie-ipq4019" for ipq4019
- reg:
Usage: required
......@@ -87,7 +88,7 @@
- "core" Clocks the pcie hw block
- "phy" Clocks the pcie PHY block
- clock-names:
Usage: required for apq8084
Usage: required for apq8084/ipq4019
Value type: <stringlist>
Definition: Should contain the following entries
- "aux" Auxiliary (AUX) clock
......@@ -126,6 +127,23 @@
Definition: Should contain the following entries
- "core" Core reset
- reset-names:
Usage: required for ipq/apq8064
Value type: <stringlist>
Definition: Should contain the following entries
- "axi_m" AXI master reset
- "axi_s" AXI slave reset
- "pipe" PIPE reset
- "axi_m_vmid" VMID reset
- "axi_s_xpu" XPU reset
- "parf" PARF reset
- "phy" PHY reset
- "axi_m_sticky" AXI sticky reset
- "pipe_sticky" PIPE sticky reset
- "pwr" PWR reset
- "ahb" AHB reset
- "phy_ahb" PHY AHB reset
- power-domains:
Usage: required for apq8084 and msm8996/apq8096
Value type: <prop-encoded-array>
......
* Renesas RCar PCIe interface
* Renesas R-Car PCIe interface
Required properties:
compatible: "renesas,pcie-r8a7779" for the R8A7779 SoC;
......
Sigma Designs Tango PCIe controller
Required properties:
- compatible: "sigma,smp8759-pcie"
- reg: address/size of PCI configuration space, address/size of register area
- bus-range: defined by size of PCI configuration space
- device_type: "pci"
- #size-cells: <2>
- #address-cells: <3>
- msi-controller
- ranges: translation from system to bus addresses
- interrupts: spec for misc interrupts, spec for MSI
Example:
pcie@2e000 {
compatible = "sigma,smp8759-pcie";
reg = <0x50000000 0x400000>, <0x2e000 0x100>;
bus-range = <0 3>;
device_type = "pci";
#size-cells = <2>;
#address-cells = <3>;
msi-controller;
ranges = <0x02000000 0x0 0x00400000 0x50400000 0x0 0x3c00000>;
interrupts =
<54 IRQ_TYPE_LEVEL_HIGH>, /* misc interrupts */
<55 IRQ_TYPE_LEVEL_HIGH>; /* MSI */
};
......@@ -348,6 +348,7 @@ PER-CPU MEM
devm_free_percpu()
PCI
devm_pci_alloc_host_bridge() : managed PCI host bridge allocation
devm_pci_remap_cfgspace() : ioremap PCI configuration space
devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource
pcim_enable_device() : after success, all PCI ops become managed
......
......@@ -10160,9 +10160,16 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
F: drivers/pci/dwc/pcie-hisi.c
PCIE DRIVER FOR HISILICON KIRIN
M: Xiaowei Song <songxiaowei@hisilicon.com>
M: Binghui Wang <wangbinghui@hisilicon.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/pcie-kirin.txt
F: drivers/pci/dwc/pcie-kirin.c
PCIE DRIVER FOR ROCKCHIP
M: Shawn Lin <shawn.lin@rock-chips.com>
M: Wenrui Li <wenrui.li@rock-chips.com>
L: linux-pci@vger.kernel.org
L: linux-rockchip@lists.infradead.org
S: Maintained
......@@ -10184,6 +10191,14 @@ S: Supported
F: Documentation/devicetree/bindings/pci/pci-thunder-*
F: drivers/pci/host/pci-thunder-*
PCIE DRIVER FOR MEDIATEK
M: Ryder Lee <ryder.lee@mediatek.com>
L: linux-pci@vger.kernel.org
L: linux-mediatek@lists.infradead.org
S: Supported
F: Documentation/devicetree/bindings/pci/mediatek*
F: drivers/pci/host/*mediatek*
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: linux-pcmcia@lists.infradead.org
......
......@@ -16,6 +16,7 @@
struct pci_sys_data;
struct pci_ops;
struct pci_bus;
struct pci_host_bridge;
struct device;
struct hw_pci {
......@@ -25,7 +26,7 @@ struct hw_pci {
unsigned int io_optional:1;
void **private_data;
int (*setup)(int nr, struct pci_sys_data *);
struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
int (*scan)(int nr, struct pci_host_bridge *);
void (*preinit)(void);
void (*postinit)(void);
u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
......
......@@ -458,10 +458,14 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
int nr, busnr;
for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
if (WARN(!sys, "PCI: unable to allocate sys data!"))
struct pci_host_bridge *bridge;
bridge = pci_alloc_host_bridge(sizeof(struct pci_sys_data));
if (WARN(!bridge, "PCI: unable to allocate bridge!"))
break;
sys = pci_host_bridge_priv(bridge);
sys->busnr = busnr;
sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq;
......@@ -473,7 +477,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
ret = hw->setup(nr, sys);
if (ret > 0) {
struct pci_host_bridge *host_bridge;
ret = pcibios_init_resource(nr, sys, hw->io_optional);
if (ret) {
......@@ -481,26 +484,37 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
break;
}
bridge->map_irq = pcibios_map_irq;
bridge->swizzle_irq = pcibios_swizzle;
if (hw->scan)
sys->bus = hw->scan(nr, sys);
else
sys->bus = pci_scan_root_bus_msi(parent,
sys->busnr, hw->ops, sys,
&sys->resources, hw->msi_ctrl);
ret = hw->scan(nr, bridge);
else {
list_splice_init(&sys->resources,
&bridge->windows);
bridge->dev.parent = parent;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = hw->ops;
bridge->msi = hw->msi_ctrl;
bridge->align_resource =
hw->align_resource;
ret = pci_scan_root_bus_bridge(bridge);
}
if (WARN(!sys->bus, "PCI: unable to scan bus!")) {
kfree(sys);
if (WARN(ret < 0, "PCI: unable to scan bus!")) {
pci_free_host_bridge(bridge);
break;
}
sys->bus = bridge->bus;
busnr = sys->bus->busn_res.end + 1;
list_add(&sys->node, head);
host_bridge = pci_find_host_bridge(sys->bus);
host_bridge->align_resource = hw->align_resource;
} else {
kfree(sys);
pci_free_host_bridge(bridge);
if (ret < 0)
break;
}
......@@ -519,8 +533,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
if (hw->postinit)
hw->postinit();
pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
list_for_each_entry(sys, &head, node) {
struct pci_bus *bus = sys->bus;
......
......@@ -152,16 +152,23 @@ static void rc_pci_fixup(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
static struct pci_bus __init *
dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
static int __init
dove_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
{
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr >= num_pcie_ports) {
BUG();
return NULL;
return -EINVAL;
}
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
list_splice_init(&sys->resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
}
static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
......@@ -504,10 +504,10 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
/* Scan an IOP13XX PCI bus. nr selects which ATU we use.
*/
struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge)
{
int which_atu;
struct pci_bus *bus = NULL;
int which_atu, ret;
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
switch (init_atu) {
case IOP13XX_INIT_ATU_ATUX:
......@@ -525,9 +525,14 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
if (!which_atu) {
BUG();
return NULL;
return -ENODEV;
}
list_splice_init(&sys->resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
switch (which_atu) {
case IOP13XX_INIT_ATU_ATUX:
if (time_after_eq(jiffies + msecs_to_jiffies(1000),
......@@ -535,18 +540,22 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
while(time_before(jiffies, atux_trhfa_timeout))
udelay(100);
bus = pci_bus_atux = pci_scan_root_bus(NULL, sys->busnr,
&iop13xx_atux_ops,
sys, &sys->resources);
bridge->ops = &iop13xx_atux_ops;
ret = pci_scan_root_bus_bridge(bridge);
if (!ret)
pci_bus_atux = bridge->bus;
break;
case IOP13XX_INIT_ATU_ATUE:
bus = pci_bus_atue = pci_scan_root_bus(NULL, sys->busnr,
&iop13xx_atue_ops,
sys, &sys->resources);
bridge->ops = &iop13xx_atue_ops;
ret = pci_scan_root_bus_bridge(bridge);
if (!ret)
pci_bus_atue = bridge->bus;
break;
default:
ret = -EINVAL;
}
return bus;
return ret;
}
/* This function is called from iop13xx_pci_init() after assigning valid
......
......@@ -11,9 +11,10 @@ extern size_t iop13xx_atue_mem_size;
extern size_t iop13xx_atux_mem_size;
struct pci_sys_data;
struct pci_host_bridge;
struct hw_pci;
int iop13xx_pci_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *);
int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge);
void iop13xx_atu_select(struct hw_pci *plat_pci);
void iop13xx_pci_init(void);
void iop13xx_map_pci_memory(void);
......
......@@ -194,16 +194,22 @@ static void rc_pci_fixup(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
static struct pci_bus __init *
mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
static int __init mv78xx0_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
{
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr >= num_pcie_ports) {
BUG();
return NULL;
return -EINVAL;
}
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
list_splice_init(&sys->resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
}
static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
......
......@@ -54,6 +54,7 @@ void orion5x_restart(enum reboot_mode, const char *);
* PCIe/PCI functions.
*/
struct pci_bus;
struct pci_host_bridge;
struct pci_sys_data;
struct pci_dev;
......@@ -61,7 +62,7 @@ void orion5x_pcie_id(u32 *dev, u32 *rev);
void orion5x_pci_disable(void);
void orion5x_pci_set_cardbus_mode(void);
int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
int orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge);
int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
struct tag;
......
......@@ -555,18 +555,27 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
return 0;
}
struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
int __init orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge)
{
if (nr == 0)
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr == 1 && !orion5x_pci_disabled)
return pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys,
&sys->resources);
list_splice_init(&sys->resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
if (nr == 0) {
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
}
if (nr == 1 && !orion5x_pci_disabled) {
bridge->ops = &pci_ops;
return pci_scan_root_bus_bridge(bridge);
}
BUG();
return NULL;
return -ENODEV;
}
int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
......@@ -39,20 +39,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return res->start;
}
#ifdef CONFIG_ACPI
/*
* Try to assign the IRQ number when probing a new device
*/
int pcibios_alloc_irq(struct pci_dev *dev)
{
if (acpi_disabled)
dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
#ifdef CONFIG_ACPI
else
return acpi_pci_irq_enable(dev);
#endif
if (!acpi_disabled)
acpi_pci_irq_enable(dev);
return 0;
}
#endif
/*
* raw_pci_read/write - Platform-specific PCI config space access.
......
......@@ -80,7 +80,6 @@ extern u32 cs5536_pci_conf_read4(int function, int reg);
#define PCI_BAR3_REG 0x1c
#define PCI_BAR4_REG 0x20
#define PCI_BAR5_REG 0x24
#define PCI_BAR_COUNT 6
#define PCI_BAR_RANGE_MASK 0xFFFFFFFF
/* CARDBUS CIS POINTER */
......
......@@ -39,7 +39,6 @@ struct pci_controller {
unsigned long io_offset;
unsigned long io_map_base;
struct resource *busn_resource;
unsigned long busn_offset;
#ifndef CONFIG_PCI_DOMAINS_GENERIC
unsigned int index;
......
......@@ -86,8 +86,7 @@ static void pcibios_scanbus(struct pci_controller *hose)
hose->mem_resource, hose->mem_offset);
pci_add_resource_offset(&resources,
hose->io_resource, hose->io_offset);
pci_add_resource_offset(&resources,
hose->busn_resource, hose->busn_offset);
pci_add_resource(&resources, hose->busn_resource);
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
hose->bus = bus;
......
......@@ -149,6 +149,12 @@
*/
#define HV_X64_DEPRECATING_AEOI_RECOMMENDED (1 << 9)
/*
* HV_VP_SET available
*/
#define HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED (1 << 11)
/*
* Crash notification flag.
*/
......
......@@ -24,7 +24,6 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
unsigned int pci_early_dump_regs;
static int pci_bf_sort;
static int smbios_type_b1_flag;
int pci_routeirq;
int noioapicquirk;
#ifdef CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS
......@@ -197,34 +196,18 @@ static int __init set_bf_sort(const struct dmi_system_id *d)
static void __init read_dmi_type_b1(const struct dmi_header *dm,
void *private_data)
{
u8 *d = (u8 *)dm + 4;
u8 *data = (u8 *)dm + 4;
if (dm->type != 0xB1)
return;
switch (((*(u32 *)d) >> 9) & 0x03) {
case 0x00:
printk(KERN_INFO "dmi type 0xB1 record - unknown flag\n");
break;
case 0x01: /* set pci=bfsort */
smbios_type_b1_flag = 1;
break;
case 0x02: /* do not set pci=bfsort */
smbios_type_b1_flag = 2;
break;
default:
break;
}
if ((((*(u32 *)data) >> 9) & 0x03) == 0x01)
set_bf_sort((const struct dmi_system_id *)private_data);
}
static int __init find_sort_method(const struct dmi_system_id *d)
{
dmi_walk(read_dmi_type_b1, NULL);
if (smbios_type_b1_flag == 1) {
set_bf_sort(d);
return 0;
}
return -1;
dmi_walk(read_dmi_type_b1, (void *)d);
return 0;
}
/*
......
......@@ -571,3 +571,50 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, pci_invalid_bar);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar);
/*
* Device [1022:7808]
* 23. USB Wake on Connect/Disconnect with Low Speed Devices
* https://support.amd.com/TechDocs/46837.pdf
* Appendix A2
* https://support.amd.com/TechDocs/42413.pdf
*/
static void pci_fixup_amd_ehci_pme(struct pci_dev *dev)
{
dev_info(&dev->dev, "PME# does not work under D3, disabling it\n");
dev->pme_support &= ~((PCI_PM_CAP_PME_D3 | PCI_PM_CAP_PME_D3cold)
>> PCI_PM_CAP_PME_SHIFT);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x7808, pci_fixup_amd_ehci_pme);
/*
* Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff]
*
* Using the [mem 0x7fa00000-0x7fbfffff] region, e.g., by assigning it to
* the 00:1c.0 Root Port, causes a conflict with [io 0x1804], which is used
* for soft poweroff and suspend-to-RAM.
*
* As far as we know, this is related to the address space, not to the Root
* Port itself. Attaching the quirk to the Root Port is a convenience, but
* it could probably also be a standalone DMI quirk.
*
* https://bugzilla.kernel.org/show_bug.cgi?id=103211
*/
static void quirk_apple_mbp_poweroff(struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
if ((!dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,4") &&
!dmi_match(DMI_PRODUCT_NAME, "MacBookPro11,5")) ||
pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x1c, 0))
return;
res = request_mem_region(0x7fa00000, 0x200000,
"MacBook Pro poweroff workaround");
if (res)
dev_info(dev, "claimed %s %pR\n", res->name, res);
else
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);
......@@ -46,7 +46,7 @@ static inline void set_bios_x(void)
pcibios_enabled = 1;
set_memory_x(PAGE_OFFSET + BIOS_BEGIN, (BIOS_END - BIOS_BEGIN) >> PAGE_SHIFT);
if (__supported_pte_mask & _PAGE_NX)
printk(KERN_INFO "PCI : PCI BIOS area is rw and x. Use pci=nobios if you want it NX.\n");
printk(KERN_INFO "PCI: PCI BIOS area is rw and x. Use pci=nobios if you want it NX.\n");
}
/*
......
......@@ -1152,16 +1152,12 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero
return;
if (state == VGA_SWITCHEROO_ON) {
unsigned d3_delay = dev->pdev->d3_delay;
pr_info("amdgpu: switched on\n");
/* don't suspend or resume card normally */
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
amdgpu_device_resume(dev, true, true);
dev->pdev->d3_delay = d3_delay;
dev->switch_power_state = DRM_SWITCH_POWER_ON;
drm_kms_helper_poll_enable(dev);
} else {
......
......@@ -113,7 +113,6 @@ static inline bool radeon_is_atpx_hybrid(void) { return false; }
#endif
#define RADEON_PX_QUIRK_DISABLE_PX (1 << 0)
#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1)
struct radeon_px_quirk {
u32 chip_vendor;
......@@ -140,8 +139,6 @@ static struct radeon_px_quirk radeon_px_quirk_list[] = {
* https://bugs.freedesktop.org/show_bug.cgi?id=101491
*/
{ PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX },
/* macbook pro 8.2 */
{ PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP },
{ 0, 0, 0, 0, 0 },
};
......@@ -1245,25 +1242,17 @@ static void radeon_check_arguments(struct radeon_device *rdev)
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct radeon_device *rdev = dev->dev_private;
if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF)
return;
if (state == VGA_SWITCHEROO_ON) {
unsigned d3_delay = dev->pdev->d3_delay;
pr_info("radeon: switched on\n");
/* don't suspend or resume card normally */
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP))
dev->pdev->d3_delay = 20;
radeon_resume_kms(dev, true, true);
dev->pdev->d3_delay = d3_delay;
dev->switch_power_state = DRM_SWITCH_POWER_ON;
drm_kms_helper_poll_enable(dev);
} else {
......
......@@ -2348,30 +2348,19 @@ static void fm10k_io_resume(struct pci_dev *pdev)
netif_device_attach(netdev);
}
/**
* fm10k_io_reset_notify - called when PCI function is reset
* @pdev: Pointer to PCI device
*
* This callback is called when the PCI function is reset such as from
* /sys/class/net/<enpX>/device/reset or similar. When prepare is true, it
* means we should prepare for a function reset. If prepare is false, it means
* the function reset just occurred.
*/
static void fm10k_io_reset_notify(struct pci_dev *pdev, bool prepare)
static void fm10k_io_reset_prepare(struct pci_dev *pdev)
{
struct fm10k_intfc *interface = pci_get_drvdata(pdev);
int err = 0;
if (prepare) {
/* warn incase we have any active VF devices */
if (pci_num_vf(pdev))
dev_warn(&pdev->dev,
"PCIe FLR may cause issues for any active VF devices\n");
/* warn incase we have any active VF devices */
if (pci_num_vf(pdev))
dev_warn(&pdev->dev,
"PCIe FLR may cause issues for any active VF devices\n");
fm10k_prepare_suspend(pci_get_drvdata(pdev));
}
fm10k_prepare_suspend(interface);
} else {
err = fm10k_handle_resume(interface);
}
static void fm10k_io_reset_done(struct pci_dev *pdev)
{
struct fm10k_intfc *interface = pci_get_drvdata(pdev);
int err = fm10k_handle_resume(interface);
if (err) {
dev_warn(&pdev->dev,
......@@ -2384,7 +2373,8 @@ static const struct pci_error_handlers fm10k_err_handler = {
.error_detected = fm10k_io_error_detected,
.slot_reset = fm10k_io_slot_reset,
.resume = fm10k_io_resume,
.reset_notify = fm10k_io_reset_notify,
.reset_prepare = fm10k_io_reset_prepare,
.reset_done = fm10k_io_reset_done,
};
static struct pci_driver fm10k_driver = {
......
......@@ -346,11 +346,13 @@ static const struct pci_device_id mwifiex_ids[] = {
MODULE_DEVICE_TABLE(pci, mwifiex_ids);
static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
/*
* Cleanup all software without cleaning anything related to PCIe and HW.
*/
static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev)
{
struct pcie_service_card *card = pci_get_drvdata(pdev);
struct mwifiex_adapter *adapter = card->adapter;
int ret;
if (!adapter) {
dev_err(&pdev->dev, "%s: adapter structure is not valid\n",
......@@ -359,35 +361,46 @@ static void mwifiex_pcie_reset_notify(struct pci_dev *pdev, bool prepare)
}
mwifiex_dbg(adapter, INFO,
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d %s\n",
__func__, pdev->vendor, pdev->device,
pdev->revision,
prepare ? "Pre-FLR" : "Post-FLR");
if (prepare) {
/* Kernel would be performing FLR after this notification.
* Cleanup all software without cleaning anything related to
* PCIe and HW.
*/
mwifiex_shutdown_sw(adapter);
clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
} else {
/* Kernel stores and restores PCIe function context before and
* after performing FLR respectively. Reconfigure the software
* and firmware including firmware redownload
*/
ret = mwifiex_reinit_sw(adapter);
if (ret) {
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
return;
}
}
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d Pre-FLR\n",
__func__, pdev->vendor, pdev->device, pdev->revision);
mwifiex_shutdown_sw(adapter);
clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
}
static const struct pci_error_handlers mwifiex_pcie_err_handler[] = {
{ .reset_notify = mwifiex_pcie_reset_notify, },
/*
* Kernel stores and restores PCIe function context before and after performing
* FLR respectively. Reconfigure the software and firmware including firmware
* redownload.
*/
static void mwifiex_pcie_reset_done(struct pci_dev *pdev)
{
struct pcie_service_card *card = pci_get_drvdata(pdev);
struct mwifiex_adapter *adapter = card->adapter;
int ret;
if (!adapter) {
dev_err(&pdev->dev, "%s: adapter structure is not valid\n",
__func__);
return;
}
mwifiex_dbg(adapter, INFO,
"%s: vendor=0x%4.04x device=0x%4.04x rev=%d Post-FLR\n",
__func__, pdev->vendor, pdev->device, pdev->revision);
ret = mwifiex_reinit_sw(adapter);
if (ret)
dev_err(&pdev->dev, "reinit failed: %d\n", ret);
else
mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
}
static const struct pci_error_handlers mwifiex_pcie_err_handler = {
.reset_prepare = mwifiex_pcie_reset_prepare,
.reset_done = mwifiex_pcie_reset_done,
};
#ifdef CONFIG_PM_SLEEP
......@@ -408,7 +421,7 @@ static struct pci_driver __refdata mwifiex_pcie = {
},
#endif
.shutdown = mwifiex_pcie_shutdown,
.err_handler = mwifiex_pcie_err_handler,
.err_handler = &mwifiex_pcie_err_handler,
};
/*
......
......@@ -2303,14 +2303,16 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return result;
}
static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
static void nvme_reset_prepare(struct pci_dev *pdev)
{
struct nvme_dev *dev = pci_get_drvdata(pdev);
nvme_dev_disable(dev, false);
}
if (prepare)
nvme_dev_disable(dev, false);
else
nvme_reset_ctrl(&dev->ctrl);
static void nvme_reset_done(struct pci_dev *pdev)
{
struct nvme_dev *dev = pci_get_drvdata(pdev);
nvme_reset_ctrl(&dev->ctrl);
}
static void nvme_shutdown(struct pci_dev *pdev)
......@@ -2434,7 +2436,8 @@ static const struct pci_error_handlers nvme_err_handler = {
.error_detected = nvme_error_detected,
.slot_reset = nvme_slot_reset,
.resume = nvme_error_resume,
.reset_notify = nvme_reset_notify,
.reset_prepare = nvme_reset_prepare,
.reset_done = nvme_reset_done,
};
static const struct pci_device_id nvme_id_table[] = {
......
......@@ -113,7 +113,8 @@ EXPORT_SYMBOL_GPL(of_irq_parse_pci);
* @pin: PCI irq pin number; passed when used as map_irq callback. Unused
*
* @slot and @pin are unused, but included in the function so that this
* function can be used directly as the map_irq callback to pci_fixup_irqs().
* function can be used directly as the map_irq callback to
* pci_assign_irq() and struct pci_host_bridge.map_irq pointer
*/
int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
{
......
......@@ -4,7 +4,8 @@
obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o vpd.o setup-bus.o vc.o mmap.o
irq.o vpd.o setup-bus.o vc.o mmap.o setup-irq.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o
......@@ -28,20 +29,6 @@ obj-$(CONFIG_HT_IRQ) += htirq.o
obj-$(CONFIG_PCI_ATS) += ats.o
obj-$(CONFIG_PCI_IOV) += iov.o
#
# Some architectures use the generic PCI setup functions
#
obj-$(CONFIG_ALPHA) += setup-irq.o
obj-$(CONFIG_ARC) += setup-irq.o
obj-$(CONFIG_ARM) += setup-irq.o
obj-$(CONFIG_ARM64) += setup-irq.o
obj-$(CONFIG_UNICORE32) += setup-irq.o
obj-$(CONFIG_SUPERH) += setup-irq.o
obj-$(CONFIG_MIPS) += setup-irq.o
obj-$(CONFIG_TILE) += setup-irq.o
obj-$(CONFIG_SPARC_LEON) += setup-irq.o
obj-$(CONFIG_M68K) += setup-irq.o
#
# ACPI Related PCI FW Functions
# ACPI _DSM provided firmware instance and string name
......
......@@ -153,23 +153,27 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
u32 max_requests;
int pos;
if (WARN_ON(pdev->pri_enabled))
return -EBUSY;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status);
if ((control & PCI_PRI_CTRL_ENABLE) ||
!(status & PCI_PRI_STATUS_STOPPED))
if (!(status & PCI_PRI_STATUS_STOPPED))
return -EBUSY;
pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests);
reqs = min(max_requests, reqs);
pdev->pri_reqs_alloc = reqs;
pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs);
control |= PCI_PRI_CTRL_ENABLE;
control = PCI_PRI_CTRL_ENABLE;
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
pdev->pri_enabled = 1;
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_pri);
......@@ -185,6 +189,9 @@ void pci_disable_pri(struct pci_dev *pdev)
u16 control;
int pos;
if (WARN_ON(!pdev->pri_enabled))
return;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return;
......@@ -192,9 +199,33 @@ void pci_disable_pri(struct pci_dev *pdev)
pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
control &= ~PCI_PRI_CTRL_ENABLE;
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
pdev->pri_enabled = 0;
}
EXPORT_SYMBOL_GPL(pci_disable_pri);
/**
* pci_restore_pri_state - Restore PRI
* @pdev: PCI device structure
*/
void pci_restore_pri_state(struct pci_dev *pdev)
{
u16 control = PCI_PRI_CTRL_ENABLE;
u32 reqs = pdev->pri_reqs_alloc;
int pos;
if (!pdev->pri_enabled)
return;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return;
pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs);
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
}
EXPORT_SYMBOL_GPL(pci_restore_pri_state);
/**
* pci_reset_pri - Resets device's PRI state
* @pdev: PCI device structure
......@@ -207,16 +238,14 @@ int pci_reset_pri(struct pci_dev *pdev)
u16 control;
int pos;
if (WARN_ON(pdev->pri_enabled))
return -EBUSY;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
if (control & PCI_PRI_CTRL_ENABLE)
return -EBUSY;
control |= PCI_PRI_CTRL_RESET;
control = PCI_PRI_CTRL_RESET;
pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
return 0;
......@@ -239,16 +268,14 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
u16 control, supported;
int pos;
if (WARN_ON(pdev->pasid_enabled))
return -EBUSY;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
if (!pos)
return -EINVAL;
pci_read_config_word(pdev, pos + PCI_PASID_CTRL, &control);
pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported);
if (control & PCI_PASID_CTRL_ENABLE)
return -EINVAL;
supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV;
/* User wants to enable anything unsupported? */
......@@ -256,9 +283,12 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
return -EINVAL;
control = PCI_PASID_CTRL_ENABLE | features;
pdev->pasid_features = features;
pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
pdev->pasid_enabled = 1;
return 0;
}
EXPORT_SYMBOL_GPL(pci_enable_pasid);
......@@ -266,21 +296,46 @@ EXPORT_SYMBOL_GPL(pci_enable_pasid);
/**
* pci_disable_pasid - Disable the PASID capability
* @pdev: PCI device structure
*
*/
void pci_disable_pasid(struct pci_dev *pdev)
{
u16 control = 0;
int pos;
if (WARN_ON(!pdev->pasid_enabled))
return;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
if (!pos)
return;
pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
pdev->pasid_enabled = 0;
}
EXPORT_SYMBOL_GPL(pci_disable_pasid);
/**
* pci_restore_pasid_state - Restore PASID capabilities
* @pdev: PCI device structure
*/
void pci_restore_pasid_state(struct pci_dev *pdev)
{
u16 control;
int pos;
if (!pdev->pasid_enabled)
return;
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
if (!pos)
return;
control = PCI_PASID_CTRL_ENABLE | pdev->pasid_features;
pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
}
EXPORT_SYMBOL_GPL(pci_restore_pasid_state);
/**
* pci_pasid_features - Check which PASID features are supported
* @pdev: PCI device structure
......
......@@ -16,6 +16,7 @@ config PCIE_DW_EP
config PCI_DRA7XX
bool "TI DRA7xx PCIe controller"
depends on SOC_DRA7XX || COMPILE_TEST
depends on (PCI && PCI_MSI_IRQ_DOMAIN) || PCI_ENDPOINT
depends on OF && HAS_IOMEM && TI_PIPE3
help
......@@ -158,4 +159,14 @@ config PCIE_ARTPEC6
Say Y here to enable PCIe controller support on Axis ARTPEC-6
SoCs. This PCIe controller uses the DesignWare core.
config PCIE_KIRIN
depends on OF && ARM64
bool "HiSilicon Kirin series SoCs PCIe controllers"
depends on PCI
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here if you want PCIe controller support
on HiSilicon Kirin series SoCs.
endmenu
......@@ -13,6 +13,7 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o
# The following drivers are for devices that use the generic ACPI
# pci_root.c driver but don't support standard ECAM config access.
......
......@@ -174,7 +174,7 @@ static int dra7xx_pcie_establish_link(struct dw_pcie *pci)
static void dra7xx_pcie_enable_msi_interrupts(struct dra7xx_pcie *dra7xx)
{
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI,
~LEG_EP_INTERRUPTS & ~MSI);
LEG_EP_INTERRUPTS | MSI);
dra7xx_pcie_writel(dra7xx,
PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
......@@ -184,7 +184,7 @@ static void dra7xx_pcie_enable_msi_interrupts(struct dra7xx_pcie *dra7xx)
static void dra7xx_pcie_enable_wrapper_interrupts(struct dra7xx_pcie *dra7xx)
{
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
~INTERRUPTS);
INTERRUPTS);
dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN,
INTERRUPTS);
}
......@@ -208,7 +208,7 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp)
dra7xx_pcie_enable_interrupts(dra7xx);
}
static struct dw_pcie_host_ops dra7xx_pcie_host_ops = {
static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = {
.host_init = dra7xx_pcie_host_init,
};
......
......@@ -590,7 +590,7 @@ static void exynos_pcie_host_init(struct pcie_port *pp)
exynos_pcie_enable_interrupts(ep);
}
static struct dw_pcie_host_ops exynos_pcie_host_ops = {
static const struct dw_pcie_host_ops exynos_pcie_host_ops = {
.rd_own_conf = exynos_pcie_rd_own_conf,
.wr_own_conf = exynos_pcie_wr_own_conf,
.host_init = exynos_pcie_host_init,
......
......@@ -24,6 +24,7 @@
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>
......@@ -59,6 +60,7 @@ struct imx6_pcie {
u32 tx_swing_full;
u32 tx_swing_low;
int link_gen;
struct regulator *vpcie;
};
/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
......@@ -284,6 +286,8 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
{
struct device *dev = imx6_pcie->pci->dev;
switch (imx6_pcie->variant) {
case IMX7D:
reset_control_assert(imx6_pcie->pciephy_reset);
......@@ -310,6 +314,14 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
break;
}
if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
int ret = regulator_disable(imx6_pcie->vpcie);
if (ret)
dev_err(dev, "failed to disable vpcie regulator: %d\n",
ret);
}
}
static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
......@@ -376,10 +388,19 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
struct device *dev = pci->dev;
int ret;
if (imx6_pcie->vpcie && !regulator_is_enabled(imx6_pcie->vpcie)) {
ret = regulator_enable(imx6_pcie->vpcie);
if (ret) {
dev_err(dev, "failed to enable vpcie regulator: %d\n",
ret);
return;
}
}
ret = clk_prepare_enable(imx6_pcie->pcie_phy);
if (ret) {
dev_err(dev, "unable to enable pcie_phy clock\n");
return;
goto err_pcie_phy;
}
ret = clk_prepare_enable(imx6_pcie->pcie_bus);
......@@ -439,6 +460,13 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
clk_disable_unprepare(imx6_pcie->pcie_bus);
err_pcie_bus:
clk_disable_unprepare(imx6_pcie->pcie_phy);
err_pcie_phy:
if (imx6_pcie->vpcie && regulator_is_enabled(imx6_pcie->vpcie) > 0) {
ret = regulator_disable(imx6_pcie->vpcie);
if (ret)
dev_err(dev, "failed to disable vpcie regulator: %d\n",
ret);
}
}
static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
......@@ -629,7 +657,7 @@ static int imx6_pcie_link_up(struct dw_pcie *pci)
PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
}
static struct dw_pcie_host_ops imx6_pcie_host_ops = {
static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
.host_init = imx6_pcie_host_init,
};
......@@ -802,6 +830,13 @@ static int imx6_pcie_probe(struct platform_device *pdev)
if (ret)
imx6_pcie->link_gen = 1;
imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
if (IS_ERR(imx6_pcie->vpcie)) {
if (PTR_ERR(imx6_pcie->vpcie) == -EPROBE_DEFER)
return -EPROBE_DEFER;
imx6_pcie->vpcie = NULL;
}
platform_set_drvdata(pdev, imx6_pcie);
ret = imx6_add_pcie_port(imx6_pcie, pdev);
......
......@@ -291,7 +291,7 @@ static void __init ks_pcie_host_init(struct pcie_port *pp)
"Asynchronous external abort");
}
static struct dw_pcie_host_ops keystone_pcie_host_ops = {
static const struct dw_pcie_host_ops keystone_pcie_host_ops = {
.rd_other_conf = ks_dw_pcie_rd_other_conf,
.wr_other_conf = ks_dw_pcie_wr_other_conf,
.host_init = ks_pcie_host_init,
......
......@@ -39,7 +39,7 @@ struct ls_pcie_drvdata {
u32 lut_offset;
u32 ltssm_shift;
u32 lut_dbg;
struct dw_pcie_host_ops *ops;
const struct dw_pcie_host_ops *ops;
const struct dw_pcie_ops *dw_pcie_ops;
};
......@@ -185,12 +185,12 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp,
return 0;
}
static struct dw_pcie_host_ops ls1021_pcie_host_ops = {
static const struct dw_pcie_host_ops ls1021_pcie_host_ops = {
.host_init = ls1021_pcie_host_init,
.msi_host_init = ls_pcie_msi_host_init,
};
static struct dw_pcie_host_ops ls_pcie_host_ops = {
static const struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.msi_host_init = ls_pcie_msi_host_init,
};
......
......@@ -160,7 +160,7 @@ static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
static struct dw_pcie_host_ops armada8k_pcie_host_ops = {
static const struct dw_pcie_host_ops armada8k_pcie_host_ops = {
.host_init = armada8k_pcie_host_init,
};
......
......@@ -184,7 +184,7 @@ static void artpec6_pcie_host_init(struct pcie_port *pp)
artpec6_pcie_enable_interrupts(artpec6_pcie);
}
static struct dw_pcie_host_ops artpec6_pcie_host_ops = {
static const struct dw_pcie_host_ops artpec6_pcie_host_ops = {
.host_init = artpec6_pcie_host_init,
};
......
......@@ -280,9 +280,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
struct device_node *np = dev->of_node;
struct platform_device *pdev = to_platform_device(dev);
struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
struct resource *cfg_res;
int i, ret;
LIST_HEAD(res);
struct resource_entry *win, *tmp;
cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
......@@ -295,16 +295,21 @@ int dw_pcie_host_init(struct pcie_port *pp)
dev_err(dev, "missing *config* reg space\n");
}
ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
bridge = pci_alloc_host_bridge(0);
if (!bridge)
return -ENOMEM;
ret = of_pci_get_host_bridge_resources(np, 0, 0xff,
&bridge->windows, &pp->io_base);
if (ret)
return ret;
ret = devm_request_pci_bus_resources(dev, &res);
ret = devm_request_pci_bus_resources(dev, &bridge->windows);
if (ret)
goto error;
/* Get the I/O and memory ranges from DT */
resource_list_for_each_entry_safe(win, tmp, &res) {
resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
switch (resource_type(win->res)) {
case IORESOURCE_IO:
ret = pci_remap_iospace(win->res, pp->io_base);
......@@ -400,27 +405,27 @@ int dw_pcie_host_init(struct pcie_port *pp)
pp->ops->host_init(pp);
pp->root_bus_nr = pp->busn->start;
bridge->dev.parent = dev;
bridge->sysdata = pp;
bridge->busnr = pp->root_bus_nr;
bridge->ops = &dw_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
bus = pci_scan_root_bus_msi(dev, pp->root_bus_nr,
&dw_pcie_ops, pp, &res,
&dw_pcie_msi_chip);
bridge->msi = &dw_pcie_msi_chip;
dw_pcie_msi_chip.dev = dev;
} else
bus = pci_scan_root_bus(dev, pp->root_bus_nr, &dw_pcie_ops,
pp, &res);
if (!bus) {
ret = -ENOMEM;
goto error;
}
ret = pci_scan_root_bus_bridge(bridge);
if (ret)
goto error;
bus = bridge->bus;
if (pp->ops->scan_bus)
pp->ops->scan_bus(pp);
#ifdef CONFIG_ARM
/* support old dtbs that incorrectly describe IRQs */
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
......@@ -431,7 +436,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
return 0;
error:
pci_free_resource_list(&res);
pci_free_host_bridge(bridge);
return ret;
}
......
......@@ -46,7 +46,7 @@ static void dw_plat_pcie_host_init(struct pcie_port *pp)
dw_pcie_msi_init(pp);
}
static struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
.host_init = dw_plat_pcie_host_init,
};
......@@ -67,7 +67,8 @@ static int dw_plat_add_pcie_port(struct pcie_port *pp,
ret = devm_request_irq(dev, pp->msi_irq,
dw_plat_pcie_msi_irq_handler,
IRQF_SHARED, "dw-plat-pcie-msi", pp);
IRQF_SHARED | IRQF_NO_THREAD,
"dw-plat-pcie-msi", pp);
if (ret) {
dev_err(dev, "failed to request MSI IRQ\n");
return ret;
......
......@@ -162,7 +162,7 @@ struct pcie_port {
struct resource *mem;
struct resource *busn;
int irq;
struct dw_pcie_host_ops *ops;
const struct dw_pcie_host_ops *ops;
int msi_irq;
struct irq_domain *irq_domain;
unsigned long msi_data;
......
This diff is collapsed.
This diff is collapsed.
......@@ -186,7 +186,7 @@ static void spear13xx_pcie_host_init(struct pcie_port *pp)
spear13xx_pcie_enable_interrupts(spear13xx_pcie);
}
static struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
static const struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
.host_init = spear13xx_pcie_host_init,
};
......
......@@ -180,6 +180,31 @@ config PCIE_ROCKCHIP
There is 1 internal PCIe port available to support GEN2 with
4 slots.
config PCIE_MEDIATEK
bool "MediaTek PCIe controller"
depends on ARM && (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.
config PCIE_TANGO_SMP8759
bool "Tango SMP8759 PCIe controller (DANGEROUS)"
depends on ARCH_TANGO && PCI_MSI && OF
depends on BROKEN
select PCI_HOST_COMMON
help
Say Y here to enable PCIe controller support for Sigma Designs
Tango SMP8759-based systems.
Note: The SMP8759 controller multiplexes PCI config and MMIO
accesses, and Linux doesn't provide a way to serialize them.
This can lead to data corruption if drivers perform concurrent
config and MMIO accesses.
config VMD
depends on PCI_MSI && X86_64 && SRCU
tristate "Intel Volume Management Device Driver"
......
......@@ -18,6 +18,8 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
obj-$(CONFIG_VMD) += vmd.o
# The following drivers are for devices that use the generic ACPI
......
......@@ -886,12 +886,14 @@ static int advk_pcie_probe(struct platform_device *pdev)
struct advk_pcie *pcie;
struct resource *res;
struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
int ret, irq;
pcie = devm_kzalloc(dev, sizeof(struct advk_pcie), GFP_KERNEL);
if (!pcie)
bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie));
if (!bridge)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->pdev = pdev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -929,14 +931,21 @@ static int advk_pcie_probe(struct platform_device *pdev)
return ret;
}
bus = pci_scan_root_bus(dev, 0, &advk_pcie_ops,
pcie, &pcie->resources);
if (!bus) {
list_splice_init(&pcie->resources, &bridge->windows);
bridge->dev.parent = dev;
bridge->sysdata = pcie;
bridge->busnr = 0;
bridge->ops = &advk_pcie_ops;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0) {
advk_pcie_remove_msi_irq_domain(pcie);
advk_pcie_remove_irq_domain(pcie);
return -ENOMEM;
return ret;
}
bus = bridge->bus;
pci_bus_assign_resources(bus);
list_for_each_entry(child, &bus->children, node)
......
......@@ -25,6 +25,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/bitops.h>
#include <linux/irq.h>
#include <linux/clk.h>
/*
* Special configuration registers directly in the first few words
......@@ -37,6 +38,7 @@
#define PCI_CONFIG 0x28 /* PCI configuration command register */
#define PCI_DATA 0x2C
#define FARADAY_PCI_STATUS_CMD 0x04 /* Status and command */
#define FARADAY_PCI_PMC 0x40 /* Power management control */
#define FARADAY_PCI_PMCSR 0x44 /* Power management status */
#define FARADAY_PCI_CTRL1 0x48 /* Control register 1 */
......@@ -45,6 +47,8 @@
#define FARADAY_PCI_MEM2_BASE_SIZE 0x54 /* Memory base and size #2 */
#define FARADAY_PCI_MEM3_BASE_SIZE 0x58 /* Memory base and size #3 */
#define PCI_STATUS_66MHZ_CAPABLE BIT(21)
/* Bits 31..28 gives INTD..INTA status */
#define PCI_CTRL2_INTSTS_SHIFT 28
#define PCI_CTRL2_INTMASK_CMDERR BIT(27)
......@@ -117,6 +121,7 @@ struct faraday_pci {
void __iomem *base;
struct irq_domain *irqdomain;
struct pci_bus *bus;
struct clk *bus_clk;
};
static int faraday_res_to_memcfg(resource_size_t mem_base,
......@@ -178,12 +183,11 @@ static int faraday_res_to_memcfg(resource_size_t mem_base,
return 0;
}
static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
int config, int size, u32 *value)
static int faraday_raw_pci_read_config(struct faraday_pci *p, int bus_number,
unsigned int fn, int config, int size,
u32 *value)
{
struct faraday_pci *p = bus->sysdata;
writel(PCI_CONF_BUS(bus->number) |
writel(PCI_CONF_BUS(bus_number) |
PCI_CONF_DEVICE(PCI_SLOT(fn)) |
PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
PCI_CONF_WHERE(config) |
......@@ -197,24 +201,28 @@ static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
else if (size == 2)
*value = (*value >> (8 * (config & 3))) & 0xFFFF;
return PCIBIOS_SUCCESSFUL;
}
static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
int config, int size, u32 *value)
{
struct faraday_pci *p = bus->sysdata;
dev_dbg(&bus->dev,
"[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
return PCIBIOS_SUCCESSFUL;
return faraday_raw_pci_read_config(p, bus->number, fn, config, size, value);
}
static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
int config, int size, u32 value)
static int faraday_raw_pci_write_config(struct faraday_pci *p, int bus_number,
unsigned int fn, int config, int size,
u32 value)
{
struct faraday_pci *p = bus->sysdata;
int ret = PCIBIOS_SUCCESSFUL;
dev_dbg(&bus->dev,
"[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
writel(PCI_CONF_BUS(bus->number) |
writel(PCI_CONF_BUS(bus_number) |
PCI_CONF_DEVICE(PCI_SLOT(fn)) |
PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
PCI_CONF_WHERE(config) |
......@@ -238,6 +246,19 @@ static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
return ret;
}
static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
int config, int size, u32 value)
{
struct faraday_pci *p = bus->sysdata;
dev_dbg(&bus->dev,
"[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
return faraday_raw_pci_write_config(p, bus->number, fn, config, size,
value);
}
static struct pci_ops faraday_pci_ops = {
.read = faraday_pci_read_config,
.write = faraday_pci_write_config,
......@@ -248,10 +269,10 @@ static void faraday_pci_ack_irq(struct irq_data *d)
struct faraday_pci *p = irq_data_get_irq_chip_data(d);
unsigned int reg;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTSTS_SHIFT);
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg);
faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
}
static void faraday_pci_mask_irq(struct irq_data *d)
......@@ -259,10 +280,10 @@ static void faraday_pci_mask_irq(struct irq_data *d)
struct faraday_pci *p = irq_data_get_irq_chip_data(d);
unsigned int reg;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
reg &= ~((0xF << PCI_CTRL2_INTSTS_SHIFT)
| BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT));
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg);
faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
}
static void faraday_pci_unmask_irq(struct irq_data *d)
......@@ -270,10 +291,10 @@ static void faraday_pci_unmask_irq(struct irq_data *d)
struct faraday_pci *p = irq_data_get_irq_chip_data(d);
unsigned int reg;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT);
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg);
faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
}
static void faraday_pci_irq_handler(struct irq_desc *desc)
......@@ -282,7 +303,7 @@ static void faraday_pci_irq_handler(struct irq_desc *desc)
struct irq_chip *irqchip = irq_desc_get_chip(desc);
unsigned int irq_stat, reg, i;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
irq_stat = reg >> PCI_CTRL2_INTSTS_SHIFT;
chained_irq_enter(irqchip, desc);
......@@ -403,8 +424,8 @@ static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
dev_info(dev, "DMA MEM%d BASE: 0x%016llx -> 0x%016llx config %08x\n",
i + 1, range.pci_addr, end, val);
if (i <= 2) {
faraday_pci_write_config(p->bus, 0, confreg[i],
4, val);
faraday_raw_pci_write_config(p, 0, 0, confreg[i],
4, val);
} else {
dev_err(dev, "ignore extraneous dma-range %d\n", i);
break;
......@@ -428,11 +449,14 @@ static int faraday_pci_probe(struct platform_device *pdev)
struct resource *mem;
struct resource *io;
struct pci_host_bridge *host;
struct clk *clk;
unsigned char max_bus_speed = PCI_SPEED_33MHz;
unsigned char cur_bus_speed = PCI_SPEED_33MHz;
int ret;
u32 val;
LIST_HEAD(res);
host = pci_alloc_host_bridge(sizeof(*p));
host = devm_pci_alloc_host_bridge(dev, sizeof(*p));
if (!host)
return -ENOMEM;
......@@ -440,10 +464,30 @@ static int faraday_pci_probe(struct platform_device *pdev)
host->ops = &faraday_pci_ops;
host->busnr = 0;
host->msi = NULL;
host->map_irq = of_irq_parse_and_map_pci;
host->swizzle_irq = pci_common_swizzle;
p = pci_host_bridge_priv(host);
host->sysdata = p;
p->dev = dev;
/* Retrieve and enable optional clocks */
clk = devm_clk_get(dev, "PCLK");
if (IS_ERR(clk))
return PTR_ERR(clk);
ret = clk_prepare_enable(clk);
if (ret) {
dev_err(dev, "could not prepare PCLK\n");
return ret;
}
p->bus_clk = devm_clk_get(dev, "PCICLK");
if (IS_ERR(p->bus_clk))
return PTR_ERR(clk);
ret = clk_prepare_enable(p->bus_clk);
if (ret) {
dev_err(dev, "could not prepare PCICLK\n");
return ret;
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
p->base = devm_ioremap_resource(dev, regs);
if (IS_ERR(p->base))
......@@ -496,17 +540,8 @@ static int faraday_pci_probe(struct platform_device *pdev)
val |= PCI_COMMAND_MEMORY;
val |= PCI_COMMAND_MASTER;
writel(val, p->base + PCI_CTRL);
list_splice_init(&res, &host->windows);
ret = pci_register_host_bridge(host);
if (ret) {
dev_err(dev, "failed to register host: %d\n", ret);
return ret;
}
p->bus = host->bus;
/* Mask and clear all interrupts */
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000);
faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000);
if (variant->cascaded_irq) {
ret = faraday_pci_setup_cascaded_irq(p);
if (ret) {
......@@ -515,12 +550,48 @@ static int faraday_pci_probe(struct platform_device *pdev)
}
}
/* Check bus clock if we can gear up to 66 MHz */
if (!IS_ERR(p->bus_clk)) {
unsigned long rate;
u32 val;
faraday_raw_pci_read_config(p, 0, 0,
FARADAY_PCI_STATUS_CMD, 4, &val);
rate = clk_get_rate(p->bus_clk);
if ((rate == 33000000) && (val & PCI_STATUS_66MHZ_CAPABLE)) {
dev_info(dev, "33MHz bus is 66MHz capable\n");
max_bus_speed = PCI_SPEED_66MHz;
ret = clk_set_rate(p->bus_clk, 66000000);
if (ret)
dev_err(dev, "failed to set bus clock\n");
} else {
dev_info(dev, "33MHz only bus\n");
max_bus_speed = PCI_SPEED_33MHz;
}
/* Bumping the clock may fail so read back the rate */
rate = clk_get_rate(p->bus_clk);
if (rate == 33000000)
cur_bus_speed = PCI_SPEED_33MHz;
if (rate == 66000000)
cur_bus_speed = PCI_SPEED_66MHz;
}
ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node);
if (ret)
return ret;
pci_scan_child_bus(p->bus);
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
list_splice_init(&res, &host->windows);
ret = pci_scan_root_bus_bridge(host);
if (ret) {
dev_err(dev, "failed to scan host: %d\n", ret);
return ret;
}
p->bus = host->bus;
p->bus->max_bus_speed = max_bus_speed;
p->bus->cur_bus_speed = cur_bus_speed;
pci_bus_assign_resources(p->bus);
pci_bus_add_devices(p->bus);
pci_free_resource_list(&res);
......
......@@ -117,8 +117,14 @@ int pci_host_common_probe(struct platform_device *pdev,
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
struct pci_config_window *cfg;
struct list_head resources;
int ret;
bridge = devm_pci_alloc_host_bridge(dev, 0);
if (!bridge)
return -ENOMEM;
type = of_get_property(np, "device_type", NULL);
if (!type || strcmp(type, "pci")) {
......@@ -138,16 +144,21 @@ int pci_host_common_probe(struct platform_device *pdev,
if (!pci_has_flag(PCI_PROBE_ONLY))
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
bus = pci_scan_root_bus(dev, cfg->busr.start, &ops->pci_ops, cfg,
&resources);
if (!bus) {
dev_err(dev, "Scanning rootbus failed");
return -ENODEV;
list_splice_init(&resources, &bridge->windows);
bridge->dev.parent = dev;
bridge->sysdata = cfg;
bridge->busnr = cfg->busr.start;
bridge->ops = &ops->pci_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0) {
dev_err(dev, "Scanning root bridge failed");
return ret;
}
#ifdef CONFIG_ARM
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
bus = bridge->bus;
/*
* We insert PCI resources into the iomem_resource and
......
This diff is collapsed.
......@@ -429,7 +429,7 @@ static int rcar_pci_probe(struct platform_device *pdev)
return 0;
}
static struct of_device_id rcar_pci_of_match[] = {
static const struct of_device_id rcar_pci_of_match[] = {
{ .compatible = "renesas,pci-r8a7790", },
{ .compatible = "renesas,pci-r8a7791", },
{ .compatible = "renesas,pci-r8a7794", },
......
......@@ -233,8 +233,8 @@ struct tegra_msi {
struct msi_controller chip;
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
struct irq_domain *domain;
unsigned long pages;
struct mutex lock;
u64 phys;
int irq;
};
......@@ -1448,9 +1448,8 @@ static int tegra_msi_setup_irq(struct msi_controller *chip,
irq_set_msi_desc(irq, desc);
msg.address_lo = virt_to_phys((void *)msi->pages);
/* 32 bit address only */
msg.address_hi = 0;
msg.address_lo = lower_32_bits(msi->phys);
msg.address_hi = upper_32_bits(msi->phys);
msg.data = hwirq;
pci_write_msi_msg(irq, &msg);
......@@ -1499,7 +1498,6 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
const struct tegra_pcie_soc *soc = pcie->soc;
struct tegra_msi *msi = &pcie->msi;
struct device *dev = pcie->dev;
unsigned long base;
int err;
u32 reg;
......@@ -1531,12 +1529,25 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
goto err;
}
/* setup AFI/FPCI range */
msi->pages = __get_free_pages(GFP_KERNEL, 0);
base = virt_to_phys((void *)msi->pages);
/*
* The PCI host bridge on Tegra contains some logic that intercepts
* MSI writes, which means that the MSI target address doesn't have
* to point to actual physical memory. Rather than allocating one 4
* KiB page of system memory that's never used, we can simply pick
* an arbitrary address within an area reserved for system memory
* in the FPCI address map.
*
* However, in order to avoid confusion, we pick an address that
* doesn't map to physical memory. The FPCI address map reserves a
* 1012 GiB region for system memory and memory-mapped I/O. Since
* none of the Tegra SoCs that contain this PCI host bridge can
* address more than 16 GiB of system memory, the last 4 KiB of
* these 1012 GiB is a good candidate.
*/
msi->phys = 0xfcfffff000;
afi_writel(pcie, base >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST);
afi_writel(pcie, base, AFI_MSI_AXI_BAR_ST);
afi_writel(pcie, msi->phys >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST);
afi_writel(pcie, msi->phys, AFI_MSI_AXI_BAR_ST);
/* this register is in 4K increments */
afi_writel(pcie, 1, AFI_MSI_BAR_SZ);
......@@ -1585,8 +1596,6 @@ static int tegra_pcie_disable_msi(struct tegra_pcie *pcie)
afi_writel(pcie, 0, AFI_MSI_EN_VEC6);
afi_writel(pcie, 0, AFI_MSI_EN_VEC7);
free_pages(msi->pages, 0);
if (msi->irq > 0)
free_irq(msi->irq, pcie);
......@@ -2238,7 +2247,7 @@ static int tegra_pcie_probe(struct platform_device *pdev)
struct pci_bus *child;
int err;
host = pci_alloc_host_bridge(sizeof(*pcie));
host = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!host)
return -ENOMEM;
......@@ -2284,16 +2293,15 @@ static int tegra_pcie_probe(struct platform_device *pdev)
host->busnr = pcie->busn.start;
host->dev.parent = &pdev->dev;
host->ops = &tegra_pcie_ops;
host->map_irq = tegra_pcie_map_irq;
host->swizzle_irq = pci_common_swizzle;
err = pci_register_host_bridge(host);
err = pci_scan_root_bus_bridge(host);
if (err < 0) {
dev_err(dev, "failed to register host: %d\n", err);
goto disable_msi;
}
pci_scan_child_bus(host->bus);
pci_fixup_irqs(pci_common_swizzle, tegra_pcie_map_irq);
pci_bus_size_bridges(host->bus);
pci_bus_assign_resources(host->bus);
......
......@@ -120,30 +120,35 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
static int versatile_pci_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
int ret, i, myslot = -1;
u32 val;
void __iomem *local_pci_cfg_base;
struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
LIST_HEAD(pci_res);
bridge = devm_pci_alloc_host_bridge(dev, 0);
if (!bridge)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
versatile_pci_base = devm_ioremap_resource(&pdev->dev, res);
versatile_pci_base = devm_ioremap_resource(dev, res);
if (IS_ERR(versatile_pci_base))
return PTR_ERR(versatile_pci_base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
versatile_cfg_base[0] = devm_ioremap_resource(&pdev->dev, res);
versatile_cfg_base[0] = devm_ioremap_resource(dev, res);
if (IS_ERR(versatile_cfg_base[0]))
return PTR_ERR(versatile_cfg_base[0]);
res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
versatile_cfg_base[1] = devm_pci_remap_cfg_resource(&pdev->dev,
res);
versatile_cfg_base[1] = devm_pci_remap_cfg_resource(dev, res);
if (IS_ERR(versatile_cfg_base[1]))
return PTR_ERR(versatile_cfg_base[1]);
ret = versatile_pci_parse_request_of_pci_ranges(&pdev->dev, &pci_res);
ret = versatile_pci_parse_request_of_pci_ranges(dev, &pci_res);
if (ret)
return ret;
......@@ -159,7 +164,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
}
}
if (myslot == -1) {
dev_err(&pdev->dev, "Cannot find PCI core!\n");
dev_err(dev, "Cannot find PCI core!\n");
return -EIO;
}
/*
......@@ -167,7 +172,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
*/
pci_slot_ignore |= (1 << myslot);
dev_info(&pdev->dev, "PCI core found (slot %d)\n", myslot);
dev_info(dev, "PCI core found (slot %d)\n", myslot);
writel(myslot, PCI_SELFID);
local_pci_cfg_base = versatile_cfg_base[1] + (myslot << 11);
......@@ -199,11 +204,20 @@ static int versatile_pci_probe(struct platform_device *pdev)
pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);
bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, NULL, &pci_res);
if (!bus)
return -ENOMEM;
list_splice_init(&pci_res, &bridge->windows);
bridge->dev.parent = dev;
bridge->sysdata = NULL;
bridge->busnr = 0;
bridge->ops = &pci_versatile_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0)
return ret;
bus = bridge->bus;
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
pci_assign_unassigned_bus_resources(bus);
list_for_each_entry(child, &bus->children, node)
pcie_bus_configure_settings(child);
......
......@@ -636,13 +636,16 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
struct xgene_pcie_port *port;
resource_size_t iobase = 0;
struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
int ret;
LIST_HEAD(res);
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
if (!port)
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
if (!bridge)
return -ENOMEM;
port = pci_host_bridge_priv(bridge);
port->node = of_node_get(dn);
port->dev = dev;
......@@ -670,11 +673,19 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret)
goto error;
bus = pci_create_root_bus(dev, 0, &xgene_pcie_ops, port, &res);
if (!bus) {
ret = -ENOMEM;
list_splice_init(&res, &bridge->windows);
bridge->dev.parent = dev;
bridge->sysdata = port;
bridge->busnr = 0;
bridge->ops = &xgene_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0)
goto error;
}
bus = bridge->bus;
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
......
......@@ -579,12 +579,14 @@ static int altera_pcie_probe(struct platform_device *pdev)
struct altera_pcie *pcie;
struct pci_bus *bus;
struct pci_bus *child;
struct pci_host_bridge *bridge;
int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!bridge)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->pdev = pdev;
ret = altera_pcie_parse_dt(pcie);
......@@ -613,12 +615,20 @@ static int altera_pcie_probe(struct platform_device *pdev)
cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
altera_pcie_host_init(pcie);
bus = pci_scan_root_bus(dev, pcie->root_bus_nr, &altera_pcie_ops,
pcie, &pcie->resources);
if (!bus)
return -ENOMEM;
list_splice_init(&pcie->resources, &bridge->windows);
bridge->dev.parent = dev;
bridge->sysdata = pcie;
bridge->busnr = pcie->root_bus_nr;
bridge->ops = &altera_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0)
return ret;
bus = bridge->bus;
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
pci_assign_unassigned_bus_resources(bus);
/* Configure PCI Express setting. */
......
......@@ -45,12 +45,15 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
struct device *dev = &bdev->dev;
struct iproc_pcie *pcie;
LIST_HEAD(resources);
struct pci_host_bridge *bridge;
int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!bridge)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev;
pcie->type = IPROC_PCIE_PAXB_BCMA;
......
......@@ -52,12 +52,15 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
struct resource reg;
resource_size_t iobase = 0;
LIST_HEAD(resources);
struct pci_host_bridge *bridge;
int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!bridge)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev;
pcie->type = (enum iproc_pcie_type) of_device_get_match_data(dev);
......
......@@ -452,14 +452,13 @@ static inline void iproc_pcie_apb_err_disable(struct pci_bus *bus,
* Note access to the configuration registers are protected at the higher layer
* by 'pci_lock' in drivers/pci/access.c
*/
static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
static void __iomem *iproc_pcie_map_cfg_bus(struct iproc_pcie *pcie,
int busno,
unsigned int devfn,
int where)
{
struct iproc_pcie *pcie = iproc_data(bus);
unsigned slot = PCI_SLOT(devfn);
unsigned fn = PCI_FUNC(devfn);
unsigned busno = bus->number;
u32 val;
u16 offset;
......@@ -499,6 +498,58 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
return (pcie->base + offset);
}
static void __iomem *iproc_pcie_bus_map_cfg_bus(struct pci_bus *bus,
unsigned int devfn,
int where)
{
return iproc_pcie_map_cfg_bus(iproc_data(bus), bus->number, devfn,
where);
}
static int iproc_pci_raw_config_read32(struct iproc_pcie *pcie,
unsigned int devfn, int where,
int size, u32 *val)
{
void __iomem *addr;
addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3);
if (!addr) {
*val = ~0;
return PCIBIOS_DEVICE_NOT_FOUND;
}
*val = readl(addr);
if (size <= 2)
*val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
return PCIBIOS_SUCCESSFUL;
}
static int iproc_pci_raw_config_write32(struct iproc_pcie *pcie,
unsigned int devfn, int where,
int size, u32 val)
{
void __iomem *addr;
u32 mask, tmp;
addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 4) {
writel(val, addr);
return PCIBIOS_SUCCESSFUL;
}
mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
tmp = readl(addr) & mask;
tmp |= val << ((where & 0x3) * 8);
writel(tmp, addr);
return PCIBIOS_SUCCESSFUL;
}
static int iproc_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
......@@ -524,7 +575,7 @@ static int iproc_pcie_config_write32(struct pci_bus *bus, unsigned int devfn,
}
static struct pci_ops iproc_pcie_ops = {
.map_bus = iproc_pcie_map_cfg_bus,
.map_bus = iproc_pcie_bus_map_cfg_bus,
.read = iproc_pcie_config_read32,
.write = iproc_pcie_config_write32,
};
......@@ -556,12 +607,11 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
msleep(100);
}
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
static int iproc_pcie_check_link(struct iproc_pcie *pcie)
{
struct device *dev = pcie->dev;
u8 hdr_type;
u32 link_ctrl, class, val;
u16 pos = PCI_EXP_CAP, link_status;
u32 hdr_type, link_ctrl, link_status, class, val;
u16 pos = PCI_EXP_CAP;
bool link_is_active = false;
/*
......@@ -578,7 +628,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
}
/* make sure we are not in EP mode */
pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type);
iproc_pci_raw_config_read32(pcie, 0, PCI_HEADER_TYPE, 1, &hdr_type);
if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) {
dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type);
return -EFAULT;
......@@ -588,13 +638,16 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
#define PCI_CLASS_BRIDGE_MASK 0xffff00
#define PCI_CLASS_BRIDGE_SHIFT 8
pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class);
iproc_pci_raw_config_read32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET,
4, &class);
class &= ~PCI_CLASS_BRIDGE_MASK;
class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class);
iproc_pci_raw_config_write32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET,
4, class);
/* check link status to see if link is active */
pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status);
iproc_pci_raw_config_read32(pcie, 0, pos + PCI_EXP_LNKSTA,
2, &link_status);
if (link_status & PCI_EXP_LNKSTA_NLW)
link_is_active = true;
......@@ -603,20 +656,21 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
#define PCI_TARGET_LINK_SPEED_MASK 0xf
#define PCI_TARGET_LINK_SPEED_GEN2 0x2
#define PCI_TARGET_LINK_SPEED_GEN1 0x1
pci_bus_read_config_dword(bus, 0,
pos + PCI_EXP_LNKCTL2,
iproc_pci_raw_config_read32(pcie, 0,
pos + PCI_EXP_LNKCTL2, 4,
&link_ctrl);
if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) ==
PCI_TARGET_LINK_SPEED_GEN2) {
link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK;
link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1;
pci_bus_write_config_dword(bus, 0,
pos + PCI_EXP_LNKCTL2,
link_ctrl);
iproc_pci_raw_config_write32(pcie, 0,
pos + PCI_EXP_LNKCTL2,
4, link_ctrl);
msleep(100);
pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA,
&link_status);
iproc_pci_raw_config_read32(pcie, 0,
pos + PCI_EXP_LNKSTA,
2, &link_status);
if (link_status & PCI_EXP_LNKSTA_NLW)
link_is_active = true;
}
......@@ -1205,7 +1259,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
struct device *dev;
int ret;
void *sysdata;
struct pci_bus *bus, *child;
struct pci_bus *child;
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
dev = pcie->dev;
......@@ -1252,18 +1307,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
sysdata = pcie;
#endif
bus = pci_create_root_bus(dev, 0, &iproc_pcie_ops, sysdata, res);
if (!bus) {
dev_err(dev, "unable to create PCI root bus\n");
ret = -ENOMEM;
goto err_power_off_phy;
}
pcie->root_bus = bus;
ret = iproc_pcie_check_link(pcie, bus);
ret = iproc_pcie_check_link(pcie);
if (ret) {
dev_err(dev, "no PCIe EP device detected\n");
goto err_rm_root_bus;
goto err_power_off_phy;
}
iproc_pcie_enable(pcie);
......@@ -1272,23 +1319,31 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
if (iproc_pcie_msi_enable(pcie))
dev_info(dev, "not using iProc MSI\n");
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
list_splice_init(res, &host->windows);
host->busnr = 0;
host->dev.parent = dev;
host->ops = &iproc_pcie_ops;
host->sysdata = sysdata;
host->map_irq = pcie->map_irq;
host->swizzle_irq = pci_common_swizzle;
if (pcie->map_irq)
pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
ret = pci_scan_root_bus_bridge(host);
if (ret < 0) {
dev_err(dev, "failed to scan host: %d\n", ret);
goto err_power_off_phy;
}
list_for_each_entry(child, &bus->children, node)
pci_assign_unassigned_bus_resources(host->bus);
pcie->root_bus = host->bus;
list_for_each_entry(child, &host->bus->children, node)
pcie_bus_configure_settings(child);
pci_bus_add_devices(bus);
pci_bus_add_devices(host->bus);
return 0;
err_rm_root_bus:
pci_stop_root_bus(bus);
pci_remove_root_bus(bus);
err_power_off_phy:
phy_power_off(pcie->phy);
err_exit_phy:
......
This diff is collapsed.
......@@ -450,29 +450,33 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
static int rcar_pcie_enable(struct rcar_pcie *pcie)
{
struct device *dev = pcie->dev;
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
struct pci_bus *bus, *child;
LIST_HEAD(res);
int ret;
/* Try setting 5 GT/s link speed */
rcar_pcie_force_speedup(pcie);
rcar_pcie_setup(&res, pcie);
rcar_pcie_setup(&bridge->windows, pcie);
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
bridge->dev.parent = dev;
bridge->sysdata = pcie;
bridge->busnr = pcie->root_bus_nr;
bridge->ops = &rcar_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
if (IS_ENABLED(CONFIG_PCI_MSI))
bus = pci_scan_root_bus_msi(dev, pcie->root_bus_nr,
&rcar_pcie_ops, pcie, &res, &pcie->msi.chip);
else
bus = pci_scan_root_bus(dev, pcie->root_bus_nr,
&rcar_pcie_ops, pcie, &res);
bridge->msi = &pcie->msi.chip;
if (!bus) {
dev_err(dev, "Scanning rootbus failed");
return -ENODEV;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0) {
kfree(bridge);
return ret;
}
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
bus = bridge->bus;
pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus);
......@@ -1127,11 +1131,14 @@ static int rcar_pcie_probe(struct platform_device *pdev)
unsigned int data;
int err;
int (*hw_init_fn)(struct rcar_pcie *);
struct pci_host_bridge *bridge;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
bridge = pci_alloc_host_bridge(sizeof(*pcie));
if (!bridge)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev;
INIT_LIST_HEAD(&pcie->resources);
......@@ -1141,12 +1148,12 @@ static int rcar_pcie_probe(struct platform_device *pdev)
err = rcar_pcie_get_resources(pcie);
if (err < 0) {
dev_err(dev, "failed to request resources: %d\n", err);
return err;
goto err_free_bridge;
}
err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
if (err)
return err;
goto err_free_bridge;
pm_runtime_enable(dev);
err = pm_runtime_get_sync(dev);
......@@ -1183,6 +1190,9 @@ 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);
......
......@@ -139,6 +139,7 @@
PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \
PCIE_CORE_INT_MMVC)
#define PCIE_RC_CONFIG_NORMAL_BASE 0x800000
#define PCIE_RC_CONFIG_BASE 0xa00000
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
#define PCIE_RC_CONFIG_SCC_SHIFT 16
......@@ -146,6 +147,9 @@
#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
#define PCIE_RC_CONFIG_DCR_CSPL_LIMIT 0xff
#define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26
#define PCIE_RC_CONFIG_DCSR (PCIE_RC_CONFIG_BASE + 0xc8)
#define PCIE_RC_CONFIG_DCSR_MPS_MASK GENMASK(7, 5)
#define PCIE_RC_CONFIG_DCSR_MPS_256 (0x1 << 5)
#define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc)
#define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10)
#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0)
......@@ -175,6 +179,8 @@
#define IB_ROOT_PORT_REG_SIZE_SHIFT 3
#define AXI_WRAPPER_IO_WRITE 0x6
#define AXI_WRAPPER_MEM_WRITE 0x2
#define AXI_WRAPPER_TYPE0_CFG 0xa
#define AXI_WRAPPER_TYPE1_CFG 0xb
#define AXI_WRAPPER_NOR_MSG 0xc
#define MAX_AXI_IB_ROOTPORT_REGION_NUM 3
......@@ -198,6 +204,7 @@
#define RC_REGION_0_ADDR_TRANS_H 0x00000000
#define RC_REGION_0_ADDR_TRANS_L 0x00000000
#define RC_REGION_0_PASS_BITS (25 - 1)
#define RC_REGION_0_TYPE_MASK GENMASK(3, 0)
#define MAX_AXI_WRAPPER_REGION_NUM 33
struct rockchip_pcie {
......@@ -295,7 +302,9 @@ static int rockchip_pcie_valid_device(struct rockchip_pcie *rockchip,
static int rockchip_pcie_rd_own_conf(struct rockchip_pcie *rockchip,
int where, int size, u32 *val)
{
void __iomem *addr = rockchip->apb_base + PCIE_RC_CONFIG_BASE + where;
void __iomem *addr;
addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + where;
if (!IS_ALIGNED((uintptr_t)addr, size)) {
*val = 0;
......@@ -319,11 +328,13 @@ static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip,
int where, int size, u32 val)
{
u32 mask, tmp, offset;
void __iomem *addr;
offset = where & ~0x3;
addr = rockchip->apb_base + PCIE_RC_CONFIG_NORMAL_BASE + offset;
if (size == 4) {
writel(val, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
writel(val, addr);
return PCIBIOS_SUCCESSFUL;
}
......@@ -334,13 +345,33 @@ static int rockchip_pcie_wr_own_conf(struct rockchip_pcie *rockchip,
* corrupt RW1C bits in adjacent registers. But the hardware
* doesn't support smaller writes.
*/
tmp = readl(rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset) & mask;
tmp = readl(addr) & mask;
tmp |= val << ((where & 0x3) * 8);
writel(tmp, rockchip->apb_base + PCIE_RC_CONFIG_BASE + offset);
writel(tmp, addr);
return PCIBIOS_SUCCESSFUL;
}
static void rockchip_pcie_cfg_configuration_accesses(
struct rockchip_pcie *rockchip, u32 type)
{
u32 ob_desc_0;
/* Configuration Accesses for region 0 */
rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
rockchip_pcie_write(rockchip,
(RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
PCIE_CORE_OB_REGION_ADDR0);
rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H,
PCIE_CORE_OB_REGION_ADDR1);
ob_desc_0 = rockchip_pcie_read(rockchip, PCIE_CORE_OB_REGION_DESC0);
ob_desc_0 &= ~(RC_REGION_0_TYPE_MASK);
ob_desc_0 |= (type | (0x1 << 23));
rockchip_pcie_write(rockchip, ob_desc_0, PCIE_CORE_OB_REGION_DESC0);
rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1);
}
static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
struct pci_bus *bus, u32 devfn,
int where, int size, u32 *val)
......@@ -355,6 +386,13 @@ static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
return PCIBIOS_BAD_REGISTER_NUMBER;
}
if (bus->parent->number == rockchip->root_bus_nr)
rockchip_pcie_cfg_configuration_accesses(rockchip,
AXI_WRAPPER_TYPE0_CFG);
else
rockchip_pcie_cfg_configuration_accesses(rockchip,
AXI_WRAPPER_TYPE1_CFG);
if (size == 4) {
*val = readl(rockchip->reg_base + busdev);
} else if (size == 2) {
......@@ -379,6 +417,13 @@ static int rockchip_pcie_wr_other_conf(struct rockchip_pcie *rockchip,
if (!IS_ALIGNED(busdev, size))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (bus->parent->number == rockchip->root_bus_nr)
rockchip_pcie_cfg_configuration_accesses(rockchip,
AXI_WRAPPER_TYPE0_CFG);
else
rockchip_pcie_cfg_configuration_accesses(rockchip,
AXI_WRAPPER_TYPE1_CFG);
if (size == 4)
writel(val, rockchip->reg_base + busdev);
else if (size == 2)
......@@ -664,15 +709,10 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP);
}
rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
rockchip_pcie_write(rockchip,
(RC_REGION_0_ADDR_TRANS_L + RC_REGION_0_PASS_BITS),
PCIE_CORE_OB_REGION_ADDR0);
rockchip_pcie_write(rockchip, RC_REGION_0_ADDR_TRANS_H,
PCIE_CORE_OB_REGION_ADDR1);
rockchip_pcie_write(rockchip, 0x0080000a, PCIE_CORE_OB_REGION_DESC0);
rockchip_pcie_write(rockchip, 0x0, PCIE_CORE_OB_REGION_DESC1);
status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCSR);
status &= ~PCIE_RC_CONFIG_DCSR_MPS_MASK;
status |= PCIE_RC_CONFIG_DCSR_MPS_256;
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCSR);
return 0;
}
......@@ -1156,13 +1196,16 @@ static int rockchip_pcie_prog_ib_atu(struct rockchip_pcie *rockchip,
return 0;
}
static int rockchip_cfg_atu(struct rockchip_pcie *rockchip)
static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
{
struct device *dev = rockchip->dev;
int offset;
int err;
int reg_no;
rockchip_pcie_cfg_configuration_accesses(rockchip,
AXI_WRAPPER_TYPE0_CFG);
for (reg_no = 0; reg_no < (rockchip->mem_size >> 20); reg_no++) {
err = rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1,
AXI_WRAPPER_MEM_WRITE,
......@@ -1251,6 +1294,9 @@ static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev)
clk_disable_unprepare(rockchip->aclk_perf_pcie);
clk_disable_unprepare(rockchip->aclk_pcie);
if (!IS_ERR(rockchip->vpcie0v9))
regulator_disable(rockchip->vpcie0v9);
return ret;
}
......@@ -1259,24 +1305,54 @@ static int __maybe_unused rockchip_pcie_resume_noirq(struct device *dev)
struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
int err;
clk_prepare_enable(rockchip->clk_pcie_pm);
clk_prepare_enable(rockchip->hclk_pcie);
clk_prepare_enable(rockchip->aclk_perf_pcie);
clk_prepare_enable(rockchip->aclk_pcie);
if (!IS_ERR(rockchip->vpcie0v9)) {
err = regulator_enable(rockchip->vpcie0v9);
if (err) {
dev_err(dev, "fail to enable vpcie0v9 regulator\n");
return err;
}
}
err = clk_prepare_enable(rockchip->clk_pcie_pm);
if (err)
goto err_pcie_pm;
err = clk_prepare_enable(rockchip->hclk_pcie);
if (err)
goto err_hclk_pcie;
err = clk_prepare_enable(rockchip->aclk_perf_pcie);
if (err)
goto err_aclk_perf_pcie;
err = clk_prepare_enable(rockchip->aclk_pcie);
if (err)
goto err_aclk_pcie;
err = rockchip_pcie_init_port(rockchip);
if (err)
return err;
goto err_pcie_resume;
err = rockchip_cfg_atu(rockchip);
err = rockchip_pcie_cfg_atu(rockchip);
if (err)
return err;
goto err_pcie_resume;
/* Need this to enter L1 again */
rockchip_pcie_update_txcredit_mui(rockchip);
rockchip_pcie_enable_interrupts(rockchip);
return 0;
err_pcie_resume:
clk_disable_unprepare(rockchip->aclk_pcie);
err_aclk_pcie:
clk_disable_unprepare(rockchip->aclk_perf_pcie);
err_aclk_perf_pcie:
clk_disable_unprepare(rockchip->hclk_pcie);
err_hclk_pcie:
clk_disable_unprepare(rockchip->clk_pcie_pm);
err_pcie_pm:
return err;
}
static int rockchip_pcie_probe(struct platform_device *pdev)
......@@ -1284,6 +1360,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
struct rockchip_pcie *rockchip;
struct device *dev = &pdev->dev;
struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
struct resource_entry *win;
resource_size_t io_base;
struct resource *mem;
......@@ -1295,10 +1372,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
if (!dev->of_node)
return -ENODEV;
rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
if (!rockchip)
bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rockchip));
if (!bridge)
return -ENOMEM;
rockchip = pci_host_bridge_priv(bridge);
platform_set_drvdata(pdev, rockchip);
rockchip->dev = dev;
......@@ -1385,22 +1464,30 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
}
}
err = rockchip_cfg_atu(rockchip);
err = rockchip_pcie_cfg_atu(rockchip);
if (err)
goto err_free_res;
rockchip->msg_region = devm_ioremap(rockchip->dev,
rockchip->msg_bus_addr, SZ_1M);
rockchip->msg_region = devm_ioremap(dev, rockchip->msg_bus_addr, SZ_1M);
if (!rockchip->msg_region) {
err = -ENOMEM;
goto err_free_res;
}
bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res);
if (!bus) {
err = -ENOMEM;
list_splice_init(&res, &bridge->windows);
bridge->dev.parent = dev;
bridge->sysdata = rockchip;
bridge->busnr = 0;
bridge->ops = &rockchip_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
err = pci_scan_root_bus_bridge(bridge);
if (!err)
goto err_free_res;
}
bus = bridge->bus;
rockchip->root_bus = bus;
pci_bus_size_bridges(bus);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -539,7 +539,10 @@ static void vmd_detach_resources(struct vmd_dev *vmd)
}
/*
* VMD domains start at 0x1000 to not clash with ACPI _SEG domains.
* VMD domains start at 0x10000 to not clash with ACPI _SEG domains.
* Per ACPI r6.0, sec 6.5.6, _SEG returns an integer, of which the lower
* 16 bits are the PCI Segment Group (domain) number. Other bits are
* currently reserved.
*/
static int vmd_find_free_domain(void)
{
......@@ -710,7 +713,8 @@ static int vmd_probe(struct pci_dev *dev, const struct pci_device_id *id)
INIT_LIST_HEAD(&vmd->irqs[i].irq_list);
err = devm_request_irq(&dev->dev, pci_irq_vector(dev, i),
vmd_irq, 0, "vmd", &vmd->irqs[i]);
vmd_irq, IRQF_NO_THREAD,
"vmd", &vmd->irqs[i]);
if (err)
return err;
}
......@@ -739,10 +743,10 @@ static void vmd_remove(struct pci_dev *dev)
struct vmd_dev *vmd = pci_get_drvdata(dev);
vmd_detach_resources(vmd);
vmd_cleanup_srcu(vmd);
sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
pci_stop_root_bus(vmd->bus);
pci_remove_root_bus(vmd->bus);
vmd_cleanup_srcu(vmd);
vmd_teardown_dma_ops(vmd);
irq_domain_remove(vmd->irq_domain);
}
......
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