diff --git a/src/soc/qualcomm/common/Kconfig b/src/soc/qualcomm/common/Kconfig index 8a3adf58d7..eca772ce59 100644 --- a/src/soc/qualcomm/common/Kconfig +++ b/src/soc/qualcomm/common/Kconfig @@ -12,6 +12,12 @@ config QC_COMMON_QUPV3_2 help Selected by chipsets that has QUPv3 HW Version 2. +config QMP_PHY_2X2_1X4 + bool + default n + help + Selected by chipsets that have PCIE QMP PHY 2X2/1X4 + if SOC_QUALCOMM_COMMON config QC_SDI_ENABLE diff --git a/src/soc/qualcomm/common/include/soc/pcie.h b/src/soc/qualcomm/common/include/soc/pcie.h index b2f9e45a3d..fa1e603f08 100644 --- a/src/soc/qualcomm/common/include/soc/pcie.h +++ b/src/soc/qualcomm/common/include/soc/pcie.h @@ -36,6 +36,15 @@ #define DEVICE_TYPE_RC 0x4 #define PCIE_PARF_BDF_TO_SID_CFG 0x2C00 #define BDF_TO_SID_BYPASS BIT(0) +#define PCIE_PARF_PM_CTRL 0x10 +#define REQ_NOT_ENTR_L1 BIT(5) +#define PCIE_PARF_SLAVE_AXI_ERR_REPORT 0x3C4 +#define AXI_SLAVE_ERR_CRS_BRESP_EN BIT(14) +#define PCIE_PARF_AXI_MSTR_WR_ADDR_HALT 0x1A8 +#define PCIE_SRIS_MODE 0x644 +#define PCIE_APP_MARGINING_CTRL 0x2C38 +#define APP_MARGINING_READY BIT(0) +#define APP_MARGINING_SW_READY BIT(1) /* ELBI */ #define PCIE3X2_ELBI_SYS_STTS 0x08 @@ -48,8 +57,24 @@ #define LINK_SPEED_GEN_1 0x1 #define LINK_SPEED_GEN_2 0x2 #define LINK_SPEED_GEN_3 0x3 +#define LINK_SPEED_GEN_4 0x4 #define PCIE_LINK_UP_MS 100 +#define PCIE_PHY_POLL_US 1000 #define LINK_WAIT_MAX_RETRIES 10 +#define PCIE_AMBA_ERR_RESP_DEFLT_OFF 0x8D0 +#define AMBA_ERR_RESP_CRS_MASK 0x18 +#define PCIE_SPCIE_CAP_OFF_0CH_REG 0x154 +#define PCIE_SPCIE_CAP_OFF_10H_REG 0x158 +#define PCIE_PL16G_CAP_OFF_20H_REG 0x188 +#define PCIE_GEN3_EQ_CONTROL_OFF 0x8A8 +#define GEN3_EQ_PSET_REQ_VEC 0x00FFFF00 +#define PCIE_GEN3_EQ_FB_MODE_DIR_CHANGE_OFF 0x8AC +#define GEN3_EQ_FMDC_T_MIN_PHASE23 0xF +#define PCIE_GEN3_RELATED_OFF 0x890 +#define RATE_SHADOW_SEL_MASK (BIT(25)|BIT(24)) +#define RATE_SHADOW_SEL_VAL (BIT(24)) +#define PCIE_CAP_HOT_PLUG_CAPABLE BIT(6) +#define PCIE_SLOT_CAPABILITIES_REG 0x84 #define COMMAND_MASK 0xffff @@ -66,6 +91,7 @@ #define PCIE_DBI_RO_WR_EN BIT(0) #define PCIE_3x2_NUM_LANES 2 +#define PCIE_1x4_NUM_LANES 4 #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C #define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8) #define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8) @@ -177,6 +203,7 @@ typedef struct { struct pcie_region mem; } pcie_cntlr_cfg_t; +#if CONFIG(QMP_PHY_2X2_1X4) typedef struct { void *qmp_phy_base; void *serdes; @@ -186,7 +213,32 @@ typedef struct { void *tx1; void *rx1; void *pcs_misc; + void *lane0_pcs; + void *lane1_pcs; + void *lane0_pcie_pcs; + void *lane1_pcie_pcs; + void *ln_shrd; +} pcie_qmp_phy_base_t; +#endif +typedef struct { +#if !CONFIG(QMP_PHY_2X2_1X4) + void *qmp_phy_base; + void *serdes; + void *tx0; + void *rx0; + void *pcs; + void *tx1; + void *rx1; + void *pcs_misc; + void *lane0_pcs; + void *lane1_pcs; + void *lane0_pcie_pcs; + void *lane1_pcie_pcs; +#else + pcie_qmp_phy_base_t porta; + pcie_qmp_phy_base_t portb; +#endif /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ const struct qcom_qmp_phy_init_tbl *serdes_tbl; unsigned int serdes_tbl_num; @@ -208,6 +260,16 @@ typedef struct { unsigned int pcs_misc_tbl_num; const struct qcom_qmp_phy_init_tbl *pcs_misc_tbl_sec; unsigned int pcs_misc_tbl_num_sec; + const struct qcom_qmp_phy_init_tbl *pcs_misc_tbl_thrd; + unsigned int pcs_misc_tbl_num_thrd; + const struct qcom_qmp_phy_init_tbl *lane0_pcie_pcs_tbl; + unsigned int lane0_pcie_pcs_tbl_num; + const struct qcom_qmp_phy_init_tbl *lane1_pcie_pcs_tbl; + unsigned int lane1_pcie_pcs_tbl_num; +#if CONFIG(QMP_PHY_2X2_1X4) + const struct qcom_qmp_phy_init_tbl *ln_shrd_tbl; + unsigned int ln_shrd_tbl_num; +#endif } pcie_qmp_phy_cfg_t; struct qcom_pcie_cntlr_t { diff --git a/src/soc/qualcomm/common/include/soc/qcom_qmp_phy.h b/src/soc/qualcomm/common/include/soc/qcom_qmp_phy.h index ec4ac3465b..046ba82ea2 100644 --- a/src/soc/qualcomm/common/include/soc/qcom_qmp_phy.h +++ b/src/soc/qualcomm/common/include/soc/qcom_qmp_phy.h @@ -3,6 +3,7 @@ #ifndef QCOM_PHY_QMP_H_ #define QCOM_PHY_QMP_H_ +#if !CONFIG(QMP_PHY_2X2_1X4) /* Only for QMP V4 PHY - QSERDES COM registers */ #define QSERDES_V4_COM_SSC_EN_CENTER 0x010 #define QSERDES_V4_COM_SSC_PER1 0x01c @@ -269,4 +270,152 @@ #define QPHY_V4_PCS_PCIE_PRESET_P10_PRE 0xbc #define QPHY_V4_PCS_PCIE_PRESET_P10_POST 0xe0 -#endif +#else +/* Only for QMP V4 2X2_1X4 PHY - QSERDES PLL registers */ +#define QSERDES_V4_PLL_SSC_STEP_SIZE1_MODE1 0x00 +#define QSERDES_V4_PLL_SSC_STEP_SIZE2_MODE1 0x04 +#define QSERDES_V4_PLL_CP_CTRL_MODE1 0x10 +#define QSERDES_V4_PLL_PLL_RCTRL_MODE1 0x14 +#define QSERDES_V4_PLL_PLL_CCTRL_MODE1 0x18 +#define QSERDES_V4_PLL_CORECLK_DIV_MODE1 0x1c +#define QSERDES_V4_PLL_LOCK_CMP1_MODE1 0x20 +#define QSERDES_V4_PLL_LOCK_CMP2_MODE1 0x24 +#define QSERDES_V4_PLL_DEC_START_MODE1 0x28 +#define QSERDES_V4_PLL_DIV_FRAC_START1_MODE1 0x30 +#define QSERDES_V4_PLL_DIV_FRAC_START2_MODE1 0x34 +#define QSERDES_V4_PLL_DIV_FRAC_START3_MODE1 0x38 +#define QSERDES_V4_PLL_HSCLK_SEL_1 0x3C +#define QSERDES_V4_PLL_SSC_STEP_SIZE1_MODE0 0x60 +#define QSERDES_V4_PLL_SSC_STEP_SIZE2_MODE0 0x64 +#define QSERDES_V4_PLL_CP_CTRL_MODE0 0x70 +#define QSERDES_V4_PLL_PLL_RCTRL_MODE0 0x74 +#define QSERDES_V4_PLL_PLL_CCTRL_MODE0 0x78 +#define QSERDES_V4_PLL_CORECLK_DIV_MODE0 0x7c +#define QSERDES_V4_PLL_LOCK_CMP1_MODE0 0x80 +#define QSERDES_V4_PLL_LOCK_CMP2_MODE0 0x84 +#define QSERDES_V4_PLL_DEC_START_MODE0 0x88 +#define QSERDES_V4_PLL_DIV_FRAC_START1_MODE0 0x90 +#define QSERDES_V4_PLL_DIV_FRAC_START2_MODE0 0x94 +#define QSERDES_V4_PLL_DIV_FRAC_START3_MODE0 0x98 +#define QSERDES_V4_PLL_HSCLK_HS_SWITCH_SEL_1 0x9c +#define QSERDES_V4_PLL_BG_TIMER 0xbc +#define QSERDES_V4_PLL_SSC_EN_CENTER 0xc0 +#define QSERDES_V4_PLL_SSC_PER1 0xcc +#define QSERDES_V4_PLL_SSC_PER2 0xd0 +#define QSERDES_V4_PLL_POST_DIV_MUX 0xd8 +#define QSERDES_V4_PLL_BIAS_EN_CLKBUFLR_EN 0xdc +#define QSERDES_V4_PLL_CLK_ENABLE1 0xe0 +#define QSERDES_V4_PLL_SYS_CLK_CTRL 0xe4 +#define QSERDES_V4_PLL_PLL_IVCO 0xf4 +#define QSERDES_V4_PLL_SYSCLK_EN_SEL 0x110 +#define QSERDES_V4_PLL_LOCK_CMP_EN 0x120 +#define QSERDES_V4_PLL_LOCK_CMP_CFG 0x124 +#define QSERDES_V4_PLL_VCO_TUNE_MAP 0x140 +#define QSERDES_V4_PLL_CLK_SELECT 0x164 +#define QSERDES_V4_PLL_CORE_CLK_EN 0x170 +#define QSERDES_V4_PLL_CMN_CONFIG_1 0x174 +#define QSERDES_V4_PLL_CMN_MISC1 0x184 +#define QSERDES_V4_PLL_CMN_MODE 0x188 +#define QSERDES_V4_PLL_VCO_DC_LEVEL_CTRL 0x198 + +/* Only for QMP V4 2X2_1X4 PHY - TX registers */ +#define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX 0x30 +#define QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX 0x34 +#define QSERDES_V4_TX_LANE_MODE_1 0x78 +#define QSERDES_V4_TX_LANE_MODE_2 0x7c +#define QSERDES_V4_TX_LANE_MODE_3 0x80 +#define QSERDES_V4_TX_TRAN_DRVR_EMP_EN 0xAC + +/* Only for QMP V4 2X2_1X4 PHY - RX registers */ +#define QSERDES_V4_RX_UCDR_FO_GAIN_RATE2 0x08 +#define QSERDES_V4_RX_UCDR_SO_GAIN_RATE2 0x18 +#define QSERDES_V4_RX_UCDR_FO_GAIN_RATE3 0x0c +#define QSERDES_V4_RX_UCDR_SO_GAIN_RATE3 0x1c +#define QSERDES_V4_RX_UCDR_PI_CONTROLS 0x20 +#define QSERDES_V4_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3 0x34 +#define QSERDES_V4_RX_RX_IVCM_CAL_CTRL2 0x9c +#define QSERDES_V4_RX_RX_IVCM_POSTCAL_OFFSET 0xa0 +#define QSERDES_V4_RX_RX_BKUP_CTRL1 0x22c +#define QSERDES_V4_RX_DFE_1 0xac +#define QSERDES_V4_RX_DFE_2 0xb0 +#define QSERDES_V4_RX_DFE_3 0xb4 +#define QSERDES_V4_RX_VGA_CAL_MAN_VAL 0xe8 +#define QSERDES_V4_RX_VGA_CAL_CNTRL1 0xe0 +#define QSERDES_V4_RX_GM_CAL 0x10c +#define QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4 0x120 +#define QSERDES_V4_RX_SIGDET_ENABLES 0x148 +#define QSERDES_V4_RX_PHPRE_CTRL 0x188 +#define QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET 0x194 +#define QSERDES_V4_RX_Q_PI_INTRINSIC_BIAS_RATE32 0x1dc +#define QSERDES_V4_RX_RX_MODE_RATE2_B0 0x1f4 +#define QSERDES_V4_RX_RX_MODE_RATE2_B1 0x1f8 +#define QSERDES_V4_RX_RX_MODE_RATE2_B2 0x1fc +#define QSERDES_V4_RX_RX_MODE_RATE2_B3 0x200 +#define QSERDES_V4_RX_RX_MODE_RATE2_B4 0x204 +#define QSERDES_V4_RX_RX_MODE_RATE2_B5 0x208 +#define QSERDES_V4_RX_RX_MODE_RATE2_B6 0x20c +#define QSERDES_V4_RX_RX_MODE_RATE3_B0 0x210 +#define QSERDES_V4_RX_RX_MODE_RATE3_B1 0x214 +#define QSERDES_V4_RX_RX_MODE_RATE3_B2 0x218 +#define QSERDES_V4_RX_RX_MODE_RATE3_B3 0x21c +#define QSERDES_V4_RX_RX_MODE_RATE3_B4 0x220 +#define QSERDES_V4_RX_RX_MODE_RATE3_B5 0x224 +#define QSERDES_V4_RX_RX_MODE_RATE3_B6 0x228 +#define QSERDES_V4_RX_TX_ADPT_CTRL 0xd4 + +/* Only for QMP V4 2X2_1X4 PHY - Lane Shared registers */ +#define QSERDES_V4_LN_SHRD_RXCLK_DIV2_CTRL 0xA0 +#define QSERDES_V4_LN_SHRD_DFE_DAC_ENABLE1 0xB4 +#define QSERDES_V4_LN_SHRD_TX_ADAPT_POST_THRESH1 0xC4 +#define QSERDES_V4_LN_SHRD_TX_ADAPT_POST_THRESH2 0xC8 +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B0 0xD4 +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B1 0xD8 +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B2 0xDC +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B3 0xE0 +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B4 0xE4 +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B5 0xE8 +#define QSERDES_V4_LN_SHRD_RX_MODE_RATE_0_1_B6 0xEC +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210 0xF0 +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3 0xF4 +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210 0xF8 +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3 0xFC +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210 0x100 +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3 0x104 +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3 0x10C +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3 0x114 +#define QSERDES_V4_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3 0x11C +#define QSERDES_V4_LN_SHRD_RX_SUMMER_CAL_SPD_MODE 0x128 + +/* Only for QMP V4 2X2_1X4 PHY - PCS COM registers */ +#define QPHY_PCIE4_PCS_COM_G3S2_PRE_GAIN 0x178 +#define QPHY_PCIE4_PCS_COM_RX_SIGDET_LVL 0x190 +#define QPHY_PCIE4_PCS_COM_EQ_CONFIG4 0x1F8 +#define QPHY_PCIE4_PCS_COM_EQ_CONFIG5 0x1FC +#define QPHY_PCIE4_PCS_COM_PCS_TX_RX_CONFIG 0x1DC +#define QPHY_PCIE4_PCS_COM_PCS_TX_RX_CONFIG2 0x1E0 + +/* Only for QMP V4 2X2_1X4 PHY - PCS PCIE registers */ +#define QPHY_PCIE4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x1C +#define QPHY_PCIE4_PCS_PCIE_OSC_DTCT_ACTIONS 0x90 +#define QPHY_PCIE4_PCS_PCIE_EQ_CONFIG1 0xA0 +#define QPHY_PCIE4_PCS_PCIE_G4_EQ_CONFIG5 0x108 +#define QPHY_PCIE4_PCS_PCIE_G4_PRE_GAIN 0x15C +#define QPHY_PCIE4_PCS_PCIE_G3_FOM_EQ_CONFIG5 0x1AC +#define QPHY_PCIE4_PCS_PCIE_G4_FOM_EQ_CONFIG5 0x1C0 +#define QPHY_PCIE4_PCS_PCIE_G3_RXEQEVAL_TIME 0xF0 +#define QPHY_PCIE4_PCS_PCIE_G4_RXEQEVAL_TIME 0xF4 +#define QPHY_PCIE4_PCS_PCIE_RX_MARGINING_CONFIG1 0x17C +#define QPHY_PCIE4_PCS_PCIE_RX_MARGINING_CONFIG3 0x184 +#define QPHY_PCIE4_PCS_PCIE_RX_MARGINING_CONFIG5 0x18C +#define QPHY_PCIE4_PCS_PCIE_PCS_TX_RX_CONFIG 0x18 + +/* Only for QMP V4 2X2_1X4 PHY - Lane 0/1 PCS registers */ +#define QPHY_PCIE4_PCS_LANE0_OUTSIG_MX_CTRL2 0x38 +#define QPHY_PCIE4_PCS_LANE1_OUTSIG_MX_CTRL2 0x38 +#define QPHY_PCIE4_PCS_LANE1_INSIG_SW_CTRL2 0x24 +#define QPHY_PCIE4_PCS_LANE1_INSIG_MX_CTRL2 0x28 + +/* Only for QMP V4 2X2_1X4 PHY - PCS PCIE MISC registers */ +#define QPHY_PCIE4_PCS_PCIE_POWER_STATE_CONFIG2 0x0C +#endif /* QMP_PHY_2X2_1X4 */ +#endif /* QCOM_PHY_QMP_H_ */ diff --git a/src/soc/qualcomm/common/pcie_common.c b/src/soc/qualcomm/common/pcie_common.c index b877563a49..2ad32b02b2 100644 --- a/src/soc/qualcomm/common/pcie_common.c +++ b/src/soc/qualcomm/common/pcie_common.c @@ -16,6 +16,12 @@ #define ROOT_PORT_BDF 0x0 #define ATU_CTRL2 PCIE_ATU_UNR_REGION_CTRL2 +#if CONFIG(QMP_PHY_2X2_1X4) +#define LINK_SPEED_DEFAULT LINK_SPEED_GEN_4 +#else +#define LINK_SPEED_DEFAULT LINK_SPEED_GEN_2 +#endif + static struct qcom_pcie_cntlr_t qcom_pcie_cfg; static inline void dw_pcie_dbi_rd_wr(bool enable) @@ -96,6 +102,43 @@ static void qcom_dw_pcie_configure(uint32_t cap_speed) printk(BIOS_INFO, "PCIe Link speed configured in Gen %d\n", cap_speed); } +#if CONFIG(QMP_PHY_2X2_1X4) +static void post_phy_pwr_up_init(struct qcom_pcie_cntlr_t *pcie) +{ + pcie_cntlr_cfg_t *pcierc = pcie->cntlr_cfg; + /* configure PCIe to RC mode */ + write32(pcierc->parf + PCIE_PARF_DEVICE_TYPE, DEVICE_TYPE_RC); + dsb(); + clrbits32(pcierc->parf + PCIE_PARF_SLAVE_AXI_ERR_REPORT, AXI_SLAVE_ERR_CRS_BRESP_EN); + clrsetbits32(pcierc->dbi_base + PCIE_AMBA_ERR_RESP_DEFLT_OFF, AMBA_ERR_RESP_CRS_MASK, 0x2); + dsb(); + write32(pcierc->parf + PCIE_PARF_AXI_MSTR_WR_ADDR_HALT, 0x0); + write32(pcierc->parf + PCIE_SRIS_MODE, 0x0); + write32(pcierc->parf + PCIE_APP_MARGINING_CTRL, (APP_MARGINING_SW_READY | APP_MARGINING_READY)); + dsb(); +} + +static void post_phy_pwr_up_dbi_init(struct qcom_pcie_cntlr_t *pcie) +{ + pcie_cntlr_cfg_t *pcierc = pcie->cntlr_cfg; + dw_pcie_dbi_rd_wr(true); + write32(pcierc->dbi_base + PCIE_SPCIE_CAP_OFF_0CH_REG, 0x55555555); + write32(pcierc->dbi_base + PCIE_SPCIE_CAP_OFF_10H_REG, 0x55555555); + write32(pcierc->dbi_base + PCIE_PL16G_CAP_OFF_20H_REG, 0x55555555); + clrbits32(pcierc->dbi_base + PCIE_SLOT_CAPABILITIES_REG, PCIE_CAP_HOT_PLUG_CAPABLE); + dsb(); + clrsetbits32(pcierc->dbi_base + PCIE_GEN3_RELATED_OFF, RATE_SHADOW_SEL_MASK, 0x0); + clrsetbits32(pcierc->dbi_base + PCIE_GEN3_EQ_FB_MODE_DIR_CHANGE_OFF, GEN3_EQ_FMDC_T_MIN_PHASE23, 0x1); + clrbits32(pcierc->dbi_base + PCIE_GEN3_EQ_CONTROL_OFF, GEN3_EQ_PSET_REQ_VEC); + dsb(); + clrsetbits32(pcierc->dbi_base + PCIE_GEN3_RELATED_OFF, RATE_SHADOW_SEL_MASK, RATE_SHADOW_SEL_VAL); + clrsetbits32(pcierc->dbi_base + PCIE_GEN3_EQ_FB_MODE_DIR_CHANGE_OFF, GEN3_EQ_FMDC_T_MIN_PHASE23, 0x1); + clrbits32(pcierc->dbi_base + PCIE_GEN3_EQ_CONTROL_OFF, GEN3_EQ_PSET_REQ_VEC); + dsb(); + dw_pcie_dbi_rd_wr(false); +} +#endif + /** * is_pcie_link_up() - Return the link state * @@ -130,7 +173,7 @@ static enum cb_err qcom_pcie_dw_link_up(struct qcom_pcie_cntlr_t *pcie) } /* DW pre link configurations */ - qcom_dw_pcie_configure(LINK_SPEED_GEN_2); + qcom_dw_pcie_configure(LINK_SPEED_DEFAULT); /* enable link training */ setbits32(pcie->cntlr_cfg->parf + PCIE_PARF_LTSSM, LTSSM_EN); @@ -282,7 +325,7 @@ static void qcom_qmp_phy_configure(void *base, const struct qcom_qmp_phy_init_tb { qcom_qmp_phy_config_lane(base, tbl, num, 0xff); } - +#if !CONFIG(QMP_PHY_2X2_1X4) static enum cb_err qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t *qphy) { uint64_t lock_us; @@ -317,7 +360,7 @@ static enum cb_err qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t *qphy) * Wait for PHY initialization to be done * PCS_STATUS: wait for 1ms for PHY STATUS bit to be set */ - lock_us = wait_us(1000, !(read32(qphy->qmp_phy_base + QPHY_PCS_STATUS) & PHY_STATUS)); + lock_us = wait_us(PCIE_PHY_POLL_US, !(read32(qphy->qmp_phy_base + QPHY_PCS_STATUS) & PHY_STATUS)); if (!lock_us) { printk(BIOS_ERR, "PCIe QMP PHY PLL failed to lock in 1ms\n"); return CB_ERR; @@ -329,6 +372,70 @@ static enum cb_err qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t *qphy) return CB_SUCCESS; } +#else +static void configure_phy_port(pcie_qmp_phy_base_t *port, pcie_qmp_phy_cfg_t *qphy, int lane_base) +{ + qcom_qmp_phy_config_lane(port->tx0, qphy->tx_tbl, qphy->tx_tbl_num, lane_base); + qcom_qmp_phy_config_lane(port->rx0, qphy->rx_tbl, qphy->rx_tbl_num, lane_base); + qcom_qmp_phy_config_lane(port->tx1, qphy->tx_tbl, qphy->tx_tbl_num, lane_base + 1); + qcom_qmp_phy_config_lane(port->rx1, qphy->rx_tbl, qphy->rx_tbl_num, lane_base + 1); + qcom_qmp_phy_configure(port->ln_shrd, qphy->ln_shrd_tbl, qphy->ln_shrd_tbl_num); + qcom_qmp_phy_configure(port->serdes, qphy->serdes_tbl, qphy->serdes_tbl_num); + qcom_qmp_phy_configure(port->pcs, qphy->pcs_tbl, qphy->pcs_tbl_num); + qcom_qmp_phy_configure(port->pcs_misc, qphy->pcs_misc_tbl, qphy->pcs_misc_tbl_num); + qcom_qmp_phy_configure(port->pcs, qphy->pcs_tbl_sec, qphy->pcs_tbl_num_sec); + qcom_qmp_phy_configure(port->pcs_misc, qphy->pcs_misc_tbl_sec, qphy->pcs_misc_tbl_num_sec); + qcom_qmp_phy_configure(port->pcs_misc, qphy->pcs_misc_tbl_thrd, qphy->pcs_misc_tbl_num_thrd); + qcom_qmp_phy_configure(port->lane0_pcie_pcs, qphy->lane0_pcie_pcs_tbl, qphy->lane0_pcie_pcs_tbl_num); + qcom_qmp_phy_configure(port->lane1_pcie_pcs, qphy->lane1_pcie_pcs_tbl, qphy->lane1_pcie_pcs_tbl_num); +} + +static enum cb_err qcom_qmp_phy_power_on(pcie_qmp_phy_cfg_t *qphy) +{ + uint64_t lock_us; + + qcom_dw_pcie_enable_pipe_clock(); + + /* + * The PHY has two independent CSR interfaces that control lanes 0/1 and + * lanes 2/3. These are called PortA and PortB. + * + * In 1x4 mode, the PCS is only used in PortA and PortB + * writes are ignored, except for lane-specific registers + */ + /* Select Lane config 0x1 - 1x4 mode 0x0 - 2x2mode */ + write32(TCSR_PCIE_CTRL_4LN_CONFIG_SEL, 0x1); + write32(qphy->porta.serdes + QSERDES_V4_PLL_BIAS_EN_CLKBUFLR_EN, 0x1c); + write32(qphy->portb.serdes + QSERDES_V4_PLL_BIAS_EN_CLKBUFLR_EN, 0x1c); + + /* Release powerdown mode and allow endpoint refclk drive */ + write32(qphy->porta.pcs + QPHY_PCS_PWR_DWN_CNTRL, SW_PWRDN | REFCLK_DRV_DSBL); + + /* Write all PLL/TX/RX/PCS config registers on Port A */ + configure_phy_port(&qphy->porta, qphy, 1); + /* Write all PLL/TX/RX/PCS config registers on Port B */ + configure_phy_port(&qphy->portb, qphy, 3); + + /* Release software reset of PCS/Serdes */ + clrbits32(qphy->porta.pcs + QPHY_SW_RESET, SW_RESET); + + /* start PCS/Serdes to operation mode */ + write32(qphy->porta.pcs + QPHY_START_CTRL, PCS_START | SERDES_START); + + /* + * Wait for PHY initialization to be done + * PCS_STATUS: wait for 1ms for PHY STATUS bit to be set + */ + lock_us = wait_us(PCIE_PHY_POLL_US, !(read32(qphy->porta.qmp_phy_base + QPHY_PCS_STATUS) & PHY_STATUS)); + if (!lock_us) { + printk(BIOS_ERR, "PCIe QMP PHY PLL failed to lock in 1ms\n"); + return CB_ERR; + } + + printk(BIOS_DEBUG, "PCIe QPHY Initialized took %lldus\n", lock_us); + return CB_SUCCESS; +} +#endif /* * Reset the PCIe PHY core. @@ -394,7 +501,10 @@ static enum cb_err qcom_dw_pcie_enable(struct qcom_pcie_cntlr_t *pcie) } qcom_dw_pcie_setup_rc(pcie); - +#if CONFIG(QMP_PHY_2X2_1X4) + post_phy_pwr_up_init(pcie); + post_phy_pwr_up_dbi_init(pcie); +#endif /* de-assert PCIe reset link to bring EP out of reset */ gpio_set(pcierc->perst, 1);