diff options
| -rw-r--r-- | Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt | 224 | ||||
| -rw-r--r-- | drivers/pci/host/pci-tegra.c | 244 |
2 files changed, 446 insertions, 22 deletions
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt index 75321ae23c08..b8cc395fffea 100644 --- a/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt +++ b/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt | |||
| @@ -60,11 +60,14 @@ Required properties: | |||
| 60 | - afi | 60 | - afi |
| 61 | - pcie_x | 61 | - pcie_x |
| 62 | 62 | ||
| 63 | Required properties on Tegra124 and later: | 63 | Required properties on Tegra124 and later (deprecated): |
| 64 | - phys: Must contain an entry for each entry in phy-names. | 64 | - phys: Must contain an entry for each entry in phy-names. |
| 65 | - phy-names: Must include the following entries: | 65 | - phy-names: Must include the following entries: |
| 66 | - pcie | 66 | - pcie |
| 67 | 67 | ||
| 68 | These properties are deprecated in favour of per-lane PHYs define in each of | ||
| 69 | the root ports (see below). | ||
| 70 | |||
| 68 | Power supplies for Tegra20: | 71 | Power supplies for Tegra20: |
| 69 | - avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V. | 72 | - avdd-pex-supply: Power supply for analog PCIe logic. Must supply 1.05 V. |
| 70 | - vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V. | 73 | - vdd-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V. |
| @@ -122,11 +125,22 @@ Required properties: | |||
| 122 | - Root port 0 uses 4 lanes, root port 1 is unused. | 125 | - Root port 0 uses 4 lanes, root port 1 is unused. |
| 123 | - Both root ports use 2 lanes. | 126 | - Both root ports use 2 lanes. |
| 124 | 127 | ||
| 125 | Example: | 128 | Required properties for Tegra124 and later: |
| 129 | - phys: Must contain an phandle to a PHY for each entry in phy-names. | ||
| 130 | - phy-names: Must include an entry for each active lane. Note that the number | ||
| 131 | of entries does not have to (though usually will) be equal to the specified | ||
| 132 | number of lanes in the nvidia,num-lanes property. Entries are of the form | ||
| 133 | "pcie-N": where N ranges from 0 to the value specified in nvidia,num-lanes. | ||
| 134 | |||
| 135 | Examples: | ||
| 136 | ========= | ||
| 137 | |||
| 138 | Tegra20: | ||
| 139 | -------- | ||
| 126 | 140 | ||
| 127 | SoC DTSI: | 141 | SoC DTSI: |
| 128 | 142 | ||
| 129 | pcie-controller { | 143 | pcie-controller@80003000 { |
| 130 | compatible = "nvidia,tegra20-pcie"; | 144 | compatible = "nvidia,tegra20-pcie"; |
| 131 | device_type = "pci"; | 145 | device_type = "pci"; |
| 132 | reg = <0x80003000 0x00000800 /* PADS registers */ | 146 | reg = <0x80003000 0x00000800 /* PADS registers */ |
| @@ -186,10 +200,9 @@ SoC DTSI: | |||
| 186 | }; | 200 | }; |
| 187 | }; | 201 | }; |
| 188 | 202 | ||
| 189 | |||
| 190 | Board DTS: | 203 | Board DTS: |
| 191 | 204 | ||
| 192 | pcie-controller { | 205 | pcie-controller@80003000 { |
| 193 | status = "okay"; | 206 | status = "okay"; |
| 194 | 207 | ||
| 195 | vdd-supply = <&pci_vdd_reg>; | 208 | vdd-supply = <&pci_vdd_reg>; |
| @@ -222,3 +235,204 @@ if a device on the PCI bus provides a non-probeable bus such as I2C or SPI, | |||
| 222 | device nodes need to be added in order to allow the bus' children to be | 235 | device nodes need to be added in order to allow the bus' children to be |
| 223 | instantiated at the proper location in the operating system's device tree (as | 236 | instantiated at the proper location in the operating system's device tree (as |
| 224 | illustrated by the optional nodes in the example above). | 237 | illustrated by the optional nodes in the example above). |
| 238 | |||
| 239 | Tegra30: | ||
| 240 | -------- | ||
| 241 | |||
| 242 | SoC DTSI: | ||
| 243 | |||
| 244 | pcie-controller@00003000 { | ||
| 245 | compatible = "nvidia,tegra30-pcie"; | ||
| 246 | device_type = "pci"; | ||
| 247 | reg = <0x00003000 0x00000800 /* PADS registers */ | ||
| 248 | 0x00003800 0x00000200 /* AFI registers */ | ||
| 249 | 0x10000000 0x10000000>; /* configuration space */ | ||
| 250 | reg-names = "pads", "afi", "cs"; | ||
| 251 | interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH /* controller interrupt */ | ||
| 252 | GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */ | ||
| 253 | interrupt-names = "intr", "msi"; | ||
| 254 | |||
| 255 | #interrupt-cells = <1>; | ||
| 256 | interrupt-map-mask = <0 0 0 0>; | ||
| 257 | interrupt-map = <0 0 0 0 &intc GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | ||
| 258 | |||
| 259 | bus-range = <0x00 0xff>; | ||
| 260 | #address-cells = <3>; | ||
| 261 | #size-cells = <2>; | ||
| 262 | |||
| 263 | ranges = <0x82000000 0 0x00000000 0x00000000 0 0x00001000 /* port 0 configuration space */ | ||
| 264 | 0x82000000 0 0x00001000 0x00001000 0 0x00001000 /* port 1 configuration space */ | ||
| 265 | 0x82000000 0 0x00004000 0x00004000 0 0x00001000 /* port 2 configuration space */ | ||
| 266 | 0x81000000 0 0 0x02000000 0 0x00010000 /* downstream I/O */ | ||
| 267 | 0x82000000 0 0x20000000 0x20000000 0 0x08000000 /* non-prefetchable memory */ | ||
| 268 | 0xc2000000 0 0x28000000 0x28000000 0 0x18000000>; /* prefetchable memory */ | ||
| 269 | |||
| 270 | clocks = <&tegra_car TEGRA30_CLK_PCIE>, | ||
| 271 | <&tegra_car TEGRA30_CLK_AFI>, | ||
| 272 | <&tegra_car TEGRA30_CLK_PLL_E>, | ||
| 273 | <&tegra_car TEGRA30_CLK_CML0>; | ||
| 274 | clock-names = "pex", "afi", "pll_e", "cml"; | ||
| 275 | resets = <&tegra_car 70>, | ||
| 276 | <&tegra_car 72>, | ||
| 277 | <&tegra_car 74>; | ||
| 278 | reset-names = "pex", "afi", "pcie_x"; | ||
| 279 | status = "disabled"; | ||
| 280 | |||
| 281 | pci@1,0 { | ||
| 282 | device_type = "pci"; | ||
| 283 | assigned-addresses = <0x82000800 0 0x00000000 0 0x1000>; | ||
| 284 | reg = <0x000800 0 0 0 0>; | ||
| 285 | status = "disabled"; | ||
| 286 | |||
| 287 | #address-cells = <3>; | ||
| 288 | #size-cells = <2>; | ||
| 289 | ranges; | ||
| 290 | |||
| 291 | nvidia,num-lanes = <2>; | ||
| 292 | }; | ||
| 293 | |||
| 294 | pci@2,0 { | ||
| 295 | device_type = "pci"; | ||
| 296 | assigned-addresses = <0x82001000 0 0x00001000 0 0x1000>; | ||
| 297 | reg = <0x001000 0 0 0 0>; | ||
| 298 | status = "disabled"; | ||
| 299 | |||
| 300 | #address-cells = <3>; | ||
| 301 | #size-cells = <2>; | ||
| 302 | ranges; | ||
| 303 | |||
| 304 | nvidia,num-lanes = <2>; | ||
| 305 | }; | ||
| 306 | |||
| 307 | pci@3,0 { | ||
| 308 | device_type = "pci"; | ||
| 309 | assigned-addresses = <0x82001800 0 0x00004000 0 0x1000>; | ||
| 310 | reg = <0x001800 0 0 0 0>; | ||
| 311 | status = "disabled"; | ||
| 312 | |||
| 313 | #address-cells = <3>; | ||
| 314 | #size-cells = <2>; | ||
| 315 | ranges; | ||
| 316 | |||
| 317 | nvidia,num-lanes = <2>; | ||
| 318 | }; | ||
| 319 | }; | ||
| 320 | |||
| 321 | Board DTS: | ||
| 322 | |||
| 323 | pcie-controller@00003000 { | ||
| 324 | status = "okay"; | ||
| 325 | |||
| 326 | avdd-pexa-supply = <&ldo1_reg>; | ||
| 327 | vdd-pexa-supply = <&ldo1_reg>; | ||
| 328 | avdd-pexb-supply = <&ldo1_reg>; | ||
| 329 | vdd-pexb-supply = <&ldo1_reg>; | ||
| 330 | avdd-pex-pll-supply = <&ldo1_reg>; | ||
| 331 | avdd-plle-supply = <&ldo1_reg>; | ||
| 332 | vddio-pex-ctl-supply = <&sys_3v3_reg>; | ||
| 333 | hvdd-pex-supply = <&sys_3v3_pexs_reg>; | ||
| 334 | |||
| 335 | pci@1,0 { | ||
| 336 | status = "okay"; | ||
| 337 | }; | ||
| 338 | |||
| 339 | pci@3,0 { | ||
| 340 | status = "okay"; | ||
| 341 | }; | ||
| 342 | }; | ||
| 343 | |||
| 344 | Tegra124: | ||
| 345 | --------- | ||
| 346 | |||
| 347 | SoC DTSI: | ||
| 348 | |||
| 349 | pcie-controller@01003000 { | ||
| 350 | compatible = "nvidia,tegra124-pcie"; | ||
| 351 | device_type = "pci"; | ||
| 352 | reg = <0x0 0x01003000 0x0 0x00000800 /* PADS registers */ | ||
| 353 | 0x0 0x01003800 0x0 0x00000800 /* AFI registers */ | ||
| 354 | 0x0 0x02000000 0x0 0x10000000>; /* configuration space */ | ||
| 355 | reg-names = "pads", "afi", "cs"; | ||
| 356 | interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */ | ||
| 357 | <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */ | ||
| 358 | interrupt-names = "intr", "msi"; | ||
| 359 | |||
| 360 | #interrupt-cells = <1>; | ||
| 361 | interrupt-map-mask = <0 0 0 0>; | ||
| 362 | interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; | ||
| 363 | |||
| 364 | bus-range = <0x00 0xff>; | ||
| 365 | #address-cells = <3>; | ||
| 366 | #size-cells = <2>; | ||
| 367 | |||
| 368 | ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000 /* port 0 configuration space */ | ||
| 369 | 0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000 /* port 1 configuration space */ | ||
| 370 | 0x81000000 0 0x0 0x0 0x12000000 0 0x00010000 /* downstream I/O (64 KiB) */ | ||
| 371 | 0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000 /* non-prefetchable memory (208 MiB) */ | ||
| 372 | 0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */ | ||
| 373 | |||
| 374 | clocks = <&tegra_car TEGRA124_CLK_PCIE>, | ||
| 375 | <&tegra_car TEGRA124_CLK_AFI>, | ||
| 376 | <&tegra_car TEGRA124_CLK_PLL_E>, | ||
| 377 | <&tegra_car TEGRA124_CLK_CML0>; | ||
| 378 | clock-names = "pex", "afi", "pll_e", "cml"; | ||
| 379 | resets = <&tegra_car 70>, | ||
| 380 | <&tegra_car 72>, | ||
| 381 | <&tegra_car 74>; | ||
| 382 | reset-names = "pex", "afi", "pcie_x"; | ||
| 383 | status = "disabled"; | ||
| 384 | |||
| 385 | pci@1,0 { | ||
| 386 | device_type = "pci"; | ||
| 387 | assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>; | ||
| 388 | reg = <0x000800 0 0 0 0>; | ||
| 389 | status = "disabled"; | ||
| 390 | |||
| 391 | #address-cells = <3>; | ||
| 392 | #size-cells = <2>; | ||
| 393 | ranges; | ||
| 394 | |||
| 395 | nvidia,num-lanes = <2>; | ||
| 396 | }; | ||
| 397 | |||
| 398 | pci@2,0 { | ||
| 399 | device_type = "pci"; | ||
| 400 | assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>; | ||
| 401 | reg = <0x001000 0 0 0 0>; | ||
| 402 | status = "disabled"; | ||
| 403 | |||
| 404 | #address-cells = <3>; | ||
| 405 | #size-cells = <2>; | ||
| 406 | ranges; | ||
| 407 | |||
| 408 | nvidia,num-lanes = <1>; | ||
| 409 | }; | ||
| 410 | }; | ||
| 411 | |||
| 412 | Board DTS: | ||
| 413 | |||
| 414 | pcie-controller@01003000 { | ||
| 415 | status = "okay"; | ||
| 416 | |||
| 417 | avddio-pex-supply = <&vdd_1v05_run>; | ||
| 418 | dvddio-pex-supply = <&vdd_1v05_run>; | ||
| 419 | avdd-pex-pll-supply = <&vdd_1v05_run>; | ||
| 420 | hvdd-pex-supply = <&vdd_3v3_lp0>; | ||
| 421 | hvdd-pex-pll-e-supply = <&vdd_3v3_lp0>; | ||
| 422 | vddio-pex-ctl-supply = <&vdd_3v3_lp0>; | ||
| 423 | avdd-pll-erefe-supply = <&avdd_1v05_run>; | ||
| 424 | |||
| 425 | /* Mini PCIe */ | ||
| 426 | pci@1,0 { | ||
| 427 | phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>; | ||
| 428 | phy-names = "pcie-0"; | ||
| 429 | status = "okay"; | ||
| 430 | }; | ||
| 431 | |||
| 432 | /* Gigabit Ethernet */ | ||
| 433 | pci@2,0 { | ||
| 434 | phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>; | ||
| 435 | phy-names = "pcie-0"; | ||
| 436 | status = "okay"; | ||
| 437 | }; | ||
| 438 | }; | ||
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 68d1f41b3cbf..c388468c202a 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c | |||
| @@ -295,6 +295,7 @@ struct tegra_pcie { | |||
| 295 | struct reset_control *afi_rst; | 295 | struct reset_control *afi_rst; |
| 296 | struct reset_control *pcie_xrst; | 296 | struct reset_control *pcie_xrst; |
| 297 | 297 | ||
| 298 | bool legacy_phy; | ||
| 298 | struct phy *phy; | 299 | struct phy *phy; |
| 299 | 300 | ||
| 300 | struct tegra_msi msi; | 301 | struct tegra_msi msi; |
| @@ -311,11 +312,14 @@ struct tegra_pcie { | |||
| 311 | 312 | ||
| 312 | struct tegra_pcie_port { | 313 | struct tegra_pcie_port { |
| 313 | struct tegra_pcie *pcie; | 314 | struct tegra_pcie *pcie; |
| 315 | struct device_node *np; | ||
| 314 | struct list_head list; | 316 | struct list_head list; |
| 315 | struct resource regs; | 317 | struct resource regs; |
| 316 | void __iomem *base; | 318 | void __iomem *base; |
| 317 | unsigned int index; | 319 | unsigned int index; |
| 318 | unsigned int lanes; | 320 | unsigned int lanes; |
| 321 | |||
| 322 | struct phy **phys; | ||
| 319 | }; | 323 | }; |
| 320 | 324 | ||
| 321 | struct tegra_pcie_bus { | 325 | struct tegra_pcie_bus { |
| @@ -860,6 +864,128 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) | |||
| 860 | return 0; | 864 | return 0; |
| 861 | } | 865 | } |
| 862 | 866 | ||
| 867 | static int tegra_pcie_phy_disable(struct tegra_pcie *pcie) | ||
| 868 | { | ||
| 869 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
| 870 | u32 value; | ||
| 871 | |||
| 872 | /* disable TX/RX data */ | ||
| 873 | value = pads_readl(pcie, PADS_CTL); | ||
| 874 | value &= ~(PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L); | ||
| 875 | pads_writel(pcie, value, PADS_CTL); | ||
| 876 | |||
| 877 | /* override IDDQ */ | ||
| 878 | value = pads_readl(pcie, PADS_CTL); | ||
| 879 | value |= PADS_CTL_IDDQ_1L; | ||
| 880 | pads_writel(pcie, PADS_CTL, value); | ||
| 881 | |||
| 882 | /* reset PLL */ | ||
| 883 | value = pads_readl(pcie, soc->pads_pll_ctl); | ||
| 884 | value &= ~PADS_PLL_CTL_RST_B4SM; | ||
| 885 | pads_writel(pcie, value, soc->pads_pll_ctl); | ||
| 886 | |||
| 887 | usleep_range(20, 100); | ||
| 888 | |||
| 889 | return 0; | ||
| 890 | } | ||
| 891 | |||
| 892 | static int tegra_pcie_port_phy_power_on(struct tegra_pcie_port *port) | ||
| 893 | { | ||
| 894 | struct device *dev = port->pcie->dev; | ||
| 895 | unsigned int i; | ||
| 896 | int err; | ||
| 897 | |||
| 898 | for (i = 0; i < port->lanes; i++) { | ||
| 899 | err = phy_power_on(port->phys[i]); | ||
| 900 | if (err < 0) { | ||
| 901 | dev_err(dev, "failed to power on PHY#%u: %d\n", i, | ||
| 902 | err); | ||
| 903 | return err; | ||
| 904 | } | ||
| 905 | } | ||
| 906 | |||
| 907 | return 0; | ||
| 908 | } | ||
| 909 | |||
| 910 | static int tegra_pcie_port_phy_power_off(struct tegra_pcie_port *port) | ||
| 911 | { | ||
| 912 | struct device *dev = port->pcie->dev; | ||
| 913 | unsigned int i; | ||
| 914 | int err; | ||
| 915 | |||
| 916 | for (i = 0; i < port->lanes; i++) { | ||
| 917 | err = phy_power_off(port->phys[i]); | ||
| 918 | if (err < 0) { | ||
| 919 | dev_err(dev, "failed to power off PHY#%u: %d\n", i, | ||
| 920 | err); | ||
| 921 | return err; | ||
| 922 | } | ||
| 923 | } | ||
| 924 | |||
| 925 | return 0; | ||
| 926 | } | ||
| 927 | |||
| 928 | static int tegra_pcie_phy_power_on(struct tegra_pcie *pcie) | ||
| 929 | { | ||
| 930 | struct tegra_pcie_port *port; | ||
| 931 | int err; | ||
| 932 | |||
| 933 | if (pcie->legacy_phy) { | ||
| 934 | if (pcie->phy) | ||
| 935 | err = phy_power_on(pcie->phy); | ||
| 936 | else | ||
| 937 | err = tegra_pcie_phy_enable(pcie); | ||
| 938 | |||
| 939 | if (err < 0) | ||
| 940 | dev_err(pcie->dev, "failed to power on PHY: %d\n", err); | ||
| 941 | |||
| 942 | return err; | ||
| 943 | } | ||
| 944 | |||
| 945 | list_for_each_entry(port, &pcie->ports, list) { | ||
| 946 | err = tegra_pcie_port_phy_power_on(port); | ||
| 947 | if (err < 0) { | ||
| 948 | dev_err(pcie->dev, | ||
| 949 | "failed to power on PCIe port %u PHY: %d\n", | ||
| 950 | port->index, err); | ||
| 951 | return err; | ||
| 952 | } | ||
| 953 | } | ||
| 954 | |||
| 955 | return 0; | ||
| 956 | } | ||
| 957 | |||
| 958 | static int tegra_pcie_phy_power_off(struct tegra_pcie *pcie) | ||
| 959 | { | ||
| 960 | struct tegra_pcie_port *port; | ||
| 961 | int err; | ||
| 962 | |||
| 963 | if (pcie->legacy_phy) { | ||
| 964 | if (pcie->phy) | ||
| 965 | err = phy_power_off(pcie->phy); | ||
| 966 | else | ||
| 967 | err = tegra_pcie_phy_disable(pcie); | ||
| 968 | |||
| 969 | if (err < 0) | ||
| 970 | dev_err(pcie->dev, "failed to power off PHY: %d\n", | ||
| 971 | err); | ||
| 972 | |||
| 973 | return err; | ||
| 974 | } | ||
| 975 | |||
| 976 | list_for_each_entry(port, &pcie->ports, list) { | ||
| 977 | err = tegra_pcie_port_phy_power_off(port); | ||
| 978 | if (err < 0) { | ||
| 979 | dev_err(pcie->dev, | ||
| 980 | "failed to power off PCIe port %u PHY: %d\n", | ||
| 981 | port->index, err); | ||
| 982 | return err; | ||
| 983 | } | ||
| 984 | } | ||
| 985 | |||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | |||
| 863 | static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | 989 | static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) |
| 864 | { | 990 | { |
| 865 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | 991 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; |
| @@ -899,13 +1025,9 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) | |||
| 899 | afi_writel(pcie, value, AFI_FUSE); | 1025 | afi_writel(pcie, value, AFI_FUSE); |
| 900 | } | 1026 | } |
| 901 | 1027 | ||
| 902 | if (!pcie->phy) | 1028 | err = tegra_pcie_phy_power_on(pcie); |
| 903 | err = tegra_pcie_phy_enable(pcie); | ||
| 904 | else | ||
| 905 | err = phy_power_on(pcie->phy); | ||
| 906 | |||
| 907 | if (err < 0) { | 1029 | if (err < 0) { |
| 908 | dev_err(pcie->dev, "failed to power on PHY: %d\n", err); | 1030 | dev_err(pcie->dev, "failed to power on PHY(s): %d\n", err); |
| 909 | return err; | 1031 | return err; |
| 910 | } | 1032 | } |
| 911 | 1033 | ||
| @@ -942,9 +1064,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie) | |||
| 942 | 1064 | ||
| 943 | /* TODO: disable and unprepare clocks? */ | 1065 | /* TODO: disable and unprepare clocks? */ |
| 944 | 1066 | ||
| 945 | err = phy_power_off(pcie->phy); | 1067 | err = tegra_pcie_phy_power_off(pcie); |
| 946 | if (err < 0) | 1068 | if (err < 0) |
| 947 | dev_warn(pcie->dev, "failed to power off PHY: %d\n", err); | 1069 | dev_err(pcie->dev, "failed to power off PHY(s): %d\n", err); |
| 948 | 1070 | ||
| 949 | reset_control_assert(pcie->pcie_xrst); | 1071 | reset_control_assert(pcie->pcie_xrst); |
| 950 | reset_control_assert(pcie->afi_rst); | 1072 | reset_control_assert(pcie->afi_rst); |
| @@ -1049,6 +1171,100 @@ static int tegra_pcie_resets_get(struct tegra_pcie *pcie) | |||
| 1049 | return 0; | 1171 | return 0; |
| 1050 | } | 1172 | } |
| 1051 | 1173 | ||
| 1174 | static int tegra_pcie_phys_get_legacy(struct tegra_pcie *pcie) | ||
| 1175 | { | ||
| 1176 | int err; | ||
| 1177 | |||
| 1178 | pcie->phy = devm_phy_optional_get(pcie->dev, "pcie"); | ||
| 1179 | if (IS_ERR(pcie->phy)) { | ||
| 1180 | err = PTR_ERR(pcie->phy); | ||
| 1181 | dev_err(pcie->dev, "failed to get PHY: %d\n", err); | ||
| 1182 | return err; | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | err = phy_init(pcie->phy); | ||
| 1186 | if (err < 0) { | ||
| 1187 | dev_err(pcie->dev, "failed to initialize PHY: %d\n", err); | ||
| 1188 | return err; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | pcie->legacy_phy = true; | ||
| 1192 | |||
| 1193 | return 0; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static struct phy *devm_of_phy_optional_get_index(struct device *dev, | ||
| 1197 | struct device_node *np, | ||
| 1198 | const char *consumer, | ||
| 1199 | unsigned int index) | ||
| 1200 | { | ||
| 1201 | struct phy *phy; | ||
| 1202 | char *name; | ||
| 1203 | |||
| 1204 | name = kasprintf(GFP_KERNEL, "%s-%u", consumer, index); | ||
| 1205 | if (!name) | ||
| 1206 | return ERR_PTR(-ENOMEM); | ||
| 1207 | |||
| 1208 | phy = devm_of_phy_get(dev, np, name); | ||
| 1209 | kfree(name); | ||
| 1210 | |||
| 1211 | if (IS_ERR(phy) && PTR_ERR(phy) == -ENODEV) | ||
| 1212 | phy = NULL; | ||
| 1213 | |||
| 1214 | return phy; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static int tegra_pcie_port_get_phys(struct tegra_pcie_port *port) | ||
| 1218 | { | ||
| 1219 | struct device *dev = port->pcie->dev; | ||
| 1220 | struct phy *phy; | ||
| 1221 | unsigned int i; | ||
| 1222 | int err; | ||
| 1223 | |||
| 1224 | port->phys = devm_kcalloc(dev, sizeof(phy), port->lanes, GFP_KERNEL); | ||
| 1225 | if (!port->phys) | ||
| 1226 | return -ENOMEM; | ||
| 1227 | |||
| 1228 | for (i = 0; i < port->lanes; i++) { | ||
| 1229 | phy = devm_of_phy_optional_get_index(dev, port->np, "pcie", i); | ||
| 1230 | if (IS_ERR(phy)) { | ||
| 1231 | dev_err(dev, "failed to get PHY#%u: %ld\n", i, | ||
| 1232 | PTR_ERR(phy)); | ||
| 1233 | return PTR_ERR(phy); | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | err = phy_init(phy); | ||
| 1237 | if (err < 0) { | ||
| 1238 | dev_err(dev, "failed to initialize PHY#%u: %d\n", i, | ||
| 1239 | err); | ||
| 1240 | return err; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | port->phys[i] = phy; | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | return 0; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | static int tegra_pcie_phys_get(struct tegra_pcie *pcie) | ||
| 1250 | { | ||
| 1251 | const struct tegra_pcie_soc_data *soc = pcie->soc_data; | ||
| 1252 | struct device_node *np = pcie->dev->of_node; | ||
| 1253 | struct tegra_pcie_port *port; | ||
| 1254 | int err; | ||
| 1255 | |||
| 1256 | if (!soc->has_gen2 || of_find_property(np, "phys", NULL) != NULL) | ||
| 1257 | return tegra_pcie_phys_get_legacy(pcie); | ||
| 1258 | |||
| 1259 | list_for_each_entry(port, &pcie->ports, list) { | ||
| 1260 | err = tegra_pcie_port_get_phys(port); | ||
| 1261 | if (err < 0) | ||
| 1262 | return err; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | return 0; | ||
| 1266 | } | ||
| 1267 | |||
| 1052 | static int tegra_pcie_get_resources(struct tegra_pcie *pcie) | 1268 | static int tegra_pcie_get_resources(struct tegra_pcie *pcie) |
| 1053 | { | 1269 | { |
| 1054 | struct platform_device *pdev = to_platform_device(pcie->dev); | 1270 | struct platform_device *pdev = to_platform_device(pcie->dev); |
| @@ -1067,16 +1283,9 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie) | |||
| 1067 | return err; | 1283 | return err; |
| 1068 | } | 1284 | } |
| 1069 | 1285 | ||
| 1070 | pcie->phy = devm_phy_optional_get(pcie->dev, "pcie"); | 1286 | err = tegra_pcie_phys_get(pcie); |
| 1071 | if (IS_ERR(pcie->phy)) { | ||
| 1072 | err = PTR_ERR(pcie->phy); | ||
| 1073 | dev_err(&pdev->dev, "failed to get PHY: %d\n", err); | ||
| 1074 | return err; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | err = phy_init(pcie->phy); | ||
| 1078 | if (err < 0) { | 1287 | if (err < 0) { |
| 1079 | dev_err(&pdev->dev, "failed to initialize PHY: %d\n", err); | 1288 | dev_err(&pdev->dev, "failed to get PHYs: %d\n", err); |
| 1080 | return err; | 1289 | return err; |
| 1081 | } | 1290 | } |
| 1082 | 1291 | ||
| @@ -1752,6 +1961,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie) | |||
| 1752 | rp->index = index; | 1961 | rp->index = index; |
| 1753 | rp->lanes = value; | 1962 | rp->lanes = value; |
| 1754 | rp->pcie = pcie; | 1963 | rp->pcie = pcie; |
| 1964 | rp->np = port; | ||
| 1755 | 1965 | ||
| 1756 | rp->base = devm_ioremap_resource(pcie->dev, &rp->regs); | 1966 | rp->base = devm_ioremap_resource(pcie->dev, &rp->regs); |
| 1757 | if (IS_ERR(rp->base)) | 1967 | if (IS_ERR(rp->base)) |
