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