diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 00:01:28 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 00:01:28 +0100 |
commit | 1b6115fbe3b3db746d7baa11399dd617fc75e1c4 (patch) | |
tree | d84d690504f0872eb8f5a1b18ed251236872fae5 /drivers/pci/host/pci-tegra.c | |
parent | Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dledfo... (diff) | |
parent | Merge branch 'pci/host-xilinx' into next (diff) | |
download | linux-1b6115fbe3b3db746d7baa11399dd617fc75e1c4.tar.xz linux-1b6115fbe3b3db746d7baa11399dd617fc75e1c4.zip |
Merge tag 'pci-v4.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
- detach driver before tearing down procfs/sysfs (Alex Williamson)
- disable PCIe services during shutdown (Sinan Kaya)
- fix ASPM oops on systems with no Root Ports (Ard Biesheuvel)
- fix ASPM LTR_L1.2_THRESHOLD programming (Bjorn Helgaas)
- fix ASPM Common_Mode_Restore_Time computation (Bjorn Helgaas)
- fix portdrv MSI/MSI-X vector allocation (Dongdong Liu, Bjorn
Helgaas)
- report non-fatal AER errors only to the affected endpoint (Gabriele
Paoloni)
- distribute bus numbers, MMIO, and I/O space among hotplug bridges to
allow more devices to be hot-added (Mika Westerberg)
- fix pciehp races during initialization and surprise link down (Mika
Westerberg)
- handle surprise-removed devices in PME handling (Qiang)
- support resizable BARs for large graphics devices (Christian König)
- expose SR-IOV offset, stride, and VF device ID via sysfs (Filippo
Sironi)
- create SR-IOV virtfn/physfn sysfs links before attaching driver
(Stuart Hayes)
- fix SR-IOV "ARI Capable Hierarchy" restore issue (Tony Nguyen)
- enforce Kconfig IOV/REALLOC dependency (Sascha El-Sharkawy)
- avoid slot reset if bridge itself is broken (Jan Glauber)
- clean up pci_reset_function() path (Jan H. Schönherr)
- make pci_map_rom() fail if the option ROM is invalid (Changbin Du)
- convert timers to timer_setup() (Kees Cook)
- move PCI_QUIRKS to PCI bus Kconfig menu (Randy Dunlap)
- constify pci_dev_type and intel_mid_pci_ops (Bhumika Goyal)
- remove unnecessary pci_dev, pci_bus, resource, pcibios_set_master()
declarations (Bjorn Helgaas)
- fix endpoint framework overflows and BUG()s (Dan Carpenter)
- fix endpoint framework issues (Kishon Vijay Abraham I)
- avoid broken Cavium CN8xxx bus reset behavior (David Daney)
- extend Cavium ACS capability quirks (Vadim Lomovtsev)
- support Synopsys DesignWare RC in ECAM mode (Ard Biesheuvel)
- turn off dra7xx clocks cleanly on shutdown (Keerthy)
- fix Faraday probe error path (Wei Yongjun)
- support HiSilicon STB SoC PCIe host controller (Jianguo Sun)
- fix Hyper-V interrupt affinity issue (Dexuan Cui)
- remove useless ACPI warning for Hyper-V pass-through devices (Vitaly
Kuznetsov)
- support multiple MSI on iProc (Sandor Bodo-Merle)
- support Layerscape LS1012a and LS1046a PCIe host controllers (Hou
Zhiqiang)
- fix Layerscape default error response (Minghuan Lian)
- support MSI on Tango host controller (Marc Gonzalez)
- support Tegra186 PCIe host controller (Manikanta Maddireddy)
- use generic accessors on Tegra when possible (Thierry Reding)
- support V3 Semiconductor PCI host controller (Linus Walleij)
* tag 'pci-v4.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (85 commits)
PCI/ASPM: Add L1 Substates definitions
PCI/ASPM: Reformat ASPM register definitions
PCI/ASPM: Use correct capability pointer to program LTR_L1.2_THRESHOLD
PCI/ASPM: Account for downstream device's Port Common_Mode_Restore_Time
PCI: xgene: Rename xgene_pcie_probe_bridge() to xgene_pcie_probe()
PCI: xilinx: Rename xilinx_pcie_link_is_up() to xilinx_pcie_link_up()
PCI: altera: Rename altera_pcie_link_is_up() to altera_pcie_link_up()
PCI: Fix kernel-doc build warning
PCI: Fail pci_map_rom() if the option ROM is invalid
PCI: Move pci_map_rom() error path
PCI: Move PCI_QUIRKS to the PCI bus menu
alpha/PCI: Make pdev_save_srm_config() static
PCI: Remove unused declarations
PCI: Remove redundant pci_dev, pci_bus, resource declarations
PCI: Remove redundant pcibios_set_master() declarations
PCI/PME: Handle invalid data when reading Root Status
PCI: hv: Use effective affinity mask
PCI: pciehp: Do not clear Presence Detect Changed during initialization
PCI: pciehp: Fix race condition handling surprise link down
PCI: Distribute available resources to hotplug-capable bridges
...
Diffstat (limited to 'drivers/pci/host/pci-tegra.c')
-rw-r--r-- | drivers/pci/host/pci-tegra.c | 158 |
1 files changed, 131 insertions, 27 deletions
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 1987fec1f126..f9d3960dc39f 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -159,10 +159,13 @@ #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420 (0x0 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1 (0x0 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401 (0x0 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222 (0x1 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1 (0x1 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211 (0x1 << 20) #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411 (0x2 << 20) +#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111 (0x2 << 20) #define AFI_FUSE 0x104 #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) @@ -253,6 +256,7 @@ struct tegra_pcie_soc { bool has_cml_clk; bool has_gen2; bool force_pca_enable; + bool program_uphy; }; static inline struct tegra_msi *to_tegra_msi(struct msi_controller *chip) @@ -492,12 +496,32 @@ static void __iomem *tegra_pcie_map_bus(struct pci_bus *bus, return addr; } +static int tegra_pcie_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + if (bus->number == 0) + return pci_generic_config_read32(bus, devfn, where, size, + value); + + return pci_generic_config_read(bus, devfn, where, size, value); +} + +static int tegra_pcie_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + if (bus->number == 0) + return pci_generic_config_write32(bus, devfn, where, size, + value); + + return pci_generic_config_write(bus, devfn, where, size, value); +} + static struct pci_ops tegra_pcie_ops = { .add_bus = tegra_pcie_add_bus, .remove_bus = tegra_pcie_remove_bus, .map_bus = tegra_pcie_map_bus, - .read = pci_generic_config_read32, - .write = pci_generic_config_write32, + .read = tegra_pcie_config_read, + .write = tegra_pcie_config_write, }; static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port) @@ -1013,10 +1037,12 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) afi_writel(pcie, value, AFI_FUSE); } - err = tegra_pcie_phy_power_on(pcie); - if (err < 0) { - dev_err(dev, "failed to power on PHY(s): %d\n", err); - return err; + if (soc->program_uphy) { + err = tegra_pcie_phy_power_on(pcie); + if (err < 0) { + dev_err(dev, "failed to power on PHY(s): %d\n", err); + return err; + } } /* take the PCIe interface module out of reset */ @@ -1049,19 +1075,23 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) static void tegra_pcie_power_off(struct tegra_pcie *pcie) { struct device *dev = pcie->dev; + const struct tegra_pcie_soc *soc = pcie->soc; int err; /* TODO: disable and unprepare clocks? */ - err = tegra_pcie_phy_power_off(pcie); - if (err < 0) - dev_err(dev, "failed to power off PHY(s): %d\n", err); + if (soc->program_uphy) { + err = tegra_pcie_phy_power_off(pcie); + if (err < 0) + dev_err(dev, "failed to power off PHY(s): %d\n", err); + } reset_control_assert(pcie->pcie_xrst); reset_control_assert(pcie->afi_rst); reset_control_assert(pcie->pex_rst); - tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); + if (!dev->pm_domain) + tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies); if (err < 0) @@ -1078,19 +1108,29 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) reset_control_assert(pcie->afi_rst); reset_control_assert(pcie->pex_rst); - tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); + if (!dev->pm_domain) + tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); /* enable regulators */ err = regulator_bulk_enable(pcie->num_supplies, pcie->supplies); if (err < 0) dev_err(dev, "failed to enable regulators: %d\n", err); - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, - pcie->pex_clk, - pcie->pex_rst); - if (err) { - dev_err(dev, "powerup sequence failed: %d\n", err); - return err; + if (dev->pm_domain) { + err = clk_prepare_enable(pcie->pex_clk); + if (err) { + dev_err(dev, "failed to enable PEX clock: %d\n", err); + return err; + } + reset_control_deassert(pcie->pex_rst); + } else { + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, + pcie->pex_clk, + pcie->pex_rst); + if (err) { + dev_err(dev, "powerup sequence failed: %d\n", err); + return err; + } } reset_control_deassert(pcie->afi_rst); @@ -1263,6 +1303,7 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) struct device *dev = pcie->dev; struct platform_device *pdev = to_platform_device(dev); struct resource *pads, *afi, *res; + const struct tegra_pcie_soc *soc = pcie->soc; int err; err = tegra_pcie_clocks_get(pcie); @@ -1277,10 +1318,12 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) return err; } - err = tegra_pcie_phys_get(pcie); - if (err < 0) { - dev_err(dev, "failed to get PHYs: %d\n", err); - return err; + if (soc->program_uphy) { + err = tegra_pcie_phys_get(pcie); + if (err < 0) { + dev_err(dev, "failed to get PHYs: %d\n", err); + return err; + } } err = tegra_pcie_power_on(pcie); @@ -1342,6 +1385,7 @@ poweroff: static int tegra_pcie_put_resources(struct tegra_pcie *pcie) { struct device *dev = pcie->dev; + const struct tegra_pcie_soc *soc = pcie->soc; int err; if (pcie->irq > 0) @@ -1349,9 +1393,11 @@ static int tegra_pcie_put_resources(struct tegra_pcie *pcie) tegra_pcie_power_off(pcie); - err = phy_exit(pcie->phy); - if (err < 0) - dev_err(dev, "failed to teardown PHY: %d\n", err); + if (soc->program_uphy) { + err = phy_exit(pcie->phy); + if (err < 0) + dev_err(dev, "failed to teardown PHY: %d\n", err); + } return 0; } @@ -1606,8 +1652,32 @@ static int tegra_pcie_get_xbar_config(struct tegra_pcie *pcie, u32 lanes, struct device *dev = pcie->dev; struct device_node *np = dev->of_node; - if (of_device_is_compatible(np, "nvidia,tegra124-pcie") || - of_device_is_compatible(np, "nvidia,tegra210-pcie")) { + if (of_device_is_compatible(np, "nvidia,tegra186-pcie")) { + switch (lanes) { + case 0x010004: + dev_info(dev, "4x1, 1x1 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401; + return 0; + + case 0x010102: + dev_info(dev, "2x1, 1X1, 1x1 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211; + return 0; + + case 0x010101: + dev_info(dev, "1x1, 1x1, 1x1 configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111; + return 0; + + default: + dev_info(dev, "wrong configuration updated in DT, " + "switching to default 2x1, 1x1, 1x1 " + "configuration\n"); + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211; + return 0; + } + } else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") || + of_device_is_compatible(np, "nvidia,tegra210-pcie")) { switch (lanes) { case 0x0000104: dev_info(dev, "4x1, 1x1 configuration\n"); @@ -1727,7 +1797,20 @@ static int tegra_pcie_get_regulators(struct tegra_pcie *pcie, u32 lane_mask) struct device_node *np = dev->of_node; unsigned int i = 0; - if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) { + if (of_device_is_compatible(np, "nvidia,tegra186-pcie")) { + pcie->num_supplies = 4; + + pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies, + sizeof(*pcie->supplies), + GFP_KERNEL); + if (!pcie->supplies) + return -ENOMEM; + + pcie->supplies[i++].supply = "dvdd-pex"; + pcie->supplies[i++].supply = "hvdd-pex-pll"; + pcie->supplies[i++].supply = "hvdd-pex"; + pcie->supplies[i++].supply = "vddio-pexctl-aud"; + } else if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) { pcie->num_supplies = 6; pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies, @@ -2066,6 +2149,7 @@ static const struct tegra_pcie_soc tegra20_pcie = { .has_cml_clk = false, .has_gen2 = false, .force_pca_enable = false, + .program_uphy = true, }; static const struct tegra_pcie_soc tegra30_pcie = { @@ -2081,6 +2165,7 @@ static const struct tegra_pcie_soc tegra30_pcie = { .has_cml_clk = true, .has_gen2 = false, .force_pca_enable = false, + .program_uphy = true, }; static const struct tegra_pcie_soc tegra124_pcie = { @@ -2095,6 +2180,7 @@ static const struct tegra_pcie_soc tegra124_pcie = { .has_cml_clk = true, .has_gen2 = true, .force_pca_enable = false, + .program_uphy = true, }; static const struct tegra_pcie_soc tegra210_pcie = { @@ -2109,9 +2195,27 @@ static const struct tegra_pcie_soc tegra210_pcie = { .has_cml_clk = true, .has_gen2 = true, .force_pca_enable = true, + .program_uphy = true, +}; + +static const struct tegra_pcie_soc tegra186_pcie = { + .num_ports = 3, + .msi_base_shift = 8, + .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, + .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0x80b880b8, + .pads_refclk_cfg1 = 0x000480b8, + .has_pex_clkreq_en = true, + .has_pex_bias_ctrl = true, + .has_intr_prsnt_sense = true, + .has_cml_clk = false, + .has_gen2 = true, + .force_pca_enable = false, + .program_uphy = false, }; static const struct of_device_id tegra_pcie_of_match[] = { + { .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie }, { .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie }, { .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie }, { .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie }, |