static int tegra_pcie_dw_host_init(struct pcie_port *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct tegra_pcie_dw *pcie = dw_pcie_to_tegra_pcie(pci); u32 val, tmp; int count = 200; dev_info(pci->dev, "-------->>> Inside %s <<<<-----------\n", __func__); if (tegra_platform_is_fpga()) { /* Program correct VID and DID on FPGA */ dw_pcie_write(pci->dbi_base + PCI_VENDOR_ID, 2, 0x10DE); dw_pcie_write(pci->dbi_base + PCI_DEVICE_ID, 2, 0x1AD1); /* Required for L1.1 working on FPGA */ val = readl(pcie->appl_base + APPL_GTH_PHY); val &= 0xFFFF0003; val &= ~(0x2); val |= 0x7F4; writel(val, pcie->appl_base + APPL_GTH_PHY); /* Program correct L0s and L1 exit latencies */ dw_pcie_read(pci->dbi_base + CFG_LINK_CAP, 4, &tmp); tmp &= ~PCI_EXP_LNKCAP_L0SEL; tmp |= 0x4; /* 512 ns to less than 1us */ tmp &= ~PCI_EXP_LNKCAP_L1EL; tmp |= 0x6; /* 32us to 64us */ dw_pcie_write(pci->dbi_base + CFG_LINK_CAP, 4, tmp); dw_pcie_read(pci->dbi_base + AUX_CLK_FREQ, 4, &tmp); tmp &= ~(0x3FF); tmp |= 0x6; dw_pcie_write(pci->dbi_base + AUX_CLK_FREQ, 4, tmp); } else { dw_pcie_read(pci->dbi_base + AUX_CLK_FREQ, 4, &tmp); tmp &= ~(0x3FF); /* CHECK: Confirm this value for Silicon */ tmp |= pcie->aux_clk_freq; dw_pcie_write(pci->dbi_base + AUX_CLK_FREQ, 4, tmp); } dw_pcie_read(pci->dbi_base + PCI_IO_BASE, 4, &tmp); tmp &= ~(IO_BASE_IO_DECODE | IO_BASE_IO_DECODE_BIT8); dw_pcie_write(pci->dbi_base + PCI_IO_BASE, 4, tmp); dw_pcie_read(pci->dbi_base + CFG_PREF_MEM_LIMIT_BASE, 4, &tmp); tmp |= CFG_PREF_MEM_LIMIT_BASE_MEM_DECODE; tmp |= CFG_PREF_MEM_LIMIT_BASE_MEM_LIMIT_DECODE; dw_pcie_write(pci->dbi_base + CFG_PREF_MEM_LIMIT_BASE, 4, tmp); /* Set De-emphasis */ dev_info(pci->dev, "SEL_DEEMPHASIS: %ld\n", SEL_DEEMPHASIS); dw_pcie_read(pci->dbi_base + PORT_LOGIC_GEN2_CTRL, 4, &tmp); dev_info(pci->dev, "PORT_LOGIC_GEN2_CTRL #1: 0x%x\n", tmp); tmp &= ~(SEL_DEEMPHASIS); dev_info(pci->dev, "PORT_LOGIC_GEN2_CTRL #2: 0x%x\n", tmp); tmp |= SEL_DEEMPHASIS; dev_info(pci->dev, "PORT_LOGIC_GEN2_CTRL #3: 0x%x\n", tmp); dw_pcie_write(pci->dbi_base + PORT_LOGIC_GEN2_CTRL, 4, tmp); /* Configure FTS */ dw_pcie_read(pci->dbi_base + PORT_LOGIC_ACK_F_ASPM_CTRL, 4, &tmp); tmp &= ~(N_FTS_MASK << N_FTS_SHIFT); tmp |= N_FTS_VAL << N_FTS_SHIFT; dw_pcie_write(pci->dbi_base + PORT_LOGIC_ACK_F_ASPM_CTRL, 4, tmp); dw_pcie_read(pci->dbi_base + PORT_LOGIC_GEN2_CTRL, 4, &tmp); tmp &= ~FTS_MASK; tmp |= FTS_VAL; dw_pcie_write(pci->dbi_base + PORT_LOGIC_GEN2_CTRL, 4, tmp); /* Enable 0xFFFF0001 response for CRS */ dw_pcie_read(pci->dbi_base + PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT, 4, &tmp); tmp &= ~(AMBA_ERROR_RESPONSE_CRS_MASK << AMBA_ERROR_RESPONSE_CRS_SHIFT); tmp |= (AMBA_ERROR_RESPONSE_CRS_OKAY_FFFF0001 << AMBA_ERROR_RESPONSE_CRS_SHIFT); dw_pcie_write(pci->dbi_base + PORT_LOGIC_AMBA_ERROR_RESPONSE_DEFAULT, 4, tmp); /* Set MPS to 256 in DEV_CTL */ dw_pcie_read(pci->dbi_base + CFG_DEV_STATUS_CONTROL, 4, &tmp); tmp &= ~CFG_DEV_STATUS_CONTROL_MPS_MASK; tmp |= 1 << CFG_DEV_STATUS_CONTROL_MPS_SHIFT; dw_pcie_write(pci->dbi_base + CFG_DEV_STATUS_CONTROL, 4, tmp); /* Configure Max Speed from DT */ dw_pcie_read(pci->dbi_base + CFG_LINK_CAP, 4, &tmp); tmp &= ~CFG_LINK_CAP_MAX_LINK_SPEED_MASK; tmp |= pcie->max_speed; dw_pcie_write(pci->dbi_base + CFG_LINK_CAP, 4, tmp); dw_pcie_read(pci->dbi_base + CFG_LINK_STATUS_CONTROL_2, 4, &tmp); tmp &= ~CFG_LINK_STATUS_CONTROL_2_TARGET_LS_MASK; tmp |= pcie->init_speed; dw_pcie_write(pci->dbi_base + CFG_LINK_STATUS_CONTROL_2, 4, tmp); /* Configure Max lane width from DT */ dw_pcie_read(pci->dbi_base + CFG_LINK_CAP, 4, &tmp); tmp &= ~CFG_LINK_CAP_MAX_WIDTH_MASK; tmp |= (pcie->num_lanes << CFG_LINK_CAP_MAX_WIDTH_SHIFT); dw_pcie_write(pci->dbi_base + CFG_LINK_CAP, 4, tmp); /* Enable ASPM counters */ val = EVENT_COUNTER_ENABLE_ALL << EVENT_COUNTER_ENABLE_SHIFT; val |= EVENT_COUNTER_GROUP_5 << EVENT_COUNTER_GROUP_SEL_SHIFT; dw_pcie_write(pci->dbi_base + pcie->event_cntr_ctrl, 4, val); init_gen3_gen4_eq_presets(pcie); program_gen3_gen4_eq_presets(pcie); /* Program T_cmrt and T_pwr_on values */ dw_pcie_read(pcie->pci.dbi_base + pcie->cfg_link_cap_l1sub, 4, &val); val &= ~(PCI_L1SS_CAP_CM_RTM_MASK | PCI_L1SS_CAP_PWRN_VAL_MASK); val |= (pcie->aspm_cmrt << PCI_L1SS_CAP_CM_RTM_SHIFT); val |= (pcie->aspm_pwr_on_t << PCI_L1SS_CAP_PWRN_VAL_SHIFT); dw_pcie_write(pcie->pci.dbi_base + pcie->cfg_link_cap_l1sub, 4, val); /* Program L0s and L1 entrance latencies */ val = readl(pci->dbi_base + PORT_LOGIC_ACK_F_ASPM_CTRL); val &= ~L0S_ENTRANCE_LAT_MASK; val |= (pcie->aspm_l0s_enter_lat << L0S_ENTRANCE_LAT_SHIFT); val |= ENTER_ASPM; writel(val, pci->dbi_base + PORT_LOGIC_ACK_F_ASPM_CTRL); /* Program what ASPM states sould get advertised */ if (pcie->disabled_aspm_states & 0x1) disable_aspm_l0s(pcie); /* Disable L0s */ if (pcie->disabled_aspm_states & 0x2) { disable_aspm_l10(pcie); /* Disable L1 */ disable_aspm_l11(pcie); /* Disable L1.1 */ disable_aspm_l12(pcie); /* Disable L1.2 */ } if (pcie->disabled_aspm_states & 0x4) disable_aspm_l11(pcie); /* Disable L1.1 */ if (pcie->disabled_aspm_states & 0x8) disable_aspm_l12(pcie); /* Disable L1.2 */ val = readl(pci->dbi_base + GEN3_RELATED_OFF); val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL; writel(val, pci->dbi_base + GEN3_RELATED_OFF); if (pcie->update_fc_fixup) { dw_pcie_read(pci->dbi_base + CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF, 4, &tmp); tmp |= 0x1 << CFG_TIMER_CTRL_ACK_NAK_SHIFT; dw_pcie_write(pci->dbi_base + CFG_TIMER_CTRL_MAX_FUNC_NUM_OFF, 4, tmp); } /* CDM check enable */ if (pcie->cdm_check) { dw_pcie_read(pci->dbi_base + PORT_LOGIC_PL_CHK_REG_CONTROL_STATUS, 4, &tmp); tmp |= PORT_LOGIC_PL_CHK_REG_CHK_REG_CONTINUOUS; tmp |= PORT_LOGIC_PL_CHK_REG_CHK_REG_START; dw_pcie_write(pci->dbi_base + PORT_LOGIC_PL_CHK_REG_CONTROL_STATUS, 4, tmp); } if (pcie->is_safety_platform) { /* Disable HW autonomous speed change */ val = readl(pci->dbi_base + CFG_LINK_STATUS_CONTROL_2); val &= ~CFG_LINK_STATUS_CONTROL_2_HW_AUTO_SPEED_DISABLE; writel(val, pci->dbi_base + CFG_LINK_STATUS_CONTROL_2); /* Disable all ASPM states */ disable_aspm_l0s(pcie); /* Disable L0s */ disable_aspm_l10(pcie); /* Disable L1 */ disable_aspm_l11(pcie); /* Disable L1.1 */ disable_aspm_l12(pcie); /* Disable L1.2 */ } #ifdef CONFIG_PCIE_TEGRA_DW_LANE_MARGIN val = readl(pci->dbi_base + GEN4_LANE_MARGINING_1); val &= ~GEN4_LANE_MARGINING_1_NUM_TIMING_STEPS_MASK; val |= NUM_TIMING_STEPS; val &= ~GEN4_LANE_MARGINING_1_MAX_VOLTAGE_OFFSET_MASK; val |= (NUM_VOLTAGE_STEPS << GEN4_LANE_MARGINING_1_MAX_VOLTAGE_OFFSET_SHIFT); writel(val, pci->dbi_base + GEN4_LANE_MARGINING_1); /* Need DBI_RO_WR_EN set to program this bit */ val = readl(pci->dbi_base + GEN4_LANE_MARGINING_2); val |= GEN4_LANE_MARGINING_2_VOLTAGE_SUPPORTED; #ifdef CONFIG_PCIE_TEGRA_DW_TWO_SIDE_LANE_MARGIN val |= GEN4_LANE_MARGINING_2_LEFT_RIGHT_TIMING; val |= GEN4_LANE_MARGINING_2_UP_DOWN_VOLTAGE; #endif writel(val, pci->dbi_base + GEN4_LANE_MARGINING_2); #endif dw_pcie_setup_rc(pp); dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000000); /* FPGA specific PHY initialization */ if (tegra_platform_is_fpga()) { val = readl(pcie->appl_base + APPL_GTH_PHY); val |= APPL_GTH_PHY_RST; writel(val, pcie->appl_base + APPL_GTH_PHY); } clk_set_rate(pcie->core_clk, GEN4_CORE_CLK_FREQ); /* assert RST */ val = readl(pcie->appl_base + APPL_PINMUX); val &= ~APPL_PINMUX_PEX_RST; writel(val, pcie->appl_base + APPL_PINMUX); usleep_range(100, 200); /* enable LTSSM */ val = readl(pcie->appl_base + APPL_CTRL); val |= APPL_CTRL_LTSSM_EN; writel(val, pcie->appl_base + APPL_CTRL); /* de-assert RST */ val = readl(pcie->appl_base + APPL_PINMUX); val |= APPL_PINMUX_PEX_RST; writel(val, pcie->appl_base + APPL_PINMUX); msleep(100); val = readl(pci->dbi_base + CFG_LINK_STATUS_CONTROL); while (!(val & CFG_LINK_STATUS_DLL_ACTIVE)) { if (!count) { val = readl(pcie->appl_base + APPL_DEBUG); val &= APPL_DEBUG_LTSSM_STATE_MASK; val >>= APPL_DEBUG_LTSSM_STATE_SHIFT; tmp = readl(pcie->appl_base + APPL_LINK_STATUS); tmp &= APPL_LINK_STATUS_RDLH_LINK_UP; if ((val == 0x11) && !tmp) { dev_info(pci->dev, "link is down in DLL, " "try again with DLFE disabled"); /* disable LTSSM */ val = readl(pcie->appl_base + APPL_CTRL); val &= ~APPL_CTRL_LTSSM_EN; writel(val, pcie->appl_base + APPL_CTRL); reset_control_assert(pcie->core_rst); reset_control_deassert(pcie->core_rst); dw_pcie_read(pci->dbi_base + pcie->dl_feature_cap, 4, &val); val &= ~DL_FEATURE_EXCHANGE_EN; dw_pcie_write(pci->dbi_base + pcie->dl_feature_cap, 4, val); tegra_pcie_dw_host_init(&pcie->pci.pp); return 0; } dev_info(pci->dev, "link is down\n"); return 0; } dev_dbg(pci->dev, "polling for link up\n"); usleep_range(1000, 2000); val = readl(pci->dbi_base + CFG_LINK_STATUS_CONTROL); count--; } dev_info(pci->dev, "link is up\n"); dw_pcie_read(pci->dbi_base + PORT_LOGIC_GEN2_CTRL, 4, &tmp); dev_info(pci->dev, "PORT_LOGIC_GEN2_CTRL #END: %d", tmp); return tegra_pcie_enable_interrupts(pp); }