Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phy: Add QMP phy based UFS phy support for sdm845

Add UFS PHY support to make SDM845 UFS work with common PHY framework.

Signed-off-by: Can Guo <cang@codeaurora.org>
Reviewed-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

authored by

Can Guo and committed by
Kishon Vijay Abraham I
cc31cdbe 6b045268

+186 -1
+171 -1
drivers/phy/qualcomm/phy-qcom-qmp.c
··· 156 156 [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, 157 157 }; 158 158 159 + static const unsigned int sdm845_ufsphy_regs_layout[] = { 160 + [QPHY_START_CTRL] = 0x00, 161 + [QPHY_PCS_READY_STATUS] = 0x160, 162 + }; 163 + 159 164 static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { 160 165 QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), 161 166 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ··· 606 601 QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), 607 602 }; 608 603 604 + static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { 605 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), 606 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), 607 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), 608 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), 609 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), 610 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5), 611 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), 612 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), 613 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), 614 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), 615 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), 616 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), 617 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04), 618 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05), 619 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff), 620 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00), 621 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), 622 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), 623 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), 624 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), 625 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), 626 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), 627 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda), 628 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), 629 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff), 630 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c), 631 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98), 632 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06), 633 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16), 634 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36), 635 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), 636 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00), 637 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1), 638 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00), 639 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32), 640 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f), 641 + 642 + /* Rate B */ 643 + QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44), 644 + }; 645 + 646 + static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = { 647 + QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), 648 + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04), 649 + QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), 650 + }; 651 + 652 + static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = { 653 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24), 654 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f), 655 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), 656 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), 657 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), 658 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b), 659 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), 660 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), 661 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b), 662 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), 663 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), 664 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04), 665 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), 666 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81), 667 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), 668 + QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), 669 + }; 670 + 671 + static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = { 672 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e), 673 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a), 674 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02), 675 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03), 676 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43), 677 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f), 678 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a), 679 + QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02), 680 + }; 609 681 610 682 /* struct qmp_phy_cfg - per-PHY initialization config */ 611 683 struct qmp_phy_cfg { ··· 736 654 /* Register offset of secondary tx/rx lanes for USB DP combo PHY */ 737 655 unsigned int tx_b_lane_offset; 738 656 unsigned int rx_b_lane_offset; 657 + 658 + /* true, if PCS block has no separate SW_RESET register */ 659 + bool no_pcs_sw_reset; 739 660 }; 740 661 741 662 /** ··· 833 748 834 749 static const char * const qmp_v3_phy_clk_l[] = { 835 750 "aux", "cfg_ahb", "ref", "com_aux", 751 + }; 752 + 753 + static const char * const sdm845_ufs_phy_clk_l[] = { 754 + "ref", "ref_aux", 836 755 }; 837 756 838 757 /* list of resets */ ··· 1006 917 .has_pwrdn_delay = true, 1007 918 .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, 1008 919 .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, 920 + }; 921 + 922 + static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { 923 + .type = PHY_TYPE_UFS, 924 + .nlanes = 2, 925 + 926 + .serdes_tbl = sdm845_ufsphy_serdes_tbl, 927 + .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), 928 + .tx_tbl = sdm845_ufsphy_tx_tbl, 929 + .tx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_tx_tbl), 930 + .rx_tbl = sdm845_ufsphy_rx_tbl, 931 + .rx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_rx_tbl), 932 + .pcs_tbl = sdm845_ufsphy_pcs_tbl, 933 + .pcs_tbl_num = ARRAY_SIZE(sdm845_ufsphy_pcs_tbl), 934 + .clk_list = sdm845_ufs_phy_clk_l, 935 + .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), 936 + .vreg_list = qmp_phy_vreg_l, 937 + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), 938 + .regs = sdm845_ufsphy_regs_layout, 939 + 940 + .start_ctrl = SERDES_START, 941 + .pwrdn_ctrl = SW_PWRDN, 942 + .mask_pcs_ready = PCS_READY, 943 + 944 + .is_dual_lane_phy = true, 945 + .tx_b_lane_offset = 0x400, 946 + .rx_b_lane_offset = 0x400, 947 + 948 + .no_pcs_sw_reset = true, 1009 949 }; 1010 950 1011 951 static void qcom_qmp_phy_configure(void __iomem *base, ··· 1249 1131 qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); 1250 1132 1251 1133 /* 1134 + * UFS PHY requires the deassert of software reset before serdes start. 1135 + * For UFS PHYs that do not have software reset control bits, defer 1136 + * starting serdes until the power on callback. 1137 + */ 1138 + if ((cfg->type == PHY_TYPE_UFS) && cfg->no_pcs_sw_reset) 1139 + goto out; 1140 + 1141 + /* 1252 1142 * Pull out PHY from POWER DOWN state. 1253 1143 * This is active low enable signal to power-down PHY. 1254 1144 */ ··· 1285 1159 } 1286 1160 qmp->phy_initialized = true; 1287 1161 1162 + out: 1288 1163 return ret; 1289 1164 1290 1165 err_pcs_ready: ··· 1308 1181 clk_disable_unprepare(qphy->pipe_clk); 1309 1182 1310 1183 /* PHY reset */ 1311 - qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); 1184 + if (!cfg->no_pcs_sw_reset) 1185 + qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); 1312 1186 1313 1187 /* stop SerDes and Phy-Coding-Sublayer */ 1314 1188 qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ··· 1325 1197 qmp->phy_initialized = false; 1326 1198 1327 1199 return 0; 1200 + } 1201 + 1202 + static int qcom_qmp_phy_poweron(struct phy *phy) 1203 + { 1204 + struct qmp_phy *qphy = phy_get_drvdata(phy); 1205 + struct qcom_qmp *qmp = qphy->qmp; 1206 + const struct qmp_phy_cfg *cfg = qmp->cfg; 1207 + void __iomem *pcs = qphy->pcs; 1208 + void __iomem *status; 1209 + unsigned int mask, val; 1210 + int ret = 0; 1211 + 1212 + if (cfg->type != PHY_TYPE_UFS) 1213 + return 0; 1214 + 1215 + /* 1216 + * For UFS PHY that has not software reset control, serdes start 1217 + * should only happen when UFS driver explicitly calls phy_power_on 1218 + * after it deasserts software reset. 1219 + */ 1220 + if (cfg->no_pcs_sw_reset && !qmp->phy_initialized && 1221 + (qmp->init_count != 0)) { 1222 + /* start SerDes and Phy-Coding-Sublayer */ 1223 + qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); 1224 + 1225 + status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; 1226 + mask = cfg->mask_pcs_ready; 1227 + 1228 + ret = readl_poll_timeout(status, val, !(val & mask), 1, 1229 + PHY_INIT_COMPLETE_TIMEOUT); 1230 + if (ret) { 1231 + dev_err(qmp->dev, "phy initialization timed-out\n"); 1232 + return ret; 1233 + } 1234 + qmp->phy_initialized = true; 1235 + } 1236 + 1237 + return ret; 1328 1238 } 1329 1239 1330 1240 static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode) ··· 1594 1428 static const struct phy_ops qcom_qmp_phy_gen_ops = { 1595 1429 .init = qcom_qmp_phy_init, 1596 1430 .exit = qcom_qmp_phy_exit, 1431 + .power_on = qcom_qmp_phy_poweron, 1597 1432 .set_mode = qcom_qmp_phy_set_mode, 1598 1433 .owner = THIS_MODULE, 1599 1434 }; ··· 1697 1530 }, { 1698 1531 .compatible = "qcom,sdm845-qmp-usb3-uni-phy", 1699 1532 .data = &qmp_v3_usb3_uniphy_cfg, 1533 + }, { 1534 + .compatible = "qcom,sdm845-qmp-ufs-phy", 1535 + .data = &sdm845_ufsphy_cfg, 1700 1536 }, 1701 1537 { }, 1702 1538 };
+15
drivers/phy/qualcomm/phy-qcom-qmp.h
··· 184 184 #define QSERDES_V3_COM_VCO_TUNE2_MODE0 0x0f8 185 185 #define QSERDES_V3_COM_VCO_TUNE1_MODE1 0x0fc 186 186 #define QSERDES_V3_COM_VCO_TUNE2_MODE1 0x100 187 + #define QSERDES_V3_COM_VCO_TUNE_INITVAL1 0x104 188 + #define QSERDES_V3_COM_VCO_TUNE_INITVAL2 0x108 187 189 #define QSERDES_V3_COM_VCO_TUNE_TIMER1 0x11c 188 190 #define QSERDES_V3_COM_VCO_TUNE_TIMER2 0x120 189 191 #define QSERDES_V3_COM_CLK_SELECT 0x138 ··· 213 211 /* Only for QMP V3 PHY - RX registers */ 214 212 #define QSERDES_V3_RX_UCDR_SO_GAIN_HALF 0x00c 215 213 #define QSERDES_V3_RX_UCDR_SO_GAIN 0x014 214 + #define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF 0x024 215 + #define QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER 0x028 216 + #define QSERDES_V3_RX_UCDR_SVS_SO_GAIN 0x02c 216 217 #define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN 0x030 217 218 #define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034 219 + #define QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c 220 + #define QSERDES_V3_RX_UCDR_PI_CONTROLS 0x044 218 221 #define QSERDES_V3_RX_RX_TERM_BW 0x07c 219 222 #define QSERDES_V3_RX_VGA_CAL_CNTRL1 0x0bc 220 223 #define QSERDES_V3_RX_VGA_CAL_CNTRL2 0x0c0 ··· 246 239 #define QPHY_V3_PCS_TXMGN_V3 0x018 247 240 #define QPHY_V3_PCS_TXMGN_V4 0x01c 248 241 #define QPHY_V3_PCS_TXMGN_LS 0x020 242 + #define QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL 0x02c 243 + #define QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL 0x034 249 244 #define QPHY_V3_PCS_TXDEEMPH_M6DB_V0 0x024 250 245 #define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0 0x028 251 246 #define QPHY_V3_PCS_TXDEEMPH_M6DB_V1 0x02c ··· 284 275 #define QPHY_V3_PCS_FLL_CNT_VAL_L 0x0cc 285 276 #define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL 0x0d0 286 277 #define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4 278 + #define QPHY_V3_PCS_RX_SYM_RESYNC_CTRL 0x134 279 + #define QPHY_V3_PCS_RX_MIN_HIBERN8_TIME 0x138 280 + #define QPHY_V3_PCS_RX_SIGDET_CTRL1 0x13c 281 + #define QPHY_V3_PCS_RX_SIGDET_CTRL2 0x140 282 + #define QPHY_V3_PCS_TX_MID_TERM_CTRL1 0x1bc 283 + #define QPHY_V3_PCS_MULTI_LANE_CTRL1 0x1c4 287 284 #define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8 288 285 #define QPHY_V3_PCS_REFGEN_REQ_CONFIG1 0x20c 289 286 #define QPHY_V3_PCS_REFGEN_REQ_CONFIG2 0x210