soc/qualcomm/common: Integrate QMP PCIe 4.0 PHY 2x2/1x4

Enable QMP PCIe 4.0 PHY 2x2/1x4 lanes.
The register details are part of HRD-X1P42100-S1 document.
https://docs.qualcomm.com/bundle/resource/topics/HRD-X1P42100-S1/

TEST= Verified that link is enumerated and NVMe is accessible via PCIE.

Change-Id: I8a3cb1b21e712e588f641f70c040a2334faf0031
Signed-off-by: Hari L <haril@qualcomm.corp-partner.google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88543
Reviewed-by: Subrata Banik <subratabanik@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
This commit is contained in:
Hari L 2025-07-28 12:20:49 +05:30 committed by Subrata Banik
commit 823fa6b8f6
4 changed files with 332 additions and 5 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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_ */

View file

@ -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);