1f315828bSThierry Reding /* 2f315828bSThierry Reding * Copyright (c) 2010, CompuLab, Ltd. 3f315828bSThierry Reding * Author: Mike Rapoport <mike@compulab.co.il> 4f315828bSThierry Reding * 5f315828bSThierry Reding * Based on NVIDIA PCIe driver 6f315828bSThierry Reding * Copyright (c) 2008-2009, NVIDIA Corporation. 7f315828bSThierry Reding * 8f315828bSThierry Reding * Copyright (c) 2013-2014, NVIDIA Corporation. 9f315828bSThierry Reding * 10f315828bSThierry Reding * SPDX-License-Identifier: GPL-2.0 11f315828bSThierry Reding */ 12f315828bSThierry Reding 13f315828bSThierry Reding #define pr_fmt(fmt) "tegra-pcie: " fmt 14f315828bSThierry Reding 15f315828bSThierry Reding #include <common.h> 16*bbc5b36bSStephen Warren #include <clk.h> 17e81ca884SSimon Glass #include <dm.h> 18f315828bSThierry Reding #include <errno.h> 19f315828bSThierry Reding #include <fdtdec.h> 20f315828bSThierry Reding #include <malloc.h> 21f315828bSThierry Reding #include <pci.h> 22*bbc5b36bSStephen Warren #include <power-domain.h> 23*bbc5b36bSStephen Warren #include <reset.h> 24f315828bSThierry Reding 25f315828bSThierry Reding #include <asm/io.h> 26f315828bSThierry Reding #include <asm/gpio.h> 27f315828bSThierry Reding 28*bbc5b36bSStephen Warren #include <linux/list.h> 29*bbc5b36bSStephen Warren 30*bbc5b36bSStephen Warren #ifndef CONFIG_TEGRA186 31f315828bSThierry Reding #include <asm/arch/clock.h> 32f315828bSThierry Reding #include <asm/arch/powergate.h> 33f315828bSThierry Reding #include <asm/arch-tegra/xusb-padctl.h> 34f315828bSThierry Reding #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> 35*bbc5b36bSStephen Warren #endif 36*bbc5b36bSStephen Warren 37*bbc5b36bSStephen Warren /* 38*bbc5b36bSStephen Warren * FIXME: TODO: This driver contains a number of ifdef CONFIG_TEGRA186 that 39*bbc5b36bSStephen Warren * should not be present. These are needed because newer Tegra SoCs support 40*bbc5b36bSStephen Warren * only the standard clock/reset APIs, whereas older Tegra SoCs support only 41*bbc5b36bSStephen Warren * a custom Tegra-specific API. ASAP the older Tegra SoCs' code should be 42*bbc5b36bSStephen Warren * fixed to implement the standard APIs, and all drivers converted to solely 43*bbc5b36bSStephen Warren * use the new standard APIs, with no ifdefs. 44*bbc5b36bSStephen Warren */ 45f315828bSThierry Reding 46f315828bSThierry Reding DECLARE_GLOBAL_DATA_PTR; 47f315828bSThierry Reding 48f315828bSThierry Reding #define AFI_AXI_BAR0_SZ 0x00 49f315828bSThierry Reding #define AFI_AXI_BAR1_SZ 0x04 50f315828bSThierry Reding #define AFI_AXI_BAR2_SZ 0x08 51f315828bSThierry Reding #define AFI_AXI_BAR3_SZ 0x0c 52f315828bSThierry Reding #define AFI_AXI_BAR4_SZ 0x10 53f315828bSThierry Reding #define AFI_AXI_BAR5_SZ 0x14 54f315828bSThierry Reding 55f315828bSThierry Reding #define AFI_AXI_BAR0_START 0x18 56f315828bSThierry Reding #define AFI_AXI_BAR1_START 0x1c 57f315828bSThierry Reding #define AFI_AXI_BAR2_START 0x20 58f315828bSThierry Reding #define AFI_AXI_BAR3_START 0x24 59f315828bSThierry Reding #define AFI_AXI_BAR4_START 0x28 60f315828bSThierry Reding #define AFI_AXI_BAR5_START 0x2c 61f315828bSThierry Reding 62f315828bSThierry Reding #define AFI_FPCI_BAR0 0x30 63f315828bSThierry Reding #define AFI_FPCI_BAR1 0x34 64f315828bSThierry Reding #define AFI_FPCI_BAR2 0x38 65f315828bSThierry Reding #define AFI_FPCI_BAR3 0x3c 66f315828bSThierry Reding #define AFI_FPCI_BAR4 0x40 67f315828bSThierry Reding #define AFI_FPCI_BAR5 0x44 68f315828bSThierry Reding 69f315828bSThierry Reding #define AFI_CACHE_BAR0_SZ 0x48 70f315828bSThierry Reding #define AFI_CACHE_BAR0_ST 0x4c 71f315828bSThierry Reding #define AFI_CACHE_BAR1_SZ 0x50 72f315828bSThierry Reding #define AFI_CACHE_BAR1_ST 0x54 73f315828bSThierry Reding 74f315828bSThierry Reding #define AFI_MSI_BAR_SZ 0x60 75f315828bSThierry Reding #define AFI_MSI_FPCI_BAR_ST 0x64 76f315828bSThierry Reding #define AFI_MSI_AXI_BAR_ST 0x68 77f315828bSThierry Reding 78f315828bSThierry Reding #define AFI_CONFIGURATION 0xac 79f315828bSThierry Reding #define AFI_CONFIGURATION_EN_FPCI (1 << 0) 80f315828bSThierry Reding 81f315828bSThierry Reding #define AFI_FPCI_ERROR_MASKS 0xb0 82f315828bSThierry Reding 83f315828bSThierry Reding #define AFI_INTR_MASK 0xb4 84f315828bSThierry Reding #define AFI_INTR_MASK_INT_MASK (1 << 0) 85f315828bSThierry Reding #define AFI_INTR_MASK_MSI_MASK (1 << 8) 86f315828bSThierry Reding 87f315828bSThierry Reding #define AFI_SM_INTR_ENABLE 0xc4 88f315828bSThierry Reding #define AFI_SM_INTR_INTA_ASSERT (1 << 0) 89f315828bSThierry Reding #define AFI_SM_INTR_INTB_ASSERT (1 << 1) 90f315828bSThierry Reding #define AFI_SM_INTR_INTC_ASSERT (1 << 2) 91f315828bSThierry Reding #define AFI_SM_INTR_INTD_ASSERT (1 << 3) 92f315828bSThierry Reding #define AFI_SM_INTR_INTA_DEASSERT (1 << 4) 93f315828bSThierry Reding #define AFI_SM_INTR_INTB_DEASSERT (1 << 5) 94f315828bSThierry Reding #define AFI_SM_INTR_INTC_DEASSERT (1 << 6) 95f315828bSThierry Reding #define AFI_SM_INTR_INTD_DEASSERT (1 << 7) 96f315828bSThierry Reding 97f315828bSThierry Reding #define AFI_AFI_INTR_ENABLE 0xc8 98f315828bSThierry Reding #define AFI_INTR_EN_INI_SLVERR (1 << 0) 99f315828bSThierry Reding #define AFI_INTR_EN_INI_DECERR (1 << 1) 100f315828bSThierry Reding #define AFI_INTR_EN_TGT_SLVERR (1 << 2) 101f315828bSThierry Reding #define AFI_INTR_EN_TGT_DECERR (1 << 3) 102f315828bSThierry Reding #define AFI_INTR_EN_TGT_WRERR (1 << 4) 103f315828bSThierry Reding #define AFI_INTR_EN_DFPCI_DECERR (1 << 5) 104f315828bSThierry Reding #define AFI_INTR_EN_AXI_DECERR (1 << 6) 105f315828bSThierry Reding #define AFI_INTR_EN_FPCI_TIMEOUT (1 << 7) 106f315828bSThierry Reding #define AFI_INTR_EN_PRSNT_SENSE (1 << 8) 107f315828bSThierry Reding 108f315828bSThierry Reding #define AFI_PCIE_CONFIG 0x0f8 109f315828bSThierry Reding #define AFI_PCIE_CONFIG_PCIE_DISABLE(x) (1 << ((x) + 1)) 110f315828bSThierry Reding #define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL 0xe 111f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20) 112f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) 113f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420 (0x0 << 20) 114f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1 (0x0 << 20) 115f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) 116f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222 (0x1 << 20) 117f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1 (0x1 << 20) 118f315828bSThierry Reding #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411 (0x2 << 20) 119*bbc5b36bSStephen Warren #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401 (0x0 << 20) 120*bbc5b36bSStephen Warren #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211 (0x1 << 20) 121*bbc5b36bSStephen Warren #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111 (0x2 << 20) 122f315828bSThierry Reding 123f315828bSThierry Reding #define AFI_FUSE 0x104 124f315828bSThierry Reding #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) 125f315828bSThierry Reding 126f315828bSThierry Reding #define AFI_PEX0_CTRL 0x110 127f315828bSThierry Reding #define AFI_PEX1_CTRL 0x118 128f315828bSThierry Reding #define AFI_PEX2_CTRL 0x128 129*bbc5b36bSStephen Warren #define AFI_PEX2_CTRL_T186 0x19c 130f315828bSThierry Reding #define AFI_PEX_CTRL_RST (1 << 0) 131f315828bSThierry Reding #define AFI_PEX_CTRL_CLKREQ_EN (1 << 1) 132f315828bSThierry Reding #define AFI_PEX_CTRL_REFCLK_EN (1 << 3) 133f315828bSThierry Reding #define AFI_PEX_CTRL_OVERRIDE_EN (1 << 4) 134f315828bSThierry Reding 135f315828bSThierry Reding #define AFI_PLLE_CONTROL 0x160 136f315828bSThierry Reding #define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9) 137f315828bSThierry Reding #define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1) 138f315828bSThierry Reding 139f315828bSThierry Reding #define AFI_PEXBIAS_CTRL_0 0x168 140f315828bSThierry Reding 141f315828bSThierry Reding #define PADS_CTL_SEL 0x0000009C 142f315828bSThierry Reding 143f315828bSThierry Reding #define PADS_CTL 0x000000A0 144f315828bSThierry Reding #define PADS_CTL_IDDQ_1L (1 << 0) 145f315828bSThierry Reding #define PADS_CTL_TX_DATA_EN_1L (1 << 6) 146f315828bSThierry Reding #define PADS_CTL_RX_DATA_EN_1L (1 << 10) 147f315828bSThierry Reding 148f315828bSThierry Reding #define PADS_PLL_CTL_TEGRA20 0x000000B8 149f315828bSThierry Reding #define PADS_PLL_CTL_TEGRA30 0x000000B4 150f315828bSThierry Reding #define PADS_PLL_CTL_RST_B4SM (0x1 << 1) 151f315828bSThierry Reding #define PADS_PLL_CTL_LOCKDET (0x1 << 8) 152f315828bSThierry Reding #define PADS_PLL_CTL_REFCLK_MASK (0x3 << 16) 153f315828bSThierry Reding #define PADS_PLL_CTL_REFCLK_INTERNAL_CML (0x0 << 16) 154f315828bSThierry Reding #define PADS_PLL_CTL_REFCLK_INTERNAL_CMOS (0x1 << 16) 155f315828bSThierry Reding #define PADS_PLL_CTL_REFCLK_EXTERNAL (0x2 << 16) 156f315828bSThierry Reding #define PADS_PLL_CTL_TXCLKREF_MASK (0x1 << 20) 157f315828bSThierry Reding #define PADS_PLL_CTL_TXCLKREF_DIV10 (0x0 << 20) 158f315828bSThierry Reding #define PADS_PLL_CTL_TXCLKREF_DIV5 (0x1 << 20) 159f315828bSThierry Reding #define PADS_PLL_CTL_TXCLKREF_BUF_EN (0x1 << 22) 160f315828bSThierry Reding 161f315828bSThierry Reding #define PADS_REFCLK_CFG0 0x000000C8 162f315828bSThierry Reding #define PADS_REFCLK_CFG1 0x000000CC 163f315828bSThierry Reding 164f315828bSThierry Reding /* 165f315828bSThierry Reding * Fields in PADS_REFCLK_CFG*. Those registers form an array of 16-bit 166f315828bSThierry Reding * entries, one entry per PCIe port. These field definitions and desired 167f315828bSThierry Reding * values aren't in the TRM, but do come from NVIDIA. 168f315828bSThierry Reding */ 169f315828bSThierry Reding #define PADS_REFCLK_CFG_TERM_SHIFT 2 /* 6:2 */ 170f315828bSThierry Reding #define PADS_REFCLK_CFG_E_TERM_SHIFT 7 171f315828bSThierry Reding #define PADS_REFCLK_CFG_PREDI_SHIFT 8 /* 11:8 */ 172f315828bSThierry Reding #define PADS_REFCLK_CFG_DRVI_SHIFT 12 /* 15:12 */ 173f315828bSThierry Reding 174f315828bSThierry Reding #define RP_VEND_XP 0x00000F00 175f315828bSThierry Reding #define RP_VEND_XP_DL_UP (1 << 30) 176f315828bSThierry Reding 177514e1913SStephen Warren #define RP_VEND_CTL2 0x00000FA8 178514e1913SStephen Warren #define RP_VEND_CTL2_PCA_ENABLE (1 << 7) 179514e1913SStephen Warren 180f315828bSThierry Reding #define RP_PRIV_MISC 0x00000FE0 181f315828bSThierry Reding #define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0) 182f315828bSThierry Reding #define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0) 183f315828bSThierry Reding 184f315828bSThierry Reding #define RP_LINK_CONTROL_STATUS 0x00000090 185f315828bSThierry Reding #define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000 186f315828bSThierry Reding #define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000 187f315828bSThierry Reding 188e81ca884SSimon Glass enum tegra_pci_id { 189e81ca884SSimon Glass TEGRA20_PCIE, 190e81ca884SSimon Glass TEGRA30_PCIE, 191e81ca884SSimon Glass TEGRA124_PCIE, 192e81ca884SSimon Glass TEGRA210_PCIE, 193*bbc5b36bSStephen Warren TEGRA186_PCIE, 194e81ca884SSimon Glass }; 195f315828bSThierry Reding 196f315828bSThierry Reding struct tegra_pcie_port { 197f315828bSThierry Reding struct tegra_pcie *pcie; 198f315828bSThierry Reding 199f315828bSThierry Reding struct fdt_resource regs; 200f315828bSThierry Reding unsigned int num_lanes; 201f315828bSThierry Reding unsigned int index; 202f315828bSThierry Reding 203f315828bSThierry Reding struct list_head list; 204f315828bSThierry Reding }; 205f315828bSThierry Reding 206f315828bSThierry Reding struct tegra_pcie_soc { 207f315828bSThierry Reding unsigned int num_ports; 208f315828bSThierry Reding unsigned long pads_pll_ctl; 209f315828bSThierry Reding unsigned long tx_ref_sel; 210*bbc5b36bSStephen Warren unsigned long afi_pex2_ctrl; 2113cfc6be4SStephen Warren u32 pads_refclk_cfg0; 2123cfc6be4SStephen Warren u32 pads_refclk_cfg1; 213f315828bSThierry Reding bool has_pex_clkreq_en; 214f315828bSThierry Reding bool has_pex_bias_ctrl; 215f315828bSThierry Reding bool has_cml_clk; 216f315828bSThierry Reding bool has_gen2; 217514e1913SStephen Warren bool force_pca_enable; 218f315828bSThierry Reding }; 219f315828bSThierry Reding 220f315828bSThierry Reding struct tegra_pcie { 221f315828bSThierry Reding struct pci_controller hose; 222f315828bSThierry Reding 223f315828bSThierry Reding struct fdt_resource pads; 224f315828bSThierry Reding struct fdt_resource afi; 225f315828bSThierry Reding struct fdt_resource cs; 226f315828bSThierry Reding 227f315828bSThierry Reding struct list_head ports; 228f315828bSThierry Reding unsigned long xbar; 229f315828bSThierry Reding 230f315828bSThierry Reding const struct tegra_pcie_soc *soc; 231*bbc5b36bSStephen Warren 232*bbc5b36bSStephen Warren #ifdef CONFIG_TEGRA186 233*bbc5b36bSStephen Warren struct clk clk_afi; 234*bbc5b36bSStephen Warren struct clk clk_pex; 235*bbc5b36bSStephen Warren struct reset_ctl reset_afi; 236*bbc5b36bSStephen Warren struct reset_ctl reset_pex; 237*bbc5b36bSStephen Warren struct reset_ctl reset_pcie_x; 238*bbc5b36bSStephen Warren struct power_domain pwrdom; 239*bbc5b36bSStephen Warren #else 240f315828bSThierry Reding struct tegra_xusb_phy *phy; 241*bbc5b36bSStephen Warren #endif 242f315828bSThierry Reding }; 243f315828bSThierry Reding 244f315828bSThierry Reding static void afi_writel(struct tegra_pcie *pcie, unsigned long value, 245f315828bSThierry Reding unsigned long offset) 246f315828bSThierry Reding { 247f315828bSThierry Reding writel(value, pcie->afi.start + offset); 248f315828bSThierry Reding } 249f315828bSThierry Reding 250f315828bSThierry Reding static unsigned long afi_readl(struct tegra_pcie *pcie, unsigned long offset) 251f315828bSThierry Reding { 252f315828bSThierry Reding return readl(pcie->afi.start + offset); 253f315828bSThierry Reding } 254f315828bSThierry Reding 255f315828bSThierry Reding static void pads_writel(struct tegra_pcie *pcie, unsigned long value, 256f315828bSThierry Reding unsigned long offset) 257f315828bSThierry Reding { 258f315828bSThierry Reding writel(value, pcie->pads.start + offset); 259f315828bSThierry Reding } 260f315828bSThierry Reding 261*bbc5b36bSStephen Warren #ifndef CONFIG_TEGRA186 262f315828bSThierry Reding static unsigned long pads_readl(struct tegra_pcie *pcie, unsigned long offset) 263f315828bSThierry Reding { 264f315828bSThierry Reding return readl(pcie->pads.start + offset); 265f315828bSThierry Reding } 266*bbc5b36bSStephen Warren #endif 267f315828bSThierry Reding 268f315828bSThierry Reding static unsigned long rp_readl(struct tegra_pcie_port *port, 269f315828bSThierry Reding unsigned long offset) 270f315828bSThierry Reding { 271f315828bSThierry Reding return readl(port->regs.start + offset); 272f315828bSThierry Reding } 273f315828bSThierry Reding 274f315828bSThierry Reding static void rp_writel(struct tegra_pcie_port *port, unsigned long value, 275f315828bSThierry Reding unsigned long offset) 276f315828bSThierry Reding { 277f315828bSThierry Reding writel(value, port->regs.start + offset); 278f315828bSThierry Reding } 279f315828bSThierry Reding 280f315828bSThierry Reding static unsigned long tegra_pcie_conf_offset(pci_dev_t bdf, int where) 281f315828bSThierry Reding { 282f315828bSThierry Reding return ((where & 0xf00) << 16) | (PCI_BUS(bdf) << 16) | 283f315828bSThierry Reding (PCI_DEV(bdf) << 11) | (PCI_FUNC(bdf) << 8) | 284f315828bSThierry Reding (where & 0xfc); 285f315828bSThierry Reding } 286f315828bSThierry Reding 287f315828bSThierry Reding static int tegra_pcie_conf_address(struct tegra_pcie *pcie, pci_dev_t bdf, 288f315828bSThierry Reding int where, unsigned long *address) 289f315828bSThierry Reding { 290f315828bSThierry Reding unsigned int bus = PCI_BUS(bdf); 291f315828bSThierry Reding 292f315828bSThierry Reding if (bus == 0) { 293f315828bSThierry Reding unsigned int dev = PCI_DEV(bdf); 294f315828bSThierry Reding struct tegra_pcie_port *port; 295f315828bSThierry Reding 296f315828bSThierry Reding list_for_each_entry(port, &pcie->ports, list) { 297f315828bSThierry Reding if (port->index + 1 == dev) { 298f315828bSThierry Reding *address = port->regs.start + (where & ~3); 299f315828bSThierry Reding return 0; 300f315828bSThierry Reding } 301f315828bSThierry Reding } 302f5c6db84SStephen Warren return -EFAULT; 303f315828bSThierry Reding } else { 304f5c6db84SStephen Warren #ifdef CONFIG_TEGRA20 305f5c6db84SStephen Warren unsigned int dev = PCI_DEV(bdf); 306f5c6db84SStephen Warren if (dev != 0) 307f5c6db84SStephen Warren return -EFAULT; 308f5c6db84SStephen Warren #endif 309f5c6db84SStephen Warren 310f315828bSThierry Reding *address = pcie->cs.start + tegra_pcie_conf_offset(bdf, where); 311f315828bSThierry Reding return 0; 312f315828bSThierry Reding } 313f315828bSThierry Reding } 314f315828bSThierry Reding 315e81ca884SSimon Glass static int pci_tegra_read_config(struct udevice *bus, pci_dev_t bdf, 316e81ca884SSimon Glass uint offset, ulong *valuep, 317e81ca884SSimon Glass enum pci_size_t size) 318f315828bSThierry Reding { 319e81ca884SSimon Glass struct tegra_pcie *pcie = dev_get_priv(bus); 320e81ca884SSimon Glass unsigned long address, value; 321f315828bSThierry Reding int err; 322f315828bSThierry Reding 323e81ca884SSimon Glass err = tegra_pcie_conf_address(pcie, bdf, offset, &address); 324f315828bSThierry Reding if (err < 0) { 325e81ca884SSimon Glass value = 0xffffffff; 326e81ca884SSimon Glass goto done; 327f315828bSThierry Reding } 328f315828bSThierry Reding 329e81ca884SSimon Glass value = readl(address); 330f315828bSThierry Reding 331f5c6db84SStephen Warren #ifdef CONFIG_TEGRA20 332f315828bSThierry Reding /* fixup root port class */ 333f315828bSThierry Reding if (PCI_BUS(bdf) == 0) { 334f5c6db84SStephen Warren if ((offset & ~3) == PCI_CLASS_REVISION) { 335e81ca884SSimon Glass value &= ~0x00ff0000; 336e81ca884SSimon Glass value |= PCI_CLASS_BRIDGE_PCI << 16; 337f315828bSThierry Reding } 338f315828bSThierry Reding } 339f5c6db84SStephen Warren #endif 340f315828bSThierry Reding 341e81ca884SSimon Glass done: 342e81ca884SSimon Glass *valuep = pci_conv_32_to_size(value, offset, size); 343e81ca884SSimon Glass 344f315828bSThierry Reding return 0; 345f315828bSThierry Reding } 346f315828bSThierry Reding 347e81ca884SSimon Glass static int pci_tegra_write_config(struct udevice *bus, pci_dev_t bdf, 348e81ca884SSimon Glass uint offset, ulong value, 349e81ca884SSimon Glass enum pci_size_t size) 350f315828bSThierry Reding { 351e81ca884SSimon Glass struct tegra_pcie *pcie = dev_get_priv(bus); 352f315828bSThierry Reding unsigned long address; 353e81ca884SSimon Glass ulong old; 354f315828bSThierry Reding int err; 355f315828bSThierry Reding 356e81ca884SSimon Glass err = tegra_pcie_conf_address(pcie, bdf, offset, &address); 357f315828bSThierry Reding if (err < 0) 358e81ca884SSimon Glass return 0; 359f315828bSThierry Reding 360e81ca884SSimon Glass old = readl(address); 361e81ca884SSimon Glass value = pci_conv_size_to_32(old, value, offset, size); 362f315828bSThierry Reding writel(value, address); 363f315828bSThierry Reding 364f315828bSThierry Reding return 0; 365f315828bSThierry Reding } 366f315828bSThierry Reding 367f315828bSThierry Reding static int tegra_pcie_port_parse_dt(const void *fdt, int node, 368f315828bSThierry Reding struct tegra_pcie_port *port) 369f315828bSThierry Reding { 370f315828bSThierry Reding const u32 *addr; 371f315828bSThierry Reding int len; 372f315828bSThierry Reding 373f315828bSThierry Reding addr = fdt_getprop(fdt, node, "assigned-addresses", &len); 374f315828bSThierry Reding if (!addr) { 375f315828bSThierry Reding error("property \"assigned-addresses\" not found"); 376f315828bSThierry Reding return -FDT_ERR_NOTFOUND; 377f315828bSThierry Reding } 378f315828bSThierry Reding 379f315828bSThierry Reding port->regs.start = fdt32_to_cpu(addr[2]); 380f315828bSThierry Reding port->regs.end = port->regs.start + fdt32_to_cpu(addr[4]); 381f315828bSThierry Reding 382f315828bSThierry Reding return 0; 383f315828bSThierry Reding } 384f315828bSThierry Reding 385f315828bSThierry Reding static int tegra_pcie_get_xbar_config(const void *fdt, int node, u32 lanes, 386e81ca884SSimon Glass enum tegra_pci_id id, unsigned long *xbar) 387f315828bSThierry Reding { 388f315828bSThierry Reding switch (id) { 389e81ca884SSimon Glass case TEGRA20_PCIE: 390f315828bSThierry Reding switch (lanes) { 391f315828bSThierry Reding case 0x00000004: 392f315828bSThierry Reding debug("single-mode configuration\n"); 393f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE; 394f315828bSThierry Reding return 0; 395f315828bSThierry Reding 396f315828bSThierry Reding case 0x00000202: 397f315828bSThierry Reding debug("dual-mode configuration\n"); 398f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL; 399f315828bSThierry Reding return 0; 400f315828bSThierry Reding } 401f315828bSThierry Reding break; 402e81ca884SSimon Glass case TEGRA30_PCIE: 403f315828bSThierry Reding switch (lanes) { 404f315828bSThierry Reding case 0x00000204: 405f315828bSThierry Reding debug("4x1, 2x1 configuration\n"); 406f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420; 407f315828bSThierry Reding return 0; 408f315828bSThierry Reding 409f315828bSThierry Reding case 0x00020202: 410f315828bSThierry Reding debug("2x3 configuration\n"); 411f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222; 412f315828bSThierry Reding return 0; 413f315828bSThierry Reding 414f315828bSThierry Reding case 0x00010104: 415f315828bSThierry Reding debug("4x1, 1x2 configuration\n"); 416f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411; 417f315828bSThierry Reding return 0; 418f315828bSThierry Reding } 419f315828bSThierry Reding break; 420e81ca884SSimon Glass case TEGRA124_PCIE: 421e81ca884SSimon Glass case TEGRA210_PCIE: 422f315828bSThierry Reding switch (lanes) { 423f315828bSThierry Reding case 0x0000104: 424f315828bSThierry Reding debug("4x1, 1x1 configuration\n"); 425f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1; 426f315828bSThierry Reding return 0; 427f315828bSThierry Reding 428f315828bSThierry Reding case 0x0000102: 429f315828bSThierry Reding debug("2x1, 1x1 configuration\n"); 430f315828bSThierry Reding *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1; 431f315828bSThierry Reding return 0; 432f315828bSThierry Reding } 433f315828bSThierry Reding break; 434*bbc5b36bSStephen Warren case TEGRA186_PCIE: 435*bbc5b36bSStephen Warren switch (lanes) { 436*bbc5b36bSStephen Warren case 0x0010004: 437*bbc5b36bSStephen Warren debug("x4 x1 configuration\n"); 438*bbc5b36bSStephen Warren *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_401; 439*bbc5b36bSStephen Warren return 0; 440*bbc5b36bSStephen Warren 441*bbc5b36bSStephen Warren case 0x0010102: 442*bbc5b36bSStephen Warren debug("x2 x1 x1 configuration\n"); 443*bbc5b36bSStephen Warren *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_211; 444*bbc5b36bSStephen Warren return 0; 445*bbc5b36bSStephen Warren 446*bbc5b36bSStephen Warren case 0x0010101: 447*bbc5b36bSStephen Warren debug("x1 x1 x1 configuration\n"); 448*bbc5b36bSStephen Warren *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_T186_111; 449*bbc5b36bSStephen Warren return 0; 450*bbc5b36bSStephen Warren } 451*bbc5b36bSStephen Warren break; 452f315828bSThierry Reding default: 453f315828bSThierry Reding break; 454f315828bSThierry Reding } 455f315828bSThierry Reding 456f315828bSThierry Reding return -FDT_ERR_NOTFOUND; 457f315828bSThierry Reding } 458f315828bSThierry Reding 459f315828bSThierry Reding static int tegra_pcie_parse_port_info(const void *fdt, int node, 460f315828bSThierry Reding unsigned int *index, 461f315828bSThierry Reding unsigned int *lanes) 462f315828bSThierry Reding { 463a62e84d7SBin Meng struct fdt_pci_addr addr; 464f315828bSThierry Reding int err; 465f315828bSThierry Reding 466f315828bSThierry Reding err = fdtdec_get_int(fdt, node, "nvidia,num-lanes", 0); 467f315828bSThierry Reding if (err < 0) { 468f315828bSThierry Reding error("failed to parse \"nvidia,num-lanes\" property"); 469f315828bSThierry Reding return err; 470f315828bSThierry Reding } 471f315828bSThierry Reding 472f315828bSThierry Reding *lanes = err; 473f315828bSThierry Reding 474053b86e6SSjoerd Simons err = fdtdec_get_pci_addr(fdt, node, 0, "reg", &addr); 475f315828bSThierry Reding if (err < 0) { 476f315828bSThierry Reding error("failed to parse \"reg\" property"); 477f315828bSThierry Reding return err; 478f315828bSThierry Reding } 479f315828bSThierry Reding 480053b86e6SSjoerd Simons *index = PCI_DEV(addr.phys_hi) - 1; 481f315828bSThierry Reding 482f315828bSThierry Reding return 0; 483f315828bSThierry Reding } 484f315828bSThierry Reding 485e81ca884SSimon Glass int __weak tegra_pcie_board_init(void) 486e81ca884SSimon Glass { 487e81ca884SSimon Glass return 0; 488e81ca884SSimon Glass } 489e81ca884SSimon Glass 490e81ca884SSimon Glass static int tegra_pcie_parse_dt(const void *fdt, int node, enum tegra_pci_id id, 491f315828bSThierry Reding struct tegra_pcie *pcie) 492f315828bSThierry Reding { 493f315828bSThierry Reding int err, subnode; 494f315828bSThierry Reding u32 lanes = 0; 495f315828bSThierry Reding 496f315828bSThierry Reding err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "pads", 497f315828bSThierry Reding &pcie->pads); 498f315828bSThierry Reding if (err < 0) { 499f315828bSThierry Reding error("resource \"pads\" not found"); 500f315828bSThierry Reding return err; 501f315828bSThierry Reding } 502f315828bSThierry Reding 503f315828bSThierry Reding err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "afi", 504f315828bSThierry Reding &pcie->afi); 505f315828bSThierry Reding if (err < 0) { 506f315828bSThierry Reding error("resource \"afi\" not found"); 507f315828bSThierry Reding return err; 508f315828bSThierry Reding } 509f315828bSThierry Reding 510f315828bSThierry Reding err = fdt_get_named_resource(fdt, node, "reg", "reg-names", "cs", 511f315828bSThierry Reding &pcie->cs); 512f315828bSThierry Reding if (err < 0) { 513f315828bSThierry Reding error("resource \"cs\" not found"); 514f315828bSThierry Reding return err; 515f315828bSThierry Reding } 516f315828bSThierry Reding 517dfa71e9fSSimon Glass err = tegra_pcie_board_init(); 518dfa71e9fSSimon Glass if (err < 0) { 519dfa71e9fSSimon Glass error("tegra_pcie_board_init() failed: err=%d", err); 520dfa71e9fSSimon Glass return err; 521dfa71e9fSSimon Glass } 522e81ca884SSimon Glass 523*bbc5b36bSStephen Warren #ifndef CONFIG_TEGRA186 524f315828bSThierry Reding pcie->phy = tegra_xusb_phy_get(TEGRA_XUSB_PADCTL_PCIE); 525f315828bSThierry Reding if (pcie->phy) { 526f315828bSThierry Reding err = tegra_xusb_phy_prepare(pcie->phy); 527f315828bSThierry Reding if (err < 0) { 528f315828bSThierry Reding error("failed to prepare PHY: %d", err); 529f315828bSThierry Reding return err; 530f315828bSThierry Reding } 531f315828bSThierry Reding } 532*bbc5b36bSStephen Warren #endif 533f315828bSThierry Reding 534f315828bSThierry Reding fdt_for_each_subnode(fdt, subnode, node) { 535f315828bSThierry Reding unsigned int index = 0, num_lanes = 0; 536f315828bSThierry Reding struct tegra_pcie_port *port; 537f315828bSThierry Reding 538f315828bSThierry Reding err = tegra_pcie_parse_port_info(fdt, subnode, &index, 539f315828bSThierry Reding &num_lanes); 540f315828bSThierry Reding if (err < 0) { 541f315828bSThierry Reding error("failed to obtain root port info"); 542f315828bSThierry Reding continue; 543f315828bSThierry Reding } 544f315828bSThierry Reding 545f315828bSThierry Reding lanes |= num_lanes << (index << 3); 546f315828bSThierry Reding 547f315828bSThierry Reding if (!fdtdec_get_is_enabled(fdt, subnode)) 548f315828bSThierry Reding continue; 549f315828bSThierry Reding 550f315828bSThierry Reding port = malloc(sizeof(*port)); 551f315828bSThierry Reding if (!port) 552f315828bSThierry Reding continue; 553f315828bSThierry Reding 554f315828bSThierry Reding memset(port, 0, sizeof(*port)); 555f315828bSThierry Reding port->num_lanes = num_lanes; 556f315828bSThierry Reding port->index = index; 557f315828bSThierry Reding 558f315828bSThierry Reding err = tegra_pcie_port_parse_dt(fdt, subnode, port); 559f315828bSThierry Reding if (err < 0) { 560f315828bSThierry Reding free(port); 561f315828bSThierry Reding continue; 562f315828bSThierry Reding } 563f315828bSThierry Reding 564f315828bSThierry Reding list_add_tail(&port->list, &pcie->ports); 565f315828bSThierry Reding port->pcie = pcie; 566f315828bSThierry Reding } 567f315828bSThierry Reding 568e81ca884SSimon Glass err = tegra_pcie_get_xbar_config(fdt, node, lanes, id, &pcie->xbar); 569f315828bSThierry Reding if (err < 0) { 570f315828bSThierry Reding error("invalid lane configuration"); 571f315828bSThierry Reding return err; 572f315828bSThierry Reding } 573f315828bSThierry Reding 574f315828bSThierry Reding return 0; 575f315828bSThierry Reding } 576f315828bSThierry Reding 577*bbc5b36bSStephen Warren #ifdef CONFIG_TEGRA186 578*bbc5b36bSStephen Warren static int tegra_pcie_power_on(struct tegra_pcie *pcie) 579*bbc5b36bSStephen Warren { 580*bbc5b36bSStephen Warren int ret; 581*bbc5b36bSStephen Warren 582*bbc5b36bSStephen Warren ret = power_domain_on(&pcie->pwrdom); 583*bbc5b36bSStephen Warren if (ret) { 584*bbc5b36bSStephen Warren error("power_domain_on() failed: %d\n", ret); 585*bbc5b36bSStephen Warren return ret; 586*bbc5b36bSStephen Warren } 587*bbc5b36bSStephen Warren 588*bbc5b36bSStephen Warren ret = clk_enable(&pcie->clk_afi); 589*bbc5b36bSStephen Warren if (ret) { 590*bbc5b36bSStephen Warren error("clk_enable(afi) failed: %d\n", ret); 591*bbc5b36bSStephen Warren return ret; 592*bbc5b36bSStephen Warren } 593*bbc5b36bSStephen Warren 594*bbc5b36bSStephen Warren ret = clk_enable(&pcie->clk_pex); 595*bbc5b36bSStephen Warren if (ret) { 596*bbc5b36bSStephen Warren error("clk_enable(pex) failed: %d\n", ret); 597*bbc5b36bSStephen Warren return ret; 598*bbc5b36bSStephen Warren } 599*bbc5b36bSStephen Warren 600*bbc5b36bSStephen Warren ret = reset_deassert(&pcie->reset_afi); 601*bbc5b36bSStephen Warren if (ret) { 602*bbc5b36bSStephen Warren error("reset_deassert(afi) failed: %d\n", ret); 603*bbc5b36bSStephen Warren return ret; 604*bbc5b36bSStephen Warren } 605*bbc5b36bSStephen Warren 606*bbc5b36bSStephen Warren ret = reset_deassert(&pcie->reset_pex); 607*bbc5b36bSStephen Warren if (ret) { 608*bbc5b36bSStephen Warren error("reset_deassert(pex) failed: %d\n", ret); 609*bbc5b36bSStephen Warren return ret; 610*bbc5b36bSStephen Warren } 611*bbc5b36bSStephen Warren 612*bbc5b36bSStephen Warren return 0; 613*bbc5b36bSStephen Warren } 614*bbc5b36bSStephen Warren #else 615f315828bSThierry Reding static int tegra_pcie_power_on(struct tegra_pcie *pcie) 616f315828bSThierry Reding { 617f315828bSThierry Reding const struct tegra_pcie_soc *soc = pcie->soc; 618f315828bSThierry Reding unsigned long value; 619f315828bSThierry Reding int err; 620f315828bSThierry Reding 621f315828bSThierry Reding /* reset PCIEXCLK logic, AFI controller and PCIe controller */ 622f315828bSThierry Reding reset_set_enable(PERIPH_ID_PCIEXCLK, 1); 623f315828bSThierry Reding reset_set_enable(PERIPH_ID_AFI, 1); 624f315828bSThierry Reding reset_set_enable(PERIPH_ID_PCIE, 1); 625f315828bSThierry Reding 626f315828bSThierry Reding err = tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); 627f315828bSThierry Reding if (err < 0) { 628f315828bSThierry Reding error("failed to power off PCIe partition: %d", err); 629f315828bSThierry Reding return err; 630f315828bSThierry Reding } 631f315828bSThierry Reding 632f315828bSThierry Reding err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, 633f315828bSThierry Reding PERIPH_ID_PCIE); 634f315828bSThierry Reding if (err < 0) { 635f315828bSThierry Reding error("failed to power up PCIe partition: %d", err); 636f315828bSThierry Reding return err; 637f315828bSThierry Reding } 638f315828bSThierry Reding 639f315828bSThierry Reding /* take AFI controller out of reset */ 640f315828bSThierry Reding reset_set_enable(PERIPH_ID_AFI, 0); 641f315828bSThierry Reding 642f315828bSThierry Reding /* enable AFI clock */ 643f315828bSThierry Reding clock_enable(PERIPH_ID_AFI); 644f315828bSThierry Reding 645f315828bSThierry Reding if (soc->has_cml_clk) { 646f315828bSThierry Reding /* enable CML clock */ 647f315828bSThierry Reding value = readl(NV_PA_CLK_RST_BASE + 0x48c); 648f315828bSThierry Reding value |= (1 << 0); 649f315828bSThierry Reding value &= ~(1 << 1); 650f315828bSThierry Reding writel(value, NV_PA_CLK_RST_BASE + 0x48c); 651f315828bSThierry Reding } 652f315828bSThierry Reding 653f315828bSThierry Reding err = tegra_plle_enable(); 654f315828bSThierry Reding if (err < 0) { 655f315828bSThierry Reding error("failed to enable PLLE: %d\n", err); 656f315828bSThierry Reding return err; 657f315828bSThierry Reding } 658f315828bSThierry Reding 659f315828bSThierry Reding return 0; 660f315828bSThierry Reding } 661f315828bSThierry Reding 662f315828bSThierry Reding static int tegra_pcie_pll_wait(struct tegra_pcie *pcie, unsigned long timeout) 663f315828bSThierry Reding { 664f315828bSThierry Reding const struct tegra_pcie_soc *soc = pcie->soc; 665f315828bSThierry Reding unsigned long start = get_timer(0); 666f315828bSThierry Reding u32 value; 667f315828bSThierry Reding 668f315828bSThierry Reding while (get_timer(start) < timeout) { 669f315828bSThierry Reding value = pads_readl(pcie, soc->pads_pll_ctl); 670f315828bSThierry Reding if (value & PADS_PLL_CTL_LOCKDET) 671f315828bSThierry Reding return 0; 672f315828bSThierry Reding } 673f315828bSThierry Reding 674f315828bSThierry Reding return -ETIMEDOUT; 675f315828bSThierry Reding } 676f315828bSThierry Reding 677f315828bSThierry Reding static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) 678f315828bSThierry Reding { 679f315828bSThierry Reding const struct tegra_pcie_soc *soc = pcie->soc; 680f315828bSThierry Reding u32 value; 681f315828bSThierry Reding int err; 682f315828bSThierry Reding 683f315828bSThierry Reding /* initialize internal PHY, enable up to 16 PCIe lanes */ 684f315828bSThierry Reding pads_writel(pcie, 0, PADS_CTL_SEL); 685f315828bSThierry Reding 686f315828bSThierry Reding /* override IDDQ to 1 on all 4 lanes */ 687f315828bSThierry Reding value = pads_readl(pcie, PADS_CTL); 688f315828bSThierry Reding value |= PADS_CTL_IDDQ_1L; 689f315828bSThierry Reding pads_writel(pcie, value, PADS_CTL); 690f315828bSThierry Reding 691f315828bSThierry Reding /* 692f315828bSThierry Reding * Set up PHY PLL inputs select PLLE output as refclock, set TX 693f315828bSThierry Reding * ref sel to div10 (not div5). 694f315828bSThierry Reding */ 695f315828bSThierry Reding value = pads_readl(pcie, soc->pads_pll_ctl); 696f315828bSThierry Reding value &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK); 697f315828bSThierry Reding value |= PADS_PLL_CTL_REFCLK_INTERNAL_CML | soc->tx_ref_sel; 698f315828bSThierry Reding pads_writel(pcie, value, soc->pads_pll_ctl); 699f315828bSThierry Reding 700f315828bSThierry Reding /* reset PLL */ 701f315828bSThierry Reding value = pads_readl(pcie, soc->pads_pll_ctl); 702f315828bSThierry Reding value &= ~PADS_PLL_CTL_RST_B4SM; 703f315828bSThierry Reding pads_writel(pcie, value, soc->pads_pll_ctl); 704f315828bSThierry Reding 705f315828bSThierry Reding udelay(20); 706f315828bSThierry Reding 707f315828bSThierry Reding /* take PLL out of reset */ 708f315828bSThierry Reding value = pads_readl(pcie, soc->pads_pll_ctl); 709f315828bSThierry Reding value |= PADS_PLL_CTL_RST_B4SM; 710f315828bSThierry Reding pads_writel(pcie, value, soc->pads_pll_ctl); 711f315828bSThierry Reding 712f315828bSThierry Reding /* wait for the PLL to lock */ 713f315828bSThierry Reding err = tegra_pcie_pll_wait(pcie, 500); 714f315828bSThierry Reding if (err < 0) { 715f315828bSThierry Reding error("PLL failed to lock: %d", err); 716f315828bSThierry Reding return err; 717f315828bSThierry Reding } 718f315828bSThierry Reding 719f315828bSThierry Reding /* turn off IDDQ override */ 720f315828bSThierry Reding value = pads_readl(pcie, PADS_CTL); 721f315828bSThierry Reding value &= ~PADS_CTL_IDDQ_1L; 722f315828bSThierry Reding pads_writel(pcie, value, PADS_CTL); 723f315828bSThierry Reding 724f315828bSThierry Reding /* enable TX/RX data */ 725f315828bSThierry Reding value = pads_readl(pcie, PADS_CTL); 726f315828bSThierry Reding value |= PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L; 727f315828bSThierry Reding pads_writel(pcie, value, PADS_CTL); 728f315828bSThierry Reding 729f315828bSThierry Reding return 0; 730f315828bSThierry Reding } 731*bbc5b36bSStephen Warren #endif 732f315828bSThierry Reding 733f315828bSThierry Reding static int tegra_pcie_enable_controller(struct tegra_pcie *pcie) 734f315828bSThierry Reding { 735f315828bSThierry Reding const struct tegra_pcie_soc *soc = pcie->soc; 736f315828bSThierry Reding struct tegra_pcie_port *port; 737f315828bSThierry Reding u32 value; 738f315828bSThierry Reding int err; 739f315828bSThierry Reding 740*bbc5b36bSStephen Warren #ifdef CONFIG_TEGRA186 741*bbc5b36bSStephen Warren { 742*bbc5b36bSStephen Warren #else 743f315828bSThierry Reding if (pcie->phy) { 744*bbc5b36bSStephen Warren #endif 745f315828bSThierry Reding value = afi_readl(pcie, AFI_PLLE_CONTROL); 746f315828bSThierry Reding value &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL; 747f315828bSThierry Reding value |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN; 748f315828bSThierry Reding afi_writel(pcie, value, AFI_PLLE_CONTROL); 749f315828bSThierry Reding } 750f315828bSThierry Reding 751f315828bSThierry Reding if (soc->has_pex_bias_ctrl) 752f315828bSThierry Reding afi_writel(pcie, 0, AFI_PEXBIAS_CTRL_0); 753f315828bSThierry Reding 754f315828bSThierry Reding value = afi_readl(pcie, AFI_PCIE_CONFIG); 755f315828bSThierry Reding value &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK; 756f315828bSThierry Reding value |= AFI_PCIE_CONFIG_PCIE_DISABLE_ALL | pcie->xbar; 757f315828bSThierry Reding 758f315828bSThierry Reding list_for_each_entry(port, &pcie->ports, list) 759f315828bSThierry Reding value &= ~AFI_PCIE_CONFIG_PCIE_DISABLE(port->index); 760f315828bSThierry Reding 761f315828bSThierry Reding afi_writel(pcie, value, AFI_PCIE_CONFIG); 762f315828bSThierry Reding 763f315828bSThierry Reding value = afi_readl(pcie, AFI_FUSE); 764f315828bSThierry Reding 765f315828bSThierry Reding if (soc->has_gen2) 766f315828bSThierry Reding value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS; 767f315828bSThierry Reding else 768f315828bSThierry Reding value |= AFI_FUSE_PCIE_T0_GEN2_DIS; 769f315828bSThierry Reding 770f315828bSThierry Reding afi_writel(pcie, value, AFI_FUSE); 771f315828bSThierry Reding 772*bbc5b36bSStephen Warren #ifndef CONFIG_TEGRA186 773f315828bSThierry Reding if (pcie->phy) 774f315828bSThierry Reding err = tegra_xusb_phy_enable(pcie->phy); 775f315828bSThierry Reding else 776f315828bSThierry Reding err = tegra_pcie_phy_enable(pcie); 777f315828bSThierry Reding 778f315828bSThierry Reding if (err < 0) { 779f315828bSThierry Reding error("failed to power on PHY: %d\n", err); 780f315828bSThierry Reding return err; 781f315828bSThierry Reding } 782*bbc5b36bSStephen Warren #endif 783f315828bSThierry Reding 784f315828bSThierry Reding /* take the PCIEXCLK logic out of reset */ 785*bbc5b36bSStephen Warren #ifdef CONFIG_TEGRA186 786*bbc5b36bSStephen Warren err = reset_deassert(&pcie->reset_pcie_x); 787*bbc5b36bSStephen Warren if (err) { 788*bbc5b36bSStephen Warren error("reset_deassert(pcie_x) failed: %d\n", err); 789*bbc5b36bSStephen Warren return err; 790*bbc5b36bSStephen Warren } 791*bbc5b36bSStephen Warren #else 792f315828bSThierry Reding reset_set_enable(PERIPH_ID_PCIEXCLK, 0); 793*bbc5b36bSStephen Warren #endif 794f315828bSThierry Reding 795f315828bSThierry Reding /* finally enable PCIe */ 796f315828bSThierry Reding value = afi_readl(pcie, AFI_CONFIGURATION); 797f315828bSThierry Reding value |= AFI_CONFIGURATION_EN_FPCI; 798f315828bSThierry Reding afi_writel(pcie, value, AFI_CONFIGURATION); 799f315828bSThierry Reding 800f315828bSThierry Reding /* disable all interrupts */ 801f315828bSThierry Reding afi_writel(pcie, 0, AFI_AFI_INTR_ENABLE); 802f315828bSThierry Reding afi_writel(pcie, 0, AFI_SM_INTR_ENABLE); 803f315828bSThierry Reding afi_writel(pcie, 0, AFI_INTR_MASK); 804f315828bSThierry Reding afi_writel(pcie, 0, AFI_FPCI_ERROR_MASKS); 805f315828bSThierry Reding 806f315828bSThierry Reding return 0; 807f315828bSThierry Reding } 808f315828bSThierry Reding 809e81ca884SSimon Glass static int tegra_pcie_setup_translations(struct udevice *bus) 810f315828bSThierry Reding { 811e81ca884SSimon Glass struct tegra_pcie *pcie = dev_get_priv(bus); 812f315828bSThierry Reding unsigned long fpci, axi, size; 813e81ca884SSimon Glass struct pci_region *io, *mem, *pref; 814e81ca884SSimon Glass int count; 815f315828bSThierry Reding 816f315828bSThierry Reding /* BAR 0: type 1 extended configuration space */ 817f315828bSThierry Reding fpci = 0xfe100000; 818f315828bSThierry Reding size = fdt_resource_size(&pcie->cs); 819f315828bSThierry Reding axi = pcie->cs.start; 820f315828bSThierry Reding 821f315828bSThierry Reding afi_writel(pcie, axi, AFI_AXI_BAR0_START); 822f315828bSThierry Reding afi_writel(pcie, size >> 12, AFI_AXI_BAR0_SZ); 823f315828bSThierry Reding afi_writel(pcie, fpci, AFI_FPCI_BAR0); 824f315828bSThierry Reding 825e81ca884SSimon Glass count = pci_get_regions(bus, &io, &mem, &pref); 826e81ca884SSimon Glass if (count != 3) 827e81ca884SSimon Glass return -EINVAL; 828e81ca884SSimon Glass 829f315828bSThierry Reding /* BAR 1: downstream I/O */ 830f315828bSThierry Reding fpci = 0xfdfc0000; 831e81ca884SSimon Glass size = io->size; 832e81ca884SSimon Glass axi = io->phys_start; 833f315828bSThierry Reding 834f315828bSThierry Reding afi_writel(pcie, axi, AFI_AXI_BAR1_START); 835f315828bSThierry Reding afi_writel(pcie, size >> 12, AFI_AXI_BAR1_SZ); 836f315828bSThierry Reding afi_writel(pcie, fpci, AFI_FPCI_BAR1); 837f315828bSThierry Reding 838f315828bSThierry Reding /* BAR 2: prefetchable memory */ 839e81ca884SSimon Glass fpci = (((pref->phys_start >> 12) & 0x0fffffff) << 4) | 0x1; 840e81ca884SSimon Glass size = pref->size; 841e81ca884SSimon Glass axi = pref->phys_start; 842f315828bSThierry Reding 843f315828bSThierry Reding afi_writel(pcie, axi, AFI_AXI_BAR2_START); 844f315828bSThierry Reding afi_writel(pcie, size >> 12, AFI_AXI_BAR2_SZ); 845f315828bSThierry Reding afi_writel(pcie, fpci, AFI_FPCI_BAR2); 846f315828bSThierry Reding 847f315828bSThierry Reding /* BAR 3: non-prefetchable memory */ 848e81ca884SSimon Glass fpci = (((mem->phys_start >> 12) & 0x0fffffff) << 4) | 0x1; 849e81ca884SSimon Glass size = mem->size; 850e81ca884SSimon Glass axi = mem->phys_start; 851f315828bSThierry Reding 852f315828bSThierry Reding afi_writel(pcie, axi, AFI_AXI_BAR3_START); 853f315828bSThierry Reding afi_writel(pcie, size >> 12, AFI_AXI_BAR3_SZ); 854f315828bSThierry Reding afi_writel(pcie, fpci, AFI_FPCI_BAR3); 855f315828bSThierry Reding 856f315828bSThierry Reding /* NULL out the remaining BARs as they are not used */ 857f315828bSThierry Reding afi_writel(pcie, 0, AFI_AXI_BAR4_START); 858f315828bSThierry Reding afi_writel(pcie, 0, AFI_AXI_BAR4_SZ); 859f315828bSThierry Reding afi_writel(pcie, 0, AFI_FPCI_BAR4); 860f315828bSThierry Reding 861f315828bSThierry Reding afi_writel(pcie, 0, AFI_AXI_BAR5_START); 862f315828bSThierry Reding afi_writel(pcie, 0, AFI_AXI_BAR5_SZ); 863f315828bSThierry Reding afi_writel(pcie, 0, AFI_FPCI_BAR5); 864f315828bSThierry Reding 865f315828bSThierry Reding /* map all upstream transactions as uncached */ 866f315828bSThierry Reding afi_writel(pcie, NV_PA_SDRAM_BASE, AFI_CACHE_BAR0_ST); 867f315828bSThierry Reding afi_writel(pcie, 0, AFI_CACHE_BAR0_SZ); 868f315828bSThierry Reding afi_writel(pcie, 0, AFI_CACHE_BAR1_ST); 869f315828bSThierry Reding afi_writel(pcie, 0, AFI_CACHE_BAR1_SZ); 870f315828bSThierry Reding 871f315828bSThierry Reding /* MSI translations are setup only when needed */ 872f315828bSThierry Reding afi_writel(pcie, 0, AFI_MSI_FPCI_BAR_ST); 873f315828bSThierry Reding afi_writel(pcie, 0, AFI_MSI_BAR_SZ); 874f315828bSThierry Reding afi_writel(pcie, 0, AFI_MSI_AXI_BAR_ST); 875f315828bSThierry Reding afi_writel(pcie, 0, AFI_MSI_BAR_SZ); 876e81ca884SSimon Glass 877e81ca884SSimon Glass return 0; 878f315828bSThierry Reding } 879f315828bSThierry Reding 880f315828bSThierry Reding static unsigned long tegra_pcie_port_get_pex_ctrl(struct tegra_pcie_port *port) 881f315828bSThierry Reding { 882f315828bSThierry Reding unsigned long ret = 0; 883f315828bSThierry Reding 884f315828bSThierry Reding switch (port->index) { 885f315828bSThierry Reding case 0: 886f315828bSThierry Reding ret = AFI_PEX0_CTRL; 887f315828bSThierry Reding break; 888f315828bSThierry Reding 889f315828bSThierry Reding case 1: 890f315828bSThierry Reding ret = AFI_PEX1_CTRL; 891f315828bSThierry Reding break; 892f315828bSThierry Reding 893f315828bSThierry Reding case 2: 894*bbc5b36bSStephen Warren ret = port->pcie->soc->afi_pex2_ctrl; 895f315828bSThierry Reding break; 896f315828bSThierry Reding } 897f315828bSThierry Reding 898f315828bSThierry Reding return ret; 899f315828bSThierry Reding } 900f315828bSThierry Reding 901f315828bSThierry Reding static void tegra_pcie_port_reset(struct tegra_pcie_port *port) 902f315828bSThierry Reding { 903f315828bSThierry Reding unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); 904f315828bSThierry Reding unsigned long value; 905f315828bSThierry Reding 906f315828bSThierry Reding /* pulse reset signel */ 907f315828bSThierry Reding value = afi_readl(port->pcie, ctrl); 908f315828bSThierry Reding value &= ~AFI_PEX_CTRL_RST; 909f315828bSThierry Reding afi_writel(port->pcie, value, ctrl); 910f315828bSThierry Reding 911f315828bSThierry Reding udelay(2000); 912f315828bSThierry Reding 913f315828bSThierry Reding value = afi_readl(port->pcie, ctrl); 914f315828bSThierry Reding value |= AFI_PEX_CTRL_RST; 915f315828bSThierry Reding afi_writel(port->pcie, value, ctrl); 916f315828bSThierry Reding } 917f315828bSThierry Reding 918f315828bSThierry Reding static void tegra_pcie_port_enable(struct tegra_pcie_port *port) 919f315828bSThierry Reding { 920f39a6a32SStephen Warren struct tegra_pcie *pcie = port->pcie; 921f39a6a32SStephen Warren const struct tegra_pcie_soc *soc = pcie->soc; 922f315828bSThierry Reding unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); 923f315828bSThierry Reding unsigned long value; 924f315828bSThierry Reding 925f315828bSThierry Reding /* enable reference clock */ 926f39a6a32SStephen Warren value = afi_readl(pcie, ctrl); 927f315828bSThierry Reding value |= AFI_PEX_CTRL_REFCLK_EN; 928f315828bSThierry Reding 929f39a6a32SStephen Warren if (pcie->soc->has_pex_clkreq_en) 930f315828bSThierry Reding value |= AFI_PEX_CTRL_CLKREQ_EN; 931f315828bSThierry Reding 932f315828bSThierry Reding value |= AFI_PEX_CTRL_OVERRIDE_EN; 933f315828bSThierry Reding 934f39a6a32SStephen Warren afi_writel(pcie, value, ctrl); 935f315828bSThierry Reding 936f315828bSThierry Reding tegra_pcie_port_reset(port); 937514e1913SStephen Warren 938514e1913SStephen Warren if (soc->force_pca_enable) { 939514e1913SStephen Warren value = rp_readl(port, RP_VEND_CTL2); 940514e1913SStephen Warren value |= RP_VEND_CTL2_PCA_ENABLE; 941514e1913SStephen Warren rp_writel(port, value, RP_VEND_CTL2); 942514e1913SStephen Warren } 943f39a6a32SStephen Warren 944f39a6a32SStephen Warren /* configure the reference clock driver */ 945f39a6a32SStephen Warren pads_writel(pcie, soc->pads_refclk_cfg0, PADS_REFCLK_CFG0); 946f39a6a32SStephen Warren if (soc->num_ports > 2) 947f39a6a32SStephen Warren pads_writel(pcie, soc->pads_refclk_cfg1, PADS_REFCLK_CFG1); 948f315828bSThierry Reding } 949f315828bSThierry Reding 950f315828bSThierry Reding static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port) 951f315828bSThierry Reding { 952f315828bSThierry Reding unsigned int retries = 3; 953f315828bSThierry Reding unsigned long value; 954f315828bSThierry Reding 955f315828bSThierry Reding value = rp_readl(port, RP_PRIV_MISC); 956f315828bSThierry Reding value &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT; 957f315828bSThierry Reding value |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT; 958f315828bSThierry Reding rp_writel(port, value, RP_PRIV_MISC); 959f315828bSThierry Reding 960f315828bSThierry Reding do { 961f315828bSThierry Reding unsigned int timeout = 200; 962f315828bSThierry Reding 963f315828bSThierry Reding do { 964f315828bSThierry Reding value = rp_readl(port, RP_VEND_XP); 965f315828bSThierry Reding if (value & RP_VEND_XP_DL_UP) 966f315828bSThierry Reding break; 967f315828bSThierry Reding 968f315828bSThierry Reding udelay(2000); 969f315828bSThierry Reding } while (--timeout); 970f315828bSThierry Reding 971f315828bSThierry Reding if (!timeout) { 972f315828bSThierry Reding debug("link %u down, retrying\n", port->index); 973f315828bSThierry Reding goto retry; 974f315828bSThierry Reding } 975f315828bSThierry Reding 976f315828bSThierry Reding timeout = 200; 977f315828bSThierry Reding 978f315828bSThierry Reding do { 979f315828bSThierry Reding value = rp_readl(port, RP_LINK_CONTROL_STATUS); 980f315828bSThierry Reding if (value & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE) 981f315828bSThierry Reding return true; 982f315828bSThierry Reding 983f315828bSThierry Reding udelay(2000); 984f315828bSThierry Reding } while (--timeout); 985f315828bSThierry Reding 986f315828bSThierry Reding retry: 987f315828bSThierry Reding tegra_pcie_port_reset(port); 988f315828bSThierry Reding } while (--retries); 989f315828bSThierry Reding 990f315828bSThierry Reding return false; 991f315828bSThierry Reding } 992f315828bSThierry Reding 993f315828bSThierry Reding static void tegra_pcie_port_disable(struct tegra_pcie_port *port) 994f315828bSThierry Reding { 995f315828bSThierry Reding unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); 996f315828bSThierry Reding unsigned long value; 997f315828bSThierry Reding 998f315828bSThierry Reding /* assert port reset */ 999f315828bSThierry Reding value = afi_readl(port->pcie, ctrl); 1000f315828bSThierry Reding value &= ~AFI_PEX_CTRL_RST; 1001f315828bSThierry Reding afi_writel(port->pcie, value, ctrl); 1002f315828bSThierry Reding 1003f315828bSThierry Reding /* disable reference clock */ 1004f315828bSThierry Reding value = afi_readl(port->pcie, ctrl); 1005f315828bSThierry Reding value &= ~AFI_PEX_CTRL_REFCLK_EN; 1006f315828bSThierry Reding afi_writel(port->pcie, value, ctrl); 1007f315828bSThierry Reding } 1008f315828bSThierry Reding 1009f315828bSThierry Reding static void tegra_pcie_port_free(struct tegra_pcie_port *port) 1010f315828bSThierry Reding { 1011f315828bSThierry Reding list_del(&port->list); 1012f315828bSThierry Reding free(port); 1013f315828bSThierry Reding } 1014f315828bSThierry Reding 1015f315828bSThierry Reding static int tegra_pcie_enable(struct tegra_pcie *pcie) 1016f315828bSThierry Reding { 1017f315828bSThierry Reding struct tegra_pcie_port *port, *tmp; 1018f315828bSThierry Reding 1019f315828bSThierry Reding list_for_each_entry_safe(port, tmp, &pcie->ports, list) { 1020f315828bSThierry Reding debug("probing port %u, using %u lanes\n", port->index, 1021f315828bSThierry Reding port->num_lanes); 1022f315828bSThierry Reding 1023f315828bSThierry Reding tegra_pcie_port_enable(port); 1024f315828bSThierry Reding 1025f315828bSThierry Reding if (tegra_pcie_port_check_link(port)) 1026f315828bSThierry Reding continue; 1027f315828bSThierry Reding 1028f315828bSThierry Reding debug("link %u down, ignoring\n", port->index); 1029f315828bSThierry Reding 1030f315828bSThierry Reding tegra_pcie_port_disable(port); 1031f315828bSThierry Reding tegra_pcie_port_free(port); 1032f315828bSThierry Reding } 1033f315828bSThierry Reding 1034f315828bSThierry Reding return 0; 1035f315828bSThierry Reding } 1036f315828bSThierry Reding 1037e81ca884SSimon Glass static const struct tegra_pcie_soc pci_tegra_soc[] = { 1038e81ca884SSimon Glass [TEGRA20_PCIE] = { 1039f315828bSThierry Reding .num_ports = 2, 1040f315828bSThierry Reding .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, 1041f315828bSThierry Reding .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10, 10423cfc6be4SStephen Warren .pads_refclk_cfg0 = 0xfa5cfa5c, 1043f315828bSThierry Reding .has_pex_clkreq_en = false, 1044f315828bSThierry Reding .has_pex_bias_ctrl = false, 1045f315828bSThierry Reding .has_cml_clk = false, 1046f315828bSThierry Reding .has_gen2 = false, 1047e81ca884SSimon Glass }, 1048e81ca884SSimon Glass [TEGRA30_PCIE] = { 1049f315828bSThierry Reding .num_ports = 3, 1050f315828bSThierry Reding .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, 1051f315828bSThierry Reding .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, 1052*bbc5b36bSStephen Warren .afi_pex2_ctrl = AFI_PEX2_CTRL, 10533cfc6be4SStephen Warren .pads_refclk_cfg0 = 0xfa5cfa5c, 10543cfc6be4SStephen Warren .pads_refclk_cfg1 = 0xfa5cfa5c, 1055f315828bSThierry Reding .has_pex_clkreq_en = true, 1056f315828bSThierry Reding .has_pex_bias_ctrl = true, 1057f315828bSThierry Reding .has_cml_clk = true, 1058f315828bSThierry Reding .has_gen2 = false, 1059e81ca884SSimon Glass }, 1060e81ca884SSimon Glass [TEGRA124_PCIE] = { 1061f315828bSThierry Reding .num_ports = 2, 1062f315828bSThierry Reding .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, 1063f315828bSThierry Reding .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, 10643cfc6be4SStephen Warren .pads_refclk_cfg0 = 0x44ac44ac, 1065f315828bSThierry Reding .has_pex_clkreq_en = true, 1066f315828bSThierry Reding .has_pex_bias_ctrl = true, 1067f315828bSThierry Reding .has_cml_clk = true, 1068f315828bSThierry Reding .has_gen2 = true, 1069e81ca884SSimon Glass }, 1070e81ca884SSimon Glass [TEGRA210_PCIE] = { 1071d9eda6c4SStephen Warren .num_ports = 2, 1072d9eda6c4SStephen Warren .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, 1073d9eda6c4SStephen Warren .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, 10743cfc6be4SStephen Warren .pads_refclk_cfg0 = 0x90b890b8, 1075d9eda6c4SStephen Warren .has_pex_clkreq_en = true, 1076d9eda6c4SStephen Warren .has_pex_bias_ctrl = true, 1077d9eda6c4SStephen Warren .has_cml_clk = true, 1078d9eda6c4SStephen Warren .has_gen2 = true, 1079d9eda6c4SStephen Warren .force_pca_enable = true, 1080*bbc5b36bSStephen Warren }, 1081*bbc5b36bSStephen Warren [TEGRA186_PCIE] = { 1082*bbc5b36bSStephen Warren .num_ports = 3, 1083*bbc5b36bSStephen Warren .afi_pex2_ctrl = AFI_PEX2_CTRL_T186, 1084*bbc5b36bSStephen Warren .pads_refclk_cfg0 = 0x80b880b8, 1085*bbc5b36bSStephen Warren .pads_refclk_cfg1 = 0x000480b8, 1086*bbc5b36bSStephen Warren .has_pex_clkreq_en = true, 1087*bbc5b36bSStephen Warren .has_pex_bias_ctrl = true, 1088*bbc5b36bSStephen Warren .has_gen2 = true, 1089*bbc5b36bSStephen Warren }, 1090d9eda6c4SStephen Warren }; 1091d9eda6c4SStephen Warren 1092e81ca884SSimon Glass static int pci_tegra_ofdata_to_platdata(struct udevice *dev) 1093f315828bSThierry Reding { 1094e81ca884SSimon Glass struct tegra_pcie *pcie = dev_get_priv(dev); 1095e81ca884SSimon Glass enum tegra_pci_id id; 1096bec05246SStephen Warren 1097e81ca884SSimon Glass id = dev_get_driver_data(dev); 1098e81ca884SSimon Glass pcie->soc = &pci_tegra_soc[id]; 1099f315828bSThierry Reding 1100f315828bSThierry Reding INIT_LIST_HEAD(&pcie->ports); 1101f315828bSThierry Reding 1102e81ca884SSimon Glass if (tegra_pcie_parse_dt(gd->fdt_blob, dev->of_offset, id, pcie)) 1103e81ca884SSimon Glass return -EINVAL; 1104e81ca884SSimon Glass 1105e81ca884SSimon Glass return 0; 1106f315828bSThierry Reding } 1107f315828bSThierry Reding 1108e81ca884SSimon Glass static int pci_tegra_probe(struct udevice *dev) 1109e81ca884SSimon Glass { 1110e81ca884SSimon Glass struct tegra_pcie *pcie = dev_get_priv(dev); 1111e81ca884SSimon Glass int err; 1112e81ca884SSimon Glass 1113*bbc5b36bSStephen Warren #ifdef CONFIG_TEGRA186 1114*bbc5b36bSStephen Warren err = clk_get_by_name(dev, "afi", &pcie->clk_afi); 1115*bbc5b36bSStephen Warren if (err) { 1116*bbc5b36bSStephen Warren debug("clk_get_by_name(afi) failed: %d\n", err); 1117*bbc5b36bSStephen Warren return err; 1118*bbc5b36bSStephen Warren } 1119*bbc5b36bSStephen Warren 1120*bbc5b36bSStephen Warren err = clk_get_by_name(dev, "pex", &pcie->clk_pex); 1121*bbc5b36bSStephen Warren if (err) { 1122*bbc5b36bSStephen Warren debug("clk_get_by_name(pex) failed: %d\n", err); 1123*bbc5b36bSStephen Warren return err; 1124*bbc5b36bSStephen Warren } 1125*bbc5b36bSStephen Warren 1126*bbc5b36bSStephen Warren err = reset_get_by_name(dev, "afi", &pcie->reset_afi); 1127*bbc5b36bSStephen Warren if (err) { 1128*bbc5b36bSStephen Warren debug("reset_get_by_name(afi) failed: %d\n", err); 1129*bbc5b36bSStephen Warren return err; 1130*bbc5b36bSStephen Warren } 1131*bbc5b36bSStephen Warren 1132*bbc5b36bSStephen Warren err = reset_get_by_name(dev, "pex", &pcie->reset_pex); 1133*bbc5b36bSStephen Warren if (err) { 1134*bbc5b36bSStephen Warren debug("reset_get_by_name(pex) failed: %d\n", err); 1135*bbc5b36bSStephen Warren return err; 1136*bbc5b36bSStephen Warren } 1137*bbc5b36bSStephen Warren 1138*bbc5b36bSStephen Warren err = reset_get_by_name(dev, "pcie_x", &pcie->reset_pcie_x); 1139*bbc5b36bSStephen Warren if (err) { 1140*bbc5b36bSStephen Warren debug("reset_get_by_name(pcie_x) failed: %d\n", err); 1141*bbc5b36bSStephen Warren return err; 1142*bbc5b36bSStephen Warren } 1143*bbc5b36bSStephen Warren 1144*bbc5b36bSStephen Warren err = power_domain_get(dev, &pcie->pwrdom); 1145*bbc5b36bSStephen Warren if (err) { 1146*bbc5b36bSStephen Warren debug("power_domain_get() failed: %d\n", err); 1147*bbc5b36bSStephen Warren return err; 1148*bbc5b36bSStephen Warren } 1149*bbc5b36bSStephen Warren #endif 1150*bbc5b36bSStephen Warren 1151f315828bSThierry Reding err = tegra_pcie_power_on(pcie); 1152f315828bSThierry Reding if (err < 0) { 1153f315828bSThierry Reding error("failed to power on"); 1154e81ca884SSimon Glass return err; 1155f315828bSThierry Reding } 1156f315828bSThierry Reding 1157f315828bSThierry Reding err = tegra_pcie_enable_controller(pcie); 1158f315828bSThierry Reding if (err < 0) { 1159f315828bSThierry Reding error("failed to enable controller"); 1160e81ca884SSimon Glass return err; 1161f315828bSThierry Reding } 1162f315828bSThierry Reding 1163e81ca884SSimon Glass err = tegra_pcie_setup_translations(dev); 1164e81ca884SSimon Glass if (err < 0) { 1165e81ca884SSimon Glass error("failed to decode ranges"); 1166e81ca884SSimon Glass return err; 1167e81ca884SSimon Glass } 1168f315828bSThierry Reding 1169f315828bSThierry Reding err = tegra_pcie_enable(pcie); 1170f315828bSThierry Reding if (err < 0) { 1171f315828bSThierry Reding error("failed to enable PCIe"); 1172e81ca884SSimon Glass return err; 1173f315828bSThierry Reding } 1174f315828bSThierry Reding 1175f315828bSThierry Reding return 0; 1176f315828bSThierry Reding } 1177f315828bSThierry Reding 1178e81ca884SSimon Glass static const struct dm_pci_ops pci_tegra_ops = { 1179e81ca884SSimon Glass .read_config = pci_tegra_read_config, 1180e81ca884SSimon Glass .write_config = pci_tegra_write_config, 1181e81ca884SSimon Glass }; 1182f315828bSThierry Reding 1183e81ca884SSimon Glass static const struct udevice_id pci_tegra_ids[] = { 1184e81ca884SSimon Glass { .compatible = "nvidia,tegra20-pcie", .data = TEGRA20_PCIE }, 1185e81ca884SSimon Glass { .compatible = "nvidia,tegra30-pcie", .data = TEGRA30_PCIE }, 1186e81ca884SSimon Glass { .compatible = "nvidia,tegra124-pcie", .data = TEGRA124_PCIE }, 1187e81ca884SSimon Glass { .compatible = "nvidia,tegra210-pcie", .data = TEGRA210_PCIE }, 1188*bbc5b36bSStephen Warren { .compatible = "nvidia,tegra186-pcie", .data = TEGRA186_PCIE }, 1189e81ca884SSimon Glass { } 1190e81ca884SSimon Glass }; 1191a02e2635SStephen Warren 1192e81ca884SSimon Glass U_BOOT_DRIVER(pci_tegra) = { 1193e81ca884SSimon Glass .name = "pci_tegra", 1194e81ca884SSimon Glass .id = UCLASS_PCI, 1195e81ca884SSimon Glass .of_match = pci_tegra_ids, 1196e81ca884SSimon Glass .ops = &pci_tegra_ops, 1197e81ca884SSimon Glass .ofdata_to_platdata = pci_tegra_ofdata_to_platdata, 1198e81ca884SSimon Glass .probe = pci_tegra_probe, 1199e81ca884SSimon Glass .priv_auto_alloc_size = sizeof(struct tegra_pcie), 1200e81ca884SSimon Glass }; 1201