diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-06 14:29:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-06 14:29:53 -0500 |
commit | 3c87b791880a2e0dad281c6494b94968d412bfa3 (patch) | |
tree | 7623ef163b20e2c5cc7d85c0b464d28e2aa4c5e3 /drivers/pci | |
parent | 0280d1a099da1d211e76ec47cc0944c993a36316 (diff) | |
parent | 7225107e158241b7e22f15b9f4c3db0b3330984d (diff) |
Merge tag 'pci-v4.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"Resource management:
- Add support for Enhanced Allocation devices (Sean O. Stalley)
- Add Enhanced Allocation register entries (Sean O. Stalley)
- Handle IORESOURCE_PCI_FIXED when sizing resources (David Daney)
- Handle IORESOURCE_PCI_FIXED when assigning resources (David Daney)
- Handle Enhanced Allocation capability for SR-IOV devices (David Daney)
- Clear IORESOURCE_UNSET when reverting to firmware-assigned address (Bjorn Helgaas)
- Make Enhanced Allocation bitmasks more obvious (Bjorn Helgaas)
- Expand Enhanced Allocation BAR output (Bjorn Helgaas)
- Add of_pci_check_probe_only to parse "linux,pci-probe-only" (Marc Zyngier)
- Fix lookup of linux,pci-probe-only property (Marc Zyngier)
- Add sparc mem64 resource parsing for root bus (Yinghai Lu)
PCI device hotplug:
- pciehp: Queue power work requests in dedicated function (Guenter Roeck)
Driver binding:
- Add builtin_pci_driver() to avoid registration boilerplate (Paul Gortmaker)
Virtualization:
- Set SR-IOV NumVFs to zero after enumeration (Alexander Duyck)
- Remove redundant validation of SR-IOV offset/stride registers (Alexander Duyck)
- Remove VFs in reverse order if virtfn_add() fails (Alexander Duyck)
- Reorder pcibios_sriov_disable() (Alexander Duyck)
- Wait 1 second between disabling VFs and clearing NumVFs (Alexander Duyck)
- Fix sriov_enable() error path for pcibios_enable_sriov() failures (Alexander Duyck)
- Enable SR-IOV ARI Capable Hierarchy before reading TotalVFs (Ben Shelton)
- Don't try to restore VF BARs (Wei Yang)
MSI:
- Don't alloc pcibios-irq when MSI is enabled (Joerg Roedel)
- Add msi_controller setup_irqs() method for special multivector setup (Lucas Stach)
- Export all remapped MSIs to sysfs attributes (Romain Bezut)
- Disable MSI on SiS 761 (Ondrej Zary)
AER:
- Clear error status registers during enumeration and restore (Taku Izumi)
Generic host bridge driver:
- Fix lookup of linux,pci-probe-only property (Marc Zyngier)
- Allow multiple hosts with different map_bus() methods (David Daney)
- Pass starting bus number to pci_scan_root_bus() (David Daney)
- Fix address window calculation for non-zero starting bus (David Daney)
Altera host bridge driver:
- Add msi.h to ARM Kbuild (Ley Foon Tan)
- Add Altera PCIe host controller driver (Ley Foon Tan)
- Add Altera PCIe MSI driver (Ley Foon Tan)
APM X-Gene host bridge driver:
- Remove msi_controller assignment (Duc Dang)
Broadcom iProc host bridge driver:
- Fix header comment "Corporation" misspelling (Florian Fainelli)
- Fix code comment to match code (Ray Jui)
- Remove unused struct iproc_pcie.irqs[] (Ray Jui)
- Call pci_fixup_irqs() for ARM64 as well as ARM (Ray Jui)
- Fix PCIe reset logic (Ray Jui)
- Improve link detection logic (Ray Jui)
- Update PCIe device tree bindings (Ray Jui)
- Add outbound mapping support (Ray Jui)
Freescale i.MX6 host bridge driver:
- Return real error code from imx6_add_pcie_port() (Fabio Estevam)
- Add PCIE_PHY_RX_ASIC_OUT_VALID definition (Fabio Estevam)
Freescale Layerscape host bridge driver:
- Remove ls_pcie_establish_link() (Minghuan Lian)
- Ignore PCIe controllers in Endpoint mode (Minghuan Lian)
- Factor out SCFG related function (Minghuan Lian)
- Update ls_add_pcie_port() (Minghuan Lian)
- Remove unused fields from struct ls_pcie (Minghuan Lian)
- Add support for LS1043a and LS2080a (Minghuan Lian)
- Add ls_pcie_msi_host_init() (Minghuan Lian)
HiSilicon host bridge driver:
- Add HiSilicon SoC Hip05 PCIe driver (Zhou Wang)
Marvell MVEBU host bridge driver:
- Return zero for reserved or unimplemented config space (Russell King)
- Use exact config access size; don't read/modify/write (Russell King)
- Use of_get_available_child_count() (Russell King)
- Use for_each_available_child_of_node() to walk child nodes (Russell King)
- Report full node name when reporting a DT error (Russell King)
- Use port->name rather than "PCIe%d.%d" (Russell King)
- Move port parsing and resource claiming to separate function (Russell King)
- Fix memory leaks and refcount leaks (Russell King)
- Split port parsing and resource claiming from port setup (Russell King)
- Use gpio_set_value_cansleep() (Russell King)
- Use devm_kcalloc() to allocate an array (Russell King)
- Use gpio_desc to carry around gpio (Russell King)
- Improve clock/reset handling (Russell King)
- Add PCI Express root complex capability block (Russell King)
- Remove code restricting accesses to slot 0 (Russell King)
NVIDIA Tegra host bridge driver:
- Wrap static pgprot_t initializer with __pgprot() (Ard Biesheuvel)
Renesas R-Car host bridge driver:
- Build pci-rcar-gen2.c only on ARM (Geert Uytterhoeven)
- Build pcie-rcar.c only on ARM (Geert Uytterhoeven)
- Make PCI aware of the I/O resources (Phil Edworthy)
- Remove dependency on ARM-specific struct hw_pci (Phil Edworthy)
- Set root bus nr to that provided in DT (Phil Edworthy)
- Fix I/O offset for multiple host bridges (Phil Edworthy)
ST Microelectronics SPEAr13xx host bridge driver:
- Fix dw_pcie_cfg_read/write() usage (Gabriele Paoloni)
Synopsys DesignWare host bridge driver:
- Make "clocks" and "clock-names" optional DT properties (Bhupesh Sharma)
- Use exact access size in dw_pcie_cfg_read() (Gabriele Paoloni)
- Simplify dw_pcie_cfg_read/write() interfaces (Gabriele Paoloni)
- Require config accesses to be naturally aligned (Gabriele Paoloni)
- Make "num-lanes" an optional DT property (Gabriele Paoloni)
- Move calculation of bus addresses to DRA7xx (Gabriele Paoloni)
- Replace ARM pci_sys_data->align_resource with global function pointer (Gabriele Paoloni)
- Factor out MSI msg setup (Lucas Stach)
- Implement multivector MSI IRQ setup (Lucas Stach)
- Make get_msi_addr() return phys_addr_t, not u32 (Lucas Stach)
- Set up high part of MSI target address (Lucas Stach)
- Fix PORT_LOGIC_LINK_WIDTH_MASK (Zhou Wang)
- Revert "PCI: designware: Program ATU with untranslated address" (Zhou Wang)
- Use of_pci_get_host_bridge_resources() to parse DT (Zhou Wang)
- Make driver arch-agnostic (Zhou Wang)
Miscellaneous:
- Make x86 pci_subsys_init() static (Alexander Kuleshov)
- Turn off Request Attributes to avoid Chelsio T5 Completion erratum (Hariprasad Shenai)"
* tag 'pci-v4.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (94 commits)
PCI: altera: Add Altera PCIe MSI driver
PCI: hisi: Add HiSilicon SoC Hip05 PCIe driver
PCI: layerscape: Add ls_pcie_msi_host_init()
PCI: layerscape: Add support for LS1043a and LS2080a
PCI: layerscape: Remove unused fields from struct ls_pcie
PCI: layerscape: Update ls_add_pcie_port()
PCI: layerscape: Factor out SCFG related function
PCI: layerscape: Ignore PCIe controllers in Endpoint mode
PCI: layerscape: Remove ls_pcie_establish_link()
PCI: designware: Make "clocks" and "clock-names" optional DT properties
PCI: designware: Make driver arch-agnostic
ARM/PCI: Replace pci_sys_data->align_resource with global function pointer
PCI: designware: Use of_pci_get_host_bridge_resources() to parse DT
Revert "PCI: designware: Program ATU with untranslated address"
PCI: designware: Move calculation of bus addresses to DRA7xx
PCI: designware: Make "num-lanes" an optional DT property
PCI: designware: Require config accesses to be naturally aligned
PCI: designware: Simplify dw_pcie_cfg_read/write() interfaces
PCI: designware: Use exact access size in dw_pcie_cfg_read()
PCI: spear: Fix dw_pcie_cfg_read/write() usage
...
Diffstat (limited to 'drivers/pci')
33 files changed, 2561 insertions, 640 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index d5e58bae95cf..f131ba947dc6 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -39,7 +39,8 @@ config PCI_TEGRA | |||
39 | 39 | ||
40 | config PCI_RCAR_GEN2 | 40 | config PCI_RCAR_GEN2 |
41 | bool "Renesas R-Car Gen2 Internal PCI controller" | 41 | bool "Renesas R-Car Gen2 Internal PCI controller" |
42 | depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST) | 42 | depends on ARM |
43 | depends on ARCH_SHMOBILE || COMPILE_TEST | ||
43 | help | 44 | help |
44 | Say Y here if you want internal PCI support on R-Car Gen2 SoC. | 45 | Say Y here if you want internal PCI support on R-Car Gen2 SoC. |
45 | There are 3 internal PCI controllers available with a single | 46 | There are 3 internal PCI controllers available with a single |
@@ -47,7 +48,8 @@ config PCI_RCAR_GEN2 | |||
47 | 48 | ||
48 | config PCI_RCAR_GEN2_PCIE | 49 | config PCI_RCAR_GEN2_PCIE |
49 | bool "Renesas R-Car PCIe controller" | 50 | bool "Renesas R-Car PCIe controller" |
50 | depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST) | 51 | depends on ARM |
52 | depends on ARCH_SHMOBILE || COMPILE_TEST | ||
51 | help | 53 | help |
52 | Say Y here if you want PCIe controller support on R-Car Gen2 SoCs. | 54 | Say Y here if you want PCIe controller support on R-Car Gen2 SoCs. |
53 | 55 | ||
@@ -105,7 +107,7 @@ config PCI_XGENE_MSI | |||
105 | 107 | ||
106 | config PCI_LAYERSCAPE | 108 | config PCI_LAYERSCAPE |
107 | bool "Freescale Layerscape PCIe controller" | 109 | bool "Freescale Layerscape PCIe controller" |
108 | depends on OF && ARM | 110 | depends on OF && (ARM || ARCH_LAYERSCAPE) |
109 | select PCIE_DW | 111 | select PCIE_DW |
110 | select MFD_SYSCON | 112 | select MFD_SYSCON |
111 | help | 113 | help |
@@ -145,4 +147,29 @@ config PCIE_IPROC_BCMA | |||
145 | Say Y here if you want to use the Broadcom iProc PCIe controller | 147 | Say Y here if you want to use the Broadcom iProc PCIe controller |
146 | through the BCMA bus interface | 148 | through the BCMA bus interface |
147 | 149 | ||
150 | config PCIE_ALTERA | ||
151 | bool "Altera PCIe controller" | ||
152 | depends on ARM || NIOS2 | ||
153 | depends on OF_PCI | ||
154 | select PCI_DOMAINS | ||
155 | help | ||
156 | Say Y here if you want to enable PCIe controller support on Altera | ||
157 | FPGA. | ||
158 | |||
159 | config PCIE_ALTERA_MSI | ||
160 | bool "Altera PCIe MSI feature" | ||
161 | depends on PCIE_ALTERA && PCI_MSI | ||
162 | select PCI_MSI_IRQ_DOMAIN | ||
163 | help | ||
164 | Say Y here if you want PCIe MSI support for the Altera FPGA. | ||
165 | This MSI driver supports Altera MSI to GIC controller IP. | ||
166 | |||
167 | config PCI_HISI | ||
168 | depends on OF && ARM64 | ||
169 | bool "HiSilicon SoC HIP05 PCIe controller" | ||
170 | select PCIEPORTBUS | ||
171 | select PCIE_DW | ||
172 | help | ||
173 | Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC | ||
174 | |||
148 | endmenu | 175 | endmenu |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 140d66f796e4..9d4d3c6924a1 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -17,3 +17,6 @@ obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o | |||
17 | obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o | 17 | obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o |
18 | obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o | 18 | obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o |
19 | obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o | 19 | obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o |
20 | obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o | ||
21 | obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o | ||
22 | obj-$(CONFIG_PCI_HISI) += pcie-hisi.o | ||
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c index 199e29a044cd..8c3688046c02 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/host/pci-dra7xx.c | |||
@@ -62,6 +62,7 @@ | |||
62 | 62 | ||
63 | #define PCIECTRL_DRA7XX_CONF_PHY_CS 0x010C | 63 | #define PCIECTRL_DRA7XX_CONF_PHY_CS 0x010C |
64 | #define LINK_UP BIT(16) | 64 | #define LINK_UP BIT(16) |
65 | #define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF | ||
65 | 66 | ||
66 | struct dra7xx_pcie { | 67 | struct dra7xx_pcie { |
67 | void __iomem *base; | 68 | void __iomem *base; |
@@ -151,6 +152,12 @@ static void dra7xx_pcie_enable_interrupts(struct pcie_port *pp) | |||
151 | static void dra7xx_pcie_host_init(struct pcie_port *pp) | 152 | static void dra7xx_pcie_host_init(struct pcie_port *pp) |
152 | { | 153 | { |
153 | dw_pcie_setup_rc(pp); | 154 | dw_pcie_setup_rc(pp); |
155 | |||
156 | pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||
157 | pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||
158 | pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||
159 | pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR; | ||
160 | |||
154 | dra7xx_pcie_establish_link(pp); | 161 | dra7xx_pcie_establish_link(pp); |
155 | if (IS_ENABLED(CONFIG_PCI_MSI)) | 162 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
156 | dw_pcie_msi_init(pp); | 163 | dw_pcie_msi_init(pp); |
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index f9f468d9a819..01095e1160a4 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c | |||
@@ -454,7 +454,7 @@ static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | |||
454 | int ret; | 454 | int ret; |
455 | 455 | ||
456 | exynos_pcie_sideband_dbi_r_mode(pp, true); | 456 | exynos_pcie_sideband_dbi_r_mode(pp, true); |
457 | ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, size, val); | 457 | ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val); |
458 | exynos_pcie_sideband_dbi_r_mode(pp, false); | 458 | exynos_pcie_sideband_dbi_r_mode(pp, false); |
459 | return ret; | 459 | return ret; |
460 | } | 460 | } |
@@ -465,8 +465,7 @@ static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | |||
465 | int ret; | 465 | int ret; |
466 | 466 | ||
467 | exynos_pcie_sideband_dbi_w_mode(pp, true); | 467 | exynos_pcie_sideband_dbi_w_mode(pp, true); |
468 | ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), | 468 | ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val); |
469 | where, size, val); | ||
470 | exynos_pcie_sideband_dbi_w_mode(pp, false); | 469 | exynos_pcie_sideband_dbi_w_mode(pp, false); |
471 | return ret; | 470 | return ret; |
472 | } | 471 | } |
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c index 265dd25169bf..5434c90db243 100644 --- a/drivers/pci/host/pci-host-generic.c +++ b/drivers/pci/host/pci-host-generic.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | struct gen_pci_cfg_bus_ops { | 28 | struct gen_pci_cfg_bus_ops { |
29 | u32 bus_shift; | 29 | u32 bus_shift; |
30 | void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int); | 30 | struct pci_ops ops; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct gen_pci_cfg_windows { | 33 | struct gen_pci_cfg_windows { |
@@ -35,7 +35,7 @@ struct gen_pci_cfg_windows { | |||
35 | struct resource *bus_range; | 35 | struct resource *bus_range; |
36 | void __iomem **win; | 36 | void __iomem **win; |
37 | 37 | ||
38 | const struct gen_pci_cfg_bus_ops *ops; | 38 | struct gen_pci_cfg_bus_ops *ops; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -65,7 +65,11 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, | |||
65 | 65 | ||
66 | static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = { | 66 | static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = { |
67 | .bus_shift = 16, | 67 | .bus_shift = 16, |
68 | .map_bus = gen_pci_map_cfg_bus_cam, | 68 | .ops = { |
69 | .map_bus = gen_pci_map_cfg_bus_cam, | ||
70 | .read = pci_generic_config_read, | ||
71 | .write = pci_generic_config_write, | ||
72 | } | ||
69 | }; | 73 | }; |
70 | 74 | ||
71 | static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, | 75 | static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, |
@@ -80,12 +84,11 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, | |||
80 | 84 | ||
81 | static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = { | 85 | static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = { |
82 | .bus_shift = 20, | 86 | .bus_shift = 20, |
83 | .map_bus = gen_pci_map_cfg_bus_ecam, | 87 | .ops = { |
84 | }; | 88 | .map_bus = gen_pci_map_cfg_bus_ecam, |
85 | 89 | .read = pci_generic_config_read, | |
86 | static struct pci_ops gen_pci_ops = { | 90 | .write = pci_generic_config_write, |
87 | .read = pci_generic_config_read, | 91 | } |
88 | .write = pci_generic_config_write, | ||
89 | }; | 92 | }; |
90 | 93 | ||
91 | static const struct of_device_id gen_pci_of_match[] = { | 94 | static const struct of_device_id gen_pci_of_match[] = { |
@@ -166,6 +169,7 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) | |||
166 | struct resource *bus_range; | 169 | struct resource *bus_range; |
167 | struct device *dev = pci->host.dev.parent; | 170 | struct device *dev = pci->host.dev.parent; |
168 | struct device_node *np = dev->of_node; | 171 | struct device_node *np = dev->of_node; |
172 | u32 sz = 1 << pci->cfg.ops->bus_shift; | ||
169 | 173 | ||
170 | err = of_address_to_resource(np, 0, &pci->cfg.res); | 174 | err = of_address_to_resource(np, 0, &pci->cfg.res); |
171 | if (err) { | 175 | if (err) { |
@@ -193,10 +197,9 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) | |||
193 | bus_range = pci->cfg.bus_range; | 197 | bus_range = pci->cfg.bus_range; |
194 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { | 198 | for (busn = bus_range->start; busn <= bus_range->end; ++busn) { |
195 | u32 idx = busn - bus_range->start; | 199 | u32 idx = busn - bus_range->start; |
196 | u32 sz = 1 << pci->cfg.ops->bus_shift; | ||
197 | 200 | ||
198 | pci->cfg.win[idx] = devm_ioremap(dev, | 201 | pci->cfg.win[idx] = devm_ioremap(dev, |
199 | pci->cfg.res.start + busn * sz, | 202 | pci->cfg.res.start + idx * sz, |
200 | sz); | 203 | sz); |
201 | if (!pci->cfg.win[idx]) | 204 | if (!pci->cfg.win[idx]) |
202 | return -ENOMEM; | 205 | return -ENOMEM; |
@@ -210,7 +213,6 @@ static int gen_pci_probe(struct platform_device *pdev) | |||
210 | int err; | 213 | int err; |
211 | const char *type; | 214 | const char *type; |
212 | const struct of_device_id *of_id; | 215 | const struct of_device_id *of_id; |
213 | const int *prop; | ||
214 | struct device *dev = &pdev->dev; | 216 | struct device *dev = &pdev->dev; |
215 | struct device_node *np = dev->of_node; | 217 | struct device_node *np = dev->of_node; |
216 | struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); | 218 | struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); |
@@ -225,17 +227,10 @@ static int gen_pci_probe(struct platform_device *pdev) | |||
225 | return -EINVAL; | 227 | return -EINVAL; |
226 | } | 228 | } |
227 | 229 | ||
228 | prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL); | 230 | of_pci_check_probe_only(); |
229 | if (prop) { | ||
230 | if (*prop) | ||
231 | pci_add_flags(PCI_PROBE_ONLY); | ||
232 | else | ||
233 | pci_clear_flags(PCI_PROBE_ONLY); | ||
234 | } | ||
235 | 231 | ||
236 | of_id = of_match_node(gen_pci_of_match, np); | 232 | of_id = of_match_node(gen_pci_of_match, np); |
237 | pci->cfg.ops = of_id->data; | 233 | pci->cfg.ops = (struct gen_pci_cfg_bus_ops *)of_id->data; |
238 | gen_pci_ops.map_bus = pci->cfg.ops->map_bus; | ||
239 | pci->host.dev.parent = dev; | 234 | pci->host.dev.parent = dev; |
240 | INIT_LIST_HEAD(&pci->host.windows); | 235 | INIT_LIST_HEAD(&pci->host.windows); |
241 | INIT_LIST_HEAD(&pci->resources); | 236 | INIT_LIST_HEAD(&pci->resources); |
@@ -256,7 +251,9 @@ static int gen_pci_probe(struct platform_device *pdev) | |||
256 | if (!pci_has_flag(PCI_PROBE_ONLY)) | 251 | if (!pci_has_flag(PCI_PROBE_ONLY)) |
257 | pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); | 252 | pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); |
258 | 253 | ||
259 | bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources); | 254 | |
255 | bus = pci_scan_root_bus(dev, pci->cfg.bus_range->start, | ||
256 | &pci->cfg.ops->ops, pci, &pci->resources); | ||
260 | if (!bus) { | 257 | if (!bus) { |
261 | dev_err(dev, "Scanning rootbus failed"); | 258 | dev_err(dev, "Scanning rootbus failed"); |
262 | return -ENODEV; | 259 | return -ENODEV; |
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 8f3a9813c4e5..22e8224126fd 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -74,6 +74,7 @@ struct imx6_pcie { | |||
74 | 74 | ||
75 | /* PHY registers (not memory-mapped) */ | 75 | /* PHY registers (not memory-mapped) */ |
76 | #define PCIE_PHY_RX_ASIC_OUT 0x100D | 76 | #define PCIE_PHY_RX_ASIC_OUT 0x100D |
77 | #define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) | ||
77 | 78 | ||
78 | #define PHY_RX_OVRD_IN_LO 0x1005 | 79 | #define PHY_RX_OVRD_IN_LO 0x1005 |
79 | #define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) | 80 | #define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) |
@@ -503,7 +504,7 @@ static int imx6_pcie_link_up(struct pcie_port *pp) | |||
503 | pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); | 504 | pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); |
504 | debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0); | 505 | debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0); |
505 | 506 | ||
506 | if (rx_valid & 0x01) | 507 | if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID) |
507 | return 0; | 508 | return 0; |
508 | 509 | ||
509 | if ((debug_r0 & 0x3f) != 0x0d) | 510 | if ((debug_r0 & 0x3f) != 0x0d) |
@@ -539,7 +540,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp, | |||
539 | IRQF_SHARED, "mx6-pcie-msi", pp); | 540 | IRQF_SHARED, "mx6-pcie-msi", pp); |
540 | if (ret) { | 541 | if (ret) { |
541 | dev_err(&pdev->dev, "failed to request MSI irq\n"); | 542 | dev_err(&pdev->dev, "failed to request MSI irq\n"); |
542 | return -ENODEV; | 543 | return ret; |
543 | } | 544 | } |
544 | } | 545 | } |
545 | 546 | ||
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c index e71da991949b..ed34c9520a02 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/host/pci-keystone-dw.c | |||
@@ -70,7 +70,7 @@ static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset, | |||
70 | *bit_pos = offset >> 3; | 70 | *bit_pos = offset >> 3; |
71 | } | 71 | } |
72 | 72 | ||
73 | u32 ks_dw_pcie_get_msi_addr(struct pcie_port *pp) | 73 | phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp) |
74 | { | 74 | { |
75 | struct keystone_pcie *ks_pcie = to_keystone_pcie(pp); | 75 | struct keystone_pcie *ks_pcie = to_keystone_pcie(pp); |
76 | 76 | ||
@@ -322,7 +322,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt) | |||
322 | void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) | 322 | void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) |
323 | { | 323 | { |
324 | struct pcie_port *pp = &ks_pcie->pp; | 324 | struct pcie_port *pp = &ks_pcie->pp; |
325 | u32 start = pp->mem.start, end = pp->mem.end; | 325 | u32 start = pp->mem->start, end = pp->mem->end; |
326 | int i, tr_size; | 326 | int i, tr_size; |
327 | 327 | ||
328 | /* Disable BARs for inbound access */ | 328 | /* Disable BARs for inbound access */ |
@@ -398,7 +398,7 @@ int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
398 | 398 | ||
399 | addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn); | 399 | addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn); |
400 | 400 | ||
401 | return dw_pcie_cfg_read(addr + (where & ~0x3), where, size, val); | 401 | return dw_pcie_cfg_read(addr + where, size, val); |
402 | } | 402 | } |
403 | 403 | ||
404 | int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, | 404 | int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, |
@@ -410,7 +410,7 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
410 | 410 | ||
411 | addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn); | 411 | addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn); |
412 | 412 | ||
413 | return dw_pcie_cfg_write(addr + (where & ~0x3), where, size, val); | 413 | return dw_pcie_cfg_write(addr + where, size, val); |
414 | } | 414 | } |
415 | 415 | ||
416 | /** | 416 | /** |
diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/host/pci-keystone.h index 478d932b602d..f0944e8c4b02 100644 --- a/drivers/pci/host/pci-keystone.h +++ b/drivers/pci/host/pci-keystone.h | |||
@@ -37,7 +37,7 @@ struct keystone_pcie { | |||
37 | 37 | ||
38 | /* Keystone DW specific MSI controller APIs/definitions */ | 38 | /* Keystone DW specific MSI controller APIs/definitions */ |
39 | void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset); | 39 | void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset); |
40 | u32 ks_dw_pcie_get_msi_addr(struct pcie_port *pp); | 40 | phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp); |
41 | 41 | ||
42 | /* Keystone specific PCI controller APIs */ | 42 | /* Keystone specific PCI controller APIs */ |
43 | void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie); | 43 | void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie); |
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c index b2328ea13dcf..3923bed93c7e 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/host/pci-layerscape.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2014 Freescale Semiconductor. | 4 | * Copyright (C) 2014 Freescale Semiconductor. |
5 | * | 5 | * |
6 | * Author: Minghuan Lian <Minghuan.Lian@freescale.com> | 6 | * Author: Minghuan Lian <Minghuan.Lian@freescale.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/delay.h> | ||
15 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/of_pci.h> | 16 | #include <linux/of_pci.h> |
@@ -32,27 +31,60 @@ | |||
32 | #define LTSSM_STATE_MASK 0x3f | 31 | #define LTSSM_STATE_MASK 0x3f |
33 | #define LTSSM_PCIE_L0 0x11 /* L0 state */ | 32 | #define LTSSM_PCIE_L0 0x11 /* L0 state */ |
34 | 33 | ||
35 | /* Symbol Timer Register and Filter Mask Register 1 */ | 34 | /* PEX Internal Configuration Registers */ |
36 | #define PCIE_STRFMR1 0x71c | 35 | #define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */ |
36 | #define PCIE_DBI_RO_WR_EN 0x8bc /* DBI Read-Only Write Enable Register */ | ||
37 | |||
38 | /* PEX LUT registers */ | ||
39 | #define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug Register */ | ||
40 | |||
41 | struct ls_pcie_drvdata { | ||
42 | u32 lut_offset; | ||
43 | u32 ltssm_shift; | ||
44 | struct pcie_host_ops *ops; | ||
45 | }; | ||
37 | 46 | ||
38 | struct ls_pcie { | 47 | struct ls_pcie { |
39 | struct list_head node; | ||
40 | struct device *dev; | ||
41 | struct pci_bus *bus; | ||
42 | void __iomem *dbi; | 48 | void __iomem *dbi; |
49 | void __iomem *lut; | ||
43 | struct regmap *scfg; | 50 | struct regmap *scfg; |
44 | struct pcie_port pp; | 51 | struct pcie_port pp; |
52 | const struct ls_pcie_drvdata *drvdata; | ||
45 | int index; | 53 | int index; |
46 | int msi_irq; | ||
47 | }; | 54 | }; |
48 | 55 | ||
49 | #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) | 56 | #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) |
50 | 57 | ||
51 | static int ls_pcie_link_up(struct pcie_port *pp) | 58 | static bool ls_pcie_is_bridge(struct ls_pcie *pcie) |
59 | { | ||
60 | u32 header_type; | ||
61 | |||
62 | header_type = ioread8(pcie->dbi + PCI_HEADER_TYPE); | ||
63 | header_type &= 0x7f; | ||
64 | |||
65 | return header_type == PCI_HEADER_TYPE_BRIDGE; | ||
66 | } | ||
67 | |||
68 | /* Clear multi-function bit */ | ||
69 | static void ls_pcie_clear_multifunction(struct ls_pcie *pcie) | ||
70 | { | ||
71 | iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE); | ||
72 | } | ||
73 | |||
74 | /* Fix class value */ | ||
75 | static void ls_pcie_fix_class(struct ls_pcie *pcie) | ||
76 | { | ||
77 | iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE); | ||
78 | } | ||
79 | |||
80 | static int ls1021_pcie_link_up(struct pcie_port *pp) | ||
52 | { | 81 | { |
53 | u32 state; | 82 | u32 state; |
54 | struct ls_pcie *pcie = to_ls_pcie(pp); | 83 | struct ls_pcie *pcie = to_ls_pcie(pp); |
55 | 84 | ||
85 | if (!pcie->scfg) | ||
86 | return 0; | ||
87 | |||
56 | regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); | 88 | regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); |
57 | state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; | 89 | state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; |
58 | 90 | ||
@@ -62,27 +94,27 @@ static int ls_pcie_link_up(struct pcie_port *pp) | |||
62 | return 1; | 94 | return 1; |
63 | } | 95 | } |
64 | 96 | ||
65 | static int ls_pcie_establish_link(struct pcie_port *pp) | 97 | static void ls1021_pcie_host_init(struct pcie_port *pp) |
66 | { | 98 | { |
67 | unsigned int retries; | 99 | struct ls_pcie *pcie = to_ls_pcie(pp); |
100 | u32 val, index[2]; | ||
68 | 101 | ||
69 | for (retries = 0; retries < 200; retries++) { | 102 | pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node, |
70 | if (dw_pcie_link_up(pp)) | 103 | "fsl,pcie-scfg"); |
71 | return 0; | 104 | if (IS_ERR(pcie->scfg)) { |
72 | usleep_range(100, 1000); | 105 | dev_err(pp->dev, "No syscfg phandle specified\n"); |
106 | pcie->scfg = NULL; | ||
107 | return; | ||
73 | } | 108 | } |
74 | 109 | ||
75 | dev_err(pp->dev, "phy link never came up\n"); | 110 | if (of_property_read_u32_array(pp->dev->of_node, |
76 | return -EINVAL; | 111 | "fsl,pcie-scfg", index, 2)) { |
77 | } | 112 | pcie->scfg = NULL; |
78 | 113 | return; | |
79 | static void ls_pcie_host_init(struct pcie_port *pp) | 114 | } |
80 | { | 115 | pcie->index = index[1]; |
81 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
82 | u32 val; | ||
83 | 116 | ||
84 | dw_pcie_setup_rc(pp); | 117 | dw_pcie_setup_rc(pp); |
85 | ls_pcie_establish_link(pp); | ||
86 | 118 | ||
87 | /* | 119 | /* |
88 | * LS1021A Workaround for internal TKT228622 | 120 | * LS1021A Workaround for internal TKT228622 |
@@ -93,21 +125,97 @@ static void ls_pcie_host_init(struct pcie_port *pp) | |||
93 | iowrite32(val, pcie->dbi + PCIE_STRFMR1); | 125 | iowrite32(val, pcie->dbi + PCIE_STRFMR1); |
94 | } | 126 | } |
95 | 127 | ||
128 | static int ls_pcie_link_up(struct pcie_port *pp) | ||
129 | { | ||
130 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
131 | u32 state; | ||
132 | |||
133 | state = (ioread32(pcie->lut + PCIE_LUT_DBG) >> | ||
134 | pcie->drvdata->ltssm_shift) & | ||
135 | LTSSM_STATE_MASK; | ||
136 | |||
137 | if (state < LTSSM_PCIE_L0) | ||
138 | return 0; | ||
139 | |||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | static void ls_pcie_host_init(struct pcie_port *pp) | ||
144 | { | ||
145 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
146 | |||
147 | iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN); | ||
148 | ls_pcie_fix_class(pcie); | ||
149 | ls_pcie_clear_multifunction(pcie); | ||
150 | iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN); | ||
151 | } | ||
152 | |||
153 | static int ls_pcie_msi_host_init(struct pcie_port *pp, | ||
154 | struct msi_controller *chip) | ||
155 | { | ||
156 | struct device_node *msi_node; | ||
157 | struct device_node *np = pp->dev->of_node; | ||
158 | |||
159 | /* | ||
160 | * The MSI domain is set by the generic of_msi_configure(). This | ||
161 | * .msi_host_init() function keeps us from doing the default MSI | ||
162 | * domain setup in dw_pcie_host_init() and also enforces the | ||
163 | * requirement that "msi-parent" exists. | ||
164 | */ | ||
165 | msi_node = of_parse_phandle(np, "msi-parent", 0); | ||
166 | if (!msi_node) { | ||
167 | dev_err(pp->dev, "failed to find msi-parent\n"); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct pcie_host_ops ls1021_pcie_host_ops = { | ||
175 | .link_up = ls1021_pcie_link_up, | ||
176 | .host_init = ls1021_pcie_host_init, | ||
177 | .msi_host_init = ls_pcie_msi_host_init, | ||
178 | }; | ||
179 | |||
96 | static struct pcie_host_ops ls_pcie_host_ops = { | 180 | static struct pcie_host_ops ls_pcie_host_ops = { |
97 | .link_up = ls_pcie_link_up, | 181 | .link_up = ls_pcie_link_up, |
98 | .host_init = ls_pcie_host_init, | 182 | .host_init = ls_pcie_host_init, |
183 | .msi_host_init = ls_pcie_msi_host_init, | ||
184 | }; | ||
185 | |||
186 | static struct ls_pcie_drvdata ls1021_drvdata = { | ||
187 | .ops = &ls1021_pcie_host_ops, | ||
188 | }; | ||
189 | |||
190 | static struct ls_pcie_drvdata ls1043_drvdata = { | ||
191 | .lut_offset = 0x10000, | ||
192 | .ltssm_shift = 24, | ||
193 | .ops = &ls_pcie_host_ops, | ||
99 | }; | 194 | }; |
100 | 195 | ||
101 | static int ls_add_pcie_port(struct ls_pcie *pcie) | 196 | static struct ls_pcie_drvdata ls2080_drvdata = { |
197 | .lut_offset = 0x80000, | ||
198 | .ltssm_shift = 0, | ||
199 | .ops = &ls_pcie_host_ops, | ||
200 | }; | ||
201 | |||
202 | static const struct of_device_id ls_pcie_of_match[] = { | ||
203 | { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, | ||
204 | { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, | ||
205 | { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, | ||
206 | { }, | ||
207 | }; | ||
208 | MODULE_DEVICE_TABLE(of, ls_pcie_of_match); | ||
209 | |||
210 | static int __init ls_add_pcie_port(struct pcie_port *pp, | ||
211 | struct platform_device *pdev) | ||
102 | { | 212 | { |
103 | struct pcie_port *pp; | ||
104 | int ret; | 213 | int ret; |
214 | struct ls_pcie *pcie = to_ls_pcie(pp); | ||
105 | 215 | ||
106 | pp = &pcie->pp; | 216 | pp->dev = &pdev->dev; |
107 | pp->dev = pcie->dev; | ||
108 | pp->dbi_base = pcie->dbi; | 217 | pp->dbi_base = pcie->dbi; |
109 | pp->root_bus_nr = -1; | 218 | pp->ops = pcie->drvdata->ops; |
110 | pp->ops = &ls_pcie_host_ops; | ||
111 | 219 | ||
112 | ret = dw_pcie_host_init(pp); | 220 | ret = dw_pcie_host_init(pp); |
113 | if (ret) { | 221 | if (ret) { |
@@ -120,17 +228,19 @@ static int ls_add_pcie_port(struct ls_pcie *pcie) | |||
120 | 228 | ||
121 | static int __init ls_pcie_probe(struct platform_device *pdev) | 229 | static int __init ls_pcie_probe(struct platform_device *pdev) |
122 | { | 230 | { |
231 | const struct of_device_id *match; | ||
123 | struct ls_pcie *pcie; | 232 | struct ls_pcie *pcie; |
124 | struct resource *dbi_base; | 233 | struct resource *dbi_base; |
125 | u32 index[2]; | ||
126 | int ret; | 234 | int ret; |
127 | 235 | ||
236 | match = of_match_device(ls_pcie_of_match, &pdev->dev); | ||
237 | if (!match) | ||
238 | return -ENODEV; | ||
239 | |||
128 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | 240 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); |
129 | if (!pcie) | 241 | if (!pcie) |
130 | return -ENOMEM; | 242 | return -ENOMEM; |
131 | 243 | ||
132 | pcie->dev = &pdev->dev; | ||
133 | |||
134 | dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); | 244 | dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); |
135 | pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); | 245 | pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); |
136 | if (IS_ERR(pcie->dbi)) { | 246 | if (IS_ERR(pcie->dbi)) { |
@@ -138,20 +248,13 @@ static int __init ls_pcie_probe(struct platform_device *pdev) | |||
138 | return PTR_ERR(pcie->dbi); | 248 | return PTR_ERR(pcie->dbi); |
139 | } | 249 | } |
140 | 250 | ||
141 | pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | 251 | pcie->drvdata = match->data; |
142 | "fsl,pcie-scfg"); | 252 | pcie->lut = pcie->dbi + pcie->drvdata->lut_offset; |
143 | if (IS_ERR(pcie->scfg)) { | ||
144 | dev_err(&pdev->dev, "No syscfg phandle specified\n"); | ||
145 | return PTR_ERR(pcie->scfg); | ||
146 | } | ||
147 | 253 | ||
148 | ret = of_property_read_u32_array(pdev->dev.of_node, | 254 | if (!ls_pcie_is_bridge(pcie)) |
149 | "fsl,pcie-scfg", index, 2); | 255 | return -ENODEV; |
150 | if (ret) | ||
151 | return ret; | ||
152 | pcie->index = index[1]; | ||
153 | 256 | ||
154 | ret = ls_add_pcie_port(pcie); | 257 | ret = ls_add_pcie_port(&pcie->pp, pdev); |
155 | if (ret < 0) | 258 | if (ret < 0) |
156 | return ret; | 259 | return ret; |
157 | 260 | ||
@@ -160,12 +263,6 @@ static int __init ls_pcie_probe(struct platform_device *pdev) | |||
160 | return 0; | 263 | return 0; |
161 | } | 264 | } |
162 | 265 | ||
163 | static const struct of_device_id ls_pcie_of_match[] = { | ||
164 | { .compatible = "fsl,ls1021a-pcie" }, | ||
165 | { }, | ||
166 | }; | ||
167 | MODULE_DEVICE_TABLE(of, ls_pcie_of_match); | ||
168 | |||
169 | static struct platform_driver ls_pcie_driver = { | 266 | static struct platform_driver ls_pcie_driver = { |
170 | .driver = { | 267 | .driver = { |
171 | .name = "layerscape-pcie", | 268 | .name = "layerscape-pcie", |
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 67ec5e1c99db..53b79c5f0559 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #define PCIE_DEV_REV_OFF 0x0008 | 30 | #define PCIE_DEV_REV_OFF 0x0008 |
31 | #define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3)) | 31 | #define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3)) |
32 | #define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3)) | 32 | #define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3)) |
33 | #define PCIE_CAP_PCIEXP 0x0060 | ||
33 | #define PCIE_HEADER_LOG_4_OFF 0x0128 | 34 | #define PCIE_HEADER_LOG_4_OFF 0x0128 |
34 | #define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4)) | 35 | #define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4)) |
35 | #define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4)) | 36 | #define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4)) |
@@ -57,14 +58,35 @@ | |||
57 | #define PCIE_STAT_BUS 0xff00 | 58 | #define PCIE_STAT_BUS 0xff00 |
58 | #define PCIE_STAT_DEV 0x1f0000 | 59 | #define PCIE_STAT_DEV 0x1f0000 |
59 | #define PCIE_STAT_LINK_DOWN BIT(0) | 60 | #define PCIE_STAT_LINK_DOWN BIT(0) |
61 | #define PCIE_RC_RTSTA 0x1a14 | ||
60 | #define PCIE_DEBUG_CTRL 0x1a60 | 62 | #define PCIE_DEBUG_CTRL 0x1a60 |
61 | #define PCIE_DEBUG_SOFT_RESET BIT(20) | 63 | #define PCIE_DEBUG_SOFT_RESET BIT(20) |
62 | 64 | ||
65 | enum { | ||
66 | PCISWCAP = PCI_BRIDGE_CONTROL + 2, | ||
67 | PCISWCAP_EXP_LIST_ID = PCISWCAP + PCI_CAP_LIST_ID, | ||
68 | PCISWCAP_EXP_DEVCAP = PCISWCAP + PCI_EXP_DEVCAP, | ||
69 | PCISWCAP_EXP_DEVCTL = PCISWCAP + PCI_EXP_DEVCTL, | ||
70 | PCISWCAP_EXP_LNKCAP = PCISWCAP + PCI_EXP_LNKCAP, | ||
71 | PCISWCAP_EXP_LNKCTL = PCISWCAP + PCI_EXP_LNKCTL, | ||
72 | PCISWCAP_EXP_SLTCAP = PCISWCAP + PCI_EXP_SLTCAP, | ||
73 | PCISWCAP_EXP_SLTCTL = PCISWCAP + PCI_EXP_SLTCTL, | ||
74 | PCISWCAP_EXP_RTCTL = PCISWCAP + PCI_EXP_RTCTL, | ||
75 | PCISWCAP_EXP_RTSTA = PCISWCAP + PCI_EXP_RTSTA, | ||
76 | PCISWCAP_EXP_DEVCAP2 = PCISWCAP + PCI_EXP_DEVCAP2, | ||
77 | PCISWCAP_EXP_DEVCTL2 = PCISWCAP + PCI_EXP_DEVCTL2, | ||
78 | PCISWCAP_EXP_LNKCAP2 = PCISWCAP + PCI_EXP_LNKCAP2, | ||
79 | PCISWCAP_EXP_LNKCTL2 = PCISWCAP + PCI_EXP_LNKCTL2, | ||
80 | PCISWCAP_EXP_SLTCAP2 = PCISWCAP + PCI_EXP_SLTCAP2, | ||
81 | PCISWCAP_EXP_SLTCTL2 = PCISWCAP + PCI_EXP_SLTCTL2, | ||
82 | }; | ||
83 | |||
63 | /* PCI configuration space of a PCI-to-PCI bridge */ | 84 | /* PCI configuration space of a PCI-to-PCI bridge */ |
64 | struct mvebu_sw_pci_bridge { | 85 | struct mvebu_sw_pci_bridge { |
65 | u16 vendor; | 86 | u16 vendor; |
66 | u16 device; | 87 | u16 device; |
67 | u16 command; | 88 | u16 command; |
89 | u16 status; | ||
68 | u16 class; | 90 | u16 class; |
69 | u8 interface; | 91 | u8 interface; |
70 | u8 revision; | 92 | u8 revision; |
@@ -84,13 +106,15 @@ struct mvebu_sw_pci_bridge { | |||
84 | u16 memlimit; | 106 | u16 memlimit; |
85 | u16 iobaseupper; | 107 | u16 iobaseupper; |
86 | u16 iolimitupper; | 108 | u16 iolimitupper; |
87 | u8 cappointer; | ||
88 | u8 reserved1; | ||
89 | u16 reserved2; | ||
90 | u32 romaddr; | 109 | u32 romaddr; |
91 | u8 intline; | 110 | u8 intline; |
92 | u8 intpin; | 111 | u8 intpin; |
93 | u16 bridgectrl; | 112 | u16 bridgectrl; |
113 | |||
114 | /* PCI express capability */ | ||
115 | u32 pcie_sltcap; | ||
116 | u16 pcie_devctl; | ||
117 | u16 pcie_rtctl; | ||
94 | }; | 118 | }; |
95 | 119 | ||
96 | struct mvebu_pcie_port; | 120 | struct mvebu_pcie_port; |
@@ -119,8 +143,7 @@ struct mvebu_pcie_port { | |||
119 | unsigned int io_target; | 143 | unsigned int io_target; |
120 | unsigned int io_attr; | 144 | unsigned int io_attr; |
121 | struct clk *clk; | 145 | struct clk *clk; |
122 | int reset_gpio; | 146 | struct gpio_desc *reset_gpio; |
123 | int reset_active_low; | ||
124 | char *reset_name; | 147 | char *reset_name; |
125 | struct mvebu_sw_pci_bridge bridge; | 148 | struct mvebu_sw_pci_bridge bridge; |
126 | struct device_node *dn; | 149 | struct device_node *dn; |
@@ -254,15 +277,22 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port, | |||
254 | struct pci_bus *bus, | 277 | struct pci_bus *bus, |
255 | u32 devfn, int where, int size, u32 *val) | 278 | u32 devfn, int where, int size, u32 *val) |
256 | { | 279 | { |
280 | void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF; | ||
281 | |||
257 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), | 282 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), |
258 | PCIE_CONF_ADDR_OFF); | 283 | PCIE_CONF_ADDR_OFF); |
259 | 284 | ||
260 | *val = mvebu_readl(port, PCIE_CONF_DATA_OFF); | 285 | switch (size) { |
261 | 286 | case 1: | |
262 | if (size == 1) | 287 | *val = readb_relaxed(conf_data + (where & 3)); |
263 | *val = (*val >> (8 * (where & 3))) & 0xff; | 288 | break; |
264 | else if (size == 2) | 289 | case 2: |
265 | *val = (*val >> (8 * (where & 3))) & 0xffff; | 290 | *val = readw_relaxed(conf_data + (where & 2)); |
291 | break; | ||
292 | case 4: | ||
293 | *val = readl_relaxed(conf_data); | ||
294 | break; | ||
295 | } | ||
266 | 296 | ||
267 | return PCIBIOS_SUCCESSFUL; | 297 | return PCIBIOS_SUCCESSFUL; |
268 | } | 298 | } |
@@ -271,22 +301,24 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port, | |||
271 | struct pci_bus *bus, | 301 | struct pci_bus *bus, |
272 | u32 devfn, int where, int size, u32 val) | 302 | u32 devfn, int where, int size, u32 val) |
273 | { | 303 | { |
274 | u32 _val, shift = 8 * (where & 3); | 304 | void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF; |
275 | 305 | ||
276 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), | 306 | mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), |
277 | PCIE_CONF_ADDR_OFF); | 307 | PCIE_CONF_ADDR_OFF); |
278 | _val = mvebu_readl(port, PCIE_CONF_DATA_OFF); | ||
279 | 308 | ||
280 | if (size == 4) | 309 | switch (size) { |
281 | _val = val; | 310 | case 1: |
282 | else if (size == 2) | 311 | writeb(val, conf_data + (where & 3)); |
283 | _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift); | 312 | break; |
284 | else if (size == 1) | 313 | case 2: |
285 | _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift); | 314 | writew(val, conf_data + (where & 2)); |
286 | else | 315 | break; |
316 | case 4: | ||
317 | writel(val, conf_data); | ||
318 | break; | ||
319 | default: | ||
287 | return PCIBIOS_BAD_REGISTER_NUMBER; | 320 | return PCIBIOS_BAD_REGISTER_NUMBER; |
288 | 321 | } | |
289 | mvebu_writel(port, _val, PCIE_CONF_DATA_OFF); | ||
290 | 322 | ||
291 | return PCIBIOS_SUCCESSFUL; | 323 | return PCIBIOS_SUCCESSFUL; |
292 | } | 324 | } |
@@ -443,6 +475,9 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port) | |||
443 | /* We support 32 bits I/O addressing */ | 475 | /* We support 32 bits I/O addressing */ |
444 | bridge->iobase = PCI_IO_RANGE_TYPE_32; | 476 | bridge->iobase = PCI_IO_RANGE_TYPE_32; |
445 | bridge->iolimit = PCI_IO_RANGE_TYPE_32; | 477 | bridge->iolimit = PCI_IO_RANGE_TYPE_32; |
478 | |||
479 | /* Add capabilities */ | ||
480 | bridge->status = PCI_STATUS_CAP_LIST; | ||
446 | } | 481 | } |
447 | 482 | ||
448 | /* | 483 | /* |
@@ -460,7 +495,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, | |||
460 | break; | 495 | break; |
461 | 496 | ||
462 | case PCI_COMMAND: | 497 | case PCI_COMMAND: |
463 | *value = bridge->command; | 498 | *value = bridge->command | bridge->status << 16; |
464 | break; | 499 | break; |
465 | 500 | ||
466 | case PCI_CLASS_REVISION: | 501 | case PCI_CLASS_REVISION: |
@@ -505,6 +540,10 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, | |||
505 | *value = (bridge->iolimitupper << 16 | bridge->iobaseupper); | 540 | *value = (bridge->iolimitupper << 16 | bridge->iobaseupper); |
506 | break; | 541 | break; |
507 | 542 | ||
543 | case PCI_CAPABILITY_LIST: | ||
544 | *value = PCISWCAP; | ||
545 | break; | ||
546 | |||
508 | case PCI_ROM_ADDRESS1: | 547 | case PCI_ROM_ADDRESS1: |
509 | *value = 0; | 548 | *value = 0; |
510 | break; | 549 | break; |
@@ -514,9 +553,67 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port, | |||
514 | *value = 0; | 553 | *value = 0; |
515 | break; | 554 | break; |
516 | 555 | ||
556 | case PCISWCAP_EXP_LIST_ID: | ||
557 | /* Set PCIe v2, root port, slot support */ | ||
558 | *value = (PCI_EXP_TYPE_ROOT_PORT << 4 | 2 | | ||
559 | PCI_EXP_FLAGS_SLOT) << 16 | PCI_CAP_ID_EXP; | ||
560 | break; | ||
561 | |||
562 | case PCISWCAP_EXP_DEVCAP: | ||
563 | *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCAP); | ||
564 | break; | ||
565 | |||
566 | case PCISWCAP_EXP_DEVCTL: | ||
567 | *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL) & | ||
568 | ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE | | ||
569 | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE); | ||
570 | *value |= bridge->pcie_devctl; | ||
571 | break; | ||
572 | |||
573 | case PCISWCAP_EXP_LNKCAP: | ||
574 | /* | ||
575 | * PCIe requires the clock power management capability to be | ||
576 | * hard-wired to zero for downstream ports | ||
577 | */ | ||
578 | *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCAP) & | ||
579 | ~PCI_EXP_LNKCAP_CLKPM; | ||
580 | break; | ||
581 | |||
582 | case PCISWCAP_EXP_LNKCTL: | ||
583 | *value = mvebu_readl(port, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL); | ||
584 | break; | ||
585 | |||
586 | case PCISWCAP_EXP_SLTCAP: | ||
587 | *value = bridge->pcie_sltcap; | ||
588 | break; | ||
589 | |||
590 | case PCISWCAP_EXP_SLTCTL: | ||
591 | *value = PCI_EXP_SLTSTA_PDS << 16; | ||
592 | break; | ||
593 | |||
594 | case PCISWCAP_EXP_RTCTL: | ||
595 | *value = bridge->pcie_rtctl; | ||
596 | break; | ||
597 | |||
598 | case PCISWCAP_EXP_RTSTA: | ||
599 | *value = mvebu_readl(port, PCIE_RC_RTSTA); | ||
600 | break; | ||
601 | |||
602 | /* PCIe requires the v2 fields to be hard-wired to zero */ | ||
603 | case PCISWCAP_EXP_DEVCAP2: | ||
604 | case PCISWCAP_EXP_DEVCTL2: | ||
605 | case PCISWCAP_EXP_LNKCAP2: | ||
606 | case PCISWCAP_EXP_LNKCTL2: | ||
607 | case PCISWCAP_EXP_SLTCAP2: | ||
608 | case PCISWCAP_EXP_SLTCTL2: | ||
517 | default: | 609 | default: |
518 | *value = 0xffffffff; | 610 | /* |
519 | return PCIBIOS_BAD_REGISTER_NUMBER; | 611 | * PCI defines configuration read accesses to reserved or |
612 | * unimplemented registers to read as zero and complete | ||
613 | * normally. | ||
614 | */ | ||
615 | *value = 0; | ||
616 | return PCIBIOS_SUCCESSFUL; | ||
520 | } | 617 | } |
521 | 618 | ||
522 | if (size == 2) | 619 | if (size == 2) |
@@ -601,6 +698,51 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port, | |||
601 | mvebu_pcie_set_local_bus_nr(port, bridge->secondary_bus); | 698 | mvebu_pcie_set_local_bus_nr(port, bridge->secondary_bus); |
602 | break; | 699 | break; |
603 | 700 | ||
701 | case PCISWCAP_EXP_DEVCTL: | ||
702 | /* | ||
703 | * Armada370 data says these bits must always | ||
704 | * be zero when in root complex mode. | ||
705 | */ | ||
706 | value &= ~(PCI_EXP_DEVCTL_URRE | PCI_EXP_DEVCTL_FERE | | ||
707 | PCI_EXP_DEVCTL_NFERE | PCI_EXP_DEVCTL_CERE); | ||
708 | |||
709 | /* | ||
710 | * If the mask is 0xffff0000, then we only want to write | ||
711 | * the device control register, rather than clearing the | ||
712 | * RW1C bits in the device status register. Mask out the | ||
713 | * status register bits. | ||
714 | */ | ||
715 | if (mask == 0xffff0000) | ||
716 | value &= 0xffff; | ||
717 | |||
718 | mvebu_writel(port, value, PCIE_CAP_PCIEXP + PCI_EXP_DEVCTL); | ||
719 | break; | ||
720 | |||
721 | case PCISWCAP_EXP_LNKCTL: | ||
722 | /* | ||
723 | * If we don't support CLKREQ, we must ensure that the | ||
724 | * CLKREQ enable bit always reads zero. Since we haven't | ||
725 | * had this capability, and it's dependent on board wiring, | ||
726 | * disable it for the time being. | ||
727 | */ | ||
728 | value &= ~PCI_EXP_LNKCTL_CLKREQ_EN; | ||
729 | |||
730 | /* | ||
731 | * If the mask is 0xffff0000, then we only want to write | ||
732 | * the link control register, rather than clearing the | ||
733 | * RW1C bits in the link status register. Mask out the | ||
734 | * status register bits. | ||
735 | */ | ||
736 | if (mask == 0xffff0000) | ||
737 | value &= 0xffff; | ||
738 | |||
739 | mvebu_writel(port, value, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL); | ||
740 | break; | ||
741 | |||
742 | case PCISWCAP_EXP_RTSTA: | ||
743 | mvebu_writel(port, value, PCIE_RC_RTSTA); | ||
744 | break; | ||
745 | |||
604 | default: | 746 | default: |
605 | break; | 747 | break; |
606 | } | 748 | } |
@@ -652,17 +794,6 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | |||
652 | if (!mvebu_pcie_link_up(port)) | 794 | if (!mvebu_pcie_link_up(port)) |
653 | return PCIBIOS_DEVICE_NOT_FOUND; | 795 | return PCIBIOS_DEVICE_NOT_FOUND; |
654 | 796 | ||
655 | /* | ||
656 | * On the secondary bus, we don't want to expose any other | ||
657 | * device than the device physically connected in the PCIe | ||
658 | * slot, visible in slot 0. In slot 1, there's a special | ||
659 | * Marvell device that only makes sense when the Armada is | ||
660 | * used as a PCIe endpoint. | ||
661 | */ | ||
662 | if (bus->number == port->bridge.secondary_bus && | ||
663 | PCI_SLOT(devfn) != 0) | ||
664 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
665 | |||
666 | /* Access the real PCIe interface */ | 797 | /* Access the real PCIe interface */ |
667 | ret = mvebu_pcie_hw_wr_conf(port, bus, devfn, | 798 | ret = mvebu_pcie_hw_wr_conf(port, bus, devfn, |
668 | where, size, val); | 799 | where, size, val); |
@@ -693,19 +824,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
693 | return PCIBIOS_DEVICE_NOT_FOUND; | 824 | return PCIBIOS_DEVICE_NOT_FOUND; |
694 | } | 825 | } |
695 | 826 | ||
696 | /* | ||
697 | * On the secondary bus, we don't want to expose any other | ||
698 | * device than the device physically connected in the PCIe | ||
699 | * slot, visible in slot 0. In slot 1, there's a special | ||
700 | * Marvell device that only makes sense when the Armada is | ||
701 | * used as a PCIe endpoint. | ||
702 | */ | ||
703 | if (bus->number == port->bridge.secondary_bus && | ||
704 | PCI_SLOT(devfn) != 0) { | ||
705 | *val = 0xffffffff; | ||
706 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
707 | } | ||
708 | |||
709 | /* Access the real PCIe interface */ | 827 | /* Access the real PCIe interface */ |
710 | ret = mvebu_pcie_hw_rd_conf(port, bus, devfn, | 828 | ret = mvebu_pcie_hw_rd_conf(port, bus, devfn, |
711 | where, size, val); | 829 | where, size, val); |
@@ -914,12 +1032,167 @@ static int mvebu_pcie_resume(struct device *dev) | |||
914 | return 0; | 1032 | return 0; |
915 | } | 1033 | } |
916 | 1034 | ||
1035 | static void mvebu_pcie_port_clk_put(void *data) | ||
1036 | { | ||
1037 | struct mvebu_pcie_port *port = data; | ||
1038 | |||
1039 | clk_put(port->clk); | ||
1040 | } | ||
1041 | |||
1042 | static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, | ||
1043 | struct mvebu_pcie_port *port, struct device_node *child) | ||
1044 | { | ||
1045 | struct device *dev = &pcie->pdev->dev; | ||
1046 | enum of_gpio_flags flags; | ||
1047 | int reset_gpio, ret; | ||
1048 | |||
1049 | port->pcie = pcie; | ||
1050 | |||
1051 | if (of_property_read_u32(child, "marvell,pcie-port", &port->port)) { | ||
1052 | dev_warn(dev, "ignoring %s, missing pcie-port property\n", | ||
1053 | of_node_full_name(child)); | ||
1054 | goto skip; | ||
1055 | } | ||
1056 | |||
1057 | if (of_property_read_u32(child, "marvell,pcie-lane", &port->lane)) | ||
1058 | port->lane = 0; | ||
1059 | |||
1060 | port->name = devm_kasprintf(dev, GFP_KERNEL, "pcie%d.%d", port->port, | ||
1061 | port->lane); | ||
1062 | if (!port->name) { | ||
1063 | ret = -ENOMEM; | ||
1064 | goto err; | ||
1065 | } | ||
1066 | |||
1067 | port->devfn = of_pci_get_devfn(child); | ||
1068 | if (port->devfn < 0) | ||
1069 | goto skip; | ||
1070 | |||
1071 | ret = mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_MEM, | ||
1072 | &port->mem_target, &port->mem_attr); | ||
1073 | if (ret < 0) { | ||
1074 | dev_err(dev, "%s: cannot get tgt/attr for mem window\n", | ||
1075 | port->name); | ||
1076 | goto skip; | ||
1077 | } | ||
1078 | |||
1079 | if (resource_size(&pcie->io) != 0) { | ||
1080 | mvebu_get_tgt_attr(dev->of_node, port->devfn, IORESOURCE_IO, | ||
1081 | &port->io_target, &port->io_attr); | ||
1082 | } else { | ||
1083 | port->io_target = -1; | ||
1084 | port->io_attr = -1; | ||
1085 | } | ||
1086 | |||
1087 | reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags); | ||
1088 | if (reset_gpio == -EPROBE_DEFER) { | ||
1089 | ret = reset_gpio; | ||
1090 | goto err; | ||
1091 | } | ||
1092 | |||
1093 | if (gpio_is_valid(reset_gpio)) { | ||
1094 | unsigned long gpio_flags; | ||
1095 | |||
1096 | port->reset_name = devm_kasprintf(dev, GFP_KERNEL, "%s-reset", | ||
1097 | port->name); | ||
1098 | if (!port->reset_name) { | ||
1099 | ret = -ENOMEM; | ||
1100 | goto err; | ||
1101 | } | ||
1102 | |||
1103 | if (flags & OF_GPIO_ACTIVE_LOW) { | ||
1104 | dev_info(dev, "%s: reset gpio is active low\n", | ||
1105 | of_node_full_name(child)); | ||
1106 | gpio_flags = GPIOF_ACTIVE_LOW | | ||
1107 | GPIOF_OUT_INIT_LOW; | ||
1108 | } else { | ||
1109 | gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
1110 | } | ||
1111 | |||
1112 | ret = devm_gpio_request_one(dev, reset_gpio, gpio_flags, | ||
1113 | port->reset_name); | ||
1114 | if (ret) { | ||
1115 | if (ret == -EPROBE_DEFER) | ||
1116 | goto err; | ||
1117 | goto skip; | ||
1118 | } | ||
1119 | |||
1120 | port->reset_gpio = gpio_to_desc(reset_gpio); | ||
1121 | } | ||
1122 | |||
1123 | port->clk = of_clk_get_by_name(child, NULL); | ||
1124 | if (IS_ERR(port->clk)) { | ||
1125 | dev_err(dev, "%s: cannot get clock\n", port->name); | ||
1126 | goto skip; | ||
1127 | } | ||
1128 | |||
1129 | ret = devm_add_action(dev, mvebu_pcie_port_clk_put, port); | ||
1130 | if (ret < 0) { | ||
1131 | clk_put(port->clk); | ||
1132 | goto err; | ||
1133 | } | ||
1134 | |||
1135 | return 1; | ||
1136 | |||
1137 | skip: | ||
1138 | ret = 0; | ||
1139 | |||
1140 | /* In the case of skipping, we need to free these */ | ||
1141 | devm_kfree(dev, port->reset_name); | ||
1142 | port->reset_name = NULL; | ||
1143 | devm_kfree(dev, port->name); | ||
1144 | port->name = NULL; | ||
1145 | |||
1146 | err: | ||
1147 | return ret; | ||
1148 | } | ||
1149 | |||
1150 | /* | ||
1151 | * Power up a PCIe port. PCIe requires the refclk to be stable for 100µs | ||
1152 | * prior to releasing PERST. See table 2-4 in section 2.6.2 AC Specifications | ||
1153 | * of the PCI Express Card Electromechanical Specification, 1.1. | ||
1154 | */ | ||
1155 | static int mvebu_pcie_powerup(struct mvebu_pcie_port *port) | ||
1156 | { | ||
1157 | int ret; | ||
1158 | |||
1159 | ret = clk_prepare_enable(port->clk); | ||
1160 | if (ret < 0) | ||
1161 | return ret; | ||
1162 | |||
1163 | if (port->reset_gpio) { | ||
1164 | u32 reset_udelay = 20000; | ||
1165 | |||
1166 | of_property_read_u32(port->dn, "reset-delay-us", | ||
1167 | &reset_udelay); | ||
1168 | |||
1169 | udelay(100); | ||
1170 | |||
1171 | gpiod_set_value_cansleep(port->reset_gpio, 0); | ||
1172 | msleep(reset_udelay / 1000); | ||
1173 | } | ||
1174 | |||
1175 | return 0; | ||
1176 | } | ||
1177 | |||
1178 | /* | ||
1179 | * Power down a PCIe port. Strictly, PCIe requires us to place the card | ||
1180 | * in D3hot state before asserting PERST#. | ||
1181 | */ | ||
1182 | static void mvebu_pcie_powerdown(struct mvebu_pcie_port *port) | ||
1183 | { | ||
1184 | if (port->reset_gpio) | ||
1185 | gpiod_set_value_cansleep(port->reset_gpio, 1); | ||
1186 | |||
1187 | clk_disable_unprepare(port->clk); | ||
1188 | } | ||
1189 | |||
917 | static int mvebu_pcie_probe(struct platform_device *pdev) | 1190 | static int mvebu_pcie_probe(struct platform_device *pdev) |
918 | { | 1191 | { |
919 | struct mvebu_pcie *pcie; | 1192 | struct mvebu_pcie *pcie; |
920 | struct device_node *np = pdev->dev.of_node; | 1193 | struct device_node *np = pdev->dev.of_node; |
921 | struct device_node *child; | 1194 | struct device_node *child; |
922 | int i, ret; | 1195 | int num, i, ret; |
923 | 1196 | ||
924 | pcie = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pcie), | 1197 | pcie = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pcie), |
925 | GFP_KERNEL); | 1198 | GFP_KERNEL); |
@@ -955,112 +1228,52 @@ static int mvebu_pcie_probe(struct platform_device *pdev) | |||
955 | return ret; | 1228 | return ret; |
956 | } | 1229 | } |
957 | 1230 | ||
958 | i = 0; | 1231 | num = of_get_available_child_count(pdev->dev.of_node); |
959 | for_each_child_of_node(pdev->dev.of_node, child) { | ||
960 | if (!of_device_is_available(child)) | ||
961 | continue; | ||
962 | i++; | ||
963 | } | ||
964 | 1232 | ||
965 | pcie->ports = devm_kzalloc(&pdev->dev, i * | 1233 | pcie->ports = devm_kcalloc(&pdev->dev, num, sizeof(*pcie->ports), |
966 | sizeof(struct mvebu_pcie_port), | ||
967 | GFP_KERNEL); | 1234 | GFP_KERNEL); |
968 | if (!pcie->ports) | 1235 | if (!pcie->ports) |
969 | return -ENOMEM; | 1236 | return -ENOMEM; |
970 | 1237 | ||
971 | i = 0; | 1238 | i = 0; |
972 | for_each_child_of_node(pdev->dev.of_node, child) { | 1239 | for_each_available_child_of_node(pdev->dev.of_node, child) { |
973 | struct mvebu_pcie_port *port = &pcie->ports[i]; | 1240 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
974 | enum of_gpio_flags flags; | ||
975 | |||
976 | if (!of_device_is_available(child)) | ||
977 | continue; | ||
978 | 1241 | ||
979 | port->pcie = pcie; | 1242 | ret = mvebu_pcie_parse_port(pcie, port, child); |
980 | |||
981 | if (of_property_read_u32(child, "marvell,pcie-port", | ||
982 | &port->port)) { | ||
983 | dev_warn(&pdev->dev, | ||
984 | "ignoring PCIe DT node, missing pcie-port property\n"); | ||
985 | continue; | ||
986 | } | ||
987 | |||
988 | if (of_property_read_u32(child, "marvell,pcie-lane", | ||
989 | &port->lane)) | ||
990 | port->lane = 0; | ||
991 | |||
992 | port->name = kasprintf(GFP_KERNEL, "pcie%d.%d", | ||
993 | port->port, port->lane); | ||
994 | |||
995 | port->devfn = of_pci_get_devfn(child); | ||
996 | if (port->devfn < 0) | ||
997 | continue; | ||
998 | |||
999 | ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM, | ||
1000 | &port->mem_target, &port->mem_attr); | ||
1001 | if (ret < 0) { | 1243 | if (ret < 0) { |
1002 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n", | 1244 | of_node_put(child); |
1003 | port->port, port->lane); | 1245 | return ret; |
1246 | } else if (ret == 0) { | ||
1004 | continue; | 1247 | continue; |
1005 | } | 1248 | } |
1006 | 1249 | ||
1007 | if (resource_size(&pcie->io) != 0) | 1250 | port->dn = child; |
1008 | mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, | 1251 | i++; |
1009 | &port->io_target, &port->io_attr); | 1252 | } |
1010 | else { | 1253 | pcie->nports = i; |
1011 | port->io_target = -1; | ||
1012 | port->io_attr = -1; | ||
1013 | } | ||
1014 | 1254 | ||
1015 | port->reset_gpio = of_get_named_gpio_flags(child, | 1255 | for (i = 0; i < pcie->nports; i++) { |
1016 | "reset-gpios", 0, &flags); | 1256 | struct mvebu_pcie_port *port = &pcie->ports[i]; |
1017 | if (gpio_is_valid(port->reset_gpio)) { | ||
1018 | u32 reset_udelay = 20000; | ||
1019 | |||
1020 | port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
1021 | port->reset_name = kasprintf(GFP_KERNEL, | ||
1022 | "pcie%d.%d-reset", port->port, port->lane); | ||
1023 | of_property_read_u32(child, "reset-delay-us", | ||
1024 | &reset_udelay); | ||
1025 | |||
1026 | ret = devm_gpio_request_one(&pdev->dev, | ||
1027 | port->reset_gpio, GPIOF_DIR_OUT, port->reset_name); | ||
1028 | if (ret) { | ||
1029 | if (ret == -EPROBE_DEFER) | ||
1030 | return ret; | ||
1031 | continue; | ||
1032 | } | ||
1033 | |||
1034 | gpio_set_value(port->reset_gpio, | ||
1035 | (port->reset_active_low) ? 1 : 0); | ||
1036 | msleep(reset_udelay/1000); | ||
1037 | } | ||
1038 | 1257 | ||
1039 | port->clk = of_clk_get_by_name(child, NULL); | 1258 | child = port->dn; |
1040 | if (IS_ERR(port->clk)) { | 1259 | if (!child) |
1041 | dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", | ||
1042 | port->port, port->lane); | ||
1043 | continue; | 1260 | continue; |
1044 | } | ||
1045 | 1261 | ||
1046 | ret = clk_prepare_enable(port->clk); | 1262 | ret = mvebu_pcie_powerup(port); |
1047 | if (ret) | 1263 | if (ret < 0) |
1048 | continue; | 1264 | continue; |
1049 | 1265 | ||
1050 | port->base = mvebu_pcie_map_registers(pdev, child, port); | 1266 | port->base = mvebu_pcie_map_registers(pdev, child, port); |
1051 | if (IS_ERR(port->base)) { | 1267 | if (IS_ERR(port->base)) { |
1052 | dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n", | 1268 | dev_err(&pdev->dev, "%s: cannot map registers\n", |
1053 | port->port, port->lane); | 1269 | port->name); |
1054 | port->base = NULL; | 1270 | port->base = NULL; |
1055 | clk_disable_unprepare(port->clk); | 1271 | mvebu_pcie_powerdown(port); |
1056 | continue; | 1272 | continue; |
1057 | } | 1273 | } |
1058 | 1274 | ||
1059 | mvebu_pcie_set_local_dev_nr(port, 1); | 1275 | mvebu_pcie_set_local_dev_nr(port, 1); |
1060 | |||
1061 | port->dn = child; | ||
1062 | mvebu_sw_pci_bridge_init(port); | 1276 | mvebu_sw_pci_bridge_init(port); |
1063 | i++; | ||
1064 | } | 1277 | } |
1065 | 1278 | ||
1066 | pcie->nports = i; | 1279 | pcie->nports = i; |
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 81df0c1fe063..3018ae52e092 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
@@ -382,8 +382,8 @@ static unsigned long tegra_pcie_conf_offset(unsigned int devfn, int where) | |||
382 | static struct tegra_pcie_bus *tegra_pcie_bus_alloc(struct tegra_pcie *pcie, | 382 | static struct tegra_pcie_bus *tegra_pcie_bus_alloc(struct tegra_pcie *pcie, |
383 | unsigned int busnr) | 383 | unsigned int busnr) |
384 | { | 384 | { |
385 | pgprot_t prot = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_XN | | 385 | pgprot_t prot = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
386 | L_PTE_MT_DEV_SHARED | L_PTE_SHARED; | 386 | L_PTE_XN | L_PTE_MT_DEV_SHARED | L_PTE_SHARED); |
387 | phys_addr_t cs = pcie->cs->start; | 387 | phys_addr_t cs = pcie->cs->start; |
388 | struct tegra_pcie_bus *bus; | 388 | struct tegra_pcie_bus *bus; |
389 | unsigned int i; | 389 | unsigned int i; |
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c index 0236ab9d5720..ae00ce22d5a6 100644 --- a/drivers/pci/host/pci-xgene.c +++ b/drivers/pci/host/pci-xgene.c | |||
@@ -509,24 +509,6 @@ static int xgene_pcie_setup(struct xgene_pcie_port *port, | |||
509 | return 0; | 509 | return 0; |
510 | } | 510 | } |
511 | 511 | ||
512 | static int xgene_pcie_msi_enable(struct pci_bus *bus) | ||
513 | { | ||
514 | struct device_node *msi_node; | ||
515 | |||
516 | msi_node = of_parse_phandle(bus->dev.of_node, | ||
517 | "msi-parent", 0); | ||
518 | if (!msi_node) | ||
519 | return -ENODEV; | ||
520 | |||
521 | bus->msi = of_pci_find_msi_chip_by_node(msi_node); | ||
522 | if (!bus->msi) | ||
523 | return -ENODEV; | ||
524 | |||
525 | of_node_put(msi_node); | ||
526 | bus->msi->dev = &bus->dev; | ||
527 | return 0; | ||
528 | } | ||
529 | |||
530 | static int xgene_pcie_probe_bridge(struct platform_device *pdev) | 512 | static int xgene_pcie_probe_bridge(struct platform_device *pdev) |
531 | { | 513 | { |
532 | struct device_node *dn = pdev->dev.of_node; | 514 | struct device_node *dn = pdev->dev.of_node; |
@@ -567,10 +549,6 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) | |||
567 | if (!bus) | 549 | if (!bus) |
568 | return -ENOMEM; | 550 | return -ENOMEM; |
569 | 551 | ||
570 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
571 | if (xgene_pcie_msi_enable(bus)) | ||
572 | dev_info(port->dev, "failed to enable MSI\n"); | ||
573 | |||
574 | pci_scan_child_bus(bus); | 552 | pci_scan_child_bus(bus); |
575 | pci_assign_unassigned_bus_resources(bus); | 553 | pci_assign_unassigned_bus_resources(bus); |
576 | pci_bus_add_devices(bus); | 554 | pci_bus_add_devices(bus); |
diff --git a/drivers/pci/host/pcie-altera-msi.c b/drivers/pci/host/pcie-altera-msi.c new file mode 100644 index 000000000000..99177f4ccde2 --- /dev/null +++ b/drivers/pci/host/pcie-altera-msi.c | |||
@@ -0,0 +1,314 @@ | |||
1 | /* | ||
2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/irqchip/chained_irq.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/msi.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | #include <linux/of_pci.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #define MSI_STATUS 0x0 | ||
29 | #define MSI_ERROR 0x4 | ||
30 | #define MSI_INTMASK 0x8 | ||
31 | |||
32 | #define MAX_MSI_VECTORS 32 | ||
33 | |||
34 | struct altera_msi { | ||
35 | DECLARE_BITMAP(used, MAX_MSI_VECTORS); | ||
36 | struct mutex lock; /* protect "used" bitmap */ | ||
37 | struct platform_device *pdev; | ||
38 | struct irq_domain *msi_domain; | ||
39 | struct irq_domain *inner_domain; | ||
40 | void __iomem *csr_base; | ||
41 | void __iomem *vector_base; | ||
42 | phys_addr_t vector_phy; | ||
43 | u32 num_of_vectors; | ||
44 | int irq; | ||
45 | }; | ||
46 | |||
47 | static inline void msi_writel(struct altera_msi *msi, const u32 value, | ||
48 | const u32 reg) | ||
49 | { | ||
50 | writel_relaxed(value, msi->csr_base + reg); | ||
51 | } | ||
52 | |||
53 | static inline u32 msi_readl(struct altera_msi *msi, const u32 reg) | ||
54 | { | ||
55 | return readl_relaxed(msi->csr_base + reg); | ||
56 | } | ||
57 | |||
58 | static void altera_msi_isr(struct irq_desc *desc) | ||
59 | { | ||
60 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
61 | struct altera_msi *msi; | ||
62 | unsigned long status; | ||
63 | u32 num_of_vectors; | ||
64 | u32 bit; | ||
65 | u32 virq; | ||
66 | |||
67 | chained_irq_enter(chip, desc); | ||
68 | msi = irq_desc_get_handler_data(desc); | ||
69 | num_of_vectors = msi->num_of_vectors; | ||
70 | |||
71 | while ((status = msi_readl(msi, MSI_STATUS)) != 0) { | ||
72 | for_each_set_bit(bit, &status, msi->num_of_vectors) { | ||
73 | /* Dummy read from vector to clear the interrupt */ | ||
74 | readl_relaxed(msi->vector_base + (bit * sizeof(u32))); | ||
75 | |||
76 | virq = irq_find_mapping(msi->inner_domain, bit); | ||
77 | if (virq) | ||
78 | generic_handle_irq(virq); | ||
79 | else | ||
80 | dev_err(&msi->pdev->dev, "unexpected MSI\n"); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | chained_irq_exit(chip, desc); | ||
85 | } | ||
86 | |||
87 | static struct irq_chip altera_msi_irq_chip = { | ||
88 | .name = "Altera PCIe MSI", | ||
89 | .irq_mask = pci_msi_mask_irq, | ||
90 | .irq_unmask = pci_msi_unmask_irq, | ||
91 | }; | ||
92 | |||
93 | static struct msi_domain_info altera_msi_domain_info = { | ||
94 | .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | | ||
95 | MSI_FLAG_PCI_MSIX), | ||
96 | .chip = &altera_msi_irq_chip, | ||
97 | }; | ||
98 | |||
99 | static void altera_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) | ||
100 | { | ||
101 | struct altera_msi *msi = irq_data_get_irq_chip_data(data); | ||
102 | phys_addr_t addr = msi->vector_phy + (data->hwirq * sizeof(u32)); | ||
103 | |||
104 | msg->address_lo = lower_32_bits(addr); | ||
105 | msg->address_hi = upper_32_bits(addr); | ||
106 | msg->data = data->hwirq; | ||
107 | |||
108 | dev_dbg(&msi->pdev->dev, "msi#%d address_hi %#x address_lo %#x\n", | ||
109 | (int)data->hwirq, msg->address_hi, msg->address_lo); | ||
110 | } | ||
111 | |||
112 | static int altera_msi_set_affinity(struct irq_data *irq_data, | ||
113 | const struct cpumask *mask, bool force) | ||
114 | { | ||
115 | return -EINVAL; | ||
116 | } | ||
117 | |||
118 | static struct irq_chip altera_msi_bottom_irq_chip = { | ||
119 | .name = "Altera MSI", | ||
120 | .irq_compose_msi_msg = altera_compose_msi_msg, | ||
121 | .irq_set_affinity = altera_msi_set_affinity, | ||
122 | }; | ||
123 | |||
124 | static int altera_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, | ||
125 | unsigned int nr_irqs, void *args) | ||
126 | { | ||
127 | struct altera_msi *msi = domain->host_data; | ||
128 | unsigned long bit; | ||
129 | u32 mask; | ||
130 | |||
131 | WARN_ON(nr_irqs != 1); | ||
132 | mutex_lock(&msi->lock); | ||
133 | |||
134 | bit = find_first_zero_bit(msi->used, msi->num_of_vectors); | ||
135 | if (bit >= msi->num_of_vectors) { | ||
136 | mutex_unlock(&msi->lock); | ||
137 | return -ENOSPC; | ||
138 | } | ||
139 | |||
140 | set_bit(bit, msi->used); | ||
141 | |||
142 | mutex_unlock(&msi->lock); | ||
143 | |||
144 | irq_domain_set_info(domain, virq, bit, &altera_msi_bottom_irq_chip, | ||
145 | domain->host_data, handle_simple_irq, | ||
146 | NULL, NULL); | ||
147 | |||
148 | mask = msi_readl(msi, MSI_INTMASK); | ||
149 | mask |= 1 << bit; | ||
150 | msi_writel(msi, mask, MSI_INTMASK); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static void altera_irq_domain_free(struct irq_domain *domain, | ||
156 | unsigned int virq, unsigned int nr_irqs) | ||
157 | { | ||
158 | struct irq_data *d = irq_domain_get_irq_data(domain, virq); | ||
159 | struct altera_msi *msi = irq_data_get_irq_chip_data(d); | ||
160 | u32 mask; | ||
161 | |||
162 | mutex_lock(&msi->lock); | ||
163 | |||
164 | if (!test_bit(d->hwirq, msi->used)) { | ||
165 | dev_err(&msi->pdev->dev, "trying to free unused MSI#%lu\n", | ||
166 | d->hwirq); | ||
167 | } else { | ||
168 | __clear_bit(d->hwirq, msi->used); | ||
169 | mask = msi_readl(msi, MSI_INTMASK); | ||
170 | mask &= ~(1 << d->hwirq); | ||
171 | msi_writel(msi, mask, MSI_INTMASK); | ||
172 | } | ||
173 | |||
174 | mutex_unlock(&msi->lock); | ||
175 | } | ||
176 | |||
177 | static const struct irq_domain_ops msi_domain_ops = { | ||
178 | .alloc = altera_irq_domain_alloc, | ||
179 | .free = altera_irq_domain_free, | ||
180 | }; | ||
181 | |||
182 | static int altera_allocate_domains(struct altera_msi *msi) | ||
183 | { | ||
184 | struct fwnode_handle *fwnode = of_node_to_fwnode(msi->pdev->dev.of_node); | ||
185 | |||
186 | msi->inner_domain = irq_domain_add_linear(NULL, msi->num_of_vectors, | ||
187 | &msi_domain_ops, msi); | ||
188 | if (!msi->inner_domain) { | ||
189 | dev_err(&msi->pdev->dev, "failed to create IRQ domain\n"); | ||
190 | return -ENOMEM; | ||
191 | } | ||
192 | |||
193 | msi->msi_domain = pci_msi_create_irq_domain(fwnode, | ||
194 | &altera_msi_domain_info, msi->inner_domain); | ||
195 | if (!msi->msi_domain) { | ||
196 | dev_err(&msi->pdev->dev, "failed to create MSI domain\n"); | ||
197 | irq_domain_remove(msi->inner_domain); | ||
198 | return -ENOMEM; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void altera_free_domains(struct altera_msi *msi) | ||
205 | { | ||
206 | irq_domain_remove(msi->msi_domain); | ||
207 | irq_domain_remove(msi->inner_domain); | ||
208 | } | ||
209 | |||
210 | static int altera_msi_remove(struct platform_device *pdev) | ||
211 | { | ||
212 | struct altera_msi *msi = platform_get_drvdata(pdev); | ||
213 | |||
214 | msi_writel(msi, 0, MSI_INTMASK); | ||
215 | irq_set_chained_handler(msi->irq, NULL); | ||
216 | irq_set_handler_data(msi->irq, NULL); | ||
217 | |||
218 | altera_free_domains(msi); | ||
219 | |||
220 | platform_set_drvdata(pdev, NULL); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int altera_msi_probe(struct platform_device *pdev) | ||
225 | { | ||
226 | struct altera_msi *msi; | ||
227 | struct device_node *np = pdev->dev.of_node; | ||
228 | struct resource *res; | ||
229 | int ret; | ||
230 | |||
231 | msi = devm_kzalloc(&pdev->dev, sizeof(struct altera_msi), | ||
232 | GFP_KERNEL); | ||
233 | if (!msi) | ||
234 | return -ENOMEM; | ||
235 | |||
236 | mutex_init(&msi->lock); | ||
237 | msi->pdev = pdev; | ||
238 | |||
239 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr"); | ||
240 | if (!res) { | ||
241 | dev_err(&pdev->dev, "no csr memory resource defined\n"); | ||
242 | return -ENODEV; | ||
243 | } | ||
244 | |||
245 | msi->csr_base = devm_ioremap_resource(&pdev->dev, res); | ||
246 | if (IS_ERR(msi->csr_base)) { | ||
247 | dev_err(&pdev->dev, "failed to map csr memory\n"); | ||
248 | return PTR_ERR(msi->csr_base); | ||
249 | } | ||
250 | |||
251 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
252 | "vector_slave"); | ||
253 | if (!res) { | ||
254 | dev_err(&pdev->dev, "no vector_slave memory resource defined\n"); | ||
255 | return -ENODEV; | ||
256 | } | ||
257 | |||
258 | msi->vector_base = devm_ioremap_resource(&pdev->dev, res); | ||
259 | if (IS_ERR(msi->vector_base)) { | ||
260 | dev_err(&pdev->dev, "failed to map vector_slave memory\n"); | ||
261 | return PTR_ERR(msi->vector_base); | ||
262 | } | ||
263 | |||
264 | msi->vector_phy = res->start; | ||
265 | |||
266 | if (of_property_read_u32(np, "num-vectors", &msi->num_of_vectors)) { | ||
267 | dev_err(&pdev->dev, "failed to parse the number of vectors\n"); | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | |||
271 | ret = altera_allocate_domains(msi); | ||
272 | if (ret) | ||
273 | return ret; | ||
274 | |||
275 | msi->irq = platform_get_irq(pdev, 0); | ||
276 | if (msi->irq <= 0) { | ||
277 | dev_err(&pdev->dev, "failed to map IRQ: %d\n", msi->irq); | ||
278 | ret = -ENODEV; | ||
279 | goto err; | ||
280 | } | ||
281 | |||
282 | irq_set_chained_handler_and_data(msi->irq, altera_msi_isr, msi); | ||
283 | platform_set_drvdata(pdev, msi); | ||
284 | |||
285 | return 0; | ||
286 | |||
287 | err: | ||
288 | altera_msi_remove(pdev); | ||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static const struct of_device_id altera_msi_of_match[] = { | ||
293 | { .compatible = "altr,msi-1.0", NULL }, | ||
294 | { }, | ||
295 | }; | ||
296 | |||
297 | static struct platform_driver altera_msi_driver = { | ||
298 | .driver = { | ||
299 | .name = "altera-msi", | ||
300 | .of_match_table = altera_msi_of_match, | ||
301 | }, | ||
302 | .probe = altera_msi_probe, | ||
303 | .remove = altera_msi_remove, | ||
304 | }; | ||
305 | |||
306 | static int __init altera_msi_init(void) | ||
307 | { | ||
308 | return platform_driver_register(&altera_msi_driver); | ||
309 | } | ||
310 | subsys_initcall(altera_msi_init); | ||
311 | |||
312 | MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); | ||
313 | MODULE_DESCRIPTION("Altera PCIe MSI support"); | ||
314 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c new file mode 100644 index 000000000000..e5dda38bdde5 --- /dev/null +++ b/drivers/pci/host/pcie-altera.c | |||
@@ -0,0 +1,579 @@ | |||
1 | /* | ||
2 | * Copyright Altera Corporation (C) 2013-2015. All rights reserved | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/irqchip/chained_irq.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | #include <linux/of_pci.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | #define RP_TX_REG0 0x2000 | ||
29 | #define RP_TX_REG1 0x2004 | ||
30 | #define RP_TX_CNTRL 0x2008 | ||
31 | #define RP_TX_EOP 0x2 | ||
32 | #define RP_TX_SOP 0x1 | ||
33 | #define RP_RXCPL_STATUS 0x2010 | ||
34 | #define RP_RXCPL_EOP 0x2 | ||
35 | #define RP_RXCPL_SOP 0x1 | ||
36 | #define RP_RXCPL_REG0 0x2014 | ||
37 | #define RP_RXCPL_REG1 0x2018 | ||
38 | #define P2A_INT_STATUS 0x3060 | ||
39 | #define P2A_INT_STS_ALL 0xf | ||
40 | #define P2A_INT_ENABLE 0x3070 | ||
41 | #define P2A_INT_ENA_ALL 0xf | ||
42 | #define RP_LTSSM 0x3c64 | ||
43 | #define LTSSM_L0 0xf | ||
44 | |||
45 | /* TLP configuration type 0 and 1 */ | ||
46 | #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ | ||
47 | #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ | ||
48 | #define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */ | ||
49 | #define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */ | ||
50 | #define TLP_PAYLOAD_SIZE 0x01 | ||
51 | #define TLP_READ_TAG 0x1d | ||
52 | #define TLP_WRITE_TAG 0x10 | ||
53 | #define TLP_CFG_DW0(fmttype) (((fmttype) << 24) | TLP_PAYLOAD_SIZE) | ||
54 | #define TLP_CFG_DW1(reqid, tag, be) (((reqid) << 16) | (tag << 8) | (be)) | ||
55 | #define TLP_CFG_DW2(bus, devfn, offset) \ | ||
56 | (((bus) << 24) | ((devfn) << 16) | (offset)) | ||
57 | #define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn)) | ||
58 | #define TLP_HDR_SIZE 3 | ||
59 | #define TLP_LOOP 500 | ||
60 | |||
61 | #define INTX_NUM 4 | ||
62 | |||
63 | #define DWORD_MASK 3 | ||
64 | |||
65 | struct altera_pcie { | ||
66 | struct platform_device *pdev; | ||
67 | void __iomem *cra_base; | ||
68 | int irq; | ||
69 | u8 root_bus_nr; | ||
70 | struct irq_domain *irq_domain; | ||
71 | struct resource bus_range; | ||
72 | struct list_head resources; | ||
73 | }; | ||
74 | |||
75 | struct tlp_rp_regpair_t { | ||
76 | u32 ctrl; | ||
77 | u32 reg0; | ||
78 | u32 reg1; | ||
79 | }; | ||
80 | |||
81 | static void altera_pcie_retrain(struct pci_dev *dev) | ||
82 | { | ||
83 | u16 linkcap, linkstat; | ||
84 | |||
85 | /* | ||
86 | * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but | ||
87 | * current speed is 2.5 GB/s. | ||
88 | */ | ||
89 | pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap); | ||
90 | |||
91 | if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) | ||
92 | return; | ||
93 | |||
94 | pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat); | ||
95 | if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) | ||
96 | pcie_capability_set_word(dev, PCI_EXP_LNKCTL, | ||
97 | PCI_EXP_LNKCTL_RL); | ||
98 | } | ||
99 | DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain); | ||
100 | |||
101 | /* | ||
102 | * Altera PCIe port uses BAR0 of RC's configuration space as the translation | ||
103 | * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space | ||
104 | * using these registers, so it can be reached by DMA from EP devices. | ||
105 | * This BAR0 will also access to MSI vector when receiving MSI/MSIX interrupt | ||
106 | * from EP devices, eventually trigger interrupt to GIC. The BAR0 of bridge | ||
107 | * should be hidden during enumeration to avoid the sizing and resource | ||
108 | * allocation by PCIe core. | ||
109 | */ | ||
110 | static bool altera_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn, | ||
111 | int offset) | ||
112 | { | ||
113 | if (pci_is_root_bus(bus) && (devfn == 0) && | ||
114 | (offset == PCI_BASE_ADDRESS_0)) | ||
115 | return true; | ||
116 | |||
117 | return false; | ||
118 | } | ||
119 | |||
120 | static inline void cra_writel(struct altera_pcie *pcie, const u32 value, | ||
121 | const u32 reg) | ||
122 | { | ||
123 | writel_relaxed(value, pcie->cra_base + reg); | ||
124 | } | ||
125 | |||
126 | static inline u32 cra_readl(struct altera_pcie *pcie, const u32 reg) | ||
127 | { | ||
128 | return readl_relaxed(pcie->cra_base + reg); | ||
129 | } | ||
130 | |||
131 | static void tlp_write_tx(struct altera_pcie *pcie, | ||
132 | struct tlp_rp_regpair_t *tlp_rp_regdata) | ||
133 | { | ||
134 | cra_writel(pcie, tlp_rp_regdata->reg0, RP_TX_REG0); | ||
135 | cra_writel(pcie, tlp_rp_regdata->reg1, RP_TX_REG1); | ||
136 | cra_writel(pcie, tlp_rp_regdata->ctrl, RP_TX_CNTRL); | ||
137 | } | ||
138 | |||
139 | static bool altera_pcie_link_is_up(struct altera_pcie *pcie) | ||
140 | { | ||
141 | return !!(cra_readl(pcie, RP_LTSSM) & LTSSM_L0); | ||
142 | } | ||
143 | |||
144 | static bool altera_pcie_valid_config(struct altera_pcie *pcie, | ||
145 | struct pci_bus *bus, int dev) | ||
146 | { | ||
147 | /* If there is no link, then there is no device */ | ||
148 | if (bus->number != pcie->root_bus_nr) { | ||
149 | if (!altera_pcie_link_is_up(pcie)) | ||
150 | return false; | ||
151 | } | ||
152 | |||
153 | /* access only one slot on each root port */ | ||
154 | if (bus->number == pcie->root_bus_nr && dev > 0) | ||
155 | return false; | ||
156 | |||
157 | /* | ||
158 | * Do not read more than one device on the bus directly attached | ||
159 | * to root port, root port can only attach to one downstream port. | ||
160 | */ | ||
161 | if (bus->primary == pcie->root_bus_nr && dev > 0) | ||
162 | return false; | ||
163 | |||
164 | return true; | ||
165 | } | ||
166 | |||
167 | static int tlp_read_packet(struct altera_pcie *pcie, u32 *value) | ||
168 | { | ||
169 | u8 loop; | ||
170 | bool sop = 0; | ||
171 | u32 ctrl; | ||
172 | u32 reg0, reg1; | ||
173 | |||
174 | /* | ||
175 | * Minimum 2 loops to read TLP headers and 1 loop to read data | ||
176 | * payload. | ||
177 | */ | ||
178 | for (loop = 0; loop < TLP_LOOP; loop++) { | ||
179 | ctrl = cra_readl(pcie, RP_RXCPL_STATUS); | ||
180 | if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) { | ||
181 | reg0 = cra_readl(pcie, RP_RXCPL_REG0); | ||
182 | reg1 = cra_readl(pcie, RP_RXCPL_REG1); | ||
183 | |||
184 | if (ctrl & RP_RXCPL_SOP) | ||
185 | sop = true; | ||
186 | |||
187 | if (ctrl & RP_RXCPL_EOP) { | ||
188 | if (value) | ||
189 | *value = reg0; | ||
190 | return PCIBIOS_SUCCESSFUL; | ||
191 | } | ||
192 | } | ||
193 | udelay(5); | ||
194 | } | ||
195 | |||
196 | return -ENOENT; | ||
197 | } | ||
198 | |||
199 | static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers, | ||
200 | u32 data, bool align) | ||
201 | { | ||
202 | struct tlp_rp_regpair_t tlp_rp_regdata; | ||
203 | |||
204 | tlp_rp_regdata.reg0 = headers[0]; | ||
205 | tlp_rp_regdata.reg1 = headers[1]; | ||
206 | tlp_rp_regdata.ctrl = RP_TX_SOP; | ||
207 | tlp_write_tx(pcie, &tlp_rp_regdata); | ||
208 | |||
209 | if (align) { | ||
210 | tlp_rp_regdata.reg0 = headers[2]; | ||
211 | tlp_rp_regdata.reg1 = 0; | ||
212 | tlp_rp_regdata.ctrl = 0; | ||
213 | tlp_write_tx(pcie, &tlp_rp_regdata); | ||
214 | |||
215 | tlp_rp_regdata.reg0 = data; | ||
216 | tlp_rp_regdata.reg1 = 0; | ||
217 | } else { | ||
218 | tlp_rp_regdata.reg0 = headers[2]; | ||
219 | tlp_rp_regdata.reg1 = data; | ||
220 | } | ||
221 | |||
222 | tlp_rp_regdata.ctrl = RP_TX_EOP; | ||
223 | tlp_write_tx(pcie, &tlp_rp_regdata); | ||
224 | } | ||
225 | |||
226 | static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn, | ||
227 | int where, u8 byte_en, u32 *value) | ||
228 | { | ||
229 | u32 headers[TLP_HDR_SIZE]; | ||
230 | |||
231 | if (bus == pcie->root_bus_nr) | ||
232 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD0); | ||
233 | else | ||
234 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1); | ||
235 | |||
236 | headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn), | ||
237 | TLP_READ_TAG, byte_en); | ||
238 | headers[2] = TLP_CFG_DW2(bus, devfn, where); | ||
239 | |||
240 | tlp_write_packet(pcie, headers, 0, false); | ||
241 | |||
242 | return tlp_read_packet(pcie, value); | ||
243 | } | ||
244 | |||
245 | static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, | ||
246 | int where, u8 byte_en, u32 value) | ||
247 | { | ||
248 | u32 headers[TLP_HDR_SIZE]; | ||
249 | int ret; | ||
250 | |||
251 | if (bus == pcie->root_bus_nr) | ||
252 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR0); | ||
253 | else | ||
254 | headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1); | ||
255 | |||
256 | headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn), | ||
257 | TLP_WRITE_TAG, byte_en); | ||
258 | headers[2] = TLP_CFG_DW2(bus, devfn, where); | ||
259 | |||
260 | /* check alignment to Qword */ | ||
261 | if ((where & 0x7) == 0) | ||
262 | tlp_write_packet(pcie, headers, value, true); | ||
263 | else | ||
264 | tlp_write_packet(pcie, headers, value, false); | ||
265 | |||
266 | ret = tlp_read_packet(pcie, NULL); | ||
267 | if (ret != PCIBIOS_SUCCESSFUL) | ||
268 | return ret; | ||
269 | |||
270 | /* | ||
271 | * Monitor changes to PCI_PRIMARY_BUS register on root port | ||
272 | * and update local copy of root bus number accordingly. | ||
273 | */ | ||
274 | if ((bus == pcie->root_bus_nr) && (where == PCI_PRIMARY_BUS)) | ||
275 | pcie->root_bus_nr = (u8)(value); | ||
276 | |||
277 | return PCIBIOS_SUCCESSFUL; | ||
278 | } | ||
279 | |||
280 | static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, | ||
281 | int where, int size, u32 *value) | ||
282 | { | ||
283 | struct altera_pcie *pcie = bus->sysdata; | ||
284 | int ret; | ||
285 | u32 data; | ||
286 | u8 byte_en; | ||
287 | |||
288 | if (altera_pcie_hide_rc_bar(bus, devfn, where)) | ||
289 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
290 | |||
291 | if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) { | ||
292 | *value = 0xffffffff; | ||
293 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
294 | } | ||
295 | |||
296 | switch (size) { | ||
297 | case 1: | ||
298 | byte_en = 1 << (where & 3); | ||
299 | break; | ||
300 | case 2: | ||
301 | byte_en = 3 << (where & 3); | ||
302 | break; | ||
303 | default: | ||
304 | byte_en = 0xf; | ||
305 | break; | ||
306 | } | ||
307 | |||
308 | ret = tlp_cfg_dword_read(pcie, bus->number, devfn, | ||
309 | (where & ~DWORD_MASK), byte_en, &data); | ||
310 | if (ret != PCIBIOS_SUCCESSFUL) | ||
311 | return ret; | ||
312 | |||
313 | switch (size) { | ||
314 | case 1: | ||
315 | *value = (data >> (8 * (where & 0x3))) & 0xff; | ||
316 | break; | ||
317 | case 2: | ||
318 | *value = (data >> (8 * (where & 0x2))) & 0xffff; | ||
319 | break; | ||
320 | default: | ||
321 | *value = data; | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | return PCIBIOS_SUCCESSFUL; | ||
326 | } | ||
327 | |||
328 | static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, | ||
329 | int where, int size, u32 value) | ||
330 | { | ||
331 | struct altera_pcie *pcie = bus->sysdata; | ||
332 | u32 data32; | ||
333 | u32 shift = 8 * (where & 3); | ||
334 | u8 byte_en; | ||
335 | |||
336 | if (altera_pcie_hide_rc_bar(bus, devfn, where)) | ||
337 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
338 | |||
339 | if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) | ||
340 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
341 | |||
342 | switch (size) { | ||
343 | case 1: | ||
344 | data32 = (value & 0xff) << shift; | ||
345 | byte_en = 1 << (where & 3); | ||
346 | break; | ||
347 | case 2: | ||
348 | data32 = (value & 0xffff) << shift; | ||
349 | byte_en = 3 << (where & 3); | ||
350 | break; | ||
351 | default: | ||
352 | data32 = value; | ||
353 | byte_en = 0xf; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | return tlp_cfg_dword_write(pcie, bus->number, devfn, | ||
358 | (where & ~DWORD_MASK), byte_en, data32); | ||
359 | } | ||
360 | |||
361 | static struct pci_ops altera_pcie_ops = { | ||
362 | .read = altera_pcie_cfg_read, | ||
363 | .write = altera_pcie_cfg_write, | ||
364 | }; | ||
365 | |||
366 | static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq, | ||
367 | irq_hw_number_t hwirq) | ||
368 | { | ||
369 | irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq); | ||
370 | irq_set_chip_data(irq, domain->host_data); | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static const struct irq_domain_ops intx_domain_ops = { | ||
376 | .map = altera_pcie_intx_map, | ||
377 | }; | ||
378 | |||
379 | static void altera_pcie_isr(struct irq_desc *desc) | ||
380 | { | ||
381 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
382 | struct altera_pcie *pcie; | ||
383 | unsigned long status; | ||
384 | u32 bit; | ||
385 | u32 virq; | ||
386 | |||
387 | chained_irq_enter(chip, desc); | ||
388 | pcie = irq_desc_get_handler_data(desc); | ||
389 | |||
390 | while ((status = cra_readl(pcie, P2A_INT_STATUS) | ||
391 | & P2A_INT_STS_ALL) != 0) { | ||
392 | for_each_set_bit(bit, &status, INTX_NUM) { | ||
393 | /* clear interrupts */ | ||
394 | cra_writel(pcie, 1 << bit, P2A_INT_STATUS); | ||
395 | |||
396 | virq = irq_find_mapping(pcie->irq_domain, bit + 1); | ||
397 | if (virq) | ||
398 | generic_handle_irq(virq); | ||
399 | else | ||
400 | dev_err(&pcie->pdev->dev, | ||
401 | "unexpected IRQ, INT%d\n", bit); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | chained_irq_exit(chip, desc); | ||
406 | } | ||
407 | |||
408 | static void altera_pcie_release_of_pci_ranges(struct altera_pcie *pcie) | ||
409 | { | ||
410 | pci_free_resource_list(&pcie->resources); | ||
411 | } | ||
412 | |||
413 | static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie) | ||
414 | { | ||
415 | int err, res_valid = 0; | ||
416 | struct device *dev = &pcie->pdev->dev; | ||
417 | struct device_node *np = dev->of_node; | ||
418 | struct resource_entry *win; | ||
419 | |||
420 | err = of_pci_get_host_bridge_resources(np, 0, 0xff, &pcie->resources, | ||
421 | NULL); | ||
422 | if (err) | ||
423 | return err; | ||
424 | |||
425 | resource_list_for_each_entry(win, &pcie->resources) { | ||
426 | struct resource *parent, *res = win->res; | ||
427 | |||
428 | switch (resource_type(res)) { | ||
429 | case IORESOURCE_MEM: | ||
430 | parent = &iomem_resource; | ||
431 | res_valid |= !(res->flags & IORESOURCE_PREFETCH); | ||
432 | break; | ||
433 | default: | ||
434 | continue; | ||
435 | } | ||
436 | |||
437 | err = devm_request_resource(dev, parent, res); | ||
438 | if (err) | ||
439 | goto out_release_res; | ||
440 | } | ||
441 | |||
442 | if (!res_valid) { | ||
443 | dev_err(dev, "non-prefetchable memory resource required\n"); | ||
444 | err = -EINVAL; | ||
445 | goto out_release_res; | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | |||
450 | out_release_res: | ||
451 | altera_pcie_release_of_pci_ranges(pcie); | ||
452 | return err; | ||
453 | } | ||
454 | |||
455 | static int altera_pcie_init_irq_domain(struct altera_pcie *pcie) | ||
456 | { | ||
457 | struct device *dev = &pcie->pdev->dev; | ||
458 | struct device_node *node = dev->of_node; | ||
459 | |||
460 | /* Setup INTx */ | ||
461 | pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM, | ||
462 | &intx_domain_ops, pcie); | ||
463 | if (!pcie->irq_domain) { | ||
464 | dev_err(dev, "Failed to get a INTx IRQ domain\n"); | ||
465 | return -ENOMEM; | ||
466 | } | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int altera_pcie_parse_dt(struct altera_pcie *pcie) | ||
472 | { | ||
473 | struct resource *cra; | ||
474 | struct platform_device *pdev = pcie->pdev; | ||
475 | |||
476 | cra = platform_get_resource_byname(pdev, IORESOURCE_MEM, "Cra"); | ||
477 | if (!cra) { | ||
478 | dev_err(&pdev->dev, "no Cra memory resource defined\n"); | ||
479 | return -ENODEV; | ||
480 | } | ||
481 | |||
482 | pcie->cra_base = devm_ioremap_resource(&pdev->dev, cra); | ||
483 | if (IS_ERR(pcie->cra_base)) { | ||
484 | dev_err(&pdev->dev, "failed to map cra memory\n"); | ||
485 | return PTR_ERR(pcie->cra_base); | ||
486 | } | ||
487 | |||
488 | /* setup IRQ */ | ||
489 | pcie->irq = platform_get_irq(pdev, 0); | ||
490 | if (pcie->irq <= 0) { | ||
491 | dev_err(&pdev->dev, "failed to get IRQ: %d\n", pcie->irq); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | irq_set_chained_handler_and_data(pcie->irq, altera_pcie_isr, pcie); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int altera_pcie_probe(struct platform_device *pdev) | ||
501 | { | ||
502 | struct altera_pcie *pcie; | ||
503 | struct pci_bus *bus; | ||
504 | struct pci_bus *child; | ||
505 | int ret; | ||
506 | |||
507 | pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); | ||
508 | if (!pcie) | ||
509 | return -ENOMEM; | ||
510 | |||
511 | pcie->pdev = pdev; | ||
512 | |||
513 | ret = altera_pcie_parse_dt(pcie); | ||
514 | if (ret) { | ||
515 | dev_err(&pdev->dev, "Parsing DT failed\n"); | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | INIT_LIST_HEAD(&pcie->resources); | ||
520 | |||
521 | ret = altera_pcie_parse_request_of_pci_ranges(pcie); | ||
522 | if (ret) { | ||
523 | dev_err(&pdev->dev, "Failed add resources\n"); | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | ret = altera_pcie_init_irq_domain(pcie); | ||
528 | if (ret) { | ||
529 | dev_err(&pdev->dev, "Failed creating IRQ Domain\n"); | ||
530 | return ret; | ||
531 | } | ||
532 | |||
533 | /* clear all interrupts */ | ||
534 | cra_writel(pcie, P2A_INT_STS_ALL, P2A_INT_STATUS); | ||
535 | /* enable all interrupts */ | ||
536 | cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); | ||
537 | |||
538 | bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops, | ||
539 | pcie, &pcie->resources); | ||
540 | if (!bus) | ||
541 | return -ENOMEM; | ||
542 | |||
543 | pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); | ||
544 | pci_assign_unassigned_bus_resources(bus); | ||
545 | |||
546 | /* Configure PCI Express setting. */ | ||
547 | list_for_each_entry(child, &bus->children, node) | ||
548 | pcie_bus_configure_settings(child); | ||
549 | |||
550 | pci_bus_add_devices(bus); | ||
551 | |||
552 | platform_set_drvdata(pdev, pcie); | ||
553 | return ret; | ||
554 | } | ||
555 | |||
556 | static const struct of_device_id altera_pcie_of_match[] = { | ||
557 | { .compatible = "altr,pcie-root-port-1.0", }, | ||
558 | {}, | ||
559 | }; | ||
560 | MODULE_DEVICE_TABLE(of, altera_pcie_of_match); | ||
561 | |||
562 | static struct platform_driver altera_pcie_driver = { | ||
563 | .probe = altera_pcie_probe, | ||
564 | .driver = { | ||
565 | .name = "altera-pcie", | ||
566 | .of_match_table = altera_pcie_of_match, | ||
567 | .suppress_bind_attrs = true, | ||
568 | }, | ||
569 | }; | ||
570 | |||
571 | static int altera_pcie_init(void) | ||
572 | { | ||
573 | return platform_driver_register(&altera_pcie_driver); | ||
574 | } | ||
575 | module_init(altera_pcie_init); | ||
576 | |||
577 | MODULE_AUTHOR("Ley Foon Tan <lftan@altera.com>"); | ||
578 | MODULE_DESCRIPTION("Altera PCIe host controller driver"); | ||
579 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 52aa6e34002b..540f077c37ea 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C | 36 | #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C |
37 | #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) | 37 | #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) |
38 | #define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8) | 38 | #define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8) |
39 | #define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8) | 39 | #define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8) |
40 | #define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8) | 40 | #define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8) |
41 | #define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8) | 41 | #define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8) |
@@ -69,39 +69,40 @@ | |||
69 | #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) | 69 | #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) |
70 | #define PCIE_ATU_UPPER_TARGET 0x91C | 70 | #define PCIE_ATU_UPPER_TARGET 0x91C |
71 | 71 | ||
72 | static struct hw_pci dw_pci; | 72 | static struct pci_ops dw_pcie_ops; |
73 | 73 | ||
74 | static unsigned long global_io_offset; | 74 | int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val) |
75 | |||
76 | static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) | ||
77 | { | 75 | { |
78 | BUG_ON(!sys->private_data); | 76 | if ((uintptr_t)addr & (size - 1)) { |
79 | 77 | *val = 0; | |
80 | return sys->private_data; | 78 | return PCIBIOS_BAD_REGISTER_NUMBER; |
81 | } | 79 | } |
82 | |||
83 | int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val) | ||
84 | { | ||
85 | *val = readl(addr); | ||
86 | 80 | ||
87 | if (size == 1) | 81 | if (size == 4) |
88 | *val = (*val >> (8 * (where & 3))) & 0xff; | 82 | *val = readl(addr); |
89 | else if (size == 2) | 83 | else if (size == 2) |
90 | *val = (*val >> (8 * (where & 3))) & 0xffff; | 84 | *val = readw(addr); |
91 | else if (size != 4) | 85 | else if (size == 1) |
86 | *val = readb(addr); | ||
87 | else { | ||
88 | *val = 0; | ||
92 | return PCIBIOS_BAD_REGISTER_NUMBER; | 89 | return PCIBIOS_BAD_REGISTER_NUMBER; |
90 | } | ||
93 | 91 | ||
94 | return PCIBIOS_SUCCESSFUL; | 92 | return PCIBIOS_SUCCESSFUL; |
95 | } | 93 | } |
96 | 94 | ||
97 | int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val) | 95 | int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val) |
98 | { | 96 | { |
97 | if ((uintptr_t)addr & (size - 1)) | ||
98 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
99 | |||
99 | if (size == 4) | 100 | if (size == 4) |
100 | writel(val, addr); | 101 | writel(val, addr); |
101 | else if (size == 2) | 102 | else if (size == 2) |
102 | writew(val, addr + (where & 2)); | 103 | writew(val, addr); |
103 | else if (size == 1) | 104 | else if (size == 1) |
104 | writeb(val, addr + (where & 3)); | 105 | writeb(val, addr); |
105 | else | 106 | else |
106 | return PCIBIOS_BAD_REGISTER_NUMBER; | 107 | return PCIBIOS_BAD_REGISTER_NUMBER; |
107 | 108 | ||
@@ -132,8 +133,7 @@ static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, | |||
132 | if (pp->ops->rd_own_conf) | 133 | if (pp->ops->rd_own_conf) |
133 | ret = pp->ops->rd_own_conf(pp, where, size, val); | 134 | ret = pp->ops->rd_own_conf(pp, where, size, val); |
134 | else | 135 | else |
135 | ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, | 136 | ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val); |
136 | size, val); | ||
137 | 137 | ||
138 | return ret; | 138 | return ret; |
139 | } | 139 | } |
@@ -146,8 +146,7 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, | |||
146 | if (pp->ops->wr_own_conf) | 146 | if (pp->ops->wr_own_conf) |
147 | ret = pp->ops->wr_own_conf(pp, where, size, val); | 147 | ret = pp->ops->wr_own_conf(pp, where, size, val); |
148 | else | 148 | else |
149 | ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), where, | 149 | ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val); |
150 | size, val); | ||
151 | 150 | ||
152 | return ret; | 151 | return ret; |
153 | } | 152 | } |
@@ -205,12 +204,16 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) | |||
205 | 204 | ||
206 | void dw_pcie_msi_init(struct pcie_port *pp) | 205 | void dw_pcie_msi_init(struct pcie_port *pp) |
207 | { | 206 | { |
207 | u64 msi_target; | ||
208 | |||
208 | pp->msi_data = __get_free_pages(GFP_KERNEL, 0); | 209 | pp->msi_data = __get_free_pages(GFP_KERNEL, 0); |
210 | msi_target = virt_to_phys((void *)pp->msi_data); | ||
209 | 211 | ||
210 | /* program the msi_data */ | 212 | /* program the msi_data */ |
211 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, | 213 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, |
212 | virt_to_phys((void *)pp->msi_data)); | 214 | (u32)(msi_target & 0xffffffff)); |
213 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0); | 215 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, |
216 | (u32)(msi_target >> 32 & 0xffffffff)); | ||
214 | } | 217 | } |
215 | 218 | ||
216 | static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) | 219 | static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) |
@@ -255,7 +258,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) | |||
255 | static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) | 258 | static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) |
256 | { | 259 | { |
257 | int irq, pos0, i; | 260 | int irq, pos0, i; |
258 | struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(desc)); | 261 | struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(desc); |
259 | 262 | ||
260 | pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS, | 263 | pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS, |
261 | order_base_2(no_irqs)); | 264 | order_base_2(no_irqs)); |
@@ -286,6 +289,9 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) | |||
286 | } | 289 | } |
287 | 290 | ||
288 | *pos = pos0; | 291 | *pos = pos0; |
292 | desc->nvec_used = no_irqs; | ||
293 | desc->msi_attrib.multiple = order_base_2(no_irqs); | ||
294 | |||
289 | return irq; | 295 | return irq; |
290 | 296 | ||
291 | no_valid_irq: | 297 | no_valid_irq: |
@@ -293,12 +299,32 @@ no_valid_irq: | |||
293 | return -ENOSPC; | 299 | return -ENOSPC; |
294 | } | 300 | } |
295 | 301 | ||
302 | static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) | ||
303 | { | ||
304 | struct msi_msg msg; | ||
305 | u64 msi_target; | ||
306 | |||
307 | if (pp->ops->get_msi_addr) | ||
308 | msi_target = pp->ops->get_msi_addr(pp); | ||
309 | else | ||
310 | msi_target = virt_to_phys((void *)pp->msi_data); | ||
311 | |||
312 | msg.address_lo = (u32)(msi_target & 0xffffffff); | ||
313 | msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); | ||
314 | |||
315 | if (pp->ops->get_msi_data) | ||
316 | msg.data = pp->ops->get_msi_data(pp, pos); | ||
317 | else | ||
318 | msg.data = pos; | ||
319 | |||
320 | pci_write_msi_msg(irq, &msg); | ||
321 | } | ||
322 | |||
296 | static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, | 323 | static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, |
297 | struct msi_desc *desc) | 324 | struct msi_desc *desc) |
298 | { | 325 | { |
299 | int irq, pos; | 326 | int irq, pos; |
300 | struct msi_msg msg; | 327 | struct pcie_port *pp = pdev->bus->sysdata; |
301 | struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata); | ||
302 | 328 | ||
303 | if (desc->msi_attrib.is_msix) | 329 | if (desc->msi_attrib.is_msix) |
304 | return -EINVAL; | 330 | return -EINVAL; |
@@ -307,33 +333,50 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, | |||
307 | if (irq < 0) | 333 | if (irq < 0) |
308 | return irq; | 334 | return irq; |
309 | 335 | ||
310 | if (pp->ops->get_msi_addr) | 336 | dw_msi_setup_msg(pp, irq, pos); |
311 | msg.address_lo = pp->ops->get_msi_addr(pp); | ||
312 | else | ||
313 | msg.address_lo = virt_to_phys((void *)pp->msi_data); | ||
314 | msg.address_hi = 0x0; | ||
315 | 337 | ||
316 | if (pp->ops->get_msi_data) | 338 | return 0; |
317 | msg.data = pp->ops->get_msi_data(pp, pos); | 339 | } |
318 | else | ||
319 | msg.data = pos; | ||
320 | 340 | ||
321 | pci_write_msi_msg(irq, &msg); | 341 | static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev, |
342 | int nvec, int type) | ||
343 | { | ||
344 | #ifdef CONFIG_PCI_MSI | ||
345 | int irq, pos; | ||
346 | struct msi_desc *desc; | ||
347 | struct pcie_port *pp = pdev->bus->sysdata; | ||
348 | |||
349 | /* MSI-X interrupts are not supported */ | ||
350 | if (type == PCI_CAP_ID_MSIX) | ||
351 | return -EINVAL; | ||
352 | |||
353 | WARN_ON(!list_is_singular(&pdev->dev.msi_list)); | ||
354 | desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list); | ||
355 | |||
356 | irq = assign_irq(nvec, desc, &pos); | ||
357 | if (irq < 0) | ||
358 | return irq; | ||
359 | |||
360 | dw_msi_setup_msg(pp, irq, pos); | ||
322 | 361 | ||
323 | return 0; | 362 | return 0; |
363 | #else | ||
364 | return -EINVAL; | ||
365 | #endif | ||
324 | } | 366 | } |
325 | 367 | ||
326 | static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) | 368 | static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) |
327 | { | 369 | { |
328 | struct irq_data *data = irq_get_irq_data(irq); | 370 | struct irq_data *data = irq_get_irq_data(irq); |
329 | struct msi_desc *msi = irq_data_get_msi_desc(data); | 371 | struct msi_desc *msi = irq_data_get_msi_desc(data); |
330 | struct pcie_port *pp = sys_to_pcie(msi_desc_to_pci_sysdata(msi)); | 372 | struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); |
331 | 373 | ||
332 | clear_irq_range(pp, irq, 1, data->hwirq); | 374 | clear_irq_range(pp, irq, 1, data->hwirq); |
333 | } | 375 | } |
334 | 376 | ||
335 | static struct msi_controller dw_pcie_msi_chip = { | 377 | static struct msi_controller dw_pcie_msi_chip = { |
336 | .setup_irq = dw_msi_setup_irq, | 378 | .setup_irq = dw_msi_setup_irq, |
379 | .setup_irqs = dw_msi_setup_irqs, | ||
337 | .teardown_irq = dw_msi_teardown_irq, | 380 | .teardown_irq = dw_msi_teardown_irq, |
338 | }; | 381 | }; |
339 | 382 | ||
@@ -362,18 +405,12 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
362 | { | 405 | { |
363 | struct device_node *np = pp->dev->of_node; | 406 | struct device_node *np = pp->dev->of_node; |
364 | struct platform_device *pdev = to_platform_device(pp->dev); | 407 | struct platform_device *pdev = to_platform_device(pp->dev); |
365 | struct of_pci_range range; | 408 | struct pci_bus *bus, *child; |
366 | struct of_pci_range_parser parser; | ||
367 | struct resource *cfg_res; | 409 | struct resource *cfg_res; |
368 | u32 val, na, ns; | 410 | u32 val; |
369 | const __be32 *addrp; | 411 | int i, ret; |
370 | int i, index, ret; | 412 | LIST_HEAD(res); |
371 | 413 | struct resource_entry *win; | |
372 | /* Find the address cell size and the number of cells in order to get | ||
373 | * the untranslated address. | ||
374 | */ | ||
375 | of_property_read_u32(np, "#address-cells", &na); | ||
376 | ns = of_n_size_cells(np); | ||
377 | 414 | ||
378 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); | 415 | cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); |
379 | if (cfg_res) { | 416 | if (cfg_res) { |
@@ -381,88 +418,61 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
381 | pp->cfg1_size = resource_size(cfg_res)/2; | 418 | pp->cfg1_size = resource_size(cfg_res)/2; |
382 | pp->cfg0_base = cfg_res->start; | 419 | pp->cfg0_base = cfg_res->start; |
383 | pp->cfg1_base = cfg_res->start + pp->cfg0_size; | 420 | pp->cfg1_base = cfg_res->start + pp->cfg0_size; |
384 | |||
385 | /* Find the untranslated configuration space address */ | ||
386 | index = of_property_match_string(np, "reg-names", "config"); | ||
387 | addrp = of_get_address(np, index, NULL, NULL); | ||
388 | pp->cfg0_mod_base = of_read_number(addrp, ns); | ||
389 | pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size; | ||
390 | } else if (!pp->va_cfg0_base) { | 421 | } else if (!pp->va_cfg0_base) { |
391 | dev_err(pp->dev, "missing *config* reg space\n"); | 422 | dev_err(pp->dev, "missing *config* reg space\n"); |
392 | } | 423 | } |
393 | 424 | ||
394 | if (of_pci_range_parser_init(&parser, np)) { | 425 | ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base); |
395 | dev_err(pp->dev, "missing ranges property\n"); | 426 | if (ret) |
396 | return -EINVAL; | 427 | return ret; |
397 | } | ||
398 | 428 | ||
399 | /* Get the I/O and memory ranges from DT */ | 429 | /* Get the I/O and memory ranges from DT */ |
400 | for_each_of_pci_range(&parser, &range) { | 430 | resource_list_for_each_entry(win, &res) { |
401 | unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; | 431 | switch (resource_type(win->res)) { |
402 | 432 | case IORESOURCE_IO: | |
403 | if (restype == IORESOURCE_IO) { | 433 | pp->io = win->res; |
404 | of_pci_range_to_resource(&range, np, &pp->io); | 434 | pp->io->name = "I/O"; |
405 | pp->io.name = "I/O"; | 435 | pp->io_size = resource_size(pp->io); |
406 | pp->io.start = max_t(resource_size_t, | 436 | pp->io_bus_addr = pp->io->start - win->offset; |
407 | PCIBIOS_MIN_IO, | 437 | ret = pci_remap_iospace(pp->io, pp->io_base); |
408 | range.pci_addr + global_io_offset); | 438 | if (ret) { |
409 | pp->io.end = min_t(resource_size_t, | 439 | dev_warn(pp->dev, "error %d: failed to map resource %pR\n", |
410 | IO_SPACE_LIMIT, | 440 | ret, pp->io); |
411 | range.pci_addr + range.size | 441 | continue; |
412 | + global_io_offset - 1); | 442 | } |
413 | pp->io_size = resource_size(&pp->io); | 443 | pp->io_base = pp->io->start; |
414 | pp->io_bus_addr = range.pci_addr; | 444 | break; |
415 | pp->io_base = range.cpu_addr; | 445 | case IORESOURCE_MEM: |
416 | 446 | pp->mem = win->res; | |
417 | /* Find the untranslated IO space address */ | 447 | pp->mem->name = "MEM"; |
418 | pp->io_mod_base = of_read_number(parser.range - | 448 | pp->mem_size = resource_size(pp->mem); |
419 | parser.np + na, ns); | 449 | pp->mem_bus_addr = pp->mem->start - win->offset; |
420 | } | 450 | break; |
421 | if (restype == IORESOURCE_MEM) { | 451 | case 0: |
422 | of_pci_range_to_resource(&range, np, &pp->mem); | 452 | pp->cfg = win->res; |
423 | pp->mem.name = "MEM"; | 453 | pp->cfg0_size = resource_size(pp->cfg)/2; |
424 | pp->mem_size = resource_size(&pp->mem); | 454 | pp->cfg1_size = resource_size(pp->cfg)/2; |
425 | pp->mem_bus_addr = range.pci_addr; | 455 | pp->cfg0_base = pp->cfg->start; |
426 | 456 | pp->cfg1_base = pp->cfg->start + pp->cfg0_size; | |
427 | /* Find the untranslated MEM space address */ | 457 | break; |
428 | pp->mem_mod_base = of_read_number(parser.range - | 458 | case IORESOURCE_BUS: |
429 | parser.np + na, ns); | 459 | pp->busn = win->res; |
430 | } | 460 | break; |
431 | if (restype == 0) { | 461 | default: |
432 | of_pci_range_to_resource(&range, np, &pp->cfg); | 462 | continue; |
433 | pp->cfg0_size = resource_size(&pp->cfg)/2; | ||
434 | pp->cfg1_size = resource_size(&pp->cfg)/2; | ||
435 | pp->cfg0_base = pp->cfg.start; | ||
436 | pp->cfg1_base = pp->cfg.start + pp->cfg0_size; | ||
437 | |||
438 | /* Find the untranslated configuration space address */ | ||
439 | pp->cfg0_mod_base = of_read_number(parser.range - | ||
440 | parser.np + na, ns); | ||
441 | pp->cfg1_mod_base = pp->cfg0_mod_base + | ||
442 | pp->cfg0_size; | ||
443 | } | 463 | } |
444 | } | 464 | } |
445 | 465 | ||
446 | ret = of_pci_parse_bus_range(np, &pp->busn); | ||
447 | if (ret < 0) { | ||
448 | pp->busn.name = np->name; | ||
449 | pp->busn.start = 0; | ||
450 | pp->busn.end = 0xff; | ||
451 | pp->busn.flags = IORESOURCE_BUS; | ||
452 | dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n", | ||
453 | ret, &pp->busn); | ||
454 | } | ||
455 | |||
456 | if (!pp->dbi_base) { | 466 | if (!pp->dbi_base) { |
457 | pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start, | 467 | pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start, |
458 | resource_size(&pp->cfg)); | 468 | resource_size(pp->cfg)); |
459 | if (!pp->dbi_base) { | 469 | if (!pp->dbi_base) { |
460 | dev_err(pp->dev, "error with ioremap\n"); | 470 | dev_err(pp->dev, "error with ioremap\n"); |
461 | return -ENOMEM; | 471 | return -ENOMEM; |
462 | } | 472 | } |
463 | } | 473 | } |
464 | 474 | ||
465 | pp->mem_base = pp->mem.start; | 475 | pp->mem_base = pp->mem->start; |
466 | 476 | ||
467 | if (!pp->va_cfg0_base) { | 477 | if (!pp->va_cfg0_base) { |
468 | pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, | 478 | pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, |
@@ -482,10 +492,9 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
482 | } | 492 | } |
483 | } | 493 | } |
484 | 494 | ||
485 | if (of_property_read_u32(np, "num-lanes", &pp->lanes)) { | 495 | ret = of_property_read_u32(np, "num-lanes", &pp->lanes); |
486 | dev_err(pp->dev, "Failed to parse the number of lanes\n"); | 496 | if (ret) |
487 | return -EINVAL; | 497 | pp->lanes = 0; |
488 | } | ||
489 | 498 | ||
490 | if (IS_ENABLED(CONFIG_PCI_MSI)) { | 499 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
491 | if (!pp->ops->msi_host_init) { | 500 | if (!pp->ops->msi_host_init) { |
@@ -511,7 +520,7 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
511 | 520 | ||
512 | if (!pp->ops->rd_other_conf) | 521 | if (!pp->ops->rd_other_conf) |
513 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, | 522 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, |
514 | PCIE_ATU_TYPE_MEM, pp->mem_mod_base, | 523 | PCIE_ATU_TYPE_MEM, pp->mem_base, |
515 | pp->mem_bus_addr, pp->mem_size); | 524 | pp->mem_bus_addr, pp->mem_size); |
516 | 525 | ||
517 | dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); | 526 | dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); |
@@ -523,15 +532,35 @@ int dw_pcie_host_init(struct pcie_port *pp) | |||
523 | val |= PORT_LOGIC_SPEED_CHANGE; | 532 | val |= PORT_LOGIC_SPEED_CHANGE; |
524 | dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); | 533 | dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); |
525 | 534 | ||
526 | #ifdef CONFIG_PCI_MSI | 535 | pp->root_bus_nr = pp->busn->start; |
527 | dw_pcie_msi_chip.dev = pp->dev; | 536 | if (IS_ENABLED(CONFIG_PCI_MSI)) { |
537 | bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr, | ||
538 | &dw_pcie_ops, pp, &res, | ||
539 | &dw_pcie_msi_chip); | ||
540 | dw_pcie_msi_chip.dev = pp->dev; | ||
541 | } else | ||
542 | bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, | ||
543 | pp, &res); | ||
544 | if (!bus) | ||
545 | return -ENOMEM; | ||
546 | |||
547 | if (pp->ops->scan_bus) | ||
548 | pp->ops->scan_bus(pp); | ||
549 | |||
550 | #ifdef CONFIG_ARM | ||
551 | /* support old dtbs that incorrectly describe IRQs */ | ||
552 | pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); | ||
528 | #endif | 553 | #endif |
529 | 554 | ||
530 | dw_pci.nr_controllers = 1; | 555 | if (!pci_has_flag(PCI_PROBE_ONLY)) { |
531 | dw_pci.private_data = (void **)&pp; | 556 | pci_bus_size_bridges(bus); |
557 | pci_bus_assign_resources(bus); | ||
532 | 558 | ||
533 | pci_common_init_dev(pp->dev, &dw_pci); | 559 | list_for_each_entry(child, &bus->children, node) |
560 | pcie_bus_configure_settings(child); | ||
561 | } | ||
534 | 562 | ||
563 | pci_bus_add_devices(bus); | ||
535 | return 0; | 564 | return 0; |
536 | } | 565 | } |
537 | 566 | ||
@@ -539,22 +568,21 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
539 | u32 devfn, int where, int size, u32 *val) | 568 | u32 devfn, int where, int size, u32 *val) |
540 | { | 569 | { |
541 | int ret, type; | 570 | int ret, type; |
542 | u32 address, busdev, cfg_size; | 571 | u32 busdev, cfg_size; |
543 | u64 cpu_addr; | 572 | u64 cpu_addr; |
544 | void __iomem *va_cfg_base; | 573 | void __iomem *va_cfg_base; |
545 | 574 | ||
546 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | | 575 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | |
547 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); | 576 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); |
548 | address = where & ~0x3; | ||
549 | 577 | ||
550 | if (bus->parent->number == pp->root_bus_nr) { | 578 | if (bus->parent->number == pp->root_bus_nr) { |
551 | type = PCIE_ATU_TYPE_CFG0; | 579 | type = PCIE_ATU_TYPE_CFG0; |
552 | cpu_addr = pp->cfg0_mod_base; | 580 | cpu_addr = pp->cfg0_base; |
553 | cfg_size = pp->cfg0_size; | 581 | cfg_size = pp->cfg0_size; |
554 | va_cfg_base = pp->va_cfg0_base; | 582 | va_cfg_base = pp->va_cfg0_base; |
555 | } else { | 583 | } else { |
556 | type = PCIE_ATU_TYPE_CFG1; | 584 | type = PCIE_ATU_TYPE_CFG1; |
557 | cpu_addr = pp->cfg1_mod_base; | 585 | cpu_addr = pp->cfg1_base; |
558 | cfg_size = pp->cfg1_size; | 586 | cfg_size = pp->cfg1_size; |
559 | va_cfg_base = pp->va_cfg1_base; | 587 | va_cfg_base = pp->va_cfg1_base; |
560 | } | 588 | } |
@@ -562,9 +590,9 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
562 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 590 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, |
563 | type, cpu_addr, | 591 | type, cpu_addr, |
564 | busdev, cfg_size); | 592 | busdev, cfg_size); |
565 | ret = dw_pcie_cfg_read(va_cfg_base + address, where, size, val); | 593 | ret = dw_pcie_cfg_read(va_cfg_base + where, size, val); |
566 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 594 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, |
567 | PCIE_ATU_TYPE_IO, pp->io_mod_base, | 595 | PCIE_ATU_TYPE_IO, pp->io_base, |
568 | pp->io_bus_addr, pp->io_size); | 596 | pp->io_bus_addr, pp->io_size); |
569 | 597 | ||
570 | return ret; | 598 | return ret; |
@@ -574,22 +602,21 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
574 | u32 devfn, int where, int size, u32 val) | 602 | u32 devfn, int where, int size, u32 val) |
575 | { | 603 | { |
576 | int ret, type; | 604 | int ret, type; |
577 | u32 address, busdev, cfg_size; | 605 | u32 busdev, cfg_size; |
578 | u64 cpu_addr; | 606 | u64 cpu_addr; |
579 | void __iomem *va_cfg_base; | 607 | void __iomem *va_cfg_base; |
580 | 608 | ||
581 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | | 609 | busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | |
582 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); | 610 | PCIE_ATU_FUNC(PCI_FUNC(devfn)); |
583 | address = where & ~0x3; | ||
584 | 611 | ||
585 | if (bus->parent->number == pp->root_bus_nr) { | 612 | if (bus->parent->number == pp->root_bus_nr) { |
586 | type = PCIE_ATU_TYPE_CFG0; | 613 | type = PCIE_ATU_TYPE_CFG0; |
587 | cpu_addr = pp->cfg0_mod_base; | 614 | cpu_addr = pp->cfg0_base; |
588 | cfg_size = pp->cfg0_size; | 615 | cfg_size = pp->cfg0_size; |
589 | va_cfg_base = pp->va_cfg0_base; | 616 | va_cfg_base = pp->va_cfg0_base; |
590 | } else { | 617 | } else { |
591 | type = PCIE_ATU_TYPE_CFG1; | 618 | type = PCIE_ATU_TYPE_CFG1; |
592 | cpu_addr = pp->cfg1_mod_base; | 619 | cpu_addr = pp->cfg1_base; |
593 | cfg_size = pp->cfg1_size; | 620 | cfg_size = pp->cfg1_size; |
594 | va_cfg_base = pp->va_cfg1_base; | 621 | va_cfg_base = pp->va_cfg1_base; |
595 | } | 622 | } |
@@ -597,9 +624,9 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, | |||
597 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 624 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, |
598 | type, cpu_addr, | 625 | type, cpu_addr, |
599 | busdev, cfg_size); | 626 | busdev, cfg_size); |
600 | ret = dw_pcie_cfg_write(va_cfg_base + address, where, size, val); | 627 | ret = dw_pcie_cfg_write(va_cfg_base + where, size, val); |
601 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, | 628 | dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, |
602 | PCIE_ATU_TYPE_IO, pp->io_mod_base, | 629 | PCIE_ATU_TYPE_IO, pp->io_base, |
603 | pp->io_bus_addr, pp->io_size); | 630 | pp->io_bus_addr, pp->io_size); |
604 | 631 | ||
605 | return ret; | 632 | return ret; |
@@ -631,7 +658,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp, | |||
631 | static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | 658 | static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, |
632 | int size, u32 *val) | 659 | int size, u32 *val) |
633 | { | 660 | { |
634 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); | 661 | struct pcie_port *pp = bus->sysdata; |
635 | int ret; | 662 | int ret; |
636 | 663 | ||
637 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { | 664 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { |
@@ -655,7 +682,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, | |||
655 | static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, | 682 | static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, |
656 | int where, int size, u32 val) | 683 | int where, int size, u32 val) |
657 | { | 684 | { |
658 | struct pcie_port *pp = sys_to_pcie(bus->sysdata); | 685 | struct pcie_port *pp = bus->sysdata; |
659 | int ret; | 686 | int ret; |
660 | 687 | ||
661 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) | 688 | if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) |
@@ -679,69 +706,6 @@ static struct pci_ops dw_pcie_ops = { | |||
679 | .write = dw_pcie_wr_conf, | 706 | .write = dw_pcie_wr_conf, |
680 | }; | 707 | }; |
681 | 708 | ||
682 | static int dw_pcie_setup(int nr, struct pci_sys_data *sys) | ||
683 | { | ||
684 | struct pcie_port *pp; | ||
685 | |||
686 | pp = sys_to_pcie(sys); | ||
687 | |||
688 | if (global_io_offset < SZ_1M && pp->io_size > 0) { | ||
689 | sys->io_offset = global_io_offset - pp->io_bus_addr; | ||
690 | pci_ioremap_io(global_io_offset, pp->io_base); | ||
691 | global_io_offset += SZ_64K; | ||
692 | pci_add_resource_offset(&sys->resources, &pp->io, | ||
693 | sys->io_offset); | ||
694 | } | ||
695 | |||
696 | sys->mem_offset = pp->mem.start - pp->mem_bus_addr; | ||
697 | pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset); | ||
698 | pci_add_resource(&sys->resources, &pp->busn); | ||
699 | |||
700 | return 1; | ||
701 | } | ||
702 | |||
703 | static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) | ||
704 | { | ||
705 | struct pci_bus *bus; | ||
706 | struct pcie_port *pp = sys_to_pcie(sys); | ||
707 | |||
708 | pp->root_bus_nr = sys->busnr; | ||
709 | |||
710 | if (IS_ENABLED(CONFIG_PCI_MSI)) | ||
711 | bus = pci_scan_root_bus_msi(pp->dev, sys->busnr, &dw_pcie_ops, | ||
712 | sys, &sys->resources, | ||
713 | &dw_pcie_msi_chip); | ||
714 | else | ||
715 | bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops, | ||
716 | sys, &sys->resources); | ||
717 | |||
718 | if (!bus) | ||
719 | return NULL; | ||
720 | |||
721 | if (bus && pp->ops->scan_bus) | ||
722 | pp->ops->scan_bus(pp); | ||
723 | |||
724 | return bus; | ||
725 | } | ||
726 | |||
727 | static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
728 | { | ||
729 | struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); | ||
730 | int irq; | ||
731 | |||
732 | irq = of_irq_parse_and_map_pci(dev, slot, pin); | ||
733 | if (!irq) | ||
734 | irq = pp->irq; | ||
735 | |||
736 | return irq; | ||
737 | } | ||
738 | |||
739 | static struct hw_pci dw_pci = { | ||
740 | .setup = dw_pcie_setup, | ||
741 | .scan = dw_pcie_scan_bus, | ||
742 | .map_irq = dw_pcie_map_irq, | ||
743 | }; | ||
744 | |||
745 | void dw_pcie_setup_rc(struct pcie_port *pp) | 709 | void dw_pcie_setup_rc(struct pcie_port *pp) |
746 | { | 710 | { |
747 | u32 val; | 711 | u32 val; |
@@ -764,6 +728,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
764 | case 8: | 728 | case 8: |
765 | val |= PORT_LINK_MODE_8_LANES; | 729 | val |= PORT_LINK_MODE_8_LANES; |
766 | break; | 730 | break; |
731 | default: | ||
732 | dev_err(pp->dev, "num-lanes %u: invalid value\n", pp->lanes); | ||
733 | return; | ||
767 | } | 734 | } |
768 | dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); | 735 | dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); |
769 | 736 | ||
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index d0bbd276840d..2356d29e8527 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h | |||
@@ -27,25 +27,21 @@ struct pcie_port { | |||
27 | u8 root_bus_nr; | 27 | u8 root_bus_nr; |
28 | void __iomem *dbi_base; | 28 | void __iomem *dbi_base; |
29 | u64 cfg0_base; | 29 | u64 cfg0_base; |
30 | u64 cfg0_mod_base; | ||
31 | void __iomem *va_cfg0_base; | 30 | void __iomem *va_cfg0_base; |
32 | u32 cfg0_size; | 31 | u32 cfg0_size; |
33 | u64 cfg1_base; | 32 | u64 cfg1_base; |
34 | u64 cfg1_mod_base; | ||
35 | void __iomem *va_cfg1_base; | 33 | void __iomem *va_cfg1_base; |
36 | u32 cfg1_size; | 34 | u32 cfg1_size; |
37 | u64 io_base; | 35 | resource_size_t io_base; |
38 | u64 io_mod_base; | ||
39 | phys_addr_t io_bus_addr; | 36 | phys_addr_t io_bus_addr; |
40 | u32 io_size; | 37 | u32 io_size; |
41 | u64 mem_base; | 38 | u64 mem_base; |
42 | u64 mem_mod_base; | ||
43 | phys_addr_t mem_bus_addr; | 39 | phys_addr_t mem_bus_addr; |
44 | u32 mem_size; | 40 | u32 mem_size; |
45 | struct resource cfg; | 41 | struct resource *cfg; |
46 | struct resource io; | 42 | struct resource *io; |
47 | struct resource mem; | 43 | struct resource *mem; |
48 | struct resource busn; | 44 | struct resource *busn; |
49 | int irq; | 45 | int irq; |
50 | u32 lanes; | 46 | u32 lanes; |
51 | struct pcie_host_ops *ops; | 47 | struct pcie_host_ops *ops; |
@@ -70,14 +66,14 @@ struct pcie_host_ops { | |||
70 | void (*host_init)(struct pcie_port *pp); | 66 | void (*host_init)(struct pcie_port *pp); |
71 | void (*msi_set_irq)(struct pcie_port *pp, int irq); | 67 | void (*msi_set_irq)(struct pcie_port *pp, int irq); |
72 | void (*msi_clear_irq)(struct pcie_port *pp, int irq); | 68 | void (*msi_clear_irq)(struct pcie_port *pp, int irq); |
73 | u32 (*get_msi_addr)(struct pcie_port *pp); | 69 | phys_addr_t (*get_msi_addr)(struct pcie_port *pp); |
74 | u32 (*get_msi_data)(struct pcie_port *pp, int pos); | 70 | u32 (*get_msi_data)(struct pcie_port *pp, int pos); |
75 | void (*scan_bus)(struct pcie_port *pp); | 71 | void (*scan_bus)(struct pcie_port *pp); |
76 | int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip); | 72 | int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip); |
77 | }; | 73 | }; |
78 | 74 | ||
79 | int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val); | 75 | int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val); |
80 | int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val); | 76 | int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val); |
81 | irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); | 77 | irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); |
82 | void dw_pcie_msi_init(struct pcie_port *pp); | 78 | void dw_pcie_msi_init(struct pcie_port *pp); |
83 | int dw_pcie_link_up(struct pcie_port *pp); | 79 | int dw_pcie_link_up(struct pcie_port *pp); |
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c new file mode 100644 index 000000000000..35457ecd8e70 --- /dev/null +++ b/drivers/pci/host/pcie-hisi.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * PCIe host controller driver for HiSilicon Hip05 SoC | ||
3 | * | ||
4 | * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com | ||
5 | * | ||
6 | * Author: Zhou Wang <wangzhou1@hisilicon.com> | ||
7 | * Dacai Zhu <zhudacai@hisilicon.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/mfd/syscon.h> | ||
16 | #include <linux/of_address.h> | ||
17 | #include <linux/of_pci.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/regmap.h> | ||
20 | |||
21 | #include "pcie-designware.h" | ||
22 | |||
23 | #define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818 | ||
24 | #define PCIE_LTSSM_LINKUP_STATE 0x11 | ||
25 | #define PCIE_LTSSM_STATE_MASK 0x3F | ||
26 | |||
27 | #define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp) | ||
28 | |||
29 | struct hisi_pcie { | ||
30 | struct regmap *subctrl; | ||
31 | void __iomem *reg_base; | ||
32 | u32 port_id; | ||
33 | struct pcie_port pp; | ||
34 | }; | ||
35 | |||
36 | static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie, | ||
37 | u32 val, u32 reg) | ||
38 | { | ||
39 | writel(val, pcie->reg_base + reg); | ||
40 | } | ||
41 | |||
42 | static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg) | ||
43 | { | ||
44 | return readl(pcie->reg_base + reg); | ||
45 | } | ||
46 | |||
47 | /* Hip05 PCIe host only supports 32-bit config access */ | ||
48 | static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, | ||
49 | u32 *val) | ||
50 | { | ||
51 | u32 reg; | ||
52 | u32 reg_val; | ||
53 | struct hisi_pcie *pcie = to_hisi_pcie(pp); | ||
54 | void *walker = ®_val; | ||
55 | |||
56 | walker += (where & 0x3); | ||
57 | reg = where & ~0x3; | ||
58 | reg_val = hisi_pcie_apb_readl(pcie, reg); | ||
59 | |||
60 | if (size == 1) | ||
61 | *val = *(u8 __force *) walker; | ||
62 | else if (size == 2) | ||
63 | *val = *(u16 __force *) walker; | ||
64 | else if (size != 4) | ||
65 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
66 | |||
67 | return PCIBIOS_SUCCESSFUL; | ||
68 | } | ||
69 | |||
70 | /* Hip05 PCIe host only supports 32-bit config access */ | ||
71 | static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, | ||
72 | u32 val) | ||
73 | { | ||
74 | u32 reg_val; | ||
75 | u32 reg; | ||
76 | struct hisi_pcie *pcie = to_hisi_pcie(pp); | ||
77 | void *walker = ®_val; | ||
78 | |||
79 | walker += (where & 0x3); | ||
80 | reg = where & ~0x3; | ||
81 | if (size == 4) | ||
82 | hisi_pcie_apb_writel(pcie, val, reg); | ||
83 | else if (size == 2) { | ||
84 | reg_val = hisi_pcie_apb_readl(pcie, reg); | ||
85 | *(u16 __force *) walker = val; | ||
86 | hisi_pcie_apb_writel(pcie, reg_val, reg); | ||
87 | } else if (size == 1) { | ||
88 | reg_val = hisi_pcie_apb_readl(pcie, reg); | ||
89 | *(u8 __force *) walker = val; | ||
90 | hisi_pcie_apb_writel(pcie, reg_val, reg); | ||
91 | } else | ||
92 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
93 | |||
94 | return PCIBIOS_SUCCESSFUL; | ||
95 | } | ||
96 | |||
97 | static int hisi_pcie_link_up(struct pcie_port *pp) | ||
98 | { | ||
99 | u32 val; | ||
100 | struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp); | ||
101 | |||
102 | regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG + | ||
103 | 0x100 * hisi_pcie->port_id, &val); | ||
104 | |||
105 | return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); | ||
106 | } | ||
107 | |||
108 | static struct pcie_host_ops hisi_pcie_host_ops = { | ||
109 | .rd_own_conf = hisi_pcie_cfg_read, | ||
110 | .wr_own_conf = hisi_pcie_cfg_write, | ||
111 | .link_up = hisi_pcie_link_up, | ||
112 | }; | ||
113 | |||
114 | static int __init hisi_add_pcie_port(struct pcie_port *pp, | ||
115 | struct platform_device *pdev) | ||
116 | { | ||
117 | int ret; | ||
118 | u32 port_id; | ||
119 | struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp); | ||
120 | |||
121 | if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) { | ||
122 | dev_err(&pdev->dev, "failed to read port-id\n"); | ||
123 | return -EINVAL; | ||
124 | } | ||
125 | if (port_id > 3) { | ||
126 | dev_err(&pdev->dev, "Invalid port-id: %d\n", port_id); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | hisi_pcie->port_id = port_id; | ||
130 | |||
131 | pp->ops = &hisi_pcie_host_ops; | ||
132 | |||
133 | ret = dw_pcie_host_init(pp); | ||
134 | if (ret) { | ||
135 | dev_err(&pdev->dev, "failed to initialize host\n"); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int __init hisi_pcie_probe(struct platform_device *pdev) | ||
143 | { | ||
144 | struct hisi_pcie *hisi_pcie; | ||
145 | struct pcie_port *pp; | ||
146 | struct resource *reg; | ||
147 | int ret; | ||
148 | |||
149 | hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL); | ||
150 | if (!hisi_pcie) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | pp = &hisi_pcie->pp; | ||
154 | pp->dev = &pdev->dev; | ||
155 | |||
156 | hisi_pcie->subctrl = | ||
157 | syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl"); | ||
158 | if (IS_ERR(hisi_pcie->subctrl)) { | ||
159 | dev_err(pp->dev, "cannot get subctrl base\n"); | ||
160 | return PTR_ERR(hisi_pcie->subctrl); | ||
161 | } | ||
162 | |||
163 | reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi"); | ||
164 | hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg); | ||
165 | if (IS_ERR(hisi_pcie->reg_base)) { | ||
166 | dev_err(pp->dev, "cannot get rc_dbi base\n"); | ||
167 | return PTR_ERR(hisi_pcie->reg_base); | ||
168 | } | ||
169 | |||
170 | hisi_pcie->pp.dbi_base = hisi_pcie->reg_base; | ||
171 | |||
172 | ret = hisi_add_pcie_port(pp, pdev); | ||
173 | if (ret) | ||
174 | return ret; | ||
175 | |||
176 | platform_set_drvdata(pdev, hisi_pcie); | ||
177 | |||
178 | dev_warn(pp->dev, "only 32-bit config accesses supported; smaller writes may corrupt adjacent RW1C fields\n"); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static const struct of_device_id hisi_pcie_of_match[] = { | ||
184 | {.compatible = "hisilicon,hip05-pcie",}, | ||
185 | {}, | ||
186 | }; | ||
187 | |||
188 | MODULE_DEVICE_TABLE(of, hisi_pcie_of_match); | ||
189 | |||
190 | static struct platform_driver hisi_pcie_driver = { | ||
191 | .probe = hisi_pcie_probe, | ||
192 | .driver = { | ||
193 | .name = "hisi-pcie", | ||
194 | .of_match_table = hisi_pcie_of_match, | ||
195 | }, | ||
196 | }; | ||
197 | |||
198 | module_platform_driver(hisi_pcie_driver); | ||
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c index 9aedc8eb2c6e..c9550dc8b8ed 100644 --- a/drivers/pci/host/pcie-iproc-platform.c +++ b/drivers/pci/host/pcie-iproc-platform.c | |||
@@ -54,6 +54,33 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev) | |||
54 | return -ENOMEM; | 54 | return -ENOMEM; |
55 | } | 55 | } |
56 | 56 | ||
57 | if (of_property_read_bool(np, "brcm,pcie-ob")) { | ||
58 | u32 val; | ||
59 | |||
60 | ret = of_property_read_u32(np, "brcm,pcie-ob-axi-offset", | ||
61 | &val); | ||
62 | if (ret) { | ||
63 | dev_err(pcie->dev, | ||
64 | "missing brcm,pcie-ob-axi-offset property\n"); | ||
65 | return ret; | ||
66 | } | ||
67 | pcie->ob.axi_offset = val; | ||
68 | |||
69 | ret = of_property_read_u32(np, "brcm,pcie-ob-window-size", | ||
70 | &val); | ||
71 | if (ret) { | ||
72 | dev_err(pcie->dev, | ||
73 | "missing brcm,pcie-ob-window-size property\n"); | ||
74 | return ret; | ||
75 | } | ||
76 | pcie->ob.window_size = (resource_size_t)val * SZ_1M; | ||
77 | |||
78 | if (of_property_read_bool(np, "brcm,pcie-ob-oarr-size")) | ||
79 | pcie->ob.set_oarr_size = true; | ||
80 | |||
81 | pcie->need_ob_cfg = true; | ||
82 | } | ||
83 | |||
57 | /* PHY use is optional */ | 84 | /* PHY use is optional */ |
58 | pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy"); | 85 | pcie->phy = devm_phy_get(&pdev->dev, "pcie-phy"); |
59 | if (IS_ERR(pcie->phy)) { | 86 | if (IS_ERR(pcie->phy)) { |
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c index fe2efb141a9b..eac719af16aa 100644 --- a/drivers/pci/host/pcie-iproc.c +++ b/drivers/pci/host/pcie-iproc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de> | 2 | * Copyright (C) 2014 Hauke Mehrtens <hauke@hauke-m.de> |
3 | * Copyright (C) 2015 Broadcom Corporatcommon ion | 3 | * Copyright (C) 2015 Broadcom Corporation |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License as | 6 | * modify it under the terms of the GNU General Public License as |
@@ -31,6 +31,8 @@ | |||
31 | #include "pcie-iproc.h" | 31 | #include "pcie-iproc.h" |
32 | 32 | ||
33 | #define CLK_CONTROL_OFFSET 0x000 | 33 | #define CLK_CONTROL_OFFSET 0x000 |
34 | #define EP_PERST_SOURCE_SELECT_SHIFT 2 | ||
35 | #define EP_PERST_SOURCE_SELECT BIT(EP_PERST_SOURCE_SELECT_SHIFT) | ||
34 | #define EP_MODE_SURVIVE_PERST_SHIFT 1 | 36 | #define EP_MODE_SURVIVE_PERST_SHIFT 1 |
35 | #define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT) | 37 | #define EP_MODE_SURVIVE_PERST BIT(EP_MODE_SURVIVE_PERST_SHIFT) |
36 | #define RC_PCIE_RST_OUTPUT_SHIFT 0 | 38 | #define RC_PCIE_RST_OUTPUT_SHIFT 0 |
@@ -58,6 +60,24 @@ | |||
58 | #define SYS_RC_INTX_EN 0x330 | 60 | #define SYS_RC_INTX_EN 0x330 |
59 | #define SYS_RC_INTX_MASK 0xf | 61 | #define SYS_RC_INTX_MASK 0xf |
60 | 62 | ||
63 | #define PCIE_LINK_STATUS_OFFSET 0xf0c | ||
64 | #define PCIE_PHYLINKUP_SHIFT 3 | ||
65 | #define PCIE_PHYLINKUP BIT(PCIE_PHYLINKUP_SHIFT) | ||
66 | #define PCIE_DL_ACTIVE_SHIFT 2 | ||
67 | #define PCIE_DL_ACTIVE BIT(PCIE_DL_ACTIVE_SHIFT) | ||
68 | |||
69 | #define OARR_VALID_SHIFT 0 | ||
70 | #define OARR_VALID BIT(OARR_VALID_SHIFT) | ||
71 | #define OARR_SIZE_CFG_SHIFT 1 | ||
72 | #define OARR_SIZE_CFG BIT(OARR_SIZE_CFG_SHIFT) | ||
73 | |||
74 | #define OARR_LO(window) (0xd20 + (window) * 8) | ||
75 | #define OARR_HI(window) (0xd24 + (window) * 8) | ||
76 | #define OMAP_LO(window) (0xd40 + (window) * 8) | ||
77 | #define OMAP_HI(window) (0xd44 + (window) * 8) | ||
78 | |||
79 | #define MAX_NUM_OB_WINDOWS 2 | ||
80 | |||
61 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) | 81 | static inline struct iproc_pcie *iproc_data(struct pci_bus *bus) |
62 | { | 82 | { |
63 | struct iproc_pcie *pcie; | 83 | struct iproc_pcie *pcie; |
@@ -119,23 +139,32 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie) | |||
119 | u32 val; | 139 | u32 val; |
120 | 140 | ||
121 | /* | 141 | /* |
122 | * Configure the PCIe controller as root complex and send a downstream | 142 | * Select perst_b signal as reset source. Put the device into reset, |
123 | * reset | 143 | * and then bring it out of reset |
124 | */ | 144 | */ |
125 | val = EP_MODE_SURVIVE_PERST | RC_PCIE_RST_OUTPUT; | 145 | val = readl(pcie->base + CLK_CONTROL_OFFSET); |
146 | val &= ~EP_PERST_SOURCE_SELECT & ~EP_MODE_SURVIVE_PERST & | ||
147 | ~RC_PCIE_RST_OUTPUT; | ||
126 | writel(val, pcie->base + CLK_CONTROL_OFFSET); | 148 | writel(val, pcie->base + CLK_CONTROL_OFFSET); |
127 | udelay(250); | 149 | udelay(250); |
128 | val &= ~EP_MODE_SURVIVE_PERST; | 150 | |
151 | val |= RC_PCIE_RST_OUTPUT; | ||
129 | writel(val, pcie->base + CLK_CONTROL_OFFSET); | 152 | writel(val, pcie->base + CLK_CONTROL_OFFSET); |
130 | msleep(250); | 153 | msleep(100); |
131 | } | 154 | } |
132 | 155 | ||
133 | static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | 156 | static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) |
134 | { | 157 | { |
135 | u8 hdr_type; | 158 | u8 hdr_type; |
136 | u32 link_ctrl; | 159 | u32 link_ctrl, class, val; |
137 | u16 pos, link_status; | 160 | u16 pos, link_status; |
138 | int link_is_active = 0; | 161 | bool link_is_active = false; |
162 | |||
163 | val = readl(pcie->base + PCIE_LINK_STATUS_OFFSET); | ||
164 | if (!(val & PCIE_PHYLINKUP) || !(val & PCIE_DL_ACTIVE)) { | ||
165 | dev_err(pcie->dev, "PHY or data link is INACTIVE!\n"); | ||
166 | return -ENODEV; | ||
167 | } | ||
139 | 168 | ||
140 | /* make sure we are not in EP mode */ | 169 | /* make sure we are not in EP mode */ |
141 | pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); | 170 | pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); |
@@ -145,14 +174,19 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | |||
145 | } | 174 | } |
146 | 175 | ||
147 | /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ | 176 | /* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */ |
148 | pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE, | 177 | #define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c |
149 | PCI_CLASS_BRIDGE_PCI); | 178 | #define PCI_CLASS_BRIDGE_MASK 0xffff00 |
179 | #define PCI_CLASS_BRIDGE_SHIFT 8 | ||
180 | pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class); | ||
181 | class &= ~PCI_CLASS_BRIDGE_MASK; | ||
182 | class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); | ||
183 | pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class); | ||
150 | 184 | ||
151 | /* check link status to see if link is active */ | 185 | /* check link status to see if link is active */ |
152 | pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); | 186 | pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP); |
153 | pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); | 187 | pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); |
154 | if (link_status & PCI_EXP_LNKSTA_NLW) | 188 | if (link_status & PCI_EXP_LNKSTA_NLW) |
155 | link_is_active = 1; | 189 | link_is_active = true; |
156 | 190 | ||
157 | if (!link_is_active) { | 191 | if (!link_is_active) { |
158 | /* try GEN 1 link speed */ | 192 | /* try GEN 1 link speed */ |
@@ -176,7 +210,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) | |||
176 | pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, | 210 | pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, |
177 | &link_status); | 211 | &link_status); |
178 | if (link_status & PCI_EXP_LNKSTA_NLW) | 212 | if (link_status & PCI_EXP_LNKSTA_NLW) |
179 | link_is_active = 1; | 213 | link_is_active = true; |
180 | } | 214 | } |
181 | } | 215 | } |
182 | 216 | ||
@@ -190,6 +224,101 @@ static void iproc_pcie_enable(struct iproc_pcie *pcie) | |||
190 | writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); | 224 | writel(SYS_RC_INTX_MASK, pcie->base + SYS_RC_INTX_EN); |
191 | } | 225 | } |
192 | 226 | ||
227 | /** | ||
228 | * Some iProc SoCs require the SW to configure the outbound address mapping | ||
229 | * | ||
230 | * Outbound address translation: | ||
231 | * | ||
232 | * iproc_pcie_address = axi_address - axi_offset | ||
233 | * OARR = iproc_pcie_address | ||
234 | * OMAP = pci_addr | ||
235 | * | ||
236 | * axi_addr -> iproc_pcie_address -> OARR -> OMAP -> pci_address | ||
237 | */ | ||
238 | static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, u64 axi_addr, | ||
239 | u64 pci_addr, resource_size_t size) | ||
240 | { | ||
241 | struct iproc_pcie_ob *ob = &pcie->ob; | ||
242 | unsigned i; | ||
243 | u64 max_size = (u64)ob->window_size * MAX_NUM_OB_WINDOWS; | ||
244 | u64 remainder; | ||
245 | |||
246 | if (size > max_size) { | ||
247 | dev_err(pcie->dev, | ||
248 | "res size 0x%pap exceeds max supported size 0x%llx\n", | ||
249 | &size, max_size); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | div64_u64_rem(size, ob->window_size, &remainder); | ||
254 | if (remainder) { | ||
255 | dev_err(pcie->dev, | ||
256 | "res size %pap needs to be multiple of window size %pap\n", | ||
257 | &size, &ob->window_size); | ||
258 | return -EINVAL; | ||
259 | } | ||
260 | |||
261 | if (axi_addr < ob->axi_offset) { | ||
262 | dev_err(pcie->dev, | ||
263 | "axi address %pap less than offset %pap\n", | ||
264 | &axi_addr, &ob->axi_offset); | ||
265 | return -EINVAL; | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * Translate the AXI address to the internal address used by the iProc | ||
270 | * PCIe core before programming the OARR | ||
271 | */ | ||
272 | axi_addr -= ob->axi_offset; | ||
273 | |||
274 | for (i = 0; i < MAX_NUM_OB_WINDOWS; i++) { | ||
275 | writel(lower_32_bits(axi_addr) | OARR_VALID | | ||
276 | (ob->set_oarr_size ? 1 : 0), pcie->base + OARR_LO(i)); | ||
277 | writel(upper_32_bits(axi_addr), pcie->base + OARR_HI(i)); | ||
278 | writel(lower_32_bits(pci_addr), pcie->base + OMAP_LO(i)); | ||
279 | writel(upper_32_bits(pci_addr), pcie->base + OMAP_HI(i)); | ||
280 | |||
281 | size -= ob->window_size; | ||
282 | if (size == 0) | ||
283 | break; | ||
284 | |||
285 | axi_addr += ob->window_size; | ||
286 | pci_addr += ob->window_size; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int iproc_pcie_map_ranges(struct iproc_pcie *pcie, | ||
293 | struct list_head *resources) | ||
294 | { | ||
295 | struct resource_entry *window; | ||
296 | int ret; | ||
297 | |||
298 | resource_list_for_each_entry(window, resources) { | ||
299 | struct resource *res = window->res; | ||
300 | u64 res_type = resource_type(res); | ||
301 | |||
302 | switch (res_type) { | ||
303 | case IORESOURCE_IO: | ||
304 | case IORESOURCE_BUS: | ||
305 | break; | ||
306 | case IORESOURCE_MEM: | ||
307 | ret = iproc_pcie_setup_ob(pcie, res->start, | ||
308 | res->start - window->offset, | ||
309 | resource_size(res)); | ||
310 | if (ret) | ||
311 | return ret; | ||
312 | break; | ||
313 | default: | ||
314 | dev_err(pcie->dev, "invalid resource %pR\n", res); | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
193 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | 322 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) |
194 | { | 323 | { |
195 | int ret; | 324 | int ret; |
@@ -213,6 +342,14 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
213 | 342 | ||
214 | iproc_pcie_reset(pcie); | 343 | iproc_pcie_reset(pcie); |
215 | 344 | ||
345 | if (pcie->need_ob_cfg) { | ||
346 | ret = iproc_pcie_map_ranges(pcie, res); | ||
347 | if (ret) { | ||
348 | dev_err(pcie->dev, "map failed\n"); | ||
349 | goto err_power_off_phy; | ||
350 | } | ||
351 | } | ||
352 | |||
216 | #ifdef CONFIG_ARM | 353 | #ifdef CONFIG_ARM |
217 | pcie->sysdata.private_data = pcie; | 354 | pcie->sysdata.private_data = pcie; |
218 | sysdata = &pcie->sysdata; | 355 | sysdata = &pcie->sysdata; |
@@ -238,9 +375,7 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) | |||
238 | 375 | ||
239 | pci_scan_child_bus(bus); | 376 | pci_scan_child_bus(bus); |
240 | pci_assign_unassigned_bus_resources(bus); | 377 | pci_assign_unassigned_bus_resources(bus); |
241 | #ifdef CONFIG_ARM | ||
242 | pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); | 378 | pci_fixup_irqs(pci_common_swizzle, pcie->map_irq); |
243 | #endif | ||
244 | pci_bus_add_devices(bus); | 379 | pci_bus_add_devices(bus); |
245 | 380 | ||
246 | return 0; | 381 | return 0; |
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/host/pcie-iproc.h index c9e4c10a462e..d3dc940f773a 100644 --- a/drivers/pci/host/pcie-iproc.h +++ b/drivers/pci/host/pcie-iproc.h | |||
@@ -14,17 +14,30 @@ | |||
14 | #ifndef _PCIE_IPROC_H | 14 | #ifndef _PCIE_IPROC_H |
15 | #define _PCIE_IPROC_H | 15 | #define _PCIE_IPROC_H |
16 | 16 | ||
17 | #define IPROC_PCIE_MAX_NUM_IRQS 6 | 17 | /** |
18 | * iProc PCIe outbound mapping | ||
19 | * @set_oarr_size: indicates the OARR size bit needs to be set | ||
20 | * @axi_offset: offset from the AXI address to the internal address used by | ||
21 | * the iProc PCIe core | ||
22 | * @window_size: outbound window size | ||
23 | */ | ||
24 | struct iproc_pcie_ob { | ||
25 | bool set_oarr_size; | ||
26 | resource_size_t axi_offset; | ||
27 | resource_size_t window_size; | ||
28 | }; | ||
18 | 29 | ||
19 | /** | 30 | /** |
20 | * iProc PCIe device | 31 | * iProc PCIe device |
21 | * @dev: pointer to device data structure | 32 | * @dev: pointer to device data structure |
22 | * @base: PCIe host controller I/O register base | 33 | * @base: PCIe host controller I/O register base |
23 | * @resources: linked list of all PCI resources | ||
24 | * @sysdata: Per PCI controller data (ARM-specific) | 34 | * @sysdata: Per PCI controller data (ARM-specific) |
25 | * @root_bus: pointer to root bus | 35 | * @root_bus: pointer to root bus |
26 | * @phy: optional PHY device that controls the Serdes | 36 | * @phy: optional PHY device that controls the Serdes |
27 | * @irqs: interrupt IDs | 37 | * @irqs: interrupt IDs |
38 | * @map_irq: function callback to map interrupts | ||
39 | * @need_ob_cfg: indidates SW needs to configure the outbound mapping window | ||
40 | * @ob: outbound mapping parameters | ||
28 | */ | 41 | */ |
29 | struct iproc_pcie { | 42 | struct iproc_pcie { |
30 | struct device *dev; | 43 | struct device *dev; |
@@ -34,8 +47,9 @@ struct iproc_pcie { | |||
34 | #endif | 47 | #endif |
35 | struct pci_bus *root_bus; | 48 | struct pci_bus *root_bus; |
36 | struct phy *phy; | 49 | struct phy *phy; |
37 | int irqs[IPROC_PCIE_MAX_NUM_IRQS]; | ||
38 | int (*map_irq)(const struct pci_dev *, u8, u8); | 50 | int (*map_irq)(const struct pci_dev *, u8, u8); |
51 | bool need_ob_cfg; | ||
52 | struct iproc_pcie_ob ob; | ||
39 | }; | 53 | }; |
40 | 54 | ||
41 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); | 55 | int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res); |
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 7678fe0820d7..f4fa6c537448 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c | |||
@@ -108,6 +108,8 @@ | |||
108 | #define RCAR_PCI_MAX_RESOURCES 4 | 108 | #define RCAR_PCI_MAX_RESOURCES 4 |
109 | #define MAX_NR_INBOUND_MAPS 6 | 109 | #define MAX_NR_INBOUND_MAPS 6 |
110 | 110 | ||
111 | static unsigned long global_io_offset; | ||
112 | |||
111 | struct rcar_msi { | 113 | struct rcar_msi { |
112 | DECLARE_BITMAP(used, INT_PCI_MSI_NR); | 114 | DECLARE_BITMAP(used, INT_PCI_MSI_NR); |
113 | struct irq_domain *domain; | 115 | struct irq_domain *domain; |
@@ -124,7 +126,16 @@ static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) | |||
124 | } | 126 | } |
125 | 127 | ||
126 | /* Structure representing the PCIe interface */ | 128 | /* Structure representing the PCIe interface */ |
129 | /* | ||
130 | * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI | ||
131 | * sysdata. Add pci_sys_data as the first element in struct gen_pci so | ||
132 | * that when we use a gen_pci pointer as sysdata, it is also a pointer to | ||
133 | * a struct pci_sys_data. | ||
134 | */ | ||
127 | struct rcar_pcie { | 135 | struct rcar_pcie { |
136 | #ifdef CONFIG_ARM | ||
137 | struct pci_sys_data sys; | ||
138 | #endif | ||
128 | struct device *dev; | 139 | struct device *dev; |
129 | void __iomem *base; | 140 | void __iomem *base; |
130 | struct resource res[RCAR_PCI_MAX_RESOURCES]; | 141 | struct resource res[RCAR_PCI_MAX_RESOURCES]; |
@@ -135,11 +146,6 @@ struct rcar_pcie { | |||
135 | struct rcar_msi msi; | 146 | struct rcar_msi msi; |
136 | }; | 147 | }; |
137 | 148 | ||
138 | static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys) | ||
139 | { | ||
140 | return sys->private_data; | ||
141 | } | ||
142 | |||
143 | static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, | 149 | static void rcar_pci_write_reg(struct rcar_pcie *pcie, unsigned long val, |
144 | unsigned long reg) | 150 | unsigned long reg) |
145 | { | 151 | { |
@@ -258,7 +264,7 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie, | |||
258 | static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, | 264 | static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, |
259 | int where, int size, u32 *val) | 265 | int where, int size, u32 *val) |
260 | { | 266 | { |
261 | struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata); | 267 | struct rcar_pcie *pcie = bus->sysdata; |
262 | int ret; | 268 | int ret; |
263 | 269 | ||
264 | ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ, | 270 | ret = rcar_pcie_config_access(pcie, RCAR_PCI_ACCESS_READ, |
@@ -283,7 +289,7 @@ static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, | |||
283 | static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, | 289 | static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, |
284 | int where, int size, u32 val) | 290 | int where, int size, u32 val) |
285 | { | 291 | { |
286 | struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata); | 292 | struct rcar_pcie *pcie = bus->sysdata; |
287 | int shift, ret; | 293 | int shift, ret; |
288 | u32 data; | 294 | u32 data; |
289 | 295 | ||
@@ -353,13 +359,12 @@ static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie) | |||
353 | rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win)); | 359 | rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win)); |
354 | } | 360 | } |
355 | 361 | ||
356 | static int rcar_pcie_setup(int nr, struct pci_sys_data *sys) | 362 | static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pcie) |
357 | { | 363 | { |
358 | struct rcar_pcie *pcie = sys_to_pcie(sys); | ||
359 | struct resource *res; | 364 | struct resource *res; |
360 | int i; | 365 | int i; |
361 | 366 | ||
362 | pcie->root_bus_nr = -1; | 367 | pcie->root_bus_nr = pcie->busn.start; |
363 | 368 | ||
364 | /* Setup PCI resources */ | 369 | /* Setup PCI resources */ |
365 | for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) { | 370 | for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) { |
@@ -372,32 +377,53 @@ static int rcar_pcie_setup(int nr, struct pci_sys_data *sys) | |||
372 | 377 | ||
373 | if (res->flags & IORESOURCE_IO) { | 378 | if (res->flags & IORESOURCE_IO) { |
374 | phys_addr_t io_start = pci_pio_to_address(res->start); | 379 | phys_addr_t io_start = pci_pio_to_address(res->start); |
375 | pci_ioremap_io(nr * SZ_64K, io_start); | 380 | pci_ioremap_io(global_io_offset, io_start); |
376 | } else | 381 | global_io_offset += SZ_64K; |
377 | pci_add_resource(&sys->resources, res); | 382 | } |
383 | |||
384 | pci_add_resource(resource, res); | ||
378 | } | 385 | } |
379 | pci_add_resource(&sys->resources, &pcie->busn); | 386 | pci_add_resource(resource, &pcie->busn); |
380 | 387 | ||
381 | return 1; | 388 | return 1; |
382 | } | 389 | } |
383 | 390 | ||
384 | static struct hw_pci rcar_pci = { | 391 | static int rcar_pcie_enable(struct rcar_pcie *pcie) |
385 | .setup = rcar_pcie_setup, | ||
386 | .map_irq = of_irq_parse_and_map_pci, | ||
387 | .ops = &rcar_pcie_ops, | ||
388 | }; | ||
389 | |||
390 | static void rcar_pcie_enable(struct rcar_pcie *pcie) | ||
391 | { | 392 | { |
392 | struct platform_device *pdev = to_platform_device(pcie->dev); | 393 | struct pci_bus *bus, *child; |
394 | LIST_HEAD(res); | ||
393 | 395 | ||
394 | rcar_pci.nr_controllers = 1; | 396 | rcar_pcie_setup(&res, pcie); |
395 | rcar_pci.private_data = (void **)&pcie; | 397 | |
396 | #ifdef CONFIG_PCI_MSI | 398 | /* Do not reassign resources if probe only */ |
397 | rcar_pci.msi_ctrl = &pcie->msi.chip; | 399 | if (!pci_has_flag(PCI_PROBE_ONLY)) |
398 | #endif | 400 | pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); |
399 | 401 | ||
400 | pci_common_init_dev(&pdev->dev, &rcar_pci); | 402 | if (IS_ENABLED(CONFIG_PCI_MSI)) |
403 | bus = pci_scan_root_bus_msi(pcie->dev, pcie->root_bus_nr, | ||
404 | &rcar_pcie_ops, pcie, &res, &pcie->msi.chip); | ||
405 | else | ||
406 | bus = pci_scan_root_bus(pcie->dev, pcie->root_bus_nr, | ||
407 | &rcar_pcie_ops, pcie, &res); | ||
408 | |||
409 | if (!bus) { | ||
410 | dev_err(pcie->dev, "Scanning rootbus failed"); | ||
411 | return -ENODEV; | ||
412 | } | ||
413 | |||
414 | pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); | ||
415 | |||
416 | if (!pci_has_flag(PCI_PROBE_ONLY)) { | ||
417 | pci_bus_size_bridges(bus); | ||
418 | pci_bus_assign_resources(bus); | ||
419 | |||
420 | list_for_each_entry(child, &bus->children, node) | ||
421 | pcie_bus_configure_settings(child); | ||
422 | } | ||
423 | |||
424 | pci_bus_add_devices(bus); | ||
425 | |||
426 | return 0; | ||
401 | } | 427 | } |
402 | 428 | ||
403 | static int phy_wait_for_ack(struct rcar_pcie *pcie) | 429 | static int phy_wait_for_ack(struct rcar_pcie *pcie) |
@@ -970,9 +996,7 @@ static int rcar_pcie_probe(struct platform_device *pdev) | |||
970 | data = rcar_pci_read_reg(pcie, MACSR); | 996 | data = rcar_pci_read_reg(pcie, MACSR); |
971 | dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); | 997 | dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); |
972 | 998 | ||
973 | rcar_pcie_enable(pcie); | 999 | return rcar_pcie_enable(pcie); |
974 | |||
975 | return 0; | ||
976 | } | 1000 | } |
977 | 1001 | ||
978 | static struct platform_driver rcar_pcie_driver = { | 1002 | static struct platform_driver rcar_pcie_driver = { |
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c index 98d2683181bc..b95b7563c052 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/host/pcie-spear13xx.c | |||
@@ -163,34 +163,34 @@ static int spear13xx_pcie_establish_link(struct pcie_port *pp) | |||
163 | * default value in capability register is 512 bytes. So force | 163 | * default value in capability register is 512 bytes. So force |
164 | * it to 128 here. | 164 | * it to 128 here. |
165 | */ | 165 | */ |
166 | dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, &val); | 166 | dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, &val); |
167 | val &= ~PCI_EXP_DEVCTL_READRQ; | 167 | val &= ~PCI_EXP_DEVCTL_READRQ; |
168 | dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + PCI_EXP_DEVCTL, 4, val); | 168 | dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, val); |
169 | 169 | ||
170 | dw_pcie_cfg_write(pp->dbi_base, PCI_VENDOR_ID, 2, 0x104A); | 170 | dw_pcie_cfg_write(pp->dbi_base + PCI_VENDOR_ID, 2, 0x104A); |
171 | dw_pcie_cfg_write(pp->dbi_base, PCI_DEVICE_ID, 2, 0xCD80); | 171 | dw_pcie_cfg_write(pp->dbi_base + PCI_DEVICE_ID, 2, 0xCD80); |
172 | 172 | ||
173 | /* | 173 | /* |
174 | * if is_gen1 is set then handle it, so that some buggy card | 174 | * if is_gen1 is set then handle it, so that some buggy card |
175 | * also works | 175 | * also works |
176 | */ | 176 | */ |
177 | if (spear13xx_pcie->is_gen1) { | 177 | if (spear13xx_pcie->is_gen1) { |
178 | dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCAP, 4, | 178 | dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCAP, |
179 | &val); | 179 | 4, &val); |
180 | if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { | 180 | if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { |
181 | val &= ~((u32)PCI_EXP_LNKCAP_SLS); | 181 | val &= ~((u32)PCI_EXP_LNKCAP_SLS); |
182 | val |= PCI_EXP_LNKCAP_SLS_2_5GB; | 182 | val |= PCI_EXP_LNKCAP_SLS_2_5GB; |
183 | dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + | 183 | dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + |
184 | PCI_EXP_LNKCAP, 4, val); | 184 | PCI_EXP_LNKCAP, 4, val); |
185 | } | 185 | } |
186 | 186 | ||
187 | dw_pcie_cfg_read(pp->dbi_base, exp_cap_off + PCI_EXP_LNKCTL2, 4, | 187 | dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2, |
188 | &val); | 188 | 2, &val); |
189 | if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { | 189 | if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { |
190 | val &= ~((u32)PCI_EXP_LNKCAP_SLS); | 190 | val &= ~((u32)PCI_EXP_LNKCAP_SLS); |
191 | val |= PCI_EXP_LNKCAP_SLS_2_5GB; | 191 | val |= PCI_EXP_LNKCAP_SLS_2_5GB; |
192 | dw_pcie_cfg_write(pp->dbi_base, exp_cap_off + | 192 | dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + |
193 | PCI_EXP_LNKCTL2, 4, val); | 193 | PCI_EXP_LNKCTL2, 2, val); |
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index f3796124ad7c..4c8f4cde6854 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -204,36 +204,39 @@ static void pciehp_power_thread(struct work_struct *work) | |||
204 | kfree(info); | 204 | kfree(info); |
205 | } | 205 | } |
206 | 206 | ||
207 | void pciehp_queue_pushbutton_work(struct work_struct *work) | 207 | static void pciehp_queue_power_work(struct slot *p_slot, int req) |
208 | { | 208 | { |
209 | struct slot *p_slot = container_of(work, struct slot, work.work); | ||
210 | struct power_work_info *info; | 209 | struct power_work_info *info; |
211 | 210 | ||
211 | p_slot->state = (req == ENABLE_REQ) ? POWERON_STATE : POWEROFF_STATE; | ||
212 | |||
212 | info = kmalloc(sizeof(*info), GFP_KERNEL); | 213 | info = kmalloc(sizeof(*info), GFP_KERNEL); |
213 | if (!info) { | 214 | if (!info) { |
214 | ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", | 215 | ctrl_err(p_slot->ctrl, "no memory to queue %s request\n", |
215 | __func__); | 216 | (req == ENABLE_REQ) ? "poweron" : "poweroff"); |
216 | return; | 217 | return; |
217 | } | 218 | } |
218 | info->p_slot = p_slot; | 219 | info->p_slot = p_slot; |
219 | INIT_WORK(&info->work, pciehp_power_thread); | 220 | INIT_WORK(&info->work, pciehp_power_thread); |
221 | info->req = req; | ||
222 | queue_work(p_slot->wq, &info->work); | ||
223 | } | ||
224 | |||
225 | void pciehp_queue_pushbutton_work(struct work_struct *work) | ||
226 | { | ||
227 | struct slot *p_slot = container_of(work, struct slot, work.work); | ||
220 | 228 | ||
221 | mutex_lock(&p_slot->lock); | 229 | mutex_lock(&p_slot->lock); |
222 | switch (p_slot->state) { | 230 | switch (p_slot->state) { |
223 | case BLINKINGOFF_STATE: | 231 | case BLINKINGOFF_STATE: |
224 | p_slot->state = POWEROFF_STATE; | 232 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
225 | info->req = DISABLE_REQ; | ||
226 | break; | 233 | break; |
227 | case BLINKINGON_STATE: | 234 | case BLINKINGON_STATE: |
228 | p_slot->state = POWERON_STATE; | 235 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
229 | info->req = ENABLE_REQ; | ||
230 | break; | 236 | break; |
231 | default: | 237 | default: |
232 | kfree(info); | 238 | break; |
233 | goto out; | ||
234 | } | 239 | } |
235 | queue_work(p_slot->wq, &info->work); | ||
236 | out: | ||
237 | mutex_unlock(&p_slot->lock); | 240 | mutex_unlock(&p_slot->lock); |
238 | } | 241 | } |
239 | 242 | ||
@@ -301,27 +304,12 @@ static void handle_button_press_event(struct slot *p_slot) | |||
301 | static void handle_surprise_event(struct slot *p_slot) | 304 | static void handle_surprise_event(struct slot *p_slot) |
302 | { | 305 | { |
303 | u8 getstatus; | 306 | u8 getstatus; |
304 | struct power_work_info *info; | ||
305 | |||
306 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
307 | if (!info) { | ||
308 | ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", | ||
309 | __func__); | ||
310 | return; | ||
311 | } | ||
312 | info->p_slot = p_slot; | ||
313 | INIT_WORK(&info->work, pciehp_power_thread); | ||
314 | 307 | ||
315 | pciehp_get_adapter_status(p_slot, &getstatus); | 308 | pciehp_get_adapter_status(p_slot, &getstatus); |
316 | if (!getstatus) { | 309 | if (!getstatus) |
317 | p_slot->state = POWEROFF_STATE; | 310 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
318 | info->req = DISABLE_REQ; | 311 | else |
319 | } else { | 312 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
320 | p_slot->state = POWERON_STATE; | ||
321 | info->req = ENABLE_REQ; | ||
322 | } | ||
323 | |||
324 | queue_work(p_slot->wq, &info->work); | ||
325 | } | 313 | } |
326 | 314 | ||
327 | /* | 315 | /* |
@@ -330,17 +318,6 @@ static void handle_surprise_event(struct slot *p_slot) | |||
330 | static void handle_link_event(struct slot *p_slot, u32 event) | 318 | static void handle_link_event(struct slot *p_slot, u32 event) |
331 | { | 319 | { |
332 | struct controller *ctrl = p_slot->ctrl; | 320 | struct controller *ctrl = p_slot->ctrl; |
333 | struct power_work_info *info; | ||
334 | |||
335 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
336 | if (!info) { | ||
337 | ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", | ||
338 | __func__); | ||
339 | return; | ||
340 | } | ||
341 | info->p_slot = p_slot; | ||
342 | info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ; | ||
343 | INIT_WORK(&info->work, pciehp_power_thread); | ||
344 | 321 | ||
345 | switch (p_slot->state) { | 322 | switch (p_slot->state) { |
346 | case BLINKINGON_STATE: | 323 | case BLINKINGON_STATE: |
@@ -348,22 +325,19 @@ static void handle_link_event(struct slot *p_slot, u32 event) | |||
348 | cancel_delayed_work(&p_slot->work); | 325 | cancel_delayed_work(&p_slot->work); |
349 | /* Fall through */ | 326 | /* Fall through */ |
350 | case STATIC_STATE: | 327 | case STATIC_STATE: |
351 | p_slot->state = event == INT_LINK_UP ? | 328 | pciehp_queue_power_work(p_slot, event == INT_LINK_UP ? |
352 | POWERON_STATE : POWEROFF_STATE; | 329 | ENABLE_REQ : DISABLE_REQ); |
353 | queue_work(p_slot->wq, &info->work); | ||
354 | break; | 330 | break; |
355 | case POWERON_STATE: | 331 | case POWERON_STATE: |
356 | if (event == INT_LINK_UP) { | 332 | if (event == INT_LINK_UP) { |
357 | ctrl_info(ctrl, | 333 | ctrl_info(ctrl, |
358 | "Link Up event ignored on slot(%s): already powering on\n", | 334 | "Link Up event ignored on slot(%s): already powering on\n", |
359 | slot_name(p_slot)); | 335 | slot_name(p_slot)); |
360 | kfree(info); | ||
361 | } else { | 336 | } else { |
362 | ctrl_info(ctrl, | 337 | ctrl_info(ctrl, |
363 | "Link Down event queued on slot(%s): currently getting powered on\n", | 338 | "Link Down event queued on slot(%s): currently getting powered on\n", |
364 | slot_name(p_slot)); | 339 | slot_name(p_slot)); |
365 | p_slot->state = POWEROFF_STATE; | 340 | pciehp_queue_power_work(p_slot, DISABLE_REQ); |
366 | queue_work(p_slot->wq, &info->work); | ||
367 | } | 341 | } |
368 | break; | 342 | break; |
369 | case POWEROFF_STATE: | 343 | case POWEROFF_STATE: |
@@ -371,19 +345,16 @@ static void handle_link_event(struct slot *p_slot, u32 event) | |||
371 | ctrl_info(ctrl, | 345 | ctrl_info(ctrl, |
372 | "Link Up event queued on slot(%s): currently getting powered off\n", | 346 | "Link Up event queued on slot(%s): currently getting powered off\n", |
373 | slot_name(p_slot)); | 347 | slot_name(p_slot)); |
374 | p_slot->state = POWERON_STATE; | 348 | pciehp_queue_power_work(p_slot, ENABLE_REQ); |
375 | queue_work(p_slot->wq, &info->work); | ||
376 | } else { | 349 | } else { |
377 | ctrl_info(ctrl, | 350 | ctrl_info(ctrl, |
378 | "Link Down event ignored on slot(%s): already powering off\n", | 351 | "Link Down event ignored on slot(%s): already powering off\n", |
379 | slot_name(p_slot)); | 352 | slot_name(p_slot)); |
380 | kfree(info); | ||
381 | } | 353 | } |
382 | break; | 354 | break; |
383 | default: | 355 | default: |
384 | ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n", | 356 | ctrl_err(ctrl, "ignoring invalid state %#x on slot(%s)\n", |
385 | p_slot->state, slot_name(p_slot)); | 357 | p_slot->state, slot_name(p_slot)); |
386 | kfree(info); | ||
387 | break; | 358 | break; |
388 | } | 359 | } |
389 | } | 360 | } |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index ee0ebff103a4..31f31d460fc9 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -54,24 +54,29 @@ static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn) | |||
54 | * The PF consumes one bus number. NumVFs, First VF Offset, and VF Stride | 54 | * The PF consumes one bus number. NumVFs, First VF Offset, and VF Stride |
55 | * determine how many additional bus numbers will be consumed by VFs. | 55 | * determine how many additional bus numbers will be consumed by VFs. |
56 | * | 56 | * |
57 | * Iterate over all valid NumVFs and calculate the maximum number of bus | 57 | * Iterate over all valid NumVFs, validate offset and stride, and calculate |
58 | * numbers that could ever be required. | 58 | * the maximum number of bus numbers that could ever be required. |
59 | */ | 59 | */ |
60 | static inline u8 virtfn_max_buses(struct pci_dev *dev) | 60 | static int compute_max_vf_buses(struct pci_dev *dev) |
61 | { | 61 | { |
62 | struct pci_sriov *iov = dev->sriov; | 62 | struct pci_sriov *iov = dev->sriov; |
63 | int nr_virtfn; | 63 | int nr_virtfn, busnr, rc = 0; |
64 | u8 max = 0; | ||
65 | int busnr; | ||
66 | 64 | ||
67 | for (nr_virtfn = 1; nr_virtfn <= iov->total_VFs; nr_virtfn++) { | 65 | for (nr_virtfn = iov->total_VFs; nr_virtfn; nr_virtfn--) { |
68 | pci_iov_set_numvfs(dev, nr_virtfn); | 66 | pci_iov_set_numvfs(dev, nr_virtfn); |
67 | if (!iov->offset || (nr_virtfn > 1 && !iov->stride)) { | ||
68 | rc = -EIO; | ||
69 | goto out; | ||
70 | } | ||
71 | |||
69 | busnr = pci_iov_virtfn_bus(dev, nr_virtfn - 1); | 72 | busnr = pci_iov_virtfn_bus(dev, nr_virtfn - 1); |
70 | if (busnr > max) | 73 | if (busnr > iov->max_VF_buses) |
71 | max = busnr; | 74 | iov->max_VF_buses = busnr; |
72 | } | 75 | } |
73 | 76 | ||
74 | return max; | 77 | out: |
78 | pci_iov_set_numvfs(dev, 0); | ||
79 | return rc; | ||
75 | } | 80 | } |
76 | 81 | ||
77 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) | 82 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) |
@@ -222,21 +227,25 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset) | |||
222 | 227 | ||
223 | int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs) | 228 | int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs) |
224 | { | 229 | { |
225 | return 0; | 230 | return 0; |
231 | } | ||
232 | |||
233 | int __weak pcibios_sriov_disable(struct pci_dev *pdev) | ||
234 | { | ||
235 | return 0; | ||
226 | } | 236 | } |
227 | 237 | ||
228 | static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | 238 | static int sriov_enable(struct pci_dev *dev, int nr_virtfn) |
229 | { | 239 | { |
230 | int rc; | 240 | int rc; |
231 | int i, j; | 241 | int i; |
232 | int nres; | 242 | int nres; |
233 | u16 offset, stride, initial; | 243 | u16 initial; |
234 | struct resource *res; | 244 | struct resource *res; |
235 | struct pci_dev *pdev; | 245 | struct pci_dev *pdev; |
236 | struct pci_sriov *iov = dev->sriov; | 246 | struct pci_sriov *iov = dev->sriov; |
237 | int bars = 0; | 247 | int bars = 0; |
238 | int bus; | 248 | int bus; |
239 | int retval; | ||
240 | 249 | ||
241 | if (!nr_virtfn) | 250 | if (!nr_virtfn) |
242 | return 0; | 251 | return 0; |
@@ -253,11 +262,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | |||
253 | (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) | 262 | (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) |
254 | return -EINVAL; | 263 | return -EINVAL; |
255 | 264 | ||
256 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset); | ||
257 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride); | ||
258 | if (!offset || (nr_virtfn > 1 && !stride)) | ||
259 | return -EIO; | ||
260 | |||
261 | nres = 0; | 265 | nres = 0; |
262 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 266 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
263 | bars |= (1 << (i + PCI_IOV_RESOURCES)); | 267 | bars |= (1 << (i + PCI_IOV_RESOURCES)); |
@@ -270,9 +274,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | |||
270 | return -ENOMEM; | 274 | return -ENOMEM; |
271 | } | 275 | } |
272 | 276 | ||
273 | iov->offset = offset; | ||
274 | iov->stride = stride; | ||
275 | |||
276 | bus = pci_iov_virtfn_bus(dev, nr_virtfn - 1); | 277 | bus = pci_iov_virtfn_bus(dev, nr_virtfn - 1); |
277 | if (bus > dev->bus->busn_res.end) { | 278 | if (bus > dev->bus->busn_res.end) { |
278 | dev_err(&dev->dev, "can't enable %d VFs (bus %02x out of range of %pR)\n", | 279 | dev_err(&dev->dev, "can't enable %d VFs (bus %02x out of range of %pR)\n", |
@@ -313,10 +314,10 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | |||
313 | if (nr_virtfn < initial) | 314 | if (nr_virtfn < initial) |
314 | initial = nr_virtfn; | 315 | initial = nr_virtfn; |
315 | 316 | ||
316 | if ((retval = pcibios_sriov_enable(dev, initial))) { | 317 | rc = pcibios_sriov_enable(dev, initial); |
317 | dev_err(&dev->dev, "failure %d from pcibios_sriov_enable()\n", | 318 | if (rc) { |
318 | retval); | 319 | dev_err(&dev->dev, "failure %d from pcibios_sriov_enable()\n", rc); |
319 | return retval; | 320 | goto err_pcibios; |
320 | } | 321 | } |
321 | 322 | ||
322 | for (i = 0; i < initial; i++) { | 323 | for (i = 0; i < initial; i++) { |
@@ -331,27 +332,24 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | |||
331 | return 0; | 332 | return 0; |
332 | 333 | ||
333 | failed: | 334 | failed: |
334 | for (j = 0; j < i; j++) | 335 | while (i--) |
335 | virtfn_remove(dev, j, 0); | 336 | virtfn_remove(dev, i, 0); |
336 | 337 | ||
338 | pcibios_sriov_disable(dev); | ||
339 | err_pcibios: | ||
337 | iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); | 340 | iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); |
338 | pci_cfg_access_lock(dev); | 341 | pci_cfg_access_lock(dev); |
339 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | 342 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); |
340 | pci_iov_set_numvfs(dev, 0); | ||
341 | ssleep(1); | 343 | ssleep(1); |
342 | pci_cfg_access_unlock(dev); | 344 | pci_cfg_access_unlock(dev); |
343 | 345 | ||
344 | if (iov->link != dev->devfn) | 346 | if (iov->link != dev->devfn) |
345 | sysfs_remove_link(&dev->dev.kobj, "dep_link"); | 347 | sysfs_remove_link(&dev->dev.kobj, "dep_link"); |
346 | 348 | ||
349 | pci_iov_set_numvfs(dev, 0); | ||
347 | return rc; | 350 | return rc; |
348 | } | 351 | } |
349 | 352 | ||
350 | int __weak pcibios_sriov_disable(struct pci_dev *pdev) | ||
351 | { | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static void sriov_disable(struct pci_dev *dev) | 353 | static void sriov_disable(struct pci_dev *dev) |
356 | { | 354 | { |
357 | int i; | 355 | int i; |
@@ -384,7 +382,7 @@ static int sriov_init(struct pci_dev *dev, int pos) | |||
384 | int rc; | 382 | int rc; |
385 | int nres; | 383 | int nres; |
386 | u32 pgsz; | 384 | u32 pgsz; |
387 | u16 ctrl, total, offset, stride; | 385 | u16 ctrl, total; |
388 | struct pci_sriov *iov; | 386 | struct pci_sriov *iov; |
389 | struct resource *res; | 387 | struct resource *res; |
390 | struct pci_dev *pdev; | 388 | struct pci_dev *pdev; |
@@ -399,10 +397,6 @@ static int sriov_init(struct pci_dev *dev, int pos) | |||
399 | ssleep(1); | 397 | ssleep(1); |
400 | } | 398 | } |
401 | 399 | ||
402 | pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total); | ||
403 | if (!total) | ||
404 | return 0; | ||
405 | |||
406 | ctrl = 0; | 400 | ctrl = 0; |
407 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | 401 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) |
408 | if (pdev->is_physfn) | 402 | if (pdev->is_physfn) |
@@ -414,11 +408,10 @@ static int sriov_init(struct pci_dev *dev, int pos) | |||
414 | 408 | ||
415 | found: | 409 | found: |
416 | pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); | 410 | pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); |
417 | pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, 0); | 411 | |
418 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset); | 412 | pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total); |
419 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride); | 413 | if (!total) |
420 | if (!offset || (total > 1 && !stride)) | 414 | return 0; |
421 | return -EIO; | ||
422 | 415 | ||
423 | pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &pgsz); | 416 | pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &pgsz); |
424 | i = PAGE_SHIFT > 12 ? PAGE_SHIFT - 12 : 0; | 417 | i = PAGE_SHIFT > 12 ? PAGE_SHIFT - 12 : 0; |
@@ -436,8 +429,15 @@ found: | |||
436 | nres = 0; | 429 | nres = 0; |
437 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 430 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
438 | res = &dev->resource[i + PCI_IOV_RESOURCES]; | 431 | res = &dev->resource[i + PCI_IOV_RESOURCES]; |
439 | bar64 = __pci_read_base(dev, pci_bar_unknown, res, | 432 | /* |
440 | pos + PCI_SRIOV_BAR + i * 4); | 433 | * If it is already FIXED, don't change it, something |
434 | * (perhaps EA or header fixups) wants it this way. | ||
435 | */ | ||
436 | if (res->flags & IORESOURCE_PCI_FIXED) | ||
437 | bar64 = (res->flags & IORESOURCE_MEM_64) ? 1 : 0; | ||
438 | else | ||
439 | bar64 = __pci_read_base(dev, pci_bar_unknown, res, | ||
440 | pos + PCI_SRIOV_BAR + i * 4); | ||
441 | if (!res->flags) | 441 | if (!res->flags) |
442 | continue; | 442 | continue; |
443 | if (resource_size(res) & (PAGE_SIZE - 1)) { | 443 | if (resource_size(res) & (PAGE_SIZE - 1)) { |
@@ -456,8 +456,6 @@ found: | |||
456 | iov->nres = nres; | 456 | iov->nres = nres; |
457 | iov->ctrl = ctrl; | 457 | iov->ctrl = ctrl; |
458 | iov->total_VFs = total; | 458 | iov->total_VFs = total; |
459 | iov->offset = offset; | ||
460 | iov->stride = stride; | ||
461 | iov->pgsz = pgsz; | 459 | iov->pgsz = pgsz; |
462 | iov->self = dev; | 460 | iov->self = dev; |
463 | pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); | 461 | pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); |
@@ -474,10 +472,15 @@ found: | |||
474 | 472 | ||
475 | dev->sriov = iov; | 473 | dev->sriov = iov; |
476 | dev->is_physfn = 1; | 474 | dev->is_physfn = 1; |
477 | iov->max_VF_buses = virtfn_max_buses(dev); | 475 | rc = compute_max_vf_buses(dev); |
476 | if (rc) | ||
477 | goto fail_max_buses; | ||
478 | 478 | ||
479 | return 0; | 479 | return 0; |
480 | 480 | ||
481 | fail_max_buses: | ||
482 | dev->sriov = NULL; | ||
483 | dev->is_physfn = 0; | ||
481 | failed: | 484 | failed: |
482 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | 485 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { |
483 | res = &dev->resource[i + PCI_IOV_RESOURCES]; | 486 | res = &dev->resource[i + PCI_IOV_RESOURCES]; |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 45a51486d080..53e463244bb7 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -106,9 +106,12 @@ void __weak arch_teardown_msi_irq(unsigned int irq) | |||
106 | 106 | ||
107 | int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | 107 | int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
108 | { | 108 | { |
109 | struct msi_controller *chip = dev->bus->msi; | ||
109 | struct msi_desc *entry; | 110 | struct msi_desc *entry; |
110 | int ret; | 111 | int ret; |
111 | 112 | ||
113 | if (chip && chip->setup_irqs) | ||
114 | return chip->setup_irqs(chip, dev, nvec, type); | ||
112 | /* | 115 | /* |
113 | * If an architecture wants to support multiple MSI, it needs to | 116 | * If an architecture wants to support multiple MSI, it needs to |
114 | * override arch_setup_msi_irqs() | 117 | * override arch_setup_msi_irqs() |
@@ -476,10 +479,11 @@ static int populate_msi_sysfs(struct pci_dev *pdev) | |||
476 | int ret = -ENOMEM; | 479 | int ret = -ENOMEM; |
477 | int num_msi = 0; | 480 | int num_msi = 0; |
478 | int count = 0; | 481 | int count = 0; |
482 | int i; | ||
479 | 483 | ||
480 | /* Determine how many msi entries we have */ | 484 | /* Determine how many msi entries we have */ |
481 | for_each_pci_msi_entry(entry, pdev) | 485 | for_each_pci_msi_entry(entry, pdev) |
482 | ++num_msi; | 486 | num_msi += entry->nvec_used; |
483 | if (!num_msi) | 487 | if (!num_msi) |
484 | return 0; | 488 | return 0; |
485 | 489 | ||
@@ -488,19 +492,21 @@ static int populate_msi_sysfs(struct pci_dev *pdev) | |||
488 | if (!msi_attrs) | 492 | if (!msi_attrs) |
489 | return -ENOMEM; | 493 | return -ENOMEM; |
490 | for_each_pci_msi_entry(entry, pdev) { | 494 | for_each_pci_msi_entry(entry, pdev) { |
491 | msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); | 495 | for (i = 0; i < entry->nvec_used; i++) { |
492 | if (!msi_dev_attr) | 496 | msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); |
493 | goto error_attrs; | 497 | if (!msi_dev_attr) |
494 | msi_attrs[count] = &msi_dev_attr->attr; | 498 | goto error_attrs; |
495 | 499 | msi_attrs[count] = &msi_dev_attr->attr; | |
496 | sysfs_attr_init(&msi_dev_attr->attr); | 500 | |
497 | msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d", | 501 | sysfs_attr_init(&msi_dev_attr->attr); |
498 | entry->irq); | 502 | msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d", |
499 | if (!msi_dev_attr->attr.name) | 503 | entry->irq + i); |
500 | goto error_attrs; | 504 | if (!msi_dev_attr->attr.name) |
501 | msi_dev_attr->attr.mode = S_IRUGO; | 505 | goto error_attrs; |
502 | msi_dev_attr->show = msi_mode_show; | 506 | msi_dev_attr->attr.mode = S_IRUGO; |
503 | ++count; | 507 | msi_dev_attr->show = msi_mode_show; |
508 | ++count; | ||
509 | } | ||
504 | } | 510 | } |
505 | 511 | ||
506 | msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL); | 512 | msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL); |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 306124bba61e..4446fcb5effd 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -172,7 +172,7 @@ static ssize_t store_remove_id(struct device_driver *driver, const char *buf, | |||
172 | __u32 vendor, device, subvendor = PCI_ANY_ID, | 172 | __u32 vendor, device, subvendor = PCI_ANY_ID, |
173 | subdevice = PCI_ANY_ID, class = 0, class_mask = 0; | 173 | subdevice = PCI_ANY_ID, class = 0, class_mask = 0; |
174 | int fields = 0; | 174 | int fields = 0; |
175 | int retval = -ENODEV; | 175 | size_t retval = -ENODEV; |
176 | 176 | ||
177 | fields = sscanf(buf, "%x %x %x %x %x %x", | 177 | fields = sscanf(buf, "%x %x %x %x %x %x", |
178 | &vendor, &device, &subvendor, &subdevice, | 178 | &vendor, &device, &subvendor, &subdevice, |
@@ -190,15 +190,13 @@ static ssize_t store_remove_id(struct device_driver *driver, const char *buf, | |||
190 | !((id->class ^ class) & class_mask)) { | 190 | !((id->class ^ class) & class_mask)) { |
191 | list_del(&dynid->node); | 191 | list_del(&dynid->node); |
192 | kfree(dynid); | 192 | kfree(dynid); |
193 | retval = 0; | 193 | retval = count; |
194 | break; | 194 | break; |
195 | } | 195 | } |
196 | } | 196 | } |
197 | spin_unlock(&pdrv->dynids.lock); | 197 | spin_unlock(&pdrv->dynids.lock); |
198 | 198 | ||
199 | if (retval) | 199 | return retval; |
200 | return retval; | ||
201 | return count; | ||
202 | } | 200 | } |
203 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | 201 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); |
204 | 202 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 78693fc5dbe9..314db8c1047a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pci_hotplug.h> | 27 | #include <linux/pci_hotplug.h> |
28 | #include <asm-generic/pci-bridge.h> | 28 | #include <asm-generic/pci-bridge.h> |
29 | #include <asm/setup.h> | 29 | #include <asm/setup.h> |
30 | #include <linux/aer.h> | ||
30 | #include "pci.h" | 31 | #include "pci.h" |
31 | 32 | ||
32 | const char *pci_power_names[] = { | 33 | const char *pci_power_names[] = { |
@@ -458,6 +459,30 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev, | |||
458 | EXPORT_SYMBOL(pci_find_parent_resource); | 459 | EXPORT_SYMBOL(pci_find_parent_resource); |
459 | 460 | ||
460 | /** | 461 | /** |
462 | * pci_find_pcie_root_port - return PCIe Root Port | ||
463 | * @dev: PCI device to query | ||
464 | * | ||
465 | * Traverse up the parent chain and return the PCIe Root Port PCI Device | ||
466 | * for a given PCI Device. | ||
467 | */ | ||
468 | struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev) | ||
469 | { | ||
470 | struct pci_dev *bridge, *highest_pcie_bridge = NULL; | ||
471 | |||
472 | bridge = pci_upstream_bridge(dev); | ||
473 | while (bridge && pci_is_pcie(bridge)) { | ||
474 | highest_pcie_bridge = bridge; | ||
475 | bridge = pci_upstream_bridge(bridge); | ||
476 | } | ||
477 | |||
478 | if (pci_pcie_type(highest_pcie_bridge) != PCI_EXP_TYPE_ROOT_PORT) | ||
479 | return NULL; | ||
480 | |||
481 | return highest_pcie_bridge; | ||
482 | } | ||
483 | EXPORT_SYMBOL(pci_find_pcie_root_port); | ||
484 | |||
485 | /** | ||
461 | * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos | 486 | * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos |
462 | * @dev: the PCI device to operate on | 487 | * @dev: the PCI device to operate on |
463 | * @pos: config space offset of status word | 488 | * @pos: config space offset of status word |
@@ -484,7 +509,7 @@ int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask) | |||
484 | } | 509 | } |
485 | 510 | ||
486 | /** | 511 | /** |
487 | * pci_restore_bars - restore a devices BAR values (e.g. after wake-up) | 512 | * pci_restore_bars - restore a device's BAR values (e.g. after wake-up) |
488 | * @dev: PCI device to have its BARs restored | 513 | * @dev: PCI device to have its BARs restored |
489 | * | 514 | * |
490 | * Restore the BAR values for a given device, so as to make it | 515 | * Restore the BAR values for a given device, so as to make it |
@@ -494,6 +519,10 @@ static void pci_restore_bars(struct pci_dev *dev) | |||
494 | { | 519 | { |
495 | int i; | 520 | int i; |
496 | 521 | ||
522 | /* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */ | ||
523 | if (dev->is_virtfn) | ||
524 | return; | ||
525 | |||
497 | for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) | 526 | for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) |
498 | pci_update_resource(dev, i); | 527 | pci_update_resource(dev, i); |
499 | } | 528 | } |
@@ -1099,6 +1128,8 @@ void pci_restore_state(struct pci_dev *dev) | |||
1099 | pci_restore_ats_state(dev); | 1128 | pci_restore_ats_state(dev); |
1100 | pci_restore_vc_state(dev); | 1129 | pci_restore_vc_state(dev); |
1101 | 1130 | ||
1131 | pci_cleanup_aer_error_status_regs(dev); | ||
1132 | |||
1102 | pci_restore_config_space(dev); | 1133 | pci_restore_config_space(dev); |
1103 | 1134 | ||
1104 | pci_restore_pcix_state(dev); | 1135 | pci_restore_pcix_state(dev); |
@@ -2196,6 +2227,198 @@ void pci_pm_init(struct pci_dev *dev) | |||
2196 | } | 2227 | } |
2197 | } | 2228 | } |
2198 | 2229 | ||
2230 | static unsigned long pci_ea_flags(struct pci_dev *dev, u8 prop) | ||
2231 | { | ||
2232 | unsigned long flags = IORESOURCE_PCI_FIXED; | ||
2233 | |||
2234 | switch (prop) { | ||
2235 | case PCI_EA_P_MEM: | ||
2236 | case PCI_EA_P_VF_MEM: | ||
2237 | flags |= IORESOURCE_MEM; | ||
2238 | break; | ||
2239 | case PCI_EA_P_MEM_PREFETCH: | ||
2240 | case PCI_EA_P_VF_MEM_PREFETCH: | ||
2241 | flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; | ||
2242 | break; | ||
2243 | case PCI_EA_P_IO: | ||
2244 | flags |= IORESOURCE_IO; | ||
2245 | break; | ||
2246 | default: | ||
2247 | return 0; | ||
2248 | } | ||
2249 | |||
2250 | return flags; | ||
2251 | } | ||
2252 | |||
2253 | static struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei, | ||
2254 | u8 prop) | ||
2255 | { | ||
2256 | if (bei <= PCI_EA_BEI_BAR5 && prop <= PCI_EA_P_IO) | ||
2257 | return &dev->resource[bei]; | ||
2258 | #ifdef CONFIG_PCI_IOV | ||
2259 | else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5 && | ||
2260 | (prop == PCI_EA_P_VF_MEM || prop == PCI_EA_P_VF_MEM_PREFETCH)) | ||
2261 | return &dev->resource[PCI_IOV_RESOURCES + | ||
2262 | bei - PCI_EA_BEI_VF_BAR0]; | ||
2263 | #endif | ||
2264 | else if (bei == PCI_EA_BEI_ROM) | ||
2265 | return &dev->resource[PCI_ROM_RESOURCE]; | ||
2266 | else | ||
2267 | return NULL; | ||
2268 | } | ||
2269 | |||
2270 | /* Read an Enhanced Allocation (EA) entry */ | ||
2271 | static int pci_ea_read(struct pci_dev *dev, int offset) | ||
2272 | { | ||
2273 | struct resource *res; | ||
2274 | int ent_size, ent_offset = offset; | ||
2275 | resource_size_t start, end; | ||
2276 | unsigned long flags; | ||
2277 | u32 dw0, bei, base, max_offset; | ||
2278 | u8 prop; | ||
2279 | bool support_64 = (sizeof(resource_size_t) >= 8); | ||
2280 | |||
2281 | pci_read_config_dword(dev, ent_offset, &dw0); | ||
2282 | ent_offset += 4; | ||
2283 | |||
2284 | /* Entry size field indicates DWORDs after 1st */ | ||
2285 | ent_size = ((dw0 & PCI_EA_ES) + 1) << 2; | ||
2286 | |||
2287 | if (!(dw0 & PCI_EA_ENABLE)) /* Entry not enabled */ | ||
2288 | goto out; | ||
2289 | |||
2290 | bei = (dw0 & PCI_EA_BEI) >> 4; | ||
2291 | prop = (dw0 & PCI_EA_PP) >> 8; | ||
2292 | |||
2293 | /* | ||
2294 | * If the Property is in the reserved range, try the Secondary | ||
2295 | * Property instead. | ||
2296 | */ | ||
2297 | if (prop > PCI_EA_P_BRIDGE_IO && prop < PCI_EA_P_MEM_RESERVED) | ||
2298 | prop = (dw0 & PCI_EA_SP) >> 16; | ||
2299 | if (prop > PCI_EA_P_BRIDGE_IO) | ||
2300 | goto out; | ||
2301 | |||
2302 | res = pci_ea_get_resource(dev, bei, prop); | ||
2303 | if (!res) { | ||
2304 | dev_err(&dev->dev, "Unsupported EA entry BEI: %u\n", bei); | ||
2305 | goto out; | ||
2306 | } | ||
2307 | |||
2308 | flags = pci_ea_flags(dev, prop); | ||
2309 | if (!flags) { | ||
2310 | dev_err(&dev->dev, "Unsupported EA properties: %#x\n", prop); | ||
2311 | goto out; | ||
2312 | } | ||
2313 | |||
2314 | /* Read Base */ | ||
2315 | pci_read_config_dword(dev, ent_offset, &base); | ||
2316 | start = (base & PCI_EA_FIELD_MASK); | ||
2317 | ent_offset += 4; | ||
2318 | |||
2319 | /* Read MaxOffset */ | ||
2320 | pci_read_config_dword(dev, ent_offset, &max_offset); | ||
2321 | ent_offset += 4; | ||
2322 | |||
2323 | /* Read Base MSBs (if 64-bit entry) */ | ||
2324 | if (base & PCI_EA_IS_64) { | ||
2325 | u32 base_upper; | ||
2326 | |||
2327 | pci_read_config_dword(dev, ent_offset, &base_upper); | ||
2328 | ent_offset += 4; | ||
2329 | |||
2330 | flags |= IORESOURCE_MEM_64; | ||
2331 | |||
2332 | /* entry starts above 32-bit boundary, can't use */ | ||
2333 | if (!support_64 && base_upper) | ||
2334 | goto out; | ||
2335 | |||
2336 | if (support_64) | ||
2337 | start |= ((u64)base_upper << 32); | ||
2338 | } | ||
2339 | |||
2340 | end = start + (max_offset | 0x03); | ||
2341 | |||
2342 | /* Read MaxOffset MSBs (if 64-bit entry) */ | ||
2343 | if (max_offset & PCI_EA_IS_64) { | ||
2344 | u32 max_offset_upper; | ||
2345 | |||
2346 | pci_read_config_dword(dev, ent_offset, &max_offset_upper); | ||
2347 | ent_offset += 4; | ||
2348 | |||
2349 | flags |= IORESOURCE_MEM_64; | ||
2350 | |||
2351 | /* entry too big, can't use */ | ||
2352 | if (!support_64 && max_offset_upper) | ||
2353 | goto out; | ||
2354 | |||
2355 | if (support_64) | ||
2356 | end += ((u64)max_offset_upper << 32); | ||
2357 | } | ||
2358 | |||
2359 | if (end < start) { | ||
2360 | dev_err(&dev->dev, "EA Entry crosses address boundary\n"); | ||
2361 | goto out; | ||
2362 | } | ||
2363 | |||
2364 | if (ent_size != ent_offset - offset) { | ||
2365 | dev_err(&dev->dev, | ||
2366 | "EA Entry Size (%d) does not match length read (%d)\n", | ||
2367 | ent_size, ent_offset - offset); | ||
2368 | goto out; | ||
2369 | } | ||
2370 | |||
2371 | res->name = pci_name(dev); | ||
2372 | res->start = start; | ||
2373 | res->end = end; | ||
2374 | res->flags = flags; | ||
2375 | |||
2376 | if (bei <= PCI_EA_BEI_BAR5) | ||
2377 | dev_printk(KERN_DEBUG, &dev->dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n", | ||
2378 | bei, res, prop); | ||
2379 | else if (bei == PCI_EA_BEI_ROM) | ||
2380 | dev_printk(KERN_DEBUG, &dev->dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n", | ||
2381 | res, prop); | ||
2382 | else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5) | ||
2383 | dev_printk(KERN_DEBUG, &dev->dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n", | ||
2384 | bei - PCI_EA_BEI_VF_BAR0, res, prop); | ||
2385 | else | ||
2386 | dev_printk(KERN_DEBUG, &dev->dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n", | ||
2387 | bei, res, prop); | ||
2388 | |||
2389 | out: | ||
2390 | return offset + ent_size; | ||
2391 | } | ||
2392 | |||
2393 | /* Enhanced Allocation Initalization */ | ||
2394 | void pci_ea_init(struct pci_dev *dev) | ||
2395 | { | ||
2396 | int ea; | ||
2397 | u8 num_ent; | ||
2398 | int offset; | ||
2399 | int i; | ||
2400 | |||
2401 | /* find PCI EA capability in list */ | ||
2402 | ea = pci_find_capability(dev, PCI_CAP_ID_EA); | ||
2403 | if (!ea) | ||
2404 | return; | ||
2405 | |||
2406 | /* determine the number of entries */ | ||
2407 | pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT, | ||
2408 | &num_ent); | ||
2409 | num_ent &= PCI_EA_NUM_ENT_MASK; | ||
2410 | |||
2411 | offset = ea + PCI_EA_FIRST_ENT; | ||
2412 | |||
2413 | /* Skip DWORD 2 for type 1 functions */ | ||
2414 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) | ||
2415 | offset += 4; | ||
2416 | |||
2417 | /* parse each EA entry */ | ||
2418 | for (i = 0; i < num_ent; ++i) | ||
2419 | offset = pci_ea_read(dev, offset); | ||
2420 | } | ||
2421 | |||
2199 | static void pci_add_saved_cap(struct pci_dev *pci_dev, | 2422 | static void pci_add_saved_cap(struct pci_dev *pci_dev, |
2200 | struct pci_cap_saved_state *new_cap) | 2423 | struct pci_cap_saved_state *new_cap) |
2201 | { | 2424 | { |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 037e787a3ad5..fd2f03fa53f3 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -79,6 +79,7 @@ void pci_dev_complete_resume(struct pci_dev *pci_dev); | |||
79 | void pci_config_pm_runtime_get(struct pci_dev *dev); | 79 | void pci_config_pm_runtime_get(struct pci_dev *dev); |
80 | void pci_config_pm_runtime_put(struct pci_dev *dev); | 80 | void pci_config_pm_runtime_put(struct pci_dev *dev); |
81 | void pci_pm_init(struct pci_dev *dev); | 81 | void pci_pm_init(struct pci_dev *dev); |
82 | void pci_ea_init(struct pci_dev *dev); | ||
82 | void pci_allocate_cap_save_buffers(struct pci_dev *dev); | 83 | void pci_allocate_cap_save_buffers(struct pci_dev *dev); |
83 | void pci_free_cap_save_buffers(struct pci_dev *dev); | 84 | void pci_free_cap_save_buffers(struct pci_dev *dev); |
84 | 85 | ||
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 9803e3d039fe..fba785e9df75 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -74,6 +74,34 @@ int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) | |||
74 | } | 74 | } |
75 | EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); | 75 | EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status); |
76 | 76 | ||
77 | int pci_cleanup_aer_error_status_regs(struct pci_dev *dev) | ||
78 | { | ||
79 | int pos; | ||
80 | u32 status; | ||
81 | int port_type; | ||
82 | |||
83 | if (!pci_is_pcie(dev)) | ||
84 | return -ENODEV; | ||
85 | |||
86 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
87 | if (!pos) | ||
88 | return -EIO; | ||
89 | |||
90 | port_type = pci_pcie_type(dev); | ||
91 | if (port_type == PCI_EXP_TYPE_ROOT_PORT) { | ||
92 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status); | ||
93 | pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status); | ||
94 | } | ||
95 | |||
96 | pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status); | ||
97 | pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status); | ||
98 | |||
99 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); | ||
100 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
77 | /** | 105 | /** |
78 | * add_error_device - list device to be handled | 106 | * add_error_device - list device to be handled |
79 | * @e_info: pointer to error info | 107 | * @e_info: pointer to error info |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index f14a970b61fa..f53b8e85f137 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/cpumask.h> | 13 | #include <linux/cpumask.h> |
14 | #include <linux/pci-aspm.h> | 14 | #include <linux/pci-aspm.h> |
15 | #include <linux/aer.h> | ||
15 | #include <asm-generic/pci-bridge.h> | 16 | #include <asm-generic/pci-bridge.h> |
16 | #include "pci.h" | 17 | #include "pci.h" |
17 | 18 | ||
@@ -1597,6 +1598,9 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | |||
1597 | 1598 | ||
1598 | static void pci_init_capabilities(struct pci_dev *dev) | 1599 | static void pci_init_capabilities(struct pci_dev *dev) |
1599 | { | 1600 | { |
1601 | /* Enhanced Allocation */ | ||
1602 | pci_ea_init(dev); | ||
1603 | |||
1600 | /* MSI/MSI-X list */ | 1604 | /* MSI/MSI-X list */ |
1601 | pci_msi_init_pci_dev(dev); | 1605 | pci_msi_init_pci_dev(dev); |
1602 | 1606 | ||
@@ -1620,6 +1624,8 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
1620 | 1624 | ||
1621 | /* Enable ACS P2P upstream forwarding */ | 1625 | /* Enable ACS P2P upstream forwarding */ |
1622 | pci_enable_acs(dev); | 1626 | pci_enable_acs(dev); |
1627 | |||
1628 | pci_cleanup_aer_error_status_regs(dev); | ||
1623 | } | 1629 | } |
1624 | 1630 | ||
1625 | /* | 1631 | /* |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index b03373fd05ca..7e327309cf69 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -2246,6 +2246,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disab | |||
2246 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); | 2246 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi); |
2247 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi); | 2247 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi); |
2248 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi); | 2248 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi); |
2249 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, 0x0761, quirk_disable_all_msi); | ||
2249 | 2250 | ||
2250 | /* Disable MSI on chipsets that are known to not support it */ | 2251 | /* Disable MSI on chipsets that are known to not support it */ |
2251 | static void quirk_disable_msi(struct pci_dev *dev) | 2252 | static void quirk_disable_msi(struct pci_dev *dev) |
@@ -3708,6 +3709,63 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, PCI_CLASS_NOT_DEFINED, 8, | |||
3708 | quirk_tw686x_class); | 3709 | quirk_tw686x_class); |
3709 | 3710 | ||
3710 | /* | 3711 | /* |
3712 | * Per PCIe r3.0, sec 2.2.9, "Completion headers must supply the same | ||
3713 | * values for the Attribute as were supplied in the header of the | ||
3714 | * corresponding Request, except as explicitly allowed when IDO is used." | ||
3715 | * | ||
3716 | * If a non-compliant device generates a completion with a different | ||
3717 | * attribute than the request, the receiver may accept it (which itself | ||
3718 | * seems non-compliant based on sec 2.3.2), or it may handle it as a | ||
3719 | * Malformed TLP or an Unexpected Completion, which will probably lead to a | ||
3720 | * device access timeout. | ||
3721 | * | ||
3722 | * If the non-compliant device generates completions with zero attributes | ||
3723 | * (instead of copying the attributes from the request), we can work around | ||
3724 | * this by disabling the "Relaxed Ordering" and "No Snoop" attributes in | ||
3725 | * upstream devices so they always generate requests with zero attributes. | ||
3726 | * | ||
3727 | * This affects other devices under the same Root Port, but since these | ||
3728 | * attributes are performance hints, there should be no functional problem. | ||
3729 | * | ||
3730 | * Note that Configuration Space accesses are never supposed to have TLP | ||
3731 | * Attributes, so we're safe waiting till after any Configuration Space | ||
3732 | * accesses to do the Root Port fixup. | ||
3733 | */ | ||
3734 | static void quirk_disable_root_port_attributes(struct pci_dev *pdev) | ||
3735 | { | ||
3736 | struct pci_dev *root_port = pci_find_pcie_root_port(pdev); | ||
3737 | |||
3738 | if (!root_port) { | ||
3739 | dev_warn(&pdev->dev, "PCIe Completion erratum may cause device errors\n"); | ||
3740 | return; | ||
3741 | } | ||
3742 | |||
3743 | dev_info(&root_port->dev, "Disabling No Snoop/Relaxed Ordering Attributes to avoid PCIe Completion erratum in %s\n", | ||
3744 | dev_name(&pdev->dev)); | ||
3745 | pcie_capability_clear_and_set_word(root_port, PCI_EXP_DEVCTL, | ||
3746 | PCI_EXP_DEVCTL_RELAX_EN | | ||
3747 | PCI_EXP_DEVCTL_NOSNOOP_EN, 0); | ||
3748 | } | ||
3749 | |||
3750 | /* | ||
3751 | * The Chelsio T5 chip fails to copy TLP Attributes from a Request to the | ||
3752 | * Completion it generates. | ||
3753 | */ | ||
3754 | static void quirk_chelsio_T5_disable_root_port_attributes(struct pci_dev *pdev) | ||
3755 | { | ||
3756 | /* | ||
3757 | * This mask/compare operation selects for Physical Function 4 on a | ||
3758 | * T5. We only need to fix up the Root Port once for any of the | ||
3759 | * PFs. PF[0..3] have PCI Device IDs of 0x50xx, but PF4 is uniquely | ||
3760 | * 0x54xx so we use that one, | ||
3761 | */ | ||
3762 | if ((pdev->device & 0xff00) == 0x5400) | ||
3763 | quirk_disable_root_port_attributes(pdev); | ||
3764 | } | ||
3765 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID, | ||
3766 | quirk_chelsio_T5_disable_root_port_attributes); | ||
3767 | |||
3768 | /* | ||
3711 | * AMD has indicated that the devices below do not support peer-to-peer | 3769 | * AMD has indicated that the devices below do not support peer-to-peer |
3712 | * in any system where they are found in the southbridge with an AMD | 3770 | * in any system where they are found in the southbridge with an AMD |
3713 | * IOMMU in the system. Multifunction devices that do not support | 3771 | * IOMMU in the system. Multifunction devices that do not support |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 508cc56130e3..1723ac1b30e1 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -1037,9 +1037,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
1037 | struct resource *r = &dev->resource[i]; | 1037 | struct resource *r = &dev->resource[i]; |
1038 | resource_size_t r_size; | 1038 | resource_size_t r_size; |
1039 | 1039 | ||
1040 | if (r->parent || ((r->flags & mask) != type && | 1040 | if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) || |
1041 | (r->flags & mask) != type2 && | 1041 | ((r->flags & mask) != type && |
1042 | (r->flags & mask) != type3)) | 1042 | (r->flags & mask) != type2 && |
1043 | (r->flags & mask) != type3)) | ||
1043 | continue; | 1044 | continue; |
1044 | r_size = resource_size(r); | 1045 | r_size = resource_size(r); |
1045 | #ifdef CONFIG_PCI_IOV | 1046 | #ifdef CONFIG_PCI_IOV |
@@ -1340,6 +1341,47 @@ void pci_bus_size_bridges(struct pci_bus *bus) | |||
1340 | } | 1341 | } |
1341 | EXPORT_SYMBOL(pci_bus_size_bridges); | 1342 | EXPORT_SYMBOL(pci_bus_size_bridges); |
1342 | 1343 | ||
1344 | static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r) | ||
1345 | { | ||
1346 | int i; | ||
1347 | struct resource *parent_r; | ||
1348 | unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
1349 | IORESOURCE_PREFETCH; | ||
1350 | |||
1351 | pci_bus_for_each_resource(b, parent_r, i) { | ||
1352 | if (!parent_r) | ||
1353 | continue; | ||
1354 | |||
1355 | if ((r->flags & mask) == (parent_r->flags & mask) && | ||
1356 | resource_contains(parent_r, r)) | ||
1357 | request_resource(parent_r, r); | ||
1358 | } | ||
1359 | } | ||
1360 | |||
1361 | /* | ||
1362 | * Try to assign any resources marked as IORESOURCE_PCI_FIXED, as they | ||
1363 | * are skipped by pbus_assign_resources_sorted(). | ||
1364 | */ | ||
1365 | static void pdev_assign_fixed_resources(struct pci_dev *dev) | ||
1366 | { | ||
1367 | int i; | ||
1368 | |||
1369 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
1370 | struct pci_bus *b; | ||
1371 | struct resource *r = &dev->resource[i]; | ||
1372 | |||
1373 | if (r->parent || !(r->flags & IORESOURCE_PCI_FIXED) || | ||
1374 | !(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) | ||
1375 | continue; | ||
1376 | |||
1377 | b = dev->bus; | ||
1378 | while (b && !r->parent) { | ||
1379 | assign_fixed_resource_on_bus(b, r); | ||
1380 | b = b->parent; | ||
1381 | } | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1343 | void __pci_bus_assign_resources(const struct pci_bus *bus, | 1385 | void __pci_bus_assign_resources(const struct pci_bus *bus, |
1344 | struct list_head *realloc_head, | 1386 | struct list_head *realloc_head, |
1345 | struct list_head *fail_head) | 1387 | struct list_head *fail_head) |
@@ -1350,6 +1392,8 @@ void __pci_bus_assign_resources(const struct pci_bus *bus, | |||
1350 | pbus_assign_resources_sorted(bus, realloc_head, fail_head); | 1392 | pbus_assign_resources_sorted(bus, realloc_head, fail_head); |
1351 | 1393 | ||
1352 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1394 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1395 | pdev_assign_fixed_resources(dev); | ||
1396 | |||
1353 | b = dev->subordinate; | 1397 | b = dev->subordinate; |
1354 | if (!b) | 1398 | if (!b) |
1355 | continue; | 1399 | continue; |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 232f9254c11a..604011e047d6 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
@@ -36,6 +36,11 @@ void pci_update_resource(struct pci_dev *dev, int resno) | |||
36 | enum pci_bar_type type; | 36 | enum pci_bar_type type; |
37 | struct resource *res = dev->resource + resno; | 37 | struct resource *res = dev->resource + resno; |
38 | 38 | ||
39 | if (dev->is_virtfn) { | ||
40 | dev_warn(&dev->dev, "can't update VF BAR%d\n", resno); | ||
41 | return; | ||
42 | } | ||
43 | |||
39 | /* | 44 | /* |
40 | * Ignore resources for unimplemented BARs and unused resource slots | 45 | * Ignore resources for unimplemented BARs and unused resource slots |
41 | * for 64 bit BARs. | 46 | * for 64 bit BARs. |
@@ -177,6 +182,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, | |||
177 | end = res->end; | 182 | end = res->end; |
178 | res->start = fw_addr; | 183 | res->start = fw_addr; |
179 | res->end = res->start + size - 1; | 184 | res->end = res->start + size - 1; |
185 | res->flags &= ~IORESOURCE_UNSET; | ||
180 | 186 | ||
181 | root = pci_find_parent_resource(dev, res); | 187 | root = pci_find_parent_resource(dev, res); |
182 | if (!root) { | 188 | if (!root) { |
@@ -194,6 +200,7 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, | |||
194 | resno, res, conflict->name, conflict); | 200 | resno, res, conflict->name, conflict); |
195 | res->start = start; | 201 | res->start = start; |
196 | res->end = end; | 202 | res->end = end; |
203 | res->flags |= IORESOURCE_UNSET; | ||
197 | return -EBUSY; | 204 | return -EBUSY; |
198 | } | 205 | } |
199 | return 0; | 206 | return 0; |