Loading Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt +130 −4 Original line number Diff line number Diff line NVIDIA Tegra PCIe controller Required properties: - compatible: For Tegra20, must contain "nvidia,tegra20-pcie". For Tegra30, "nvidia,tegra30-pcie". For Tegra124, must contain "nvidia,tegra124-pcie". Otherwise, must contain "nvidia,<chip>-pcie", plus one of the above, where <chip> is tegra132 or tegra210. - compatible: Must be: - "nvidia,tegra20-pcie": for Tegra20 - "nvidia,tegra30-pcie": for Tegra30 - "nvidia,tegra124-pcie": for Tegra124 and Tegra132 - "nvidia,tegra210-pcie": for Tegra210 - "nvidia,tegra186-pcie": for Tegra186 - power-domains: To ungate power partition by BPMP powergate driver. Must contain BPMP phandle and PCIe power partition ID. This is required only for Tegra186. - device_type: Must be "pci" - reg: A list of physical base address and length for each set of controller registers. Must contain an entry for each entry in the reg-names property. Loading Loading @@ -124,6 +129,16 @@ Power supplies for Tegra210: - vddio-pex-ctl-supply: Power supply for PCIe control I/O partition. Must supply 1.8 V. Power supplies for Tegra186: - Required: - dvdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V. - hvdd-pex-pll-supply: High-voltage supply for PLLE (shared with USB3). Must supply 1.8 V. - hvdd-pex-supply: High-voltage supply for PCIe I/O and PCIe output clocks. Must supply 1.8 V. - vddio-pexctl-aud-supply: Power supply for PCIe side band signals. Must supply 1.8 V. Root ports are defined as subnodes of the PCIe controller node. Required properties: Loading Loading @@ -546,3 +561,114 @@ Board DTS: status = "okay"; }; }; Tegra186: --------- SoC DTSI: pcie@10003000 { compatible = "nvidia,tegra186-pcie"; power-domains = <&bpmp TEGRA186_POWER_DOMAIN_PCX>; device_type = "pci"; reg = <0x0 0x10003000 0x0 0x00000800 /* PADS registers */ 0x0 0x10003800 0x0 0x00000800 /* AFI registers */ 0x0 0x40000000 0x0 0x10000000>; /* configuration space */ reg-names = "pads", "afi", "cs"; interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */ interrupt-names = "intr", "msi"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; bus-range = <0x00 0xff>; #address-cells = <3>; #size-cells = <2>; ranges = <0x82000000 0 0x10000000 0x0 0x10000000 0 0x00001000 /* port 0 configuration space */ 0x82000000 0 0x10001000 0x0 0x10001000 0 0x00001000 /* port 1 configuration space */ 0x82000000 0 0x10004000 0x0 0x10004000 0 0x00001000 /* port 2 configuration space */ 0x81000000 0 0x0 0x0 0x50000000 0 0x00010000 /* downstream I/O (64 KiB) */ 0x82000000 0 0x50100000 0x0 0x50100000 0 0x07F00000 /* non-prefetchable memory (127 MiB) */ 0xc2000000 0 0x58000000 0x0 0x58000000 0 0x28000000>; /* prefetchable memory (640 MiB) */ clocks = <&bpmp TEGRA186_CLK_AFI>, <&bpmp TEGRA186_CLK_PCIE>, <&bpmp TEGRA186_CLK_PLLE>; clock-names = "afi", "pex", "pll_e"; resets = <&bpmp TEGRA186_RESET_AFI>, <&bpmp TEGRA186_RESET_PCIE>, <&bpmp TEGRA186_RESET_PCIEXCLK>; reset-names = "afi", "pex", "pcie_x"; status = "disabled"; pci@1,0 { device_type = "pci"; assigned-addresses = <0x82000800 0 0x10000000 0 0x1000>; reg = <0x000800 0 0 0 0>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <2>; }; pci@2,0 { device_type = "pci"; assigned-addresses = <0x82001000 0 0x10001000 0 0x1000>; reg = <0x001000 0 0 0 0>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <1>; }; pci@3,0 { device_type = "pci"; assigned-addresses = <0x82001800 0 0x10004000 0 0x1000>; reg = <0x001800 0 0 0 0>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <1>; }; }; Board DTS: pcie@10003000 { status = "okay"; dvdd-pex-supply = <&vdd_pex>; hvdd-pex-pll-supply = <&vdd_1v8>; hvdd-pex-supply = <&vdd_1v8>; vddio-pexctl-aud-supply = <&vdd_1v8>; pci@1,0 { nvidia,num-lanes = <4>; status = "okay"; }; pci@2,0 { nvidia,num-lanes = <0>; status = "disabled"; }; pci@3,0 { nvidia,num-lanes = <1>; status = "disabled"; }; }; drivers/pci/host/pci-tegra.c +131 −27 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -252,6 +255,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) Loading Loading @@ -491,12 +495,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) Loading Loading @@ -1012,11 +1036,13 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) afi_writel(pcie, value, AFI_FUSE); } 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 */ reset_control_deassert(pcie->pcie_xrst); Loading Loading @@ -1048,18 +1074,22 @@ 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? */ 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); if (!dev->pm_domain) tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies); Loading @@ -1077,6 +1107,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) reset_control_assert(pcie->afi_rst); reset_control_assert(pcie->pex_rst); if (!dev->pm_domain) tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); /* enable regulators */ Loading @@ -1084,6 +1115,14 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) if (err < 0) dev_err(dev, "failed to enable regulators: %d\n", 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); Loading @@ -1091,6 +1130,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) dev_err(dev, "powerup sequence failed: %d\n", err); return err; } } reset_control_deassert(pcie->afi_rst); Loading Loading @@ -1262,6 +1302,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); Loading @@ -1276,11 +1317,13 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) 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); if (err) { Loading Loading @@ -1341,6 +1384,7 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) 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) Loading @@ -1348,9 +1392,11 @@ static int tegra_pcie_put_resources(struct tegra_pcie *pcie) tegra_pcie_power_off(pcie); if (soc->program_uphy) { err = phy_exit(pcie->phy); if (err < 0) dev_err(dev, "failed to teardown PHY: %d\n", err); } return 0; } Loading Loading @@ -1616,7 +1662,31 @@ 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") || 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: Loading Loading @@ -1737,7 +1807,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, Loading Loading @@ -2076,6 +2159,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 = { Loading @@ -2091,6 +2175,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 = { Loading @@ -2105,6 +2190,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 = { Loading @@ -2119,9 +2205,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 }, Loading Loading
Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt +130 −4 Original line number Diff line number Diff line NVIDIA Tegra PCIe controller Required properties: - compatible: For Tegra20, must contain "nvidia,tegra20-pcie". For Tegra30, "nvidia,tegra30-pcie". For Tegra124, must contain "nvidia,tegra124-pcie". Otherwise, must contain "nvidia,<chip>-pcie", plus one of the above, where <chip> is tegra132 or tegra210. - compatible: Must be: - "nvidia,tegra20-pcie": for Tegra20 - "nvidia,tegra30-pcie": for Tegra30 - "nvidia,tegra124-pcie": for Tegra124 and Tegra132 - "nvidia,tegra210-pcie": for Tegra210 - "nvidia,tegra186-pcie": for Tegra186 - power-domains: To ungate power partition by BPMP powergate driver. Must contain BPMP phandle and PCIe power partition ID. This is required only for Tegra186. - device_type: Must be "pci" - reg: A list of physical base address and length for each set of controller registers. Must contain an entry for each entry in the reg-names property. Loading Loading @@ -124,6 +129,16 @@ Power supplies for Tegra210: - vddio-pex-ctl-supply: Power supply for PCIe control I/O partition. Must supply 1.8 V. Power supplies for Tegra186: - Required: - dvdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V. - hvdd-pex-pll-supply: High-voltage supply for PLLE (shared with USB3). Must supply 1.8 V. - hvdd-pex-supply: High-voltage supply for PCIe I/O and PCIe output clocks. Must supply 1.8 V. - vddio-pexctl-aud-supply: Power supply for PCIe side band signals. Must supply 1.8 V. Root ports are defined as subnodes of the PCIe controller node. Required properties: Loading Loading @@ -546,3 +561,114 @@ Board DTS: status = "okay"; }; }; Tegra186: --------- SoC DTSI: pcie@10003000 { compatible = "nvidia,tegra186-pcie"; power-domains = <&bpmp TEGRA186_POWER_DOMAIN_PCX>; device_type = "pci"; reg = <0x0 0x10003000 0x0 0x00000800 /* PADS registers */ 0x0 0x10003800 0x0 0x00000800 /* AFI registers */ 0x0 0x40000000 0x0 0x10000000>; /* configuration space */ reg-names = "pads", "afi", "cs"; interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */ interrupt-names = "intr", "msi"; #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 0>; interrupt-map = <0 0 0 0 &gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>; bus-range = <0x00 0xff>; #address-cells = <3>; #size-cells = <2>; ranges = <0x82000000 0 0x10000000 0x0 0x10000000 0 0x00001000 /* port 0 configuration space */ 0x82000000 0 0x10001000 0x0 0x10001000 0 0x00001000 /* port 1 configuration space */ 0x82000000 0 0x10004000 0x0 0x10004000 0 0x00001000 /* port 2 configuration space */ 0x81000000 0 0x0 0x0 0x50000000 0 0x00010000 /* downstream I/O (64 KiB) */ 0x82000000 0 0x50100000 0x0 0x50100000 0 0x07F00000 /* non-prefetchable memory (127 MiB) */ 0xc2000000 0 0x58000000 0x0 0x58000000 0 0x28000000>; /* prefetchable memory (640 MiB) */ clocks = <&bpmp TEGRA186_CLK_AFI>, <&bpmp TEGRA186_CLK_PCIE>, <&bpmp TEGRA186_CLK_PLLE>; clock-names = "afi", "pex", "pll_e"; resets = <&bpmp TEGRA186_RESET_AFI>, <&bpmp TEGRA186_RESET_PCIE>, <&bpmp TEGRA186_RESET_PCIEXCLK>; reset-names = "afi", "pex", "pcie_x"; status = "disabled"; pci@1,0 { device_type = "pci"; assigned-addresses = <0x82000800 0 0x10000000 0 0x1000>; reg = <0x000800 0 0 0 0>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <2>; }; pci@2,0 { device_type = "pci"; assigned-addresses = <0x82001000 0 0x10001000 0 0x1000>; reg = <0x001000 0 0 0 0>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <1>; }; pci@3,0 { device_type = "pci"; assigned-addresses = <0x82001800 0 0x10004000 0 0x1000>; reg = <0x001800 0 0 0 0>; status = "disabled"; #address-cells = <3>; #size-cells = <2>; ranges; nvidia,num-lanes = <1>; }; }; Board DTS: pcie@10003000 { status = "okay"; dvdd-pex-supply = <&vdd_pex>; hvdd-pex-pll-supply = <&vdd_1v8>; hvdd-pex-supply = <&vdd_1v8>; vddio-pexctl-aud-supply = <&vdd_1v8>; pci@1,0 { nvidia,num-lanes = <4>; status = "okay"; }; pci@2,0 { nvidia,num-lanes = <0>; status = "disabled"; }; pci@3,0 { nvidia,num-lanes = <1>; status = "disabled"; }; };
drivers/pci/host/pci-tegra.c +131 −27 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -252,6 +255,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) Loading Loading @@ -491,12 +495,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) Loading Loading @@ -1012,11 +1036,13 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) afi_writel(pcie, value, AFI_FUSE); } 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 */ reset_control_deassert(pcie->pcie_xrst); Loading Loading @@ -1048,18 +1074,22 @@ 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? */ 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); if (!dev->pm_domain) tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies); Loading @@ -1077,6 +1107,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) reset_control_assert(pcie->afi_rst); reset_control_assert(pcie->pex_rst); if (!dev->pm_domain) tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); /* enable regulators */ Loading @@ -1084,6 +1115,14 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) if (err < 0) dev_err(dev, "failed to enable regulators: %d\n", 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); Loading @@ -1091,6 +1130,7 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie) dev_err(dev, "powerup sequence failed: %d\n", err); return err; } } reset_control_deassert(pcie->afi_rst); Loading Loading @@ -1262,6 +1302,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); Loading @@ -1276,11 +1317,13 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) 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); if (err) { Loading Loading @@ -1341,6 +1384,7 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) 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) Loading @@ -1348,9 +1392,11 @@ static int tegra_pcie_put_resources(struct tegra_pcie *pcie) tegra_pcie_power_off(pcie); if (soc->program_uphy) { err = phy_exit(pcie->phy); if (err < 0) dev_err(dev, "failed to teardown PHY: %d\n", err); } return 0; } Loading Loading @@ -1616,7 +1662,31 @@ 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") || 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: Loading Loading @@ -1737,7 +1807,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, Loading Loading @@ -2076,6 +2159,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 = { Loading @@ -2091,6 +2175,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 = { Loading @@ -2105,6 +2190,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 = { Loading @@ -2119,9 +2205,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 }, Loading