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

phy: qualcomm: phy-qcom-qmp-ufs: Add High Speed Gear 5 support for SM8550

On SM8550, two sets of UFS PHY settings are provided, one set is to support
HS-G5, another set is to support HS-G4 and lower gears. The two sets of PHY
settings are programming different values to different registers, mixing
the two sets and/or overwriting one set with another set is definitely not
blessed by UFS PHY designers.

To add HS-G5 support for SM8550, split the two sets of PHY settings into
their dedicated overlay tables, only the common parts of the two sets of
PHY settings are left in the .tbls.

Consider we are going to add even higher gear support in future, to avoid
adding more tables with different names, rename the .tbls_hs_g4 and make it
an array, a size of 2 is enough as of now.

In this case, .tbls alone is not a complete set of PHY settings, so either
tbls_hs_overlay[0] or tbls_hs_overlay[1] must be applied on top of the
.tbls to become a complete set of PHY settings.

Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Can Guo <quic_cang@quicinc.com>
Link: https://lore.kernel.org/r/1703557892-1822-1-git-send-email-quic_cang@quicinc.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Can Guo and committed by
Vinod Koul
b34ae859 7551d945

+159 -22
+2
drivers/phy/qualcomm/phy-qcom-qmp-pcs-ufs-v6.h
··· 19 19 #define QPHY_V6_PCS_UFS_BIST_FIXED_PAT_CTRL 0x060 20 20 #define QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY 0x074 21 21 #define QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY 0x0bc 22 + #define QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY 0x12c 22 23 #define QPHY_V6_PCS_UFS_DEBUG_BUS_CLKSEL 0x158 23 24 #define QPHY_V6_PCS_UFS_LINECFG_DISABLE 0x17c 24 25 #define QPHY_V6_PCS_UFS_RX_MIN_HIBERN8_TIME 0x184 ··· 29 28 #define QPHY_V6_PCS_UFS_READY_STATUS 0x1a8 30 29 #define QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1 0x1f4 31 30 #define QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1 0x1fc 31 + #define QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME 0x220 32 32 33 33 #endif
+2
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-com-v6.h
··· 60 60 #define QSERDES_V6_COM_SYSCLK_BUF_ENABLE 0xe8 61 61 #define QSERDES_V6_COM_PLL_IVCO 0xf4 62 62 #define QSERDES_V6_COM_PLL_IVCO_MODE1 0xf8 63 + #define QSERDES_V6_COM_CMN_IETRIM 0xfc 64 + #define QSERDES_V6_COM_CMN_IPTRIM 0x100 63 65 #define QSERDES_V6_COM_SYSCLK_EN_SEL 0x110 64 66 #define QSERDES_V6_COM_RESETSM_CNTRL 0x118 65 67 #define QSERDES_V6_COM_LOCK_CMP_EN 0x120
+8
drivers/phy/qualcomm/phy-qcom-qmp-qserdes-txrx-ufs-v6.h
··· 15 15 16 16 #define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE2 0x08 17 17 #define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4 0x10 18 + #define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4 0x24 18 19 #define QSERDES_UFS_V6_RX_UCDR_SO_SATURATION 0x28 20 + #define QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4 0x54 19 21 #define QSERDES_UFS_V6_RX_UCDR_PI_CTRL1 0x58 20 22 #define QSERDES_UFS_V6_RX_RX_TERM_BW_CTRL0 0xc4 21 23 #define QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2 0xd4 22 24 #define QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4 0xdc 25 + #define QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4 0xf0 26 + #define QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS 0xf4 23 27 #define QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL 0x178 28 + #define QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x1bc 24 29 #define QSERDES_UFS_V6_RX_INTERFACE_MODE 0x1e0 30 + #define QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3 0x1c4 25 31 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0 0x208 26 32 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1 0x20c 27 33 #define QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3 0x214 ··· 39 33 #define QSERDES_UFS_V6_RX_MODE_RATE3_B5 0x264 40 34 #define QSERDES_UFS_V6_RX_MODE_RATE3_B8 0x270 41 35 #define QSERDES_UFS_V6_RX_MODE_RATE4_B3 0x280 36 + #define QSERDES_UFS_V6_RX_MODE_RATE4_B4 0x284 42 37 #define QSERDES_UFS_V6_RX_MODE_RATE4_B6 0x28c 38 + #define QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL 0x2f8 43 39 44 40 #endif
+147 -22
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
··· 41 41 42 42 #define PHY_INIT_COMPLETE_TIMEOUT 10000 43 43 44 + #define NUM_OVERLAY 2 45 + 44 46 struct qmp_phy_init_tbl { 45 47 unsigned int offset; 46 48 unsigned int val; ··· 756 754 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11), 757 755 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), 758 756 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01), 759 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04), 760 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f), 761 757 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00), 762 758 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41), 763 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a), 764 759 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18), 765 760 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14), 766 761 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f), 767 762 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06), 763 + }; 764 + 765 + static const struct qmp_phy_init_tbl sm8550_ufsphy_hs_b_serdes[] = { 766 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44), 767 + }; 768 + 769 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_serdes[] = { 770 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04), 771 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f), 772 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a), 768 773 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c), 769 774 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x0a), 770 775 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18), ··· 780 771 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x07), 781 772 }; 782 773 783 - static const struct qmp_phy_init_tbl sm8550_ufsphy_hs_b_serdes[] = { 784 - QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44), 774 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g5_serdes[] = { 775 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f), 776 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x1b), 777 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x1c), 778 + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06), 785 779 }; 786 780 787 781 static const struct qmp_phy_init_tbl sm8550_ufsphy_tx[] = { 788 782 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05), 789 783 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07), 784 + }; 785 + 786 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_tx[] = { 790 787 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_FR_DCC_CTRL, 0x4c), 791 788 }; 792 789 793 790 static const struct qmp_phy_init_tbl sm8550_ufsphy_rx[] = { 794 791 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c), 795 - QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e), 796 792 797 793 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xc2), 798 794 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xc2), ··· 813 799 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02), 814 800 }; 815 801 802 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_rx[] = { 803 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e), 804 + }; 805 + 806 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g5_rx[] = { 807 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0c), 808 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4, 0x04), 809 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14), 810 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS, 0x07), 811 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e), 812 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02), 813 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c), 814 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06), 815 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x08), 816 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B3, 0xb9), 817 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B4, 0x4f), 818 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B6, 0xff), 819 + QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30), 820 + }; 821 + 816 822 static const struct qmp_phy_init_tbl sm8550_ufsphy_pcs[] = { 817 823 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x69), 818 824 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f), 819 825 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), 820 - QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x2b), 821 826 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02), 827 + }; 828 + 829 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g4_pcs[] = { 830 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x2b), 822 831 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04), 823 832 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04), 833 + }; 834 + 835 + static const struct qmp_phy_init_tbl sm8550_ufsphy_g5_pcs[] = { 836 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33), 837 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4f), 838 + QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e), 824 839 }; 825 840 826 841 static const struct qmp_phy_init_tbl sm8650_ufsphy_serdes[] = { ··· 932 889 int rx_num; 933 890 const struct qmp_phy_init_tbl *pcs; 934 891 int pcs_num; 892 + /* Maximum supported Gear of this tbls */ 893 + u32 max_gear; 935 894 }; 936 895 937 896 /* struct qmp_phy_cfg - per-PHY initialization config */ ··· 941 896 int lanes; 942 897 943 898 const struct qmp_ufs_offsets *offsets; 899 + /* Maximum supported Gear of this config */ 900 + u32 max_supported_gear; 944 901 945 902 /* Main init sequence for PHY blocks - serdes, tx, rx, pcs */ 946 903 const struct qmp_phy_cfg_tbls tbls; 947 904 /* Additional sequence for HS Series B */ 948 905 const struct qmp_phy_cfg_tbls tbls_hs_b; 949 - /* Additional sequence for HS G4 */ 950 - const struct qmp_phy_cfg_tbls tbls_hs_g4; 906 + /* Additional sequence for different HS Gears */ 907 + const struct qmp_phy_cfg_tbls tbls_hs_overlay[NUM_OVERLAY]; 951 908 952 909 /* clock ids to be requested */ 953 910 const char * const *clk_list; ··· 1052 1005 .lanes = 1, 1053 1006 1054 1007 .offsets = &qmp_ufs_offsets, 1008 + .max_supported_gear = UFS_HS_G3, 1055 1009 1056 1010 .tbls = { 1057 1011 .serdes = msm8996_ufsphy_serdes, ··· 1078 1030 .lanes = 2, 1079 1031 1080 1032 .offsets = &qmp_ufs_offsets, 1033 + .max_supported_gear = UFS_HS_G4, 1081 1034 1082 1035 .tbls = { 1083 1036 .serdes = sm8350_ufsphy_serdes, ··· 1094 1045 .serdes = sm8350_ufsphy_hs_b_serdes, 1095 1046 .serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes), 1096 1047 }, 1097 - .tbls_hs_g4 = { 1048 + .tbls_hs_overlay[0] = { 1098 1049 .tx = sm8350_ufsphy_g4_tx, 1099 1050 .tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx), 1100 1051 .rx = sm8350_ufsphy_g4_rx, 1101 1052 .rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx), 1102 1053 .pcs = sm8350_ufsphy_g4_pcs, 1103 1054 .pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs), 1055 + .max_gear = UFS_HS_G4, 1104 1056 }, 1105 1057 .clk_list = sm8450_ufs_phy_clk_l, 1106 1058 .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ··· 1114 1064 .lanes = 2, 1115 1065 1116 1066 .offsets = &qmp_ufs_offsets, 1067 + .max_supported_gear = UFS_HS_G4, 1117 1068 1118 1069 .tbls = { 1119 1070 .serdes = sm8150_ufsphy_serdes, ··· 1130 1079 .serdes = sm8150_ufsphy_hs_b_serdes, 1131 1080 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes), 1132 1081 }, 1133 - .tbls_hs_g4 = { 1082 + .tbls_hs_overlay[0] = { 1134 1083 .tx = sm8250_ufsphy_hs_g4_tx, 1135 1084 .tx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_tx), 1136 1085 .rx = sc7280_ufsphy_hs_g4_rx, 1137 1086 .rx_num = ARRAY_SIZE(sc7280_ufsphy_hs_g4_rx), 1138 1087 .pcs = sm8150_ufsphy_hs_g4_pcs, 1139 1088 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs), 1089 + .max_gear = UFS_HS_G4, 1140 1090 }, 1141 1091 .clk_list = sm8450_ufs_phy_clk_l, 1142 1092 .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ··· 1150 1098 .lanes = 2, 1151 1099 1152 1100 .offsets = &qmp_ufs_offsets, 1101 + .max_supported_gear = UFS_HS_G4, 1153 1102 1154 1103 .tbls = { 1155 1104 .serdes = sm8350_ufsphy_serdes, ··· 1166 1113 .serdes = sm8350_ufsphy_hs_b_serdes, 1167 1114 .serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes), 1168 1115 }, 1169 - .tbls_hs_g4 = { 1116 + .tbls_hs_overlay[0] = { 1170 1117 .tx = sm8350_ufsphy_g4_tx, 1171 1118 .tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx), 1172 1119 .rx = sm8350_ufsphy_g4_rx, 1173 1120 .rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx), 1174 1121 .pcs = sm8350_ufsphy_g4_pcs, 1175 1122 .pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs), 1123 + .max_gear = UFS_HS_G4, 1176 1124 }, 1177 1125 .clk_list = sdm845_ufs_phy_clk_l, 1178 1126 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ··· 1186 1132 .lanes = 2, 1187 1133 1188 1134 .offsets = &qmp_ufs_offsets, 1135 + .max_supported_gear = UFS_HS_G3, 1189 1136 1190 1137 .tbls = { 1191 1138 .serdes = sdm845_ufsphy_serdes, ··· 1215 1160 .lanes = 1, 1216 1161 1217 1162 .offsets = &qmp_ufs_offsets, 1163 + .max_supported_gear = UFS_HS_G3, 1218 1164 1219 1165 .tbls = { 1220 1166 .serdes = sm6115_ufsphy_serdes, ··· 1244 1188 .lanes = 1, 1245 1189 1246 1190 .offsets = &qmp_ufs_offsets, 1191 + .max_supported_gear = UFS_HS_G3, 1247 1192 1248 1193 .tbls = { 1249 1194 .serdes = sdm845_ufsphy_serdes, ··· 1273 1216 .lanes = 2, 1274 1217 1275 1218 .offsets = &qmp_ufs_offsets, 1219 + .max_supported_gear = UFS_HS_G4, 1276 1220 1277 1221 .tbls = { 1278 1222 .serdes = sm8150_ufsphy_serdes, ··· 1289 1231 .serdes = sm8150_ufsphy_hs_b_serdes, 1290 1232 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes), 1291 1233 }, 1292 - .tbls_hs_g4 = { 1234 + .tbls_hs_overlay[0] = { 1293 1235 .tx = sm8150_ufsphy_hs_g4_tx, 1294 1236 .tx_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_tx), 1295 1237 .rx = sm8150_ufsphy_hs_g4_rx, 1296 1238 .rx_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_rx), 1297 1239 .pcs = sm8150_ufsphy_hs_g4_pcs, 1298 1240 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs), 1241 + .max_gear = UFS_HS_G4, 1299 1242 }, 1300 1243 .clk_list = sdm845_ufs_phy_clk_l, 1301 1244 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ··· 1309 1250 .lanes = 2, 1310 1251 1311 1252 .offsets = &qmp_ufs_offsets, 1253 + .max_supported_gear = UFS_HS_G4, 1312 1254 1313 1255 .tbls = { 1314 1256 .serdes = sm8150_ufsphy_serdes, ··· 1325 1265 .serdes = sm8150_ufsphy_hs_b_serdes, 1326 1266 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes), 1327 1267 }, 1328 - .tbls_hs_g4 = { 1268 + .tbls_hs_overlay[0] = { 1329 1269 .tx = sm8250_ufsphy_hs_g4_tx, 1330 1270 .tx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_tx), 1331 1271 .rx = sm8250_ufsphy_hs_g4_rx, 1332 1272 .rx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_rx), 1333 1273 .pcs = sm8150_ufsphy_hs_g4_pcs, 1334 1274 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs), 1275 + .max_gear = UFS_HS_G4, 1335 1276 }, 1336 1277 .clk_list = sdm845_ufs_phy_clk_l, 1337 1278 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ··· 1345 1284 .lanes = 2, 1346 1285 1347 1286 .offsets = &qmp_ufs_offsets, 1287 + .max_supported_gear = UFS_HS_G4, 1348 1288 1349 1289 .tbls = { 1350 1290 .serdes = sm8350_ufsphy_serdes, ··· 1361 1299 .serdes = sm8350_ufsphy_hs_b_serdes, 1362 1300 .serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes), 1363 1301 }, 1364 - .tbls_hs_g4 = { 1302 + .tbls_hs_overlay[0] = { 1365 1303 .tx = sm8350_ufsphy_g4_tx, 1366 1304 .tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx), 1367 1305 .rx = sm8350_ufsphy_g4_rx, 1368 1306 .rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx), 1369 1307 .pcs = sm8350_ufsphy_g4_pcs, 1370 1308 .pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs), 1309 + .max_gear = UFS_HS_G4, 1371 1310 }, 1372 1311 .clk_list = sdm845_ufs_phy_clk_l, 1373 1312 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ··· 1381 1318 .lanes = 2, 1382 1319 1383 1320 .offsets = &qmp_ufs_offsets, 1321 + .max_supported_gear = UFS_HS_G4, 1384 1322 1385 1323 .tbls = { 1386 1324 .serdes = sm8350_ufsphy_serdes, ··· 1397 1333 .serdes = sm8350_ufsphy_hs_b_serdes, 1398 1334 .serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes), 1399 1335 }, 1400 - .tbls_hs_g4 = { 1336 + .tbls_hs_overlay[0] = { 1401 1337 .tx = sm8350_ufsphy_g4_tx, 1402 1338 .tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx), 1403 1339 .rx = sm8350_ufsphy_g4_rx, 1404 1340 .rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx), 1405 1341 .pcs = sm8350_ufsphy_g4_pcs, 1406 1342 .pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs), 1343 + .max_gear = UFS_HS_G4, 1407 1344 }, 1408 1345 .clk_list = sm8450_ufs_phy_clk_l, 1409 1346 .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ··· 1417 1352 .lanes = 2, 1418 1353 1419 1354 .offsets = &qmp_ufs_offsets_v6, 1355 + .max_supported_gear = UFS_HS_G5, 1420 1356 1421 1357 .tbls = { 1422 1358 .serdes = sm8550_ufsphy_serdes, ··· 1433 1367 .serdes = sm8550_ufsphy_hs_b_serdes, 1434 1368 .serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes), 1435 1369 }, 1370 + .tbls_hs_overlay[0] = { 1371 + .serdes = sm8550_ufsphy_g4_serdes, 1372 + .serdes_num = ARRAY_SIZE(sm8550_ufsphy_g4_serdes), 1373 + .tx = sm8550_ufsphy_g4_tx, 1374 + .tx_num = ARRAY_SIZE(sm8550_ufsphy_g4_tx), 1375 + .rx = sm8550_ufsphy_g4_rx, 1376 + .rx_num = ARRAY_SIZE(sm8550_ufsphy_g4_rx), 1377 + .pcs = sm8550_ufsphy_g4_pcs, 1378 + .pcs_num = ARRAY_SIZE(sm8550_ufsphy_g4_pcs), 1379 + .max_gear = UFS_HS_G4, 1380 + }, 1381 + .tbls_hs_overlay[1] = { 1382 + .serdes = sm8550_ufsphy_g5_serdes, 1383 + .serdes_num = ARRAY_SIZE(sm8550_ufsphy_g5_serdes), 1384 + .rx = sm8550_ufsphy_g5_rx, 1385 + .rx_num = ARRAY_SIZE(sm8550_ufsphy_g5_rx), 1386 + .pcs = sm8550_ufsphy_g5_pcs, 1387 + .pcs_num = ARRAY_SIZE(sm8550_ufsphy_g5_pcs), 1388 + .max_gear = UFS_HS_G5, 1389 + }, 1436 1390 .clk_list = sdm845_ufs_phy_clk_l, 1437 1391 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), 1438 1392 .vreg_list = qmp_phy_vreg_l, ··· 1464 1378 .lanes = 2, 1465 1379 1466 1380 .offsets = &qmp_ufs_offsets_v6, 1381 + .max_supported_gear = UFS_HS_G5, 1467 1382 1468 1383 .tbls = { 1469 1384 .serdes = sm8650_ufsphy_serdes, ··· 1538 1451 qmp_ufs_configure(pcs, tbls->pcs, tbls->pcs_num); 1539 1452 } 1540 1453 1454 + static int qmp_ufs_get_gear_overlay(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg) 1455 + { 1456 + u32 max_gear, floor_max_gear = cfg->max_supported_gear; 1457 + int idx, ret = -EINVAL; 1458 + 1459 + for (idx = NUM_OVERLAY - 1; idx >= 0; idx--) { 1460 + max_gear = cfg->tbls_hs_overlay[idx].max_gear; 1461 + 1462 + /* Skip if the table is not available */ 1463 + if (max_gear == 0) 1464 + continue; 1465 + 1466 + /* Direct matching, bail */ 1467 + if (qmp->submode == max_gear) 1468 + return idx; 1469 + 1470 + /* If no direct matching, the lowest gear is the best matching */ 1471 + if (max_gear < floor_max_gear) { 1472 + ret = idx; 1473 + floor_max_gear = max_gear; 1474 + } 1475 + } 1476 + 1477 + return ret; 1478 + } 1479 + 1541 1480 static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg *cfg) 1542 1481 { 1482 + int i; 1483 + 1543 1484 qmp_ufs_serdes_init(qmp, &cfg->tbls); 1485 + qmp_ufs_lanes_init(qmp, &cfg->tbls); 1486 + qmp_ufs_pcs_init(qmp, &cfg->tbls); 1487 + 1488 + i = qmp_ufs_get_gear_overlay(qmp, cfg); 1489 + if (i >= 0) { 1490 + qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_overlay[i]); 1491 + qmp_ufs_lanes_init(qmp, &cfg->tbls_hs_overlay[i]); 1492 + qmp_ufs_pcs_init(qmp, &cfg->tbls_hs_overlay[i]); 1493 + } 1494 + 1544 1495 if (qmp->mode == PHY_MODE_UFS_HS_B) 1545 1496 qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_b); 1546 - qmp_ufs_lanes_init(qmp, &cfg->tbls); 1547 - if (qmp->submode == UFS_HS_G4) 1548 - qmp_ufs_lanes_init(qmp, &cfg->tbls_hs_g4); 1549 - qmp_ufs_pcs_init(qmp, &cfg->tbls); 1550 - if (qmp->submode == UFS_HS_G4) 1551 - qmp_ufs_pcs_init(qmp, &cfg->tbls_hs_g4); 1552 1497 } 1553 1498 1554 1499 static int qmp_ufs_com_init(struct qmp_ufs *qmp) ··· 1752 1633 static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode) 1753 1634 { 1754 1635 struct qmp_ufs *qmp = phy_get_drvdata(phy); 1636 + const struct qmp_phy_cfg *cfg = qmp->cfg; 1637 + 1638 + if (submode > cfg->max_supported_gear || submode == 0) { 1639 + dev_err(qmp->dev, "Invalid PHY submode %d\n", submode); 1640 + return -EINVAL; 1641 + } 1755 1642 1756 1643 qmp->mode = mode; 1757 1644 qmp->submode = submode;