18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PCIe host controller driver for Tegra194 SoC 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2019 NVIDIA Corporation. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Vidya Sagar <vidyas@nvidia.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 118c2ecf20Sopenharmony_ci#include <linux/clk.h> 128c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/gpio.h> 158c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 168c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 178c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/of.h> 218c2ecf20Sopenharmony_ci#include <linux/of_device.h> 228c2ecf20Sopenharmony_ci#include <linux/of_gpio.h> 238c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 248c2ecf20Sopenharmony_ci#include <linux/of_pci.h> 258c2ecf20Sopenharmony_ci#include <linux/pci.h> 268c2ecf20Sopenharmony_ci#include <linux/phy/phy.h> 278c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 288c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 298c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 308c2ecf20Sopenharmony_ci#include <linux/random.h> 318c2ecf20Sopenharmony_ci#include <linux/reset.h> 328c2ecf20Sopenharmony_ci#include <linux/resource.h> 338c2ecf20Sopenharmony_ci#include <linux/types.h> 348c2ecf20Sopenharmony_ci#include "pcie-designware.h" 358c2ecf20Sopenharmony_ci#include <soc/tegra/bpmp.h> 368c2ecf20Sopenharmony_ci#include <soc/tegra/bpmp-abi.h> 378c2ecf20Sopenharmony_ci#include "../../pci.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define APPL_PINMUX 0x0 408c2ecf20Sopenharmony_ci#define APPL_PINMUX_PEX_RST BIT(0) 418c2ecf20Sopenharmony_ci#define APPL_PINMUX_CLKREQ_OVERRIDE_EN BIT(2) 428c2ecf20Sopenharmony_ci#define APPL_PINMUX_CLKREQ_OVERRIDE BIT(3) 438c2ecf20Sopenharmony_ci#define APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE_EN BIT(4) 448c2ecf20Sopenharmony_ci#define APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE BIT(5) 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define APPL_CTRL 0x4 478c2ecf20Sopenharmony_ci#define APPL_CTRL_SYS_PRE_DET_STATE BIT(6) 488c2ecf20Sopenharmony_ci#define APPL_CTRL_LTSSM_EN BIT(7) 498c2ecf20Sopenharmony_ci#define APPL_CTRL_HW_HOT_RST_EN BIT(20) 508c2ecf20Sopenharmony_ci#define APPL_CTRL_HW_HOT_RST_MODE_MASK GENMASK(1, 0) 518c2ecf20Sopenharmony_ci#define APPL_CTRL_HW_HOT_RST_MODE_SHIFT 22 528c2ecf20Sopenharmony_ci#define APPL_CTRL_HW_HOT_RST_MODE_IMDT_RST 0x1 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0 0x8 558c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_LINK_STATE_INT_EN BIT(0) 568c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_MSI_RCV_INT_EN BIT(4) 578c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_INT_INT_EN BIT(8) 588c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_PCI_CMD_EN_INT_EN BIT(15) 598c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_CDM_REG_CHK_INT_EN BIT(19) 608c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_SYS_INTR_EN BIT(30) 618c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L0_0_SYS_MSI_INTR_EN BIT(31) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L0 0xC 648c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L0_LINK_STATE_INT BIT(0) 658c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L0_INT_INT BIT(8) 668c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L0_PCI_CMD_EN_INT BIT(15) 678c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L0_PEX_RST_INT BIT(16) 688c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L0_CDM_REG_CHK_INT BIT(18) 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_0_0 0x1C 718c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_0_0_LINK_REQ_RST_NOT_INT_EN BIT(1) 728c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_0_0_RDLH_LINK_UP_INT_EN BIT(3) 738c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_0_0_HOT_RESET_DONE_INT_EN BIT(30) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_0_0 0x20 768c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED BIT(1) 778c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_0_0_RDLH_LINK_UP_CHGED BIT(3) 788c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_0_0_HOT_RESET_DONE BIT(30) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_1 0x2C 818c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_2 0x30 828c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_3 0x34 838c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_6 0x3C 848c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_7 0x40 858c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_15_CFG_BME_CHGED BIT(1) 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_8_0 0x44 888c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_8_BW_MGT_INT_EN BIT(2) 898c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_8_AUTO_BW_INT_EN BIT(3) 908c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_8_INTX_EN BIT(11) 918c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_8_AER_INT_EN BIT(15) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_8_0 0x4C 948c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_8_0_EDMA_INT_MASK GENMASK(11, 6) 958c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS BIT(2) 968c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS BIT(3) 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_9 0x54 998c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_10 0x58 1008c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_11 0x64 1018c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_13 0x74 1028c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_14 0x78 1038c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_15 0x7C 1048c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_17 0x88 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_18 0x90 1078c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_18_CDM_REG_CHK_CMPLT BIT(2) 1088c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_18_CDM_REG_CHK_CMP_ERR BIT(1) 1098c2ecf20Sopenharmony_ci#define APPL_INTR_EN_L1_18_CDM_REG_CHK_LOGIC_ERR BIT(0) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_18 0x94 1128c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT BIT(2) 1138c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR BIT(1) 1148c2ecf20Sopenharmony_ci#define APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR BIT(0) 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#define APPL_MSI_CTRL_1 0xAC 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define APPL_MSI_CTRL_2 0xB0 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define APPL_LEGACY_INTX 0xB8 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define APPL_LTR_MSG_1 0xC4 1238c2ecf20Sopenharmony_ci#define LTR_MSG_REQ BIT(15) 1248c2ecf20Sopenharmony_ci#define LTR_MST_NO_SNOOP_SHIFT 16 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#define APPL_LTR_MSG_2 0xC8 1278c2ecf20Sopenharmony_ci#define APPL_LTR_MSG_2_LTR_MSG_REQ_STATE BIT(3) 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci#define APPL_LINK_STATUS 0xCC 1308c2ecf20Sopenharmony_ci#define APPL_LINK_STATUS_RDLH_LINK_UP BIT(0) 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#define APPL_DEBUG 0xD0 1338c2ecf20Sopenharmony_ci#define APPL_DEBUG_PM_LINKST_IN_L2_LAT BIT(21) 1348c2ecf20Sopenharmony_ci#define APPL_DEBUG_PM_LINKST_IN_L0 0x11 1358c2ecf20Sopenharmony_ci#define APPL_DEBUG_LTSSM_STATE_MASK GENMASK(8, 3) 1368c2ecf20Sopenharmony_ci#define APPL_DEBUG_LTSSM_STATE_SHIFT 3 1378c2ecf20Sopenharmony_ci#define LTSSM_STATE_PRE_DETECT 5 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci#define APPL_RADM_STATUS 0xE4 1408c2ecf20Sopenharmony_ci#define APPL_PM_XMT_TURNOFF_STATE BIT(0) 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci#define APPL_DM_TYPE 0x100 1438c2ecf20Sopenharmony_ci#define APPL_DM_TYPE_MASK GENMASK(3, 0) 1448c2ecf20Sopenharmony_ci#define APPL_DM_TYPE_RP 0x4 1458c2ecf20Sopenharmony_ci#define APPL_DM_TYPE_EP 0x0 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#define APPL_CFG_BASE_ADDR 0x104 1488c2ecf20Sopenharmony_ci#define APPL_CFG_BASE_ADDR_MASK GENMASK(31, 12) 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define APPL_CFG_IATU_DMA_BASE_ADDR 0x108 1518c2ecf20Sopenharmony_ci#define APPL_CFG_IATU_DMA_BASE_ADDR_MASK GENMASK(31, 18) 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#define APPL_CFG_MISC 0x110 1548c2ecf20Sopenharmony_ci#define APPL_CFG_MISC_SLV_EP_MODE BIT(14) 1558c2ecf20Sopenharmony_ci#define APPL_CFG_MISC_ARCACHE_MASK GENMASK(13, 10) 1568c2ecf20Sopenharmony_ci#define APPL_CFG_MISC_ARCACHE_SHIFT 10 1578c2ecf20Sopenharmony_ci#define APPL_CFG_MISC_ARCACHE_VAL 3 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci#define APPL_CFG_SLCG_OVERRIDE 0x114 1608c2ecf20Sopenharmony_ci#define APPL_CFG_SLCG_OVERRIDE_SLCG_EN_MASTER BIT(0) 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#define APPL_CAR_RESET_OVRD 0x12C 1638c2ecf20Sopenharmony_ci#define APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N BIT(0) 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci#define IO_BASE_IO_DECODE BIT(0) 1668c2ecf20Sopenharmony_ci#define IO_BASE_IO_DECODE_BIT8 BIT(8) 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci#define CFG_PREF_MEM_LIMIT_BASE_MEM_DECODE BIT(0) 1698c2ecf20Sopenharmony_ci#define CFG_PREF_MEM_LIMIT_BASE_MEM_LIMIT_DECODE BIT(16) 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#define CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF 0x718 1728c2ecf20Sopenharmony_ci#define CFG_TIMER_CTRL_ACK_NAK_SHIFT (19) 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#define EVENT_COUNTER_ALL_CLEAR 0x3 1758c2ecf20Sopenharmony_ci#define EVENT_COUNTER_ENABLE_ALL 0x7 1768c2ecf20Sopenharmony_ci#define EVENT_COUNTER_ENABLE_SHIFT 2 1778c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_SEL_MASK GENMASK(7, 0) 1788c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_SEL_SHIFT 16 1798c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_Tx_L0S 0x2 1808c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_Rx_L0S 0x3 1818c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_L1 0x5 1828c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_L1_1 0x7 1838c2ecf20Sopenharmony_ci#define EVENT_COUNTER_EVENT_L1_2 0x8 1848c2ecf20Sopenharmony_ci#define EVENT_COUNTER_GROUP_SEL_SHIFT 24 1858c2ecf20Sopenharmony_ci#define EVENT_COUNTER_GROUP_5 0x5 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci#define N_FTS_VAL 52 1888c2ecf20Sopenharmony_ci#define FTS_VAL 52 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci#define PORT_LOGIC_MSI_CTRL_INT_0_EN 0x828 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci#define GEN3_EQ_CONTROL_OFF 0x8a8 1938c2ecf20Sopenharmony_ci#define GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_SHIFT 8 1948c2ecf20Sopenharmony_ci#define GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_MASK GENMASK(23, 8) 1958c2ecf20Sopenharmony_ci#define GEN3_EQ_CONTROL_OFF_FB_MODE_MASK GENMASK(3, 0) 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci#define GEN3_RELATED_OFF 0x890 1988c2ecf20Sopenharmony_ci#define GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL BIT(0) 1998c2ecf20Sopenharmony_ci#define GEN3_RELATED_OFF_GEN3_EQ_DISABLE BIT(16) 2008c2ecf20Sopenharmony_ci#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT 24 2018c2ecf20Sopenharmony_ci#define GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK GENMASK(25, 24) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci#define PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT 0x8D0 2048c2ecf20Sopenharmony_ci#define AMBA_ERROR_RESPONSE_CRS_SHIFT 3 2058c2ecf20Sopenharmony_ci#define AMBA_ERROR_RESPONSE_CRS_MASK GENMASK(1, 0) 2068c2ecf20Sopenharmony_ci#define AMBA_ERROR_RESPONSE_CRS_OKAY 0 2078c2ecf20Sopenharmony_ci#define AMBA_ERROR_RESPONSE_CRS_OKAY_FFFFFFFF 1 2088c2ecf20Sopenharmony_ci#define AMBA_ERROR_RESPONSE_CRS_OKAY_FFFF0001 2 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci#define MSIX_ADDR_MATCH_LOW_OFF 0x940 2118c2ecf20Sopenharmony_ci#define MSIX_ADDR_MATCH_LOW_OFF_EN BIT(0) 2128c2ecf20Sopenharmony_ci#define MSIX_ADDR_MATCH_LOW_OFF_MASK GENMASK(31, 2) 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci#define MSIX_ADDR_MATCH_HIGH_OFF 0x944 2158c2ecf20Sopenharmony_ci#define MSIX_ADDR_MATCH_HIGH_OFF_MASK GENMASK(31, 0) 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci#define PORT_LOGIC_MSIX_DOORBELL 0x948 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci#define CAP_SPCIE_CAP_OFF 0x154 2208c2ecf20Sopenharmony_ci#define CAP_SPCIE_CAP_OFF_DSP_TX_PRESET0_MASK GENMASK(3, 0) 2218c2ecf20Sopenharmony_ci#define CAP_SPCIE_CAP_OFF_USP_TX_PRESET0_MASK GENMASK(11, 8) 2228c2ecf20Sopenharmony_ci#define CAP_SPCIE_CAP_OFF_USP_TX_PRESET0_SHIFT 8 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci#define PME_ACK_TIMEOUT 10000 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci#define LTSSM_TIMEOUT 50000 /* 50ms */ 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#define GEN3_GEN4_EQ_PRESET_INIT 5 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci#define GEN1_CORE_CLK_FREQ 62500000 2318c2ecf20Sopenharmony_ci#define GEN2_CORE_CLK_FREQ 125000000 2328c2ecf20Sopenharmony_ci#define GEN3_CORE_CLK_FREQ 250000000 2338c2ecf20Sopenharmony_ci#define GEN4_CORE_CLK_FREQ 500000000 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci#define LTR_MSG_TIMEOUT (100 * 1000) 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci#define PERST_DEBOUNCE_TIME (5 * 1000) 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#define EP_STATE_DISABLED 0 2408c2ecf20Sopenharmony_ci#define EP_STATE_ENABLED 1 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic const unsigned int pcie_gen_freq[] = { 2438c2ecf20Sopenharmony_ci GEN1_CORE_CLK_FREQ, /* PCI_EXP_LNKSTA_CLS == 0; undefined */ 2448c2ecf20Sopenharmony_ci GEN1_CORE_CLK_FREQ, 2458c2ecf20Sopenharmony_ci GEN2_CORE_CLK_FREQ, 2468c2ecf20Sopenharmony_ci GEN3_CORE_CLK_FREQ, 2478c2ecf20Sopenharmony_ci GEN4_CORE_CLK_FREQ 2488c2ecf20Sopenharmony_ci}; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic const u32 event_cntr_ctrl_offset[] = { 2518c2ecf20Sopenharmony_ci 0x1d8, 2528c2ecf20Sopenharmony_ci 0x1a8, 2538c2ecf20Sopenharmony_ci 0x1a8, 2548c2ecf20Sopenharmony_ci 0x1a8, 2558c2ecf20Sopenharmony_ci 0x1c4, 2568c2ecf20Sopenharmony_ci 0x1d8 2578c2ecf20Sopenharmony_ci}; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic const u32 event_cntr_data_offset[] = { 2608c2ecf20Sopenharmony_ci 0x1dc, 2618c2ecf20Sopenharmony_ci 0x1ac, 2628c2ecf20Sopenharmony_ci 0x1ac, 2638c2ecf20Sopenharmony_ci 0x1ac, 2648c2ecf20Sopenharmony_ci 0x1c8, 2658c2ecf20Sopenharmony_ci 0x1dc 2668c2ecf20Sopenharmony_ci}; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistruct tegra_pcie_dw { 2698c2ecf20Sopenharmony_ci struct device *dev; 2708c2ecf20Sopenharmony_ci struct resource *appl_res; 2718c2ecf20Sopenharmony_ci struct resource *dbi_res; 2728c2ecf20Sopenharmony_ci struct resource *atu_dma_res; 2738c2ecf20Sopenharmony_ci void __iomem *appl_base; 2748c2ecf20Sopenharmony_ci struct clk *core_clk; 2758c2ecf20Sopenharmony_ci struct reset_control *core_apb_rst; 2768c2ecf20Sopenharmony_ci struct reset_control *core_rst; 2778c2ecf20Sopenharmony_ci struct dw_pcie pci; 2788c2ecf20Sopenharmony_ci struct tegra_bpmp *bpmp; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci enum dw_pcie_device_mode mode; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci bool supports_clkreq; 2838c2ecf20Sopenharmony_ci bool enable_cdm_check; 2848c2ecf20Sopenharmony_ci bool link_state; 2858c2ecf20Sopenharmony_ci bool update_fc_fixup; 2868c2ecf20Sopenharmony_ci u8 init_link_width; 2878c2ecf20Sopenharmony_ci u32 msi_ctrl_int; 2888c2ecf20Sopenharmony_ci u32 num_lanes; 2898c2ecf20Sopenharmony_ci u32 cid; 2908c2ecf20Sopenharmony_ci u32 cfg_link_cap_l1sub; 2918c2ecf20Sopenharmony_ci u32 pcie_cap_base; 2928c2ecf20Sopenharmony_ci u32 aspm_cmrt; 2938c2ecf20Sopenharmony_ci u32 aspm_pwr_on_t; 2948c2ecf20Sopenharmony_ci u32 aspm_l0s_enter_lat; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci struct regulator *pex_ctl_supply; 2978c2ecf20Sopenharmony_ci struct regulator *slot_ctl_3v3; 2988c2ecf20Sopenharmony_ci struct regulator *slot_ctl_12v; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci unsigned int phy_count; 3018c2ecf20Sopenharmony_ci struct phy **phys; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci struct dentry *debugfs; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* Endpoint mode specific */ 3068c2ecf20Sopenharmony_ci struct gpio_desc *pex_rst_gpiod; 3078c2ecf20Sopenharmony_ci struct gpio_desc *pex_refclk_sel_gpiod; 3088c2ecf20Sopenharmony_ci unsigned int pex_rst_irq; 3098c2ecf20Sopenharmony_ci int ep_state; 3108c2ecf20Sopenharmony_ci}; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistruct tegra_pcie_dw_of_data { 3138c2ecf20Sopenharmony_ci enum dw_pcie_device_mode mode; 3148c2ecf20Sopenharmony_ci}; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic inline struct tegra_pcie_dw *to_tegra_pcie(struct dw_pcie *pci) 3178c2ecf20Sopenharmony_ci{ 3188c2ecf20Sopenharmony_ci return container_of(pci, struct tegra_pcie_dw, pci); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic inline void appl_writel(struct tegra_pcie_dw *pcie, const u32 value, 3228c2ecf20Sopenharmony_ci const u32 reg) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci writel_relaxed(value, pcie->appl_base + reg); 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic inline u32 appl_readl(struct tegra_pcie_dw *pcie, const u32 reg) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci return readl_relaxed(pcie->appl_base + reg); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistruct tegra_pcie_soc { 3338c2ecf20Sopenharmony_ci enum dw_pcie_device_mode mode; 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic void apply_bad_link_workaround(struct pcie_port *pp) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 3398c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 3408c2ecf20Sopenharmony_ci u32 current_link_width; 3418c2ecf20Sopenharmony_ci u16 val; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* 3448c2ecf20Sopenharmony_ci * NOTE:- Since this scenario is uncommon and link as such is not 3458c2ecf20Sopenharmony_ci * stable anyway, not waiting to confirm if link is really 3468c2ecf20Sopenharmony_ci * transitioning to Gen-2 speed 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_ci val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA); 3498c2ecf20Sopenharmony_ci if (val & PCI_EXP_LNKSTA_LBMS) { 3508c2ecf20Sopenharmony_ci current_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val); 3518c2ecf20Sopenharmony_ci if (pcie->init_link_width > current_link_width) { 3528c2ecf20Sopenharmony_ci dev_warn(pci->dev, "PCIe link is bad, width reduced\n"); 3538c2ecf20Sopenharmony_ci val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + 3548c2ecf20Sopenharmony_ci PCI_EXP_LNKCTL2); 3558c2ecf20Sopenharmony_ci val &= ~PCI_EXP_LNKCTL2_TLS; 3568c2ecf20Sopenharmony_ci val |= PCI_EXP_LNKCTL2_TLS_2_5GT; 3578c2ecf20Sopenharmony_ci dw_pcie_writew_dbi(pci, pcie->pcie_cap_base + 3588c2ecf20Sopenharmony_ci PCI_EXP_LNKCTL2, val); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + 3618c2ecf20Sopenharmony_ci PCI_EXP_LNKCTL); 3628c2ecf20Sopenharmony_ci val |= PCI_EXP_LNKCTL_RL; 3638c2ecf20Sopenharmony_ci dw_pcie_writew_dbi(pci, pcie->pcie_cap_base + 3648c2ecf20Sopenharmony_ci PCI_EXP_LNKCTL, val); 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci } 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic irqreturn_t tegra_pcie_rp_irq_handler(int irq, void *arg) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = arg; 3728c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 3738c2ecf20Sopenharmony_ci struct pcie_port *pp = &pci->pp; 3748c2ecf20Sopenharmony_ci u32 val, status_l0, status_l1; 3758c2ecf20Sopenharmony_ci u16 val_w; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0); 3788c2ecf20Sopenharmony_ci if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) { 3798c2ecf20Sopenharmony_ci status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0); 3808c2ecf20Sopenharmony_ci appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_0_0); 3818c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) { 3828c2ecf20Sopenharmony_ci /* SBR & Surprise Link Down WAR */ 3838c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CAR_RESET_OVRD); 3848c2ecf20Sopenharmony_ci val &= ~APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N; 3858c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CAR_RESET_OVRD); 3868c2ecf20Sopenharmony_ci udelay(1); 3878c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CAR_RESET_OVRD); 3888c2ecf20Sopenharmony_ci val |= APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N; 3898c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CAR_RESET_OVRD); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); 3928c2ecf20Sopenharmony_ci val |= PORT_LOGIC_SPEED_CHANGE; 3938c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci if (status_l0 & APPL_INTR_STATUS_L0_INT_INT) { 3988c2ecf20Sopenharmony_ci status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0); 3998c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) { 4008c2ecf20Sopenharmony_ci appl_writel(pcie, 4018c2ecf20Sopenharmony_ci APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS, 4028c2ecf20Sopenharmony_ci APPL_INTR_STATUS_L1_8_0); 4038c2ecf20Sopenharmony_ci apply_bad_link_workaround(pp); 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) { 4068c2ecf20Sopenharmony_ci appl_writel(pcie, 4078c2ecf20Sopenharmony_ci APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS, 4088c2ecf20Sopenharmony_ci APPL_INTR_STATUS_L1_8_0); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci val_w = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + 4118c2ecf20Sopenharmony_ci PCI_EXP_LNKSTA); 4128c2ecf20Sopenharmony_ci dev_dbg(pci->dev, "Link Speed : Gen-%u\n", val_w & 4138c2ecf20Sopenharmony_ci PCI_EXP_LNKSTA_CLS); 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci if (status_l0 & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) { 4188c2ecf20Sopenharmony_ci status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_18); 4198c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS); 4208c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) { 4218c2ecf20Sopenharmony_ci dev_info(pci->dev, "CDM check complete\n"); 4228c2ecf20Sopenharmony_ci val |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) { 4258c2ecf20Sopenharmony_ci dev_err(pci->dev, "CDM comparison mismatch\n"); 4268c2ecf20Sopenharmony_ci val |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR; 4278c2ecf20Sopenharmony_ci } 4288c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) { 4298c2ecf20Sopenharmony_ci dev_err(pci->dev, "CDM Logic error\n"); 4308c2ecf20Sopenharmony_ci val |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR; 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val); 4338c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR); 4348c2ecf20Sopenharmony_ci dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", val); 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci return IRQ_HANDLED; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic void pex_ep_event_hot_rst_done(struct tegra_pcie_dw *pcie) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci u32 val; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L0); 4458c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_0_0); 4468c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_1); 4478c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_2); 4488c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_3); 4498c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_6); 4508c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_7); 4518c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_8_0); 4528c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_9); 4538c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_10); 4548c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_11); 4558c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_13); 4568c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_14); 4578c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_15); 4588c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_17); 4598c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_MSI_CTRL_2); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 4628c2ecf20Sopenharmony_ci val |= APPL_CTRL_LTSSM_EN; 4638c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cistatic irqreturn_t tegra_pcie_ep_irq_thread(int irq, void *arg) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = arg; 4698c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 4708c2ecf20Sopenharmony_ci u32 val, speed; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) & 4738c2ecf20Sopenharmony_ci PCI_EXP_LNKSTA_CLS; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (speed >= ARRAY_SIZE(pcie_gen_freq)) 4768c2ecf20Sopenharmony_ci speed = 0; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci /* If EP doesn't advertise L1SS, just return */ 4818c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, pcie->cfg_link_cap_l1sub); 4828c2ecf20Sopenharmony_ci if (!(val & (PCI_L1SS_CAP_ASPM_L1_1 | PCI_L1SS_CAP_ASPM_L1_2))) 4838c2ecf20Sopenharmony_ci return IRQ_HANDLED; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* Check if BME is set to '1' */ 4868c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCI_COMMAND); 4878c2ecf20Sopenharmony_ci if (val & PCI_COMMAND_MASTER) { 4888c2ecf20Sopenharmony_ci ktime_t timeout; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci /* 110us for both snoop and no-snoop */ 4918c2ecf20Sopenharmony_ci val = 110 | (2 << PCI_LTR_SCALE_SHIFT) | LTR_MSG_REQ; 4928c2ecf20Sopenharmony_ci val |= (val << LTR_MST_NO_SNOOP_SHIFT); 4938c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_LTR_MSG_1); 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci /* Send LTR upstream */ 4968c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_LTR_MSG_2); 4978c2ecf20Sopenharmony_ci val |= APPL_LTR_MSG_2_LTR_MSG_REQ_STATE; 4988c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_LTR_MSG_2); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci timeout = ktime_add_us(ktime_get(), LTR_MSG_TIMEOUT); 5018c2ecf20Sopenharmony_ci for (;;) { 5028c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_LTR_MSG_2); 5038c2ecf20Sopenharmony_ci if (!(val & APPL_LTR_MSG_2_LTR_MSG_REQ_STATE)) 5048c2ecf20Sopenharmony_ci break; 5058c2ecf20Sopenharmony_ci if (ktime_after(ktime_get(), timeout)) 5068c2ecf20Sopenharmony_ci break; 5078c2ecf20Sopenharmony_ci usleep_range(1000, 1100); 5088c2ecf20Sopenharmony_ci } 5098c2ecf20Sopenharmony_ci if (val & APPL_LTR_MSG_2_LTR_MSG_REQ_STATE) 5108c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to send LTR message\n"); 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic irqreturn_t tegra_pcie_ep_hard_irq(int irq, void *arg) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = arg; 5198c2ecf20Sopenharmony_ci struct dw_pcie_ep *ep = &pcie->pci.ep; 5208c2ecf20Sopenharmony_ci int spurious = 1; 5218c2ecf20Sopenharmony_ci u32 status_l0, status_l1, link_status; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0); 5248c2ecf20Sopenharmony_ci if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) { 5258c2ecf20Sopenharmony_ci status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0); 5268c2ecf20Sopenharmony_ci appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_0_0); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_0_0_HOT_RESET_DONE) 5298c2ecf20Sopenharmony_ci pex_ep_event_hot_rst_done(pcie); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_0_0_RDLH_LINK_UP_CHGED) { 5328c2ecf20Sopenharmony_ci link_status = appl_readl(pcie, APPL_LINK_STATUS); 5338c2ecf20Sopenharmony_ci if (link_status & APPL_LINK_STATUS_RDLH_LINK_UP) { 5348c2ecf20Sopenharmony_ci dev_dbg(pcie->dev, "Link is up with Host\n"); 5358c2ecf20Sopenharmony_ci dw_pcie_ep_linkup(ep); 5368c2ecf20Sopenharmony_ci } 5378c2ecf20Sopenharmony_ci } 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci spurious = 0; 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci if (status_l0 & APPL_INTR_STATUS_L0_PCI_CMD_EN_INT) { 5438c2ecf20Sopenharmony_ci status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_15); 5448c2ecf20Sopenharmony_ci appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_15); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci if (status_l1 & APPL_INTR_STATUS_L1_15_CFG_BME_CHGED) 5478c2ecf20Sopenharmony_ci return IRQ_WAKE_THREAD; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci spurious = 0; 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (spurious) { 5538c2ecf20Sopenharmony_ci dev_warn(pcie->dev, "Random interrupt (STATUS = 0x%08X)\n", 5548c2ecf20Sopenharmony_ci status_l0); 5558c2ecf20Sopenharmony_ci appl_writel(pcie, status_l0, APPL_INTR_STATUS_L0); 5568c2ecf20Sopenharmony_ci } 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_rd_own_conf(struct pci_bus *bus, u32 devfn, int where, 5628c2ecf20Sopenharmony_ci int size, u32 *val) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci /* 5658c2ecf20Sopenharmony_ci * This is an endpoint mode specific register happen to appear even 5668c2ecf20Sopenharmony_ci * when controller is operating in root port mode and system hangs 5678c2ecf20Sopenharmony_ci * when it is accessed with link being in ASPM-L1 state. 5688c2ecf20Sopenharmony_ci * So skip accessing it altogether 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_ci if (!PCI_SLOT(devfn) && where == PORT_LOGIC_MSIX_DOORBELL) { 5718c2ecf20Sopenharmony_ci *val = 0x00000000; 5728c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci return pci_generic_config_read(bus, devfn, where, size, val); 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_wr_own_conf(struct pci_bus *bus, u32 devfn, int where, 5798c2ecf20Sopenharmony_ci int size, u32 val) 5808c2ecf20Sopenharmony_ci{ 5818c2ecf20Sopenharmony_ci /* 5828c2ecf20Sopenharmony_ci * This is an endpoint mode specific register happen to appear even 5838c2ecf20Sopenharmony_ci * when controller is operating in root port mode and system hangs 5848c2ecf20Sopenharmony_ci * when it is accessed with link being in ASPM-L1 state. 5858c2ecf20Sopenharmony_ci * So skip accessing it altogether 5868c2ecf20Sopenharmony_ci */ 5878c2ecf20Sopenharmony_ci if (!PCI_SLOT(devfn) && where == PORT_LOGIC_MSIX_DOORBELL) 5888c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return pci_generic_config_write(bus, devfn, where, size, val); 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic struct pci_ops tegra_pci_ops = { 5948c2ecf20Sopenharmony_ci .map_bus = dw_pcie_own_conf_map_bus, 5958c2ecf20Sopenharmony_ci .read = tegra_pcie_dw_rd_own_conf, 5968c2ecf20Sopenharmony_ci .write = tegra_pcie_dw_wr_own_conf, 5978c2ecf20Sopenharmony_ci}; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci#if defined(CONFIG_PCIEASPM) 6008c2ecf20Sopenharmony_cistatic void disable_aspm_l11(struct tegra_pcie_dw *pcie) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci u32 val; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub); 6058c2ecf20Sopenharmony_ci val &= ~PCI_L1SS_CAP_ASPM_L1_1; 6068c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub, val); 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_cistatic void disable_aspm_l12(struct tegra_pcie_dw *pcie) 6108c2ecf20Sopenharmony_ci{ 6118c2ecf20Sopenharmony_ci u32 val; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub); 6148c2ecf20Sopenharmony_ci val &= ~PCI_L1SS_CAP_ASPM_L1_2; 6158c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, pcie->cfg_link_cap_l1sub, val); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_cistatic inline u32 event_counter_prog(struct tegra_pcie_dw *pcie, u32 event) 6198c2ecf20Sopenharmony_ci{ 6208c2ecf20Sopenharmony_ci u32 val; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(&pcie->pci, event_cntr_ctrl_offset[pcie->cid]); 6238c2ecf20Sopenharmony_ci val &= ~(EVENT_COUNTER_EVENT_SEL_MASK << EVENT_COUNTER_EVENT_SEL_SHIFT); 6248c2ecf20Sopenharmony_ci val |= EVENT_COUNTER_GROUP_5 << EVENT_COUNTER_GROUP_SEL_SHIFT; 6258c2ecf20Sopenharmony_ci val |= event << EVENT_COUNTER_EVENT_SEL_SHIFT; 6268c2ecf20Sopenharmony_ci val |= EVENT_COUNTER_ENABLE_ALL << EVENT_COUNTER_ENABLE_SHIFT; 6278c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, event_cntr_ctrl_offset[pcie->cid], val); 6288c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(&pcie->pci, event_cntr_data_offset[pcie->cid]); 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci return val; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic int aspm_state_cnt(struct seq_file *s, void *data) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = (struct tegra_pcie_dw *) 6368c2ecf20Sopenharmony_ci dev_get_drvdata(s->private); 6378c2ecf20Sopenharmony_ci u32 val; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci seq_printf(s, "Tx L0s entry count : %u\n", 6408c2ecf20Sopenharmony_ci event_counter_prog(pcie, EVENT_COUNTER_EVENT_Tx_L0S)); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci seq_printf(s, "Rx L0s entry count : %u\n", 6438c2ecf20Sopenharmony_ci event_counter_prog(pcie, EVENT_COUNTER_EVENT_Rx_L0S)); 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci seq_printf(s, "Link L1 entry count : %u\n", 6468c2ecf20Sopenharmony_ci event_counter_prog(pcie, EVENT_COUNTER_EVENT_L1)); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci seq_printf(s, "Link L1.1 entry count : %u\n", 6498c2ecf20Sopenharmony_ci event_counter_prog(pcie, EVENT_COUNTER_EVENT_L1_1)); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci seq_printf(s, "Link L1.2 entry count : %u\n", 6528c2ecf20Sopenharmony_ci event_counter_prog(pcie, EVENT_COUNTER_EVENT_L1_2)); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci /* Clear all counters */ 6558c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, event_cntr_ctrl_offset[pcie->cid], 6568c2ecf20Sopenharmony_ci EVENT_COUNTER_ALL_CLEAR); 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci /* Re-enable counting */ 6598c2ecf20Sopenharmony_ci val = EVENT_COUNTER_ENABLE_ALL << EVENT_COUNTER_ENABLE_SHIFT; 6608c2ecf20Sopenharmony_ci val |= EVENT_COUNTER_GROUP_5 << EVENT_COUNTER_GROUP_SEL_SHIFT; 6618c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, event_cntr_ctrl_offset[pcie->cid], val); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci return 0; 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistatic void init_host_aspm(struct tegra_pcie_dw *pcie) 6678c2ecf20Sopenharmony_ci{ 6688c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 6698c2ecf20Sopenharmony_ci u32 val; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci val = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_L1SS); 6728c2ecf20Sopenharmony_ci pcie->cfg_link_cap_l1sub = val + PCI_L1SS_CAP; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci /* Enable ASPM counters */ 6758c2ecf20Sopenharmony_ci val = EVENT_COUNTER_ENABLE_ALL << EVENT_COUNTER_ENABLE_SHIFT; 6768c2ecf20Sopenharmony_ci val |= EVENT_COUNTER_GROUP_5 << EVENT_COUNTER_GROUP_SEL_SHIFT; 6778c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, event_cntr_ctrl_offset[pcie->cid], val); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci /* Program T_cmrt and T_pwr_on values */ 6808c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, pcie->cfg_link_cap_l1sub); 6818c2ecf20Sopenharmony_ci val &= ~(PCI_L1SS_CAP_CM_RESTORE_TIME | PCI_L1SS_CAP_P_PWR_ON_VALUE); 6828c2ecf20Sopenharmony_ci val |= (pcie->aspm_cmrt << 8); 6838c2ecf20Sopenharmony_ci val |= (pcie->aspm_pwr_on_t << 19); 6848c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, pcie->cfg_link_cap_l1sub, val); 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci /* Program L0s and L1 entrance latencies */ 6878c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCIE_PORT_AFR); 6888c2ecf20Sopenharmony_ci val &= ~PORT_AFR_L0S_ENTRANCE_LAT_MASK; 6898c2ecf20Sopenharmony_ci val |= (pcie->aspm_l0s_enter_lat << PORT_AFR_L0S_ENTRANCE_LAT_SHIFT); 6908c2ecf20Sopenharmony_ci val |= PORT_AFR_ENTER_ASPM; 6918c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PCIE_PORT_AFR, val); 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic void init_debugfs(struct tegra_pcie_dw *pcie) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci debugfs_create_devm_seqfile(pcie->dev, "aspm_state_cnt", pcie->debugfs, 6978c2ecf20Sopenharmony_ci aspm_state_cnt); 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci#else 7008c2ecf20Sopenharmony_cistatic inline void disable_aspm_l12(struct tegra_pcie_dw *pcie) { return; } 7018c2ecf20Sopenharmony_cistatic inline void disable_aspm_l11(struct tegra_pcie_dw *pcie) { return; } 7028c2ecf20Sopenharmony_cistatic inline void init_host_aspm(struct tegra_pcie_dw *pcie) { return; } 7038c2ecf20Sopenharmony_cistatic inline void init_debugfs(struct tegra_pcie_dw *pcie) { return; } 7048c2ecf20Sopenharmony_ci#endif 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic void tegra_pcie_enable_system_interrupts(struct pcie_port *pp) 7078c2ecf20Sopenharmony_ci{ 7088c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 7098c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 7108c2ecf20Sopenharmony_ci u32 val; 7118c2ecf20Sopenharmony_ci u16 val_w; 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L0_0); 7148c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_LINK_STATE_INT_EN; 7158c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L0_0); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L1_0_0); 7188c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_0_0_LINK_REQ_RST_NOT_INT_EN; 7198c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L1_0_0); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci if (pcie->enable_cdm_check) { 7228c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L0_0); 7238c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_CDM_REG_CHK_INT_EN; 7248c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L0_0); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L1_18); 7278c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_18_CDM_REG_CHK_CMP_ERR; 7288c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_18_CDM_REG_CHK_LOGIC_ERR; 7298c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L1_18); 7308c2ecf20Sopenharmony_ci } 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base + 7338c2ecf20Sopenharmony_ci PCI_EXP_LNKSTA); 7348c2ecf20Sopenharmony_ci pcie->init_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val_w); 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base + 7378c2ecf20Sopenharmony_ci PCI_EXP_LNKCTL); 7388c2ecf20Sopenharmony_ci val_w |= PCI_EXP_LNKCTL_LBMIE; 7398c2ecf20Sopenharmony_ci dw_pcie_writew_dbi(&pcie->pci, pcie->pcie_cap_base + PCI_EXP_LNKCTL, 7408c2ecf20Sopenharmony_ci val_w); 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic void tegra_pcie_enable_legacy_interrupts(struct pcie_port *pp) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 7468c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 7478c2ecf20Sopenharmony_ci u32 val; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* Enable legacy interrupt generation */ 7508c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L0_0); 7518c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_SYS_INTR_EN; 7528c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_INT_INT_EN; 7538c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L0_0); 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L1_8_0); 7568c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_8_INTX_EN; 7578c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_8_AUTO_BW_INT_EN; 7588c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_8_BW_MGT_INT_EN; 7598c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PCIEAER)) 7608c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_8_AER_INT_EN; 7618c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L1_8_0); 7628c2ecf20Sopenharmony_ci} 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_cistatic void tegra_pcie_enable_msi_interrupts(struct pcie_port *pp) 7658c2ecf20Sopenharmony_ci{ 7668c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 7678c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 7688c2ecf20Sopenharmony_ci u32 val; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci dw_pcie_msi_init(pp); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci /* Enable MSI interrupt generation */ 7738c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L0_0); 7748c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_SYS_MSI_INTR_EN; 7758c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_MSI_RCV_INT_EN; 7768c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L0_0); 7778c2ecf20Sopenharmony_ci} 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_cistatic void tegra_pcie_enable_interrupts(struct pcie_port *pp) 7808c2ecf20Sopenharmony_ci{ 7818c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 7828c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci /* Clear interrupt statuses before enabling interrupts */ 7858c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L0); 7868c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_0_0); 7878c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_1); 7888c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_2); 7898c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_3); 7908c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_6); 7918c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_7); 7928c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_8_0); 7938c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_9); 7948c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_10); 7958c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_11); 7968c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_13); 7978c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_14); 7988c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_15); 7998c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_17); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci tegra_pcie_enable_system_interrupts(pp); 8028c2ecf20Sopenharmony_ci tegra_pcie_enable_legacy_interrupts(pp); 8038c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PCI_MSI)) 8048c2ecf20Sopenharmony_ci tegra_pcie_enable_msi_interrupts(pp); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic void config_gen3_gen4_eq_presets(struct tegra_pcie_dw *pcie) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 8108c2ecf20Sopenharmony_ci u32 val, offset, i; 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci /* Program init preset */ 8138c2ecf20Sopenharmony_ci for (i = 0; i < pcie->num_lanes; i++) { 8148c2ecf20Sopenharmony_ci val = dw_pcie_readw_dbi(pci, CAP_SPCIE_CAP_OFF + (i * 2)); 8158c2ecf20Sopenharmony_ci val &= ~CAP_SPCIE_CAP_OFF_DSP_TX_PRESET0_MASK; 8168c2ecf20Sopenharmony_ci val |= GEN3_GEN4_EQ_PRESET_INIT; 8178c2ecf20Sopenharmony_ci val &= ~CAP_SPCIE_CAP_OFF_USP_TX_PRESET0_MASK; 8188c2ecf20Sopenharmony_ci val |= (GEN3_GEN4_EQ_PRESET_INIT << 8198c2ecf20Sopenharmony_ci CAP_SPCIE_CAP_OFF_USP_TX_PRESET0_SHIFT); 8208c2ecf20Sopenharmony_ci dw_pcie_writew_dbi(pci, CAP_SPCIE_CAP_OFF + (i * 2), val); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci offset = dw_pcie_find_ext_capability(pci, 8238c2ecf20Sopenharmony_ci PCI_EXT_CAP_ID_PL_16GT) + 8248c2ecf20Sopenharmony_ci PCI_PL_16GT_LE_CTRL; 8258c2ecf20Sopenharmony_ci val = dw_pcie_readb_dbi(pci, offset + i); 8268c2ecf20Sopenharmony_ci val &= ~PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK; 8278c2ecf20Sopenharmony_ci val |= GEN3_GEN4_EQ_PRESET_INIT; 8288c2ecf20Sopenharmony_ci val &= ~PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK; 8298c2ecf20Sopenharmony_ci val |= (GEN3_GEN4_EQ_PRESET_INIT << 8308c2ecf20Sopenharmony_ci PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT); 8318c2ecf20Sopenharmony_ci dw_pcie_writeb_dbi(pci, offset + i, val); 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); 8358c2ecf20Sopenharmony_ci val &= ~GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK; 8368c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF); 8398c2ecf20Sopenharmony_ci val &= ~GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_MASK; 8408c2ecf20Sopenharmony_ci val |= (0x3ff << GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_SHIFT); 8418c2ecf20Sopenharmony_ci val &= ~GEN3_EQ_CONTROL_OFF_FB_MODE_MASK; 8428c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, val); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); 8458c2ecf20Sopenharmony_ci val &= ~GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK; 8468c2ecf20Sopenharmony_ci val |= (0x1 << GEN3_RELATED_OFF_RATE_SHADOW_SEL_SHIFT); 8478c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_EQ_CONTROL_OFF); 8508c2ecf20Sopenharmony_ci val &= ~GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_MASK; 8518c2ecf20Sopenharmony_ci val |= (0x360 << GEN3_EQ_CONTROL_OFF_PSET_REQ_VEC_SHIFT); 8528c2ecf20Sopenharmony_ci val &= ~GEN3_EQ_CONTROL_OFF_FB_MODE_MASK; 8538c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_EQ_CONTROL_OFF, val); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); 8568c2ecf20Sopenharmony_ci val &= ~GEN3_RELATED_OFF_RATE_SHADOW_SEL_MASK; 8578c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); 8588c2ecf20Sopenharmony_ci} 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_cistatic void tegra_pcie_prepare_host(struct pcie_port *pp) 8618c2ecf20Sopenharmony_ci{ 8628c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 8638c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 8648c2ecf20Sopenharmony_ci u32 val; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCI_IO_BASE); 8678c2ecf20Sopenharmony_ci val &= ~(IO_BASE_IO_DECODE | IO_BASE_IO_DECODE_BIT8); 8688c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PCI_IO_BASE, val); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PCI_PREF_MEMORY_BASE); 8718c2ecf20Sopenharmony_ci val |= CFG_PREF_MEM_LIMIT_BASE_MEM_DECODE; 8728c2ecf20Sopenharmony_ci val |= CFG_PREF_MEM_LIMIT_BASE_MEM_LIMIT_DECODE; 8738c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PCI_PREF_MEMORY_BASE, val); 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci /* Enable as 0xFFFF0001 response for CRS */ 8788c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT); 8798c2ecf20Sopenharmony_ci val &= ~(AMBA_ERROR_RESPONSE_CRS_MASK << AMBA_ERROR_RESPONSE_CRS_SHIFT); 8808c2ecf20Sopenharmony_ci val |= (AMBA_ERROR_RESPONSE_CRS_OKAY_FFFF0001 << 8818c2ecf20Sopenharmony_ci AMBA_ERROR_RESPONSE_CRS_SHIFT); 8828c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT, val); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci /* Configure Max lane width from DT */ 8858c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP); 8868c2ecf20Sopenharmony_ci val &= ~PCI_EXP_LNKCAP_MLW; 8878c2ecf20Sopenharmony_ci val |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, pcie->num_lanes); 8888c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP, val); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci config_gen3_gen4_eq_presets(pcie); 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci init_host_aspm(pcie); 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); 8958c2ecf20Sopenharmony_ci val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL; 8968c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (pcie->update_fc_fixup) { 8998c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF); 9008c2ecf20Sopenharmony_ci val |= 0x1 << CFG_TIMER_CTRL_ACK_NAK_SHIFT; 9018c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF, val); 9028c2ecf20Sopenharmony_ci } 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci dw_pcie_setup_rc(pp); 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci /* Assert RST */ 9098c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_PINMUX); 9108c2ecf20Sopenharmony_ci val &= ~APPL_PINMUX_PEX_RST; 9118c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_PINMUX); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci usleep_range(100, 200); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci /* Enable LTSSM */ 9168c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 9178c2ecf20Sopenharmony_ci val |= APPL_CTRL_LTSSM_EN; 9188c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci /* De-assert RST */ 9218c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_PINMUX); 9228c2ecf20Sopenharmony_ci val |= APPL_PINMUX_PEX_RST; 9238c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_PINMUX); 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci msleep(100); 9268c2ecf20Sopenharmony_ci} 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_host_init(struct pcie_port *pp) 9298c2ecf20Sopenharmony_ci{ 9308c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 9318c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 9328c2ecf20Sopenharmony_ci u32 val, tmp, offset, speed; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci pp->bridge->ops = &tegra_pci_ops; 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci tegra_pcie_prepare_host(pp); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (dw_pcie_wait_for_link(pci)) { 9398c2ecf20Sopenharmony_ci /* 9408c2ecf20Sopenharmony_ci * There are some endpoints which can't get the link up if 9418c2ecf20Sopenharmony_ci * root port has Data Link Feature (DLF) enabled. 9428c2ecf20Sopenharmony_ci * Refer Spec rev 4.0 ver 1.0 sec 3.4.2 & 7.7.4 for more info 9438c2ecf20Sopenharmony_ci * on Scaled Flow Control and DLF. 9448c2ecf20Sopenharmony_ci * So, need to confirm that is indeed the case here and attempt 9458c2ecf20Sopenharmony_ci * link up once again with DLF disabled. 9468c2ecf20Sopenharmony_ci */ 9478c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_DEBUG); 9488c2ecf20Sopenharmony_ci val &= APPL_DEBUG_LTSSM_STATE_MASK; 9498c2ecf20Sopenharmony_ci val >>= APPL_DEBUG_LTSSM_STATE_SHIFT; 9508c2ecf20Sopenharmony_ci tmp = appl_readl(pcie, APPL_LINK_STATUS); 9518c2ecf20Sopenharmony_ci tmp &= APPL_LINK_STATUS_RDLH_LINK_UP; 9528c2ecf20Sopenharmony_ci if (!(val == 0x11 && !tmp)) { 9538c2ecf20Sopenharmony_ci /* Link is down for all good reasons */ 9548c2ecf20Sopenharmony_ci return 0; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci dev_info(pci->dev, "Link is down in DLL"); 9588c2ecf20Sopenharmony_ci dev_info(pci->dev, "Trying again with DLFE disabled\n"); 9598c2ecf20Sopenharmony_ci /* Disable LTSSM */ 9608c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 9618c2ecf20Sopenharmony_ci val &= ~APPL_CTRL_LTSSM_EN; 9628c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci reset_control_assert(pcie->core_rst); 9658c2ecf20Sopenharmony_ci reset_control_deassert(pcie->core_rst); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_DLF); 9688c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, offset + PCI_DLF_CAP); 9698c2ecf20Sopenharmony_ci val &= ~PCI_DLF_EXCHANGE_ENABLE; 9708c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, offset + PCI_DLF_CAP, val); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci tegra_pcie_prepare_host(pp); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci if (dw_pcie_wait_for_link(pci)) 9758c2ecf20Sopenharmony_ci return 0; 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci speed = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA) & 9798c2ecf20Sopenharmony_ci PCI_EXP_LNKSTA_CLS; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if (speed >= ARRAY_SIZE(pcie_gen_freq)) 9828c2ecf20Sopenharmony_ci speed = 0; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci clk_set_rate(pcie->core_clk, pcie_gen_freq[speed]); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci tegra_pcie_enable_interrupts(pp); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci return 0; 9898c2ecf20Sopenharmony_ci} 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_link_up(struct dw_pcie *pci) 9928c2ecf20Sopenharmony_ci{ 9938c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 9948c2ecf20Sopenharmony_ci u32 val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci return !!(val & PCI_EXP_LNKSTA_DLLLA); 9978c2ecf20Sopenharmony_ci} 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_cistatic void tegra_pcie_set_msi_vec_num(struct pcie_port *pp) 10008c2ecf20Sopenharmony_ci{ 10018c2ecf20Sopenharmony_ci pp->num_vectors = MAX_MSI_IRQS; 10028c2ecf20Sopenharmony_ci} 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_start_link(struct dw_pcie *pci) 10058c2ecf20Sopenharmony_ci{ 10068c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci enable_irq(pcie->pex_rst_irq); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci return 0; 10118c2ecf20Sopenharmony_ci} 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_cistatic void tegra_pcie_dw_stop_link(struct dw_pcie *pci) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci disable_irq(pcie->pex_rst_irq); 10188c2ecf20Sopenharmony_ci} 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_cistatic const struct dw_pcie_ops tegra_dw_pcie_ops = { 10218c2ecf20Sopenharmony_ci .link_up = tegra_pcie_dw_link_up, 10228c2ecf20Sopenharmony_ci .start_link = tegra_pcie_dw_start_link, 10238c2ecf20Sopenharmony_ci .stop_link = tegra_pcie_dw_stop_link, 10248c2ecf20Sopenharmony_ci}; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_cistatic struct dw_pcie_host_ops tegra_pcie_dw_host_ops = { 10278c2ecf20Sopenharmony_ci .host_init = tegra_pcie_dw_host_init, 10288c2ecf20Sopenharmony_ci .set_num_vectors = tegra_pcie_set_msi_vec_num, 10298c2ecf20Sopenharmony_ci}; 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_cistatic void tegra_pcie_disable_phy(struct tegra_pcie_dw *pcie) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci unsigned int phy_count = pcie->phy_count; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci while (phy_count--) { 10368c2ecf20Sopenharmony_ci phy_power_off(pcie->phys[phy_count]); 10378c2ecf20Sopenharmony_ci phy_exit(pcie->phys[phy_count]); 10388c2ecf20Sopenharmony_ci } 10398c2ecf20Sopenharmony_ci} 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_cistatic int tegra_pcie_enable_phy(struct tegra_pcie_dw *pcie) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci unsigned int i; 10448c2ecf20Sopenharmony_ci int ret; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci for (i = 0; i < pcie->phy_count; i++) { 10478c2ecf20Sopenharmony_ci ret = phy_init(pcie->phys[i]); 10488c2ecf20Sopenharmony_ci if (ret < 0) 10498c2ecf20Sopenharmony_ci goto phy_power_off; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci ret = phy_power_on(pcie->phys[i]); 10528c2ecf20Sopenharmony_ci if (ret < 0) 10538c2ecf20Sopenharmony_ci goto phy_exit; 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci return 0; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ciphy_power_off: 10598c2ecf20Sopenharmony_ci while (i--) { 10608c2ecf20Sopenharmony_ci phy_power_off(pcie->phys[i]); 10618c2ecf20Sopenharmony_ciphy_exit: 10628c2ecf20Sopenharmony_ci phy_exit(pcie->phys[i]); 10638c2ecf20Sopenharmony_ci } 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci return ret; 10668c2ecf20Sopenharmony_ci} 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_parse_dt(struct tegra_pcie_dw *pcie) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci struct device_node *np = pcie->dev->of_node; 10718c2ecf20Sopenharmony_ci int ret; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "nvidia,aspm-cmrt-us", &pcie->aspm_cmrt); 10748c2ecf20Sopenharmony_ci if (ret < 0) { 10758c2ecf20Sopenharmony_ci dev_info(pcie->dev, "Failed to read ASPM T_cmrt: %d\n", ret); 10768c2ecf20Sopenharmony_ci return ret; 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "nvidia,aspm-pwr-on-t-us", 10808c2ecf20Sopenharmony_ci &pcie->aspm_pwr_on_t); 10818c2ecf20Sopenharmony_ci if (ret < 0) 10828c2ecf20Sopenharmony_ci dev_info(pcie->dev, "Failed to read ASPM Power On time: %d\n", 10838c2ecf20Sopenharmony_ci ret); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "nvidia,aspm-l0s-entrance-latency-us", 10868c2ecf20Sopenharmony_ci &pcie->aspm_l0s_enter_lat); 10878c2ecf20Sopenharmony_ci if (ret < 0) 10888c2ecf20Sopenharmony_ci dev_info(pcie->dev, 10898c2ecf20Sopenharmony_ci "Failed to read ASPM L0s Entrance latency: %d\n", ret); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "num-lanes", &pcie->num_lanes); 10928c2ecf20Sopenharmony_ci if (ret < 0) { 10938c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to read num-lanes: %d\n", ret); 10948c2ecf20Sopenharmony_ci return ret; 10958c2ecf20Sopenharmony_ci } 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci ret = of_property_read_u32_index(np, "nvidia,bpmp", 1, &pcie->cid); 10988c2ecf20Sopenharmony_ci if (ret) { 10998c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to read Controller-ID: %d\n", ret); 11008c2ecf20Sopenharmony_ci return ret; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci ret = of_property_count_strings(np, "phy-names"); 11048c2ecf20Sopenharmony_ci if (ret < 0) { 11058c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to find PHY entries: %d\n", 11068c2ecf20Sopenharmony_ci ret); 11078c2ecf20Sopenharmony_ci return ret; 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci pcie->phy_count = ret; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci if (of_property_read_bool(np, "nvidia,update-fc-fixup")) 11128c2ecf20Sopenharmony_ci pcie->update_fc_fixup = true; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci pcie->supports_clkreq = 11158c2ecf20Sopenharmony_ci of_property_read_bool(pcie->dev->of_node, "supports-clkreq"); 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci pcie->enable_cdm_check = 11188c2ecf20Sopenharmony_ci of_property_read_bool(np, "snps,enable-cdm-check"); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci if (pcie->mode == DW_PCIE_RC_TYPE) 11218c2ecf20Sopenharmony_ci return 0; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci /* Endpoint mode specific DT entries */ 11248c2ecf20Sopenharmony_ci pcie->pex_rst_gpiod = devm_gpiod_get(pcie->dev, "reset", GPIOD_IN); 11258c2ecf20Sopenharmony_ci if (IS_ERR(pcie->pex_rst_gpiod)) { 11268c2ecf20Sopenharmony_ci int err = PTR_ERR(pcie->pex_rst_gpiod); 11278c2ecf20Sopenharmony_ci const char *level = KERN_ERR; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci if (err == -EPROBE_DEFER) 11308c2ecf20Sopenharmony_ci level = KERN_DEBUG; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci dev_printk(level, pcie->dev, 11338c2ecf20Sopenharmony_ci dev_fmt("Failed to get PERST GPIO: %d\n"), 11348c2ecf20Sopenharmony_ci err); 11358c2ecf20Sopenharmony_ci return err; 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci pcie->pex_refclk_sel_gpiod = devm_gpiod_get(pcie->dev, 11398c2ecf20Sopenharmony_ci "nvidia,refclk-select", 11408c2ecf20Sopenharmony_ci GPIOD_OUT_HIGH); 11418c2ecf20Sopenharmony_ci if (IS_ERR(pcie->pex_refclk_sel_gpiod)) { 11428c2ecf20Sopenharmony_ci int err = PTR_ERR(pcie->pex_refclk_sel_gpiod); 11438c2ecf20Sopenharmony_ci const char *level = KERN_ERR; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci if (err == -EPROBE_DEFER) 11468c2ecf20Sopenharmony_ci level = KERN_DEBUG; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci dev_printk(level, pcie->dev, 11498c2ecf20Sopenharmony_ci dev_fmt("Failed to get REFCLK select GPIOs: %d\n"), 11508c2ecf20Sopenharmony_ci err); 11518c2ecf20Sopenharmony_ci pcie->pex_refclk_sel_gpiod = NULL; 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci return 0; 11558c2ecf20Sopenharmony_ci} 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_cistatic int tegra_pcie_bpmp_set_ctrl_state(struct tegra_pcie_dw *pcie, 11588c2ecf20Sopenharmony_ci bool enable) 11598c2ecf20Sopenharmony_ci{ 11608c2ecf20Sopenharmony_ci struct mrq_uphy_response resp; 11618c2ecf20Sopenharmony_ci struct tegra_bpmp_message msg; 11628c2ecf20Sopenharmony_ci struct mrq_uphy_request req; 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci /* Controller-5 doesn't need to have its state set by BPMP-FW */ 11658c2ecf20Sopenharmony_ci if (pcie->cid == 5) 11668c2ecf20Sopenharmony_ci return 0; 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci memset(&req, 0, sizeof(req)); 11698c2ecf20Sopenharmony_ci memset(&resp, 0, sizeof(resp)); 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci req.cmd = CMD_UPHY_PCIE_CONTROLLER_STATE; 11728c2ecf20Sopenharmony_ci req.controller_state.pcie_controller = pcie->cid; 11738c2ecf20Sopenharmony_ci req.controller_state.enable = enable; 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_ci memset(&msg, 0, sizeof(msg)); 11768c2ecf20Sopenharmony_ci msg.mrq = MRQ_UPHY; 11778c2ecf20Sopenharmony_ci msg.tx.data = &req; 11788c2ecf20Sopenharmony_ci msg.tx.size = sizeof(req); 11798c2ecf20Sopenharmony_ci msg.rx.data = &resp; 11808c2ecf20Sopenharmony_ci msg.rx.size = sizeof(resp); 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci return tegra_bpmp_transfer(pcie->bpmp, &msg); 11838c2ecf20Sopenharmony_ci} 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_cistatic int tegra_pcie_bpmp_set_pll_state(struct tegra_pcie_dw *pcie, 11868c2ecf20Sopenharmony_ci bool enable) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci struct mrq_uphy_response resp; 11898c2ecf20Sopenharmony_ci struct tegra_bpmp_message msg; 11908c2ecf20Sopenharmony_ci struct mrq_uphy_request req; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci memset(&req, 0, sizeof(req)); 11938c2ecf20Sopenharmony_ci memset(&resp, 0, sizeof(resp)); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (enable) { 11968c2ecf20Sopenharmony_ci req.cmd = CMD_UPHY_PCIE_EP_CONTROLLER_PLL_INIT; 11978c2ecf20Sopenharmony_ci req.ep_ctrlr_pll_init.ep_controller = pcie->cid; 11988c2ecf20Sopenharmony_ci } else { 11998c2ecf20Sopenharmony_ci req.cmd = CMD_UPHY_PCIE_EP_CONTROLLER_PLL_OFF; 12008c2ecf20Sopenharmony_ci req.ep_ctrlr_pll_off.ep_controller = pcie->cid; 12018c2ecf20Sopenharmony_ci } 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci memset(&msg, 0, sizeof(msg)); 12048c2ecf20Sopenharmony_ci msg.mrq = MRQ_UPHY; 12058c2ecf20Sopenharmony_ci msg.tx.data = &req; 12068c2ecf20Sopenharmony_ci msg.tx.size = sizeof(req); 12078c2ecf20Sopenharmony_ci msg.rx.data = &resp; 12088c2ecf20Sopenharmony_ci msg.rx.size = sizeof(resp); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci return tegra_bpmp_transfer(pcie->bpmp, &msg); 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_cistatic void tegra_pcie_downstream_dev_to_D0(struct tegra_pcie_dw *pcie) 12148c2ecf20Sopenharmony_ci{ 12158c2ecf20Sopenharmony_ci struct pcie_port *pp = &pcie->pci.pp; 12168c2ecf20Sopenharmony_ci struct pci_bus *child, *root_bus = NULL; 12178c2ecf20Sopenharmony_ci struct pci_dev *pdev; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci /* 12208c2ecf20Sopenharmony_ci * link doesn't go into L2 state with some of the endpoints with Tegra 12218c2ecf20Sopenharmony_ci * if they are not in D0 state. So, need to make sure that immediate 12228c2ecf20Sopenharmony_ci * downstream devices are in D0 state before sending PME_TurnOff to put 12238c2ecf20Sopenharmony_ci * link into L2 state. 12248c2ecf20Sopenharmony_ci * This is as per PCI Express Base r4.0 v1.0 September 27-2017, 12258c2ecf20Sopenharmony_ci * 5.2 Link State Power Management (Page #428). 12268c2ecf20Sopenharmony_ci */ 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci list_for_each_entry(child, &pp->bridge->bus->children, node) { 12298c2ecf20Sopenharmony_ci /* Bring downstream devices to D0 if they are not already in */ 12308c2ecf20Sopenharmony_ci if (child->parent == pp->bridge->bus) { 12318c2ecf20Sopenharmony_ci root_bus = child; 12328c2ecf20Sopenharmony_ci break; 12338c2ecf20Sopenharmony_ci } 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci if (!root_bus) { 12378c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to find downstream devices\n"); 12388c2ecf20Sopenharmony_ci return; 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci list_for_each_entry(pdev, &root_bus->devices, bus_list) { 12428c2ecf20Sopenharmony_ci if (PCI_SLOT(pdev->devfn) == 0) { 12438c2ecf20Sopenharmony_ci if (pci_set_power_state(pdev, PCI_D0)) 12448c2ecf20Sopenharmony_ci dev_err(pcie->dev, 12458c2ecf20Sopenharmony_ci "Failed to transition %s to D0 state\n", 12468c2ecf20Sopenharmony_ci dev_name(&pdev->dev)); 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci} 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_cistatic int tegra_pcie_get_slot_regulators(struct tegra_pcie_dw *pcie) 12528c2ecf20Sopenharmony_ci{ 12538c2ecf20Sopenharmony_ci pcie->slot_ctl_3v3 = devm_regulator_get_optional(pcie->dev, "vpcie3v3"); 12548c2ecf20Sopenharmony_ci if (IS_ERR(pcie->slot_ctl_3v3)) { 12558c2ecf20Sopenharmony_ci if (PTR_ERR(pcie->slot_ctl_3v3) != -ENODEV) 12568c2ecf20Sopenharmony_ci return PTR_ERR(pcie->slot_ctl_3v3); 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci pcie->slot_ctl_3v3 = NULL; 12598c2ecf20Sopenharmony_ci } 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci pcie->slot_ctl_12v = devm_regulator_get_optional(pcie->dev, "vpcie12v"); 12628c2ecf20Sopenharmony_ci if (IS_ERR(pcie->slot_ctl_12v)) { 12638c2ecf20Sopenharmony_ci if (PTR_ERR(pcie->slot_ctl_12v) != -ENODEV) 12648c2ecf20Sopenharmony_ci return PTR_ERR(pcie->slot_ctl_12v); 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci pcie->slot_ctl_12v = NULL; 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci return 0; 12708c2ecf20Sopenharmony_ci} 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_cistatic int tegra_pcie_enable_slot_regulators(struct tegra_pcie_dw *pcie) 12738c2ecf20Sopenharmony_ci{ 12748c2ecf20Sopenharmony_ci int ret; 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci if (pcie->slot_ctl_3v3) { 12778c2ecf20Sopenharmony_ci ret = regulator_enable(pcie->slot_ctl_3v3); 12788c2ecf20Sopenharmony_ci if (ret < 0) { 12798c2ecf20Sopenharmony_ci dev_err(pcie->dev, 12808c2ecf20Sopenharmony_ci "Failed to enable 3.3V slot supply: %d\n", ret); 12818c2ecf20Sopenharmony_ci return ret; 12828c2ecf20Sopenharmony_ci } 12838c2ecf20Sopenharmony_ci } 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci if (pcie->slot_ctl_12v) { 12868c2ecf20Sopenharmony_ci ret = regulator_enable(pcie->slot_ctl_12v); 12878c2ecf20Sopenharmony_ci if (ret < 0) { 12888c2ecf20Sopenharmony_ci dev_err(pcie->dev, 12898c2ecf20Sopenharmony_ci "Failed to enable 12V slot supply: %d\n", ret); 12908c2ecf20Sopenharmony_ci goto fail_12v_enable; 12918c2ecf20Sopenharmony_ci } 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci /* 12958c2ecf20Sopenharmony_ci * According to PCI Express Card Electromechanical Specification 12968c2ecf20Sopenharmony_ci * Revision 1.1, Table-2.4, T_PVPERL (Power stable to PERST# inactive) 12978c2ecf20Sopenharmony_ci * should be a minimum of 100ms. 12988c2ecf20Sopenharmony_ci */ 12998c2ecf20Sopenharmony_ci if (pcie->slot_ctl_3v3 || pcie->slot_ctl_12v) 13008c2ecf20Sopenharmony_ci msleep(100); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci return 0; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_cifail_12v_enable: 13058c2ecf20Sopenharmony_ci if (pcie->slot_ctl_3v3) 13068c2ecf20Sopenharmony_ci regulator_disable(pcie->slot_ctl_3v3); 13078c2ecf20Sopenharmony_ci return ret; 13088c2ecf20Sopenharmony_ci} 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_cistatic void tegra_pcie_disable_slot_regulators(struct tegra_pcie_dw *pcie) 13118c2ecf20Sopenharmony_ci{ 13128c2ecf20Sopenharmony_ci if (pcie->slot_ctl_12v) 13138c2ecf20Sopenharmony_ci regulator_disable(pcie->slot_ctl_12v); 13148c2ecf20Sopenharmony_ci if (pcie->slot_ctl_3v3) 13158c2ecf20Sopenharmony_ci regulator_disable(pcie->slot_ctl_3v3); 13168c2ecf20Sopenharmony_ci} 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_cistatic int tegra_pcie_config_controller(struct tegra_pcie_dw *pcie, 13198c2ecf20Sopenharmony_ci bool en_hw_hot_rst) 13208c2ecf20Sopenharmony_ci{ 13218c2ecf20Sopenharmony_ci int ret; 13228c2ecf20Sopenharmony_ci u32 val; 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci ret = tegra_pcie_bpmp_set_ctrl_state(pcie, true); 13258c2ecf20Sopenharmony_ci if (ret) { 13268c2ecf20Sopenharmony_ci dev_err(pcie->dev, 13278c2ecf20Sopenharmony_ci "Failed to enable controller %u: %d\n", pcie->cid, ret); 13288c2ecf20Sopenharmony_ci return ret; 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci ret = tegra_pcie_enable_slot_regulators(pcie); 13328c2ecf20Sopenharmony_ci if (ret < 0) 13338c2ecf20Sopenharmony_ci goto fail_slot_reg_en; 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci ret = regulator_enable(pcie->pex_ctl_supply); 13368c2ecf20Sopenharmony_ci if (ret < 0) { 13378c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to enable regulator: %d\n", ret); 13388c2ecf20Sopenharmony_ci goto fail_reg_en; 13398c2ecf20Sopenharmony_ci } 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci ret = clk_prepare_enable(pcie->core_clk); 13428c2ecf20Sopenharmony_ci if (ret) { 13438c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to enable core clock: %d\n", ret); 13448c2ecf20Sopenharmony_ci goto fail_core_clk; 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci ret = reset_control_deassert(pcie->core_apb_rst); 13488c2ecf20Sopenharmony_ci if (ret) { 13498c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to deassert core APB reset: %d\n", 13508c2ecf20Sopenharmony_ci ret); 13518c2ecf20Sopenharmony_ci goto fail_core_apb_rst; 13528c2ecf20Sopenharmony_ci } 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci if (en_hw_hot_rst) { 13558c2ecf20Sopenharmony_ci /* Enable HW_HOT_RST mode */ 13568c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 13578c2ecf20Sopenharmony_ci val &= ~(APPL_CTRL_HW_HOT_RST_MODE_MASK << 13588c2ecf20Sopenharmony_ci APPL_CTRL_HW_HOT_RST_MODE_SHIFT); 13598c2ecf20Sopenharmony_ci val |= APPL_CTRL_HW_HOT_RST_EN; 13608c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 13618c2ecf20Sopenharmony_ci } 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci ret = tegra_pcie_enable_phy(pcie); 13648c2ecf20Sopenharmony_ci if (ret) { 13658c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to enable PHY: %d\n", ret); 13668c2ecf20Sopenharmony_ci goto fail_phy; 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci /* Update CFG base address */ 13708c2ecf20Sopenharmony_ci appl_writel(pcie, pcie->dbi_res->start & APPL_CFG_BASE_ADDR_MASK, 13718c2ecf20Sopenharmony_ci APPL_CFG_BASE_ADDR); 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci /* Configure this core for RP mode operation */ 13748c2ecf20Sopenharmony_ci appl_writel(pcie, APPL_DM_TYPE_RP, APPL_DM_TYPE); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci appl_writel(pcie, 0x0, APPL_CFG_SLCG_OVERRIDE); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 13798c2ecf20Sopenharmony_ci appl_writel(pcie, val | APPL_CTRL_SYS_PRE_DET_STATE, APPL_CTRL); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CFG_MISC); 13828c2ecf20Sopenharmony_ci val |= (APPL_CFG_MISC_ARCACHE_VAL << APPL_CFG_MISC_ARCACHE_SHIFT); 13838c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CFG_MISC); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci if (!pcie->supports_clkreq) { 13868c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_PINMUX); 13878c2ecf20Sopenharmony_ci val |= APPL_PINMUX_CLKREQ_OVERRIDE_EN; 13888c2ecf20Sopenharmony_ci val &= ~APPL_PINMUX_CLKREQ_OVERRIDE; 13898c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_PINMUX); 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci /* Update iATU_DMA base address */ 13938c2ecf20Sopenharmony_ci appl_writel(pcie, 13948c2ecf20Sopenharmony_ci pcie->atu_dma_res->start & APPL_CFG_IATU_DMA_BASE_ADDR_MASK, 13958c2ecf20Sopenharmony_ci APPL_CFG_IATU_DMA_BASE_ADDR); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci reset_control_deassert(pcie->core_rst); 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci, 14008c2ecf20Sopenharmony_ci PCI_CAP_ID_EXP); 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci /* Disable ASPM-L1SS advertisement as there is no CLKREQ routing */ 14038c2ecf20Sopenharmony_ci if (!pcie->supports_clkreq) { 14048c2ecf20Sopenharmony_ci disable_aspm_l11(pcie); 14058c2ecf20Sopenharmony_ci disable_aspm_l12(pcie); 14068c2ecf20Sopenharmony_ci } 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci return ret; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_cifail_phy: 14118c2ecf20Sopenharmony_ci reset_control_assert(pcie->core_apb_rst); 14128c2ecf20Sopenharmony_cifail_core_apb_rst: 14138c2ecf20Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 14148c2ecf20Sopenharmony_cifail_core_clk: 14158c2ecf20Sopenharmony_ci regulator_disable(pcie->pex_ctl_supply); 14168c2ecf20Sopenharmony_cifail_reg_en: 14178c2ecf20Sopenharmony_ci tegra_pcie_disable_slot_regulators(pcie); 14188c2ecf20Sopenharmony_cifail_slot_reg_en: 14198c2ecf20Sopenharmony_ci tegra_pcie_bpmp_set_ctrl_state(pcie, false); 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci return ret; 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic int __deinit_controller(struct tegra_pcie_dw *pcie) 14258c2ecf20Sopenharmony_ci{ 14268c2ecf20Sopenharmony_ci int ret; 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci ret = reset_control_assert(pcie->core_rst); 14298c2ecf20Sopenharmony_ci if (ret) { 14308c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to assert \"core\" reset: %d\n", 14318c2ecf20Sopenharmony_ci ret); 14328c2ecf20Sopenharmony_ci return ret; 14338c2ecf20Sopenharmony_ci } 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci tegra_pcie_disable_phy(pcie); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci ret = reset_control_assert(pcie->core_apb_rst); 14388c2ecf20Sopenharmony_ci if (ret) { 14398c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to assert APB reset: %d\n", ret); 14408c2ecf20Sopenharmony_ci return ret; 14418c2ecf20Sopenharmony_ci } 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci ret = regulator_disable(pcie->pex_ctl_supply); 14468c2ecf20Sopenharmony_ci if (ret) { 14478c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to disable regulator: %d\n", ret); 14488c2ecf20Sopenharmony_ci return ret; 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci tegra_pcie_disable_slot_regulators(pcie); 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci ret = tegra_pcie_bpmp_set_ctrl_state(pcie, false); 14548c2ecf20Sopenharmony_ci if (ret) { 14558c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to disable controller %d: %d\n", 14568c2ecf20Sopenharmony_ci pcie->cid, ret); 14578c2ecf20Sopenharmony_ci return ret; 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci return ret; 14618c2ecf20Sopenharmony_ci} 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_cistatic int tegra_pcie_init_controller(struct tegra_pcie_dw *pcie) 14648c2ecf20Sopenharmony_ci{ 14658c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 14668c2ecf20Sopenharmony_ci struct pcie_port *pp = &pci->pp; 14678c2ecf20Sopenharmony_ci int ret; 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci ret = tegra_pcie_config_controller(pcie, false); 14708c2ecf20Sopenharmony_ci if (ret < 0) 14718c2ecf20Sopenharmony_ci return ret; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci pp->ops = &tegra_pcie_dw_host_ops; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci ret = dw_pcie_host_init(pp); 14768c2ecf20Sopenharmony_ci if (ret < 0) { 14778c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to add PCIe port: %d\n", ret); 14788c2ecf20Sopenharmony_ci goto fail_host_init; 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci return 0; 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_cifail_host_init: 14848c2ecf20Sopenharmony_ci return __deinit_controller(pcie); 14858c2ecf20Sopenharmony_ci} 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic int tegra_pcie_try_link_l2(struct tegra_pcie_dw *pcie) 14888c2ecf20Sopenharmony_ci{ 14898c2ecf20Sopenharmony_ci u32 val; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci if (!tegra_pcie_dw_link_up(&pcie->pci)) 14928c2ecf20Sopenharmony_ci return 0; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_RADM_STATUS); 14958c2ecf20Sopenharmony_ci val |= APPL_PM_XMT_TURNOFF_STATE; 14968c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_RADM_STATUS); 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci return readl_poll_timeout_atomic(pcie->appl_base + APPL_DEBUG, val, 14998c2ecf20Sopenharmony_ci val & APPL_DEBUG_PM_LINKST_IN_L2_LAT, 15008c2ecf20Sopenharmony_ci 1, PME_ACK_TIMEOUT); 15018c2ecf20Sopenharmony_ci} 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_cistatic void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie) 15048c2ecf20Sopenharmony_ci{ 15058c2ecf20Sopenharmony_ci u32 data; 15068c2ecf20Sopenharmony_ci int err; 15078c2ecf20Sopenharmony_ci 15088c2ecf20Sopenharmony_ci if (!tegra_pcie_dw_link_up(&pcie->pci)) { 15098c2ecf20Sopenharmony_ci dev_dbg(pcie->dev, "PCIe link is not up...!\n"); 15108c2ecf20Sopenharmony_ci return; 15118c2ecf20Sopenharmony_ci } 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_ci if (tegra_pcie_try_link_l2(pcie)) { 15148c2ecf20Sopenharmony_ci dev_info(pcie->dev, "Link didn't transition to L2 state\n"); 15158c2ecf20Sopenharmony_ci /* 15168c2ecf20Sopenharmony_ci * TX lane clock freq will reset to Gen1 only if link is in L2 15178c2ecf20Sopenharmony_ci * or detect state. 15188c2ecf20Sopenharmony_ci * So apply pex_rst to end point to force RP to go into detect 15198c2ecf20Sopenharmony_ci * state 15208c2ecf20Sopenharmony_ci */ 15218c2ecf20Sopenharmony_ci data = appl_readl(pcie, APPL_PINMUX); 15228c2ecf20Sopenharmony_ci data &= ~APPL_PINMUX_PEX_RST; 15238c2ecf20Sopenharmony_ci appl_writel(pcie, data, APPL_PINMUX); 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci err = readl_poll_timeout_atomic(pcie->appl_base + APPL_DEBUG, 15268c2ecf20Sopenharmony_ci data, 15278c2ecf20Sopenharmony_ci ((data & 15288c2ecf20Sopenharmony_ci APPL_DEBUG_LTSSM_STATE_MASK) >> 15298c2ecf20Sopenharmony_ci APPL_DEBUG_LTSSM_STATE_SHIFT) == 15308c2ecf20Sopenharmony_ci LTSSM_STATE_PRE_DETECT, 15318c2ecf20Sopenharmony_ci 1, LTSSM_TIMEOUT); 15328c2ecf20Sopenharmony_ci if (err) { 15338c2ecf20Sopenharmony_ci dev_info(pcie->dev, "Link didn't go to detect state\n"); 15348c2ecf20Sopenharmony_ci } else { 15358c2ecf20Sopenharmony_ci /* Disable LTSSM after link is in detect state */ 15368c2ecf20Sopenharmony_ci data = appl_readl(pcie, APPL_CTRL); 15378c2ecf20Sopenharmony_ci data &= ~APPL_CTRL_LTSSM_EN; 15388c2ecf20Sopenharmony_ci appl_writel(pcie, data, APPL_CTRL); 15398c2ecf20Sopenharmony_ci } 15408c2ecf20Sopenharmony_ci } 15418c2ecf20Sopenharmony_ci /* 15428c2ecf20Sopenharmony_ci * DBI registers may not be accessible after this as PLL-E would be 15438c2ecf20Sopenharmony_ci * down depending on how CLKREQ is pulled by end point 15448c2ecf20Sopenharmony_ci */ 15458c2ecf20Sopenharmony_ci data = appl_readl(pcie, APPL_PINMUX); 15468c2ecf20Sopenharmony_ci data |= (APPL_PINMUX_CLKREQ_OVERRIDE_EN | APPL_PINMUX_CLKREQ_OVERRIDE); 15478c2ecf20Sopenharmony_ci /* Cut REFCLK to slot */ 15488c2ecf20Sopenharmony_ci data |= APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE_EN; 15498c2ecf20Sopenharmony_ci data &= ~APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE; 15508c2ecf20Sopenharmony_ci appl_writel(pcie, data, APPL_PINMUX); 15518c2ecf20Sopenharmony_ci} 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_cistatic int tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie) 15548c2ecf20Sopenharmony_ci{ 15558c2ecf20Sopenharmony_ci tegra_pcie_downstream_dev_to_D0(pcie); 15568c2ecf20Sopenharmony_ci dw_pcie_host_deinit(&pcie->pci.pp); 15578c2ecf20Sopenharmony_ci tegra_pcie_dw_pme_turnoff(pcie); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci return __deinit_controller(pcie); 15608c2ecf20Sopenharmony_ci} 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_cistatic int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) 15638c2ecf20Sopenharmony_ci{ 15648c2ecf20Sopenharmony_ci struct pcie_port *pp = &pcie->pci.pp; 15658c2ecf20Sopenharmony_ci struct device *dev = pcie->dev; 15668c2ecf20Sopenharmony_ci char *name; 15678c2ecf20Sopenharmony_ci int ret; 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PCI_MSI)) { 15708c2ecf20Sopenharmony_ci pp->msi_irq = of_irq_get_byname(dev->of_node, "msi"); 15718c2ecf20Sopenharmony_ci if (!pp->msi_irq) { 15728c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get MSI interrupt\n"); 15738c2ecf20Sopenharmony_ci return -ENODEV; 15748c2ecf20Sopenharmony_ci } 15758c2ecf20Sopenharmony_ci } 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci ret = pm_runtime_get_sync(dev); 15808c2ecf20Sopenharmony_ci if (ret < 0) { 15818c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get runtime sync for PCIe dev: %d\n", 15828c2ecf20Sopenharmony_ci ret); 15838c2ecf20Sopenharmony_ci goto fail_pm_get_sync; 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci ret = pinctrl_pm_select_default_state(dev); 15878c2ecf20Sopenharmony_ci if (ret < 0) { 15888c2ecf20Sopenharmony_ci dev_err(dev, "Failed to configure sideband pins: %d\n", ret); 15898c2ecf20Sopenharmony_ci goto fail_pm_get_sync; 15908c2ecf20Sopenharmony_ci } 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci tegra_pcie_init_controller(pcie); 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci pcie->link_state = tegra_pcie_dw_link_up(&pcie->pci); 15958c2ecf20Sopenharmony_ci if (!pcie->link_state) { 15968c2ecf20Sopenharmony_ci ret = -ENOMEDIUM; 15978c2ecf20Sopenharmony_ci goto fail_host_init; 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); 16018c2ecf20Sopenharmony_ci if (!name) { 16028c2ecf20Sopenharmony_ci ret = -ENOMEM; 16038c2ecf20Sopenharmony_ci goto fail_host_init; 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci pcie->debugfs = debugfs_create_dir(name, NULL); 16078c2ecf20Sopenharmony_ci init_debugfs(pcie); 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci return ret; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_cifail_host_init: 16128c2ecf20Sopenharmony_ci tegra_pcie_deinit_controller(pcie); 16138c2ecf20Sopenharmony_cifail_pm_get_sync: 16148c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev); 16158c2ecf20Sopenharmony_ci pm_runtime_disable(dev); 16168c2ecf20Sopenharmony_ci return ret; 16178c2ecf20Sopenharmony_ci} 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_cistatic void pex_ep_event_pex_rst_assert(struct tegra_pcie_dw *pcie) 16208c2ecf20Sopenharmony_ci{ 16218c2ecf20Sopenharmony_ci u32 val; 16228c2ecf20Sopenharmony_ci int ret; 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci if (pcie->ep_state == EP_STATE_DISABLED) 16258c2ecf20Sopenharmony_ci return; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci /* Disable LTSSM */ 16288c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 16298c2ecf20Sopenharmony_ci val &= ~APPL_CTRL_LTSSM_EN; 16308c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci ret = readl_poll_timeout(pcie->appl_base + APPL_DEBUG, val, 16338c2ecf20Sopenharmony_ci ((val & APPL_DEBUG_LTSSM_STATE_MASK) >> 16348c2ecf20Sopenharmony_ci APPL_DEBUG_LTSSM_STATE_SHIFT) == 16358c2ecf20Sopenharmony_ci LTSSM_STATE_PRE_DETECT, 16368c2ecf20Sopenharmony_ci 1, LTSSM_TIMEOUT); 16378c2ecf20Sopenharmony_ci if (ret) 16388c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to go Detect state: %d\n", ret); 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci reset_control_assert(pcie->core_rst); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci tegra_pcie_disable_phy(pcie); 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci reset_control_assert(pcie->core_apb_rst); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci pm_runtime_put_sync(pcie->dev); 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci ret = tegra_pcie_bpmp_set_pll_state(pcie, false); 16518c2ecf20Sopenharmony_ci if (ret) 16528c2ecf20Sopenharmony_ci dev_err(pcie->dev, "Failed to turn off UPHY: %d\n", ret); 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci pcie->ep_state = EP_STATE_DISABLED; 16558c2ecf20Sopenharmony_ci dev_dbg(pcie->dev, "Uninitialization of endpoint is completed\n"); 16568c2ecf20Sopenharmony_ci} 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_cistatic void pex_ep_event_pex_rst_deassert(struct tegra_pcie_dw *pcie) 16598c2ecf20Sopenharmony_ci{ 16608c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 16618c2ecf20Sopenharmony_ci struct dw_pcie_ep *ep = &pci->ep; 16628c2ecf20Sopenharmony_ci struct device *dev = pcie->dev; 16638c2ecf20Sopenharmony_ci u32 val; 16648c2ecf20Sopenharmony_ci int ret; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci if (pcie->ep_state == EP_STATE_ENABLED) 16678c2ecf20Sopenharmony_ci return; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 16708c2ecf20Sopenharmony_ci if (ret < 0) { 16718c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get runtime sync for PCIe dev: %d\n", 16728c2ecf20Sopenharmony_ci ret); 16738c2ecf20Sopenharmony_ci return; 16748c2ecf20Sopenharmony_ci } 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci ret = tegra_pcie_bpmp_set_pll_state(pcie, true); 16778c2ecf20Sopenharmony_ci if (ret) { 16788c2ecf20Sopenharmony_ci dev_err(dev, "Failed to init UPHY for PCIe EP: %d\n", ret); 16798c2ecf20Sopenharmony_ci goto fail_pll_init; 16808c2ecf20Sopenharmony_ci } 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci ret = clk_prepare_enable(pcie->core_clk); 16838c2ecf20Sopenharmony_ci if (ret) { 16848c2ecf20Sopenharmony_ci dev_err(dev, "Failed to enable core clock: %d\n", ret); 16858c2ecf20Sopenharmony_ci goto fail_core_clk_enable; 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci ret = reset_control_deassert(pcie->core_apb_rst); 16898c2ecf20Sopenharmony_ci if (ret) { 16908c2ecf20Sopenharmony_ci dev_err(dev, "Failed to deassert core APB reset: %d\n", ret); 16918c2ecf20Sopenharmony_ci goto fail_core_apb_rst; 16928c2ecf20Sopenharmony_ci } 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_ci ret = tegra_pcie_enable_phy(pcie); 16958c2ecf20Sopenharmony_ci if (ret) { 16968c2ecf20Sopenharmony_ci dev_err(dev, "Failed to enable PHY: %d\n", ret); 16978c2ecf20Sopenharmony_ci goto fail_phy; 16988c2ecf20Sopenharmony_ci } 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci /* Clear any stale interrupt statuses */ 17018c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L0); 17028c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_0_0); 17038c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_1); 17048c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_2); 17058c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_3); 17068c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_6); 17078c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_7); 17088c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_8_0); 17098c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_9); 17108c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_10); 17118c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_11); 17128c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_13); 17138c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_14); 17148c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_15); 17158c2ecf20Sopenharmony_ci appl_writel(pcie, 0xFFFFFFFF, APPL_INTR_STATUS_L1_17); 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci /* configure this core for EP mode operation */ 17188c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_DM_TYPE); 17198c2ecf20Sopenharmony_ci val &= ~APPL_DM_TYPE_MASK; 17208c2ecf20Sopenharmony_ci val |= APPL_DM_TYPE_EP; 17218c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_DM_TYPE); 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci appl_writel(pcie, 0x0, APPL_CFG_SLCG_OVERRIDE); 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 17268c2ecf20Sopenharmony_ci val |= APPL_CTRL_SYS_PRE_DET_STATE; 17278c2ecf20Sopenharmony_ci val |= APPL_CTRL_HW_HOT_RST_EN; 17288c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CFG_MISC); 17318c2ecf20Sopenharmony_ci val |= APPL_CFG_MISC_SLV_EP_MODE; 17328c2ecf20Sopenharmony_ci val |= (APPL_CFG_MISC_ARCACHE_VAL << APPL_CFG_MISC_ARCACHE_SHIFT); 17338c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CFG_MISC); 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_PINMUX); 17368c2ecf20Sopenharmony_ci val |= APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE_EN; 17378c2ecf20Sopenharmony_ci val |= APPL_PINMUX_CLK_OUTPUT_IN_OVERRIDE; 17388c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_PINMUX); 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci appl_writel(pcie, pcie->dbi_res->start & APPL_CFG_BASE_ADDR_MASK, 17418c2ecf20Sopenharmony_ci APPL_CFG_BASE_ADDR); 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci appl_writel(pcie, pcie->atu_dma_res->start & 17448c2ecf20Sopenharmony_ci APPL_CFG_IATU_DMA_BASE_ADDR_MASK, 17458c2ecf20Sopenharmony_ci APPL_CFG_IATU_DMA_BASE_ADDR); 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L0_0); 17488c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_SYS_INTR_EN; 17498c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_LINK_STATE_INT_EN; 17508c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L0_0_PCI_CMD_EN_INT_EN; 17518c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L0_0); 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_INTR_EN_L1_0_0); 17548c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_0_0_HOT_RESET_DONE_INT_EN; 17558c2ecf20Sopenharmony_ci val |= APPL_INTR_EN_L1_0_0_RDLH_LINK_UP_INT_EN; 17568c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_INTR_EN_L1_0_0); 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci reset_control_deassert(pcie->core_rst); 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci if (pcie->update_fc_fixup) { 17618c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF); 17628c2ecf20Sopenharmony_ci val |= 0x1 << CFG_TIMER_CTRL_ACK_NAK_SHIFT; 17638c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF, val); 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci config_gen3_gen4_eq_presets(pcie); 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_ci init_host_aspm(pcie); 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci /* Disable ASPM-L1SS advertisement if there is no CLKREQ routing */ 17718c2ecf20Sopenharmony_ci if (!pcie->supports_clkreq) { 17728c2ecf20Sopenharmony_ci disable_aspm_l11(pcie); 17738c2ecf20Sopenharmony_ci disable_aspm_l12(pcie); 17748c2ecf20Sopenharmony_ci } 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); 17778c2ecf20Sopenharmony_ci val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL; 17788c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci, 17818c2ecf20Sopenharmony_ci PCI_CAP_ID_EXP); 17828c2ecf20Sopenharmony_ci clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ); 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci val = (ep->msi_mem_phys & MSIX_ADDR_MATCH_LOW_OFF_MASK); 17858c2ecf20Sopenharmony_ci val |= MSIX_ADDR_MATCH_LOW_OFF_EN; 17868c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, MSIX_ADDR_MATCH_LOW_OFF, val); 17878c2ecf20Sopenharmony_ci val = (upper_32_bits(ep->msi_mem_phys) & MSIX_ADDR_MATCH_HIGH_OFF_MASK); 17888c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(pci, MSIX_ADDR_MATCH_HIGH_OFF, val); 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci ret = dw_pcie_ep_init_complete(ep); 17918c2ecf20Sopenharmony_ci if (ret) { 17928c2ecf20Sopenharmony_ci dev_err(dev, "Failed to complete initialization: %d\n", ret); 17938c2ecf20Sopenharmony_ci goto fail_init_complete; 17948c2ecf20Sopenharmony_ci } 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci dw_pcie_ep_init_notify(ep); 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci /* Enable LTSSM */ 17998c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 18008c2ecf20Sopenharmony_ci val |= APPL_CTRL_LTSSM_EN; 18018c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci pcie->ep_state = EP_STATE_ENABLED; 18048c2ecf20Sopenharmony_ci dev_dbg(dev, "Initialization of endpoint is completed\n"); 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci return; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_cifail_init_complete: 18098c2ecf20Sopenharmony_ci reset_control_assert(pcie->core_rst); 18108c2ecf20Sopenharmony_ci tegra_pcie_disable_phy(pcie); 18118c2ecf20Sopenharmony_cifail_phy: 18128c2ecf20Sopenharmony_ci reset_control_assert(pcie->core_apb_rst); 18138c2ecf20Sopenharmony_cifail_core_apb_rst: 18148c2ecf20Sopenharmony_ci clk_disable_unprepare(pcie->core_clk); 18158c2ecf20Sopenharmony_cifail_core_clk_enable: 18168c2ecf20Sopenharmony_ci tegra_pcie_bpmp_set_pll_state(pcie, false); 18178c2ecf20Sopenharmony_cifail_pll_init: 18188c2ecf20Sopenharmony_ci pm_runtime_put_sync(dev); 18198c2ecf20Sopenharmony_ci} 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic irqreturn_t tegra_pcie_ep_pex_rst_irq(int irq, void *arg) 18228c2ecf20Sopenharmony_ci{ 18238c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = arg; 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci if (gpiod_get_value(pcie->pex_rst_gpiod)) 18268c2ecf20Sopenharmony_ci pex_ep_event_pex_rst_assert(pcie); 18278c2ecf20Sopenharmony_ci else 18288c2ecf20Sopenharmony_ci pex_ep_event_pex_rst_deassert(pcie); 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci return IRQ_HANDLED; 18318c2ecf20Sopenharmony_ci} 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_cistatic int tegra_pcie_ep_raise_legacy_irq(struct tegra_pcie_dw *pcie, u16 irq) 18348c2ecf20Sopenharmony_ci{ 18358c2ecf20Sopenharmony_ci /* Tegra194 supports only INTA */ 18368c2ecf20Sopenharmony_ci if (irq > 1) 18378c2ecf20Sopenharmony_ci return -EINVAL; 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci appl_writel(pcie, 1, APPL_LEGACY_INTX); 18408c2ecf20Sopenharmony_ci usleep_range(1000, 2000); 18418c2ecf20Sopenharmony_ci appl_writel(pcie, 0, APPL_LEGACY_INTX); 18428c2ecf20Sopenharmony_ci return 0; 18438c2ecf20Sopenharmony_ci} 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_cistatic int tegra_pcie_ep_raise_msi_irq(struct tegra_pcie_dw *pcie, u16 irq) 18468c2ecf20Sopenharmony_ci{ 18478c2ecf20Sopenharmony_ci if (unlikely(irq > 31)) 18488c2ecf20Sopenharmony_ci return -EINVAL; 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci appl_writel(pcie, BIT(irq), APPL_MSI_CTRL_1); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci return 0; 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int tegra_pcie_ep_raise_msix_irq(struct tegra_pcie_dw *pcie, u16 irq) 18568c2ecf20Sopenharmony_ci{ 18578c2ecf20Sopenharmony_ci struct dw_pcie_ep *ep = &pcie->pci.ep; 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci writel(irq, ep->msi_mem); 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci return 0; 18628c2ecf20Sopenharmony_ci} 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_cistatic int tegra_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 18658c2ecf20Sopenharmony_ci enum pci_epc_irq_type type, 18668c2ecf20Sopenharmony_ci u16 interrupt_num) 18678c2ecf20Sopenharmony_ci{ 18688c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 18698c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci switch (type) { 18728c2ecf20Sopenharmony_ci case PCI_EPC_IRQ_LEGACY: 18738c2ecf20Sopenharmony_ci return tegra_pcie_ep_raise_legacy_irq(pcie, interrupt_num); 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci case PCI_EPC_IRQ_MSI: 18768c2ecf20Sopenharmony_ci return tegra_pcie_ep_raise_msi_irq(pcie, interrupt_num); 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci case PCI_EPC_IRQ_MSIX: 18798c2ecf20Sopenharmony_ci return tegra_pcie_ep_raise_msix_irq(pcie, interrupt_num); 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci default: 18828c2ecf20Sopenharmony_ci dev_err(pci->dev, "Unknown IRQ type\n"); 18838c2ecf20Sopenharmony_ci return -EPERM; 18848c2ecf20Sopenharmony_ci } 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci return 0; 18878c2ecf20Sopenharmony_ci} 18888c2ecf20Sopenharmony_ci 18898c2ecf20Sopenharmony_cistatic const struct pci_epc_features tegra_pcie_epc_features = { 18908c2ecf20Sopenharmony_ci .linkup_notifier = true, 18918c2ecf20Sopenharmony_ci .core_init_notifier = true, 18928c2ecf20Sopenharmony_ci .msi_capable = false, 18938c2ecf20Sopenharmony_ci .msix_capable = false, 18948c2ecf20Sopenharmony_ci .reserved_bar = 1 << BAR_2 | 1 << BAR_3 | 1 << BAR_4 | 1 << BAR_5, 18958c2ecf20Sopenharmony_ci .bar_fixed_64bit = 1 << BAR_0, 18968c2ecf20Sopenharmony_ci .bar_fixed_size[0] = SZ_1M, 18978c2ecf20Sopenharmony_ci}; 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_cistatic const struct pci_epc_features* 19008c2ecf20Sopenharmony_citegra_pcie_ep_get_features(struct dw_pcie_ep *ep) 19018c2ecf20Sopenharmony_ci{ 19028c2ecf20Sopenharmony_ci return &tegra_pcie_epc_features; 19038c2ecf20Sopenharmony_ci} 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_cistatic struct dw_pcie_ep_ops pcie_ep_ops = { 19068c2ecf20Sopenharmony_ci .raise_irq = tegra_pcie_ep_raise_irq, 19078c2ecf20Sopenharmony_ci .get_features = tegra_pcie_ep_get_features, 19088c2ecf20Sopenharmony_ci}; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_cistatic int tegra_pcie_config_ep(struct tegra_pcie_dw *pcie, 19118c2ecf20Sopenharmony_ci struct platform_device *pdev) 19128c2ecf20Sopenharmony_ci{ 19138c2ecf20Sopenharmony_ci struct dw_pcie *pci = &pcie->pci; 19148c2ecf20Sopenharmony_ci struct device *dev = pcie->dev; 19158c2ecf20Sopenharmony_ci struct dw_pcie_ep *ep; 19168c2ecf20Sopenharmony_ci struct resource *res; 19178c2ecf20Sopenharmony_ci char *name; 19188c2ecf20Sopenharmony_ci int ret; 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci ep = &pci->ep; 19218c2ecf20Sopenharmony_ci ep->ops = &pcie_ep_ops; 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); 19248c2ecf20Sopenharmony_ci if (!res) 19258c2ecf20Sopenharmony_ci return -EINVAL; 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci ep->phys_base = res->start; 19288c2ecf20Sopenharmony_ci ep->addr_size = resource_size(res); 19298c2ecf20Sopenharmony_ci ep->page_size = SZ_64K; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci ret = gpiod_set_debounce(pcie->pex_rst_gpiod, PERST_DEBOUNCE_TIME); 19328c2ecf20Sopenharmony_ci if (ret < 0) { 19338c2ecf20Sopenharmony_ci dev_err(dev, "Failed to set PERST GPIO debounce time: %d\n", 19348c2ecf20Sopenharmony_ci ret); 19358c2ecf20Sopenharmony_ci return ret; 19368c2ecf20Sopenharmony_ci } 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci ret = gpiod_to_irq(pcie->pex_rst_gpiod); 19398c2ecf20Sopenharmony_ci if (ret < 0) { 19408c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get IRQ for PERST GPIO: %d\n", ret); 19418c2ecf20Sopenharmony_ci return ret; 19428c2ecf20Sopenharmony_ci } 19438c2ecf20Sopenharmony_ci pcie->pex_rst_irq = (unsigned int)ret; 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci name = devm_kasprintf(dev, GFP_KERNEL, "tegra_pcie_%u_pex_rst_irq", 19468c2ecf20Sopenharmony_ci pcie->cid); 19478c2ecf20Sopenharmony_ci if (!name) { 19488c2ecf20Sopenharmony_ci dev_err(dev, "Failed to create PERST IRQ string\n"); 19498c2ecf20Sopenharmony_ci return -ENOMEM; 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci irq_set_status_flags(pcie->pex_rst_irq, IRQ_NOAUTOEN); 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci pcie->ep_state = EP_STATE_DISABLED; 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(dev, pcie->pex_rst_irq, NULL, 19578c2ecf20Sopenharmony_ci tegra_pcie_ep_pex_rst_irq, 19588c2ecf20Sopenharmony_ci IRQF_TRIGGER_RISING | 19598c2ecf20Sopenharmony_ci IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 19608c2ecf20Sopenharmony_ci name, (void *)pcie); 19618c2ecf20Sopenharmony_ci if (ret < 0) { 19628c2ecf20Sopenharmony_ci dev_err(dev, "Failed to request IRQ for PERST: %d\n", ret); 19638c2ecf20Sopenharmony_ci return ret; 19648c2ecf20Sopenharmony_ci } 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_ci name = devm_kasprintf(dev, GFP_KERNEL, "tegra_pcie_%u_ep_work", 19678c2ecf20Sopenharmony_ci pcie->cid); 19688c2ecf20Sopenharmony_ci if (!name) { 19698c2ecf20Sopenharmony_ci dev_err(dev, "Failed to create PCIe EP work thread string\n"); 19708c2ecf20Sopenharmony_ci return -ENOMEM; 19718c2ecf20Sopenharmony_ci } 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci ret = dw_pcie_ep_init(ep); 19768c2ecf20Sopenharmony_ci if (ret) { 19778c2ecf20Sopenharmony_ci dev_err(dev, "Failed to initialize DWC Endpoint subsystem: %d\n", 19788c2ecf20Sopenharmony_ci ret); 19798c2ecf20Sopenharmony_ci pm_runtime_disable(dev); 19808c2ecf20Sopenharmony_ci return ret; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci 19838c2ecf20Sopenharmony_ci return 0; 19848c2ecf20Sopenharmony_ci} 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_probe(struct platform_device *pdev) 19878c2ecf20Sopenharmony_ci{ 19888c2ecf20Sopenharmony_ci const struct tegra_pcie_dw_of_data *data; 19898c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 19908c2ecf20Sopenharmony_ci struct resource *atu_dma_res; 19918c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie; 19928c2ecf20Sopenharmony_ci struct resource *dbi_res; 19938c2ecf20Sopenharmony_ci struct pcie_port *pp; 19948c2ecf20Sopenharmony_ci struct dw_pcie *pci; 19958c2ecf20Sopenharmony_ci struct phy **phys; 19968c2ecf20Sopenharmony_ci char *name; 19978c2ecf20Sopenharmony_ci int ret; 19988c2ecf20Sopenharmony_ci u32 i; 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci data = of_device_get_match_data(dev); 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 20038c2ecf20Sopenharmony_ci if (!pcie) 20048c2ecf20Sopenharmony_ci return -ENOMEM; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci pci = &pcie->pci; 20078c2ecf20Sopenharmony_ci pci->dev = &pdev->dev; 20088c2ecf20Sopenharmony_ci pci->ops = &tegra_dw_pcie_ops; 20098c2ecf20Sopenharmony_ci pci->n_fts[0] = N_FTS_VAL; 20108c2ecf20Sopenharmony_ci pci->n_fts[1] = FTS_VAL; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci pp = &pci->pp; 20138c2ecf20Sopenharmony_ci pcie->dev = &pdev->dev; 20148c2ecf20Sopenharmony_ci pcie->mode = (enum dw_pcie_device_mode)data->mode; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci ret = tegra_pcie_dw_parse_dt(pcie); 20178c2ecf20Sopenharmony_ci if (ret < 0) { 20188c2ecf20Sopenharmony_ci const char *level = KERN_ERR; 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci if (ret == -EPROBE_DEFER) 20218c2ecf20Sopenharmony_ci level = KERN_DEBUG; 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci dev_printk(level, dev, 20248c2ecf20Sopenharmony_ci dev_fmt("Failed to parse device tree: %d\n"), 20258c2ecf20Sopenharmony_ci ret); 20268c2ecf20Sopenharmony_ci return ret; 20278c2ecf20Sopenharmony_ci } 20288c2ecf20Sopenharmony_ci 20298c2ecf20Sopenharmony_ci ret = tegra_pcie_get_slot_regulators(pcie); 20308c2ecf20Sopenharmony_ci if (ret < 0) { 20318c2ecf20Sopenharmony_ci const char *level = KERN_ERR; 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ci if (ret == -EPROBE_DEFER) 20348c2ecf20Sopenharmony_ci level = KERN_DEBUG; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci dev_printk(level, dev, 20378c2ecf20Sopenharmony_ci dev_fmt("Failed to get slot regulators: %d\n"), 20388c2ecf20Sopenharmony_ci ret); 20398c2ecf20Sopenharmony_ci return ret; 20408c2ecf20Sopenharmony_ci } 20418c2ecf20Sopenharmony_ci 20428c2ecf20Sopenharmony_ci if (pcie->pex_refclk_sel_gpiod) 20438c2ecf20Sopenharmony_ci gpiod_set_value(pcie->pex_refclk_sel_gpiod, 1); 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci pcie->pex_ctl_supply = devm_regulator_get(dev, "vddio-pex-ctl"); 20468c2ecf20Sopenharmony_ci if (IS_ERR(pcie->pex_ctl_supply)) { 20478c2ecf20Sopenharmony_ci ret = PTR_ERR(pcie->pex_ctl_supply); 20488c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 20498c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get regulator: %ld\n", 20508c2ecf20Sopenharmony_ci PTR_ERR(pcie->pex_ctl_supply)); 20518c2ecf20Sopenharmony_ci return ret; 20528c2ecf20Sopenharmony_ci } 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci pcie->core_clk = devm_clk_get(dev, "core"); 20558c2ecf20Sopenharmony_ci if (IS_ERR(pcie->core_clk)) { 20568c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get core clock: %ld\n", 20578c2ecf20Sopenharmony_ci PTR_ERR(pcie->core_clk)); 20588c2ecf20Sopenharmony_ci return PTR_ERR(pcie->core_clk); 20598c2ecf20Sopenharmony_ci } 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci pcie->appl_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 20628c2ecf20Sopenharmony_ci "appl"); 20638c2ecf20Sopenharmony_ci if (!pcie->appl_res) { 20648c2ecf20Sopenharmony_ci dev_err(dev, "Failed to find \"appl\" region\n"); 20658c2ecf20Sopenharmony_ci return -ENODEV; 20668c2ecf20Sopenharmony_ci } 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci pcie->appl_base = devm_ioremap_resource(dev, pcie->appl_res); 20698c2ecf20Sopenharmony_ci if (IS_ERR(pcie->appl_base)) 20708c2ecf20Sopenharmony_ci return PTR_ERR(pcie->appl_base); 20718c2ecf20Sopenharmony_ci 20728c2ecf20Sopenharmony_ci pcie->core_apb_rst = devm_reset_control_get(dev, "apb"); 20738c2ecf20Sopenharmony_ci if (IS_ERR(pcie->core_apb_rst)) { 20748c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get APB reset: %ld\n", 20758c2ecf20Sopenharmony_ci PTR_ERR(pcie->core_apb_rst)); 20768c2ecf20Sopenharmony_ci return PTR_ERR(pcie->core_apb_rst); 20778c2ecf20Sopenharmony_ci } 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci phys = devm_kcalloc(dev, pcie->phy_count, sizeof(*phys), GFP_KERNEL); 20808c2ecf20Sopenharmony_ci if (!phys) 20818c2ecf20Sopenharmony_ci return -ENOMEM; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci for (i = 0; i < pcie->phy_count; i++) { 20848c2ecf20Sopenharmony_ci name = kasprintf(GFP_KERNEL, "p2u-%u", i); 20858c2ecf20Sopenharmony_ci if (!name) { 20868c2ecf20Sopenharmony_ci dev_err(dev, "Failed to create P2U string\n"); 20878c2ecf20Sopenharmony_ci return -ENOMEM; 20888c2ecf20Sopenharmony_ci } 20898c2ecf20Sopenharmony_ci phys[i] = devm_phy_get(dev, name); 20908c2ecf20Sopenharmony_ci kfree(name); 20918c2ecf20Sopenharmony_ci if (IS_ERR(phys[i])) { 20928c2ecf20Sopenharmony_ci ret = PTR_ERR(phys[i]); 20938c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 20948c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get PHY: %d\n", ret); 20958c2ecf20Sopenharmony_ci return ret; 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci } 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci pcie->phys = phys; 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); 21028c2ecf20Sopenharmony_ci if (!dbi_res) { 21038c2ecf20Sopenharmony_ci dev_err(dev, "Failed to find \"dbi\" region\n"); 21048c2ecf20Sopenharmony_ci return -ENODEV; 21058c2ecf20Sopenharmony_ci } 21068c2ecf20Sopenharmony_ci pcie->dbi_res = dbi_res; 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci pci->dbi_base = devm_ioremap_resource(dev, dbi_res); 21098c2ecf20Sopenharmony_ci if (IS_ERR(pci->dbi_base)) 21108c2ecf20Sopenharmony_ci return PTR_ERR(pci->dbi_base); 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci /* Tegra HW locates DBI2 at a fixed offset from DBI */ 21138c2ecf20Sopenharmony_ci pci->dbi_base2 = pci->dbi_base + 0x1000; 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci atu_dma_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 21168c2ecf20Sopenharmony_ci "atu_dma"); 21178c2ecf20Sopenharmony_ci if (!atu_dma_res) { 21188c2ecf20Sopenharmony_ci dev_err(dev, "Failed to find \"atu_dma\" region\n"); 21198c2ecf20Sopenharmony_ci return -ENODEV; 21208c2ecf20Sopenharmony_ci } 21218c2ecf20Sopenharmony_ci pcie->atu_dma_res = atu_dma_res; 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_ci pci->atu_base = devm_ioremap_resource(dev, atu_dma_res); 21248c2ecf20Sopenharmony_ci if (IS_ERR(pci->atu_base)) 21258c2ecf20Sopenharmony_ci return PTR_ERR(pci->atu_base); 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci pcie->core_rst = devm_reset_control_get(dev, "core"); 21288c2ecf20Sopenharmony_ci if (IS_ERR(pcie->core_rst)) { 21298c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get core reset: %ld\n", 21308c2ecf20Sopenharmony_ci PTR_ERR(pcie->core_rst)); 21318c2ecf20Sopenharmony_ci return PTR_ERR(pcie->core_rst); 21328c2ecf20Sopenharmony_ci } 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_ci pp->irq = platform_get_irq_byname(pdev, "intr"); 21358c2ecf20Sopenharmony_ci if (pp->irq < 0) 21368c2ecf20Sopenharmony_ci return pp->irq; 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci pcie->bpmp = tegra_bpmp_get(dev); 21398c2ecf20Sopenharmony_ci if (IS_ERR(pcie->bpmp)) 21408c2ecf20Sopenharmony_ci return PTR_ERR(pcie->bpmp); 21418c2ecf20Sopenharmony_ci 21428c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, pcie); 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci switch (pcie->mode) { 21458c2ecf20Sopenharmony_ci case DW_PCIE_RC_TYPE: 21468c2ecf20Sopenharmony_ci ret = devm_request_irq(dev, pp->irq, tegra_pcie_rp_irq_handler, 21478c2ecf20Sopenharmony_ci IRQF_SHARED, "tegra-pcie-intr", pcie); 21488c2ecf20Sopenharmony_ci if (ret) { 21498c2ecf20Sopenharmony_ci dev_err(dev, "Failed to request IRQ %d: %d\n", pp->irq, 21508c2ecf20Sopenharmony_ci ret); 21518c2ecf20Sopenharmony_ci goto fail; 21528c2ecf20Sopenharmony_ci } 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci ret = tegra_pcie_config_rp(pcie); 21558c2ecf20Sopenharmony_ci if (ret && ret != -ENOMEDIUM) 21568c2ecf20Sopenharmony_ci goto fail; 21578c2ecf20Sopenharmony_ci else 21588c2ecf20Sopenharmony_ci return 0; 21598c2ecf20Sopenharmony_ci break; 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci case DW_PCIE_EP_TYPE: 21628c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(dev, pp->irq, 21638c2ecf20Sopenharmony_ci tegra_pcie_ep_hard_irq, 21648c2ecf20Sopenharmony_ci tegra_pcie_ep_irq_thread, 21658c2ecf20Sopenharmony_ci IRQF_SHARED | IRQF_ONESHOT, 21668c2ecf20Sopenharmony_ci "tegra-pcie-ep-intr", pcie); 21678c2ecf20Sopenharmony_ci if (ret) { 21688c2ecf20Sopenharmony_ci dev_err(dev, "Failed to request IRQ %d: %d\n", pp->irq, 21698c2ecf20Sopenharmony_ci ret); 21708c2ecf20Sopenharmony_ci goto fail; 21718c2ecf20Sopenharmony_ci } 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci ret = tegra_pcie_config_ep(pcie, pdev); 21748c2ecf20Sopenharmony_ci if (ret < 0) 21758c2ecf20Sopenharmony_ci goto fail; 21768c2ecf20Sopenharmony_ci break; 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci default: 21798c2ecf20Sopenharmony_ci dev_err(dev, "Invalid PCIe device type %d\n", pcie->mode); 21808c2ecf20Sopenharmony_ci } 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_cifail: 21838c2ecf20Sopenharmony_ci tegra_bpmp_put(pcie->bpmp); 21848c2ecf20Sopenharmony_ci return ret; 21858c2ecf20Sopenharmony_ci} 21868c2ecf20Sopenharmony_ci 21878c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_remove(struct platform_device *pdev) 21888c2ecf20Sopenharmony_ci{ 21898c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci if (!pcie->link_state) 21928c2ecf20Sopenharmony_ci return 0; 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci debugfs_remove_recursive(pcie->debugfs); 21958c2ecf20Sopenharmony_ci tegra_pcie_deinit_controller(pcie); 21968c2ecf20Sopenharmony_ci pm_runtime_put_sync(pcie->dev); 21978c2ecf20Sopenharmony_ci pm_runtime_disable(pcie->dev); 21988c2ecf20Sopenharmony_ci tegra_bpmp_put(pcie->bpmp); 21998c2ecf20Sopenharmony_ci if (pcie->pex_refclk_sel_gpiod) 22008c2ecf20Sopenharmony_ci gpiod_set_value(pcie->pex_refclk_sel_gpiod, 0); 22018c2ecf20Sopenharmony_ci 22028c2ecf20Sopenharmony_ci return 0; 22038c2ecf20Sopenharmony_ci} 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_suspend_late(struct device *dev) 22068c2ecf20Sopenharmony_ci{ 22078c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = dev_get_drvdata(dev); 22088c2ecf20Sopenharmony_ci u32 val; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci if (!pcie->link_state) 22118c2ecf20Sopenharmony_ci return 0; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci /* Enable HW_HOT_RST mode */ 22148c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 22158c2ecf20Sopenharmony_ci val &= ~(APPL_CTRL_HW_HOT_RST_MODE_MASK << 22168c2ecf20Sopenharmony_ci APPL_CTRL_HW_HOT_RST_MODE_SHIFT); 22178c2ecf20Sopenharmony_ci val |= APPL_CTRL_HW_HOT_RST_EN; 22188c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 22198c2ecf20Sopenharmony_ci 22208c2ecf20Sopenharmony_ci return 0; 22218c2ecf20Sopenharmony_ci} 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_suspend_noirq(struct device *dev) 22248c2ecf20Sopenharmony_ci{ 22258c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = dev_get_drvdata(dev); 22268c2ecf20Sopenharmony_ci 22278c2ecf20Sopenharmony_ci if (!pcie->link_state) 22288c2ecf20Sopenharmony_ci return 0; 22298c2ecf20Sopenharmony_ci 22308c2ecf20Sopenharmony_ci /* Save MSI interrupt vector */ 22318c2ecf20Sopenharmony_ci pcie->msi_ctrl_int = dw_pcie_readl_dbi(&pcie->pci, 22328c2ecf20Sopenharmony_ci PORT_LOGIC_MSI_CTRL_INT_0_EN); 22338c2ecf20Sopenharmony_ci tegra_pcie_downstream_dev_to_D0(pcie); 22348c2ecf20Sopenharmony_ci tegra_pcie_dw_pme_turnoff(pcie); 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci return __deinit_controller(pcie); 22378c2ecf20Sopenharmony_ci} 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_resume_noirq(struct device *dev) 22408c2ecf20Sopenharmony_ci{ 22418c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = dev_get_drvdata(dev); 22428c2ecf20Sopenharmony_ci int ret; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci if (!pcie->link_state) 22458c2ecf20Sopenharmony_ci return 0; 22468c2ecf20Sopenharmony_ci 22478c2ecf20Sopenharmony_ci ret = tegra_pcie_config_controller(pcie, true); 22488c2ecf20Sopenharmony_ci if (ret < 0) 22498c2ecf20Sopenharmony_ci return ret; 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci ret = tegra_pcie_dw_host_init(&pcie->pci.pp); 22528c2ecf20Sopenharmony_ci if (ret < 0) { 22538c2ecf20Sopenharmony_ci dev_err(dev, "Failed to init host: %d\n", ret); 22548c2ecf20Sopenharmony_ci goto fail_host_init; 22558c2ecf20Sopenharmony_ci } 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci /* Restore MSI interrupt vector */ 22588c2ecf20Sopenharmony_ci dw_pcie_writel_dbi(&pcie->pci, PORT_LOGIC_MSI_CTRL_INT_0_EN, 22598c2ecf20Sopenharmony_ci pcie->msi_ctrl_int); 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci return 0; 22628c2ecf20Sopenharmony_ci 22638c2ecf20Sopenharmony_cifail_host_init: 22648c2ecf20Sopenharmony_ci return __deinit_controller(pcie); 22658c2ecf20Sopenharmony_ci} 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_cistatic int tegra_pcie_dw_resume_early(struct device *dev) 22688c2ecf20Sopenharmony_ci{ 22698c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = dev_get_drvdata(dev); 22708c2ecf20Sopenharmony_ci u32 val; 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_ci if (!pcie->link_state) 22738c2ecf20Sopenharmony_ci return 0; 22748c2ecf20Sopenharmony_ci 22758c2ecf20Sopenharmony_ci /* Disable HW_HOT_RST mode */ 22768c2ecf20Sopenharmony_ci val = appl_readl(pcie, APPL_CTRL); 22778c2ecf20Sopenharmony_ci val &= ~(APPL_CTRL_HW_HOT_RST_MODE_MASK << 22788c2ecf20Sopenharmony_ci APPL_CTRL_HW_HOT_RST_MODE_SHIFT); 22798c2ecf20Sopenharmony_ci val |= APPL_CTRL_HW_HOT_RST_MODE_IMDT_RST << 22808c2ecf20Sopenharmony_ci APPL_CTRL_HW_HOT_RST_MODE_SHIFT; 22818c2ecf20Sopenharmony_ci val &= ~APPL_CTRL_HW_HOT_RST_EN; 22828c2ecf20Sopenharmony_ci appl_writel(pcie, val, APPL_CTRL); 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci return 0; 22858c2ecf20Sopenharmony_ci} 22868c2ecf20Sopenharmony_ci 22878c2ecf20Sopenharmony_cistatic void tegra_pcie_dw_shutdown(struct platform_device *pdev) 22888c2ecf20Sopenharmony_ci{ 22898c2ecf20Sopenharmony_ci struct tegra_pcie_dw *pcie = platform_get_drvdata(pdev); 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci if (!pcie->link_state) 22928c2ecf20Sopenharmony_ci return; 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci debugfs_remove_recursive(pcie->debugfs); 22958c2ecf20Sopenharmony_ci tegra_pcie_downstream_dev_to_D0(pcie); 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci disable_irq(pcie->pci.pp.irq); 22988c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PCI_MSI)) 22998c2ecf20Sopenharmony_ci disable_irq(pcie->pci.pp.msi_irq); 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_ci tegra_pcie_dw_pme_turnoff(pcie); 23028c2ecf20Sopenharmony_ci __deinit_controller(pcie); 23038c2ecf20Sopenharmony_ci} 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_cistatic const struct tegra_pcie_dw_of_data tegra_pcie_dw_rc_of_data = { 23068c2ecf20Sopenharmony_ci .mode = DW_PCIE_RC_TYPE, 23078c2ecf20Sopenharmony_ci}; 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_cistatic const struct tegra_pcie_dw_of_data tegra_pcie_dw_ep_of_data = { 23108c2ecf20Sopenharmony_ci .mode = DW_PCIE_EP_TYPE, 23118c2ecf20Sopenharmony_ci}; 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_cistatic const struct of_device_id tegra_pcie_dw_of_match[] = { 23148c2ecf20Sopenharmony_ci { 23158c2ecf20Sopenharmony_ci .compatible = "nvidia,tegra194-pcie", 23168c2ecf20Sopenharmony_ci .data = &tegra_pcie_dw_rc_of_data, 23178c2ecf20Sopenharmony_ci }, 23188c2ecf20Sopenharmony_ci { 23198c2ecf20Sopenharmony_ci .compatible = "nvidia,tegra194-pcie-ep", 23208c2ecf20Sopenharmony_ci .data = &tegra_pcie_dw_ep_of_data, 23218c2ecf20Sopenharmony_ci }, 23228c2ecf20Sopenharmony_ci {}, 23238c2ecf20Sopenharmony_ci}; 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_cistatic const struct dev_pm_ops tegra_pcie_dw_pm_ops = { 23268c2ecf20Sopenharmony_ci .suspend_late = tegra_pcie_dw_suspend_late, 23278c2ecf20Sopenharmony_ci .suspend_noirq = tegra_pcie_dw_suspend_noirq, 23288c2ecf20Sopenharmony_ci .resume_noirq = tegra_pcie_dw_resume_noirq, 23298c2ecf20Sopenharmony_ci .resume_early = tegra_pcie_dw_resume_early, 23308c2ecf20Sopenharmony_ci}; 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_cistatic struct platform_driver tegra_pcie_dw_driver = { 23338c2ecf20Sopenharmony_ci .probe = tegra_pcie_dw_probe, 23348c2ecf20Sopenharmony_ci .remove = tegra_pcie_dw_remove, 23358c2ecf20Sopenharmony_ci .shutdown = tegra_pcie_dw_shutdown, 23368c2ecf20Sopenharmony_ci .driver = { 23378c2ecf20Sopenharmony_ci .name = "tegra194-pcie", 23388c2ecf20Sopenharmony_ci .pm = &tegra_pcie_dw_pm_ops, 23398c2ecf20Sopenharmony_ci .of_match_table = tegra_pcie_dw_of_match, 23408c2ecf20Sopenharmony_ci }, 23418c2ecf20Sopenharmony_ci}; 23428c2ecf20Sopenharmony_cimodule_platform_driver(tegra_pcie_dw_driver); 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, tegra_pcie_dw_of_match); 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ciMODULE_AUTHOR("Vidya Sagar <vidyas@nvidia.com>"); 23478c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA PCIe host controller driver"); 23488c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2349