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

Configure Feed

Select the types of activity you want to include in your feed.

Merge patch series "ufs: qcom: Add HS-G4 support"

Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> says:

This series adds HS-G4 support to the Qcom UFS driver and PHY driver.
The newer Qcom platforms support configuring the UFS controller and
PHY in dual gears (i.e., controller/PHY can be configured to run in
two gear speeds). This is accomplished by adding two different PHY
init sequences to the PHY driver and the UFS driver requesting the one
that's required based on the platform configuration.

Initially the ufs-qcom driver will use the default gear G2 for
enumerating the UFS device. Afer enumeration, the max gear supported
by both the controller and device would be found out and that will be
used thereafter. But for using the max gear after enumeration, the
ufs-qcom driver requires the UFS device to be reinitialized. For this
purpose, a separate quirk has been introduced in the UFS core along
with a callback and those will be used by the ufs-qcom driver.

This series has been tested on following platforms:

* Qcom RB5 development platform powered by SM8250 SoC
* SM8450 based dev board
* Qdrive3/sa8540p-ride board based on SC8280XP (derivative)

Link: https://lore.kernel.org/r/20221222141001.54849-1-manivannan.sadhasivam@linaro.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

+197 -130
+8
MAINTAINERS
··· 21393 21393 S: Maintained 21394 21394 F: drivers/ufs/host/ufs-mediatek* 21395 21395 21396 + UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER QUALCOMM HOOKS 21397 + M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 21398 + L: linux-arm-msm@vger.kernel.org 21399 + L: linux-scsi@vger.kernel.org 21400 + S: Maintained 21401 + F: Documentation/devicetree/bindings/ufs/qcom,ufs.yaml 21402 + F: drivers/ufs/host/ufs-qcom* 21403 + 21396 21404 UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER RENESAS HOOKS 21397 21405 M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> 21398 21406 L: linux-renesas-soc@vger.kernel.org
+6
drivers/ufs/core/ufshcd-priv.h
··· 223 223 hba->vops->config_scaling_param(hba, p, data); 224 224 } 225 225 226 + static inline void ufshcd_vops_reinit_notify(struct ufs_hba *hba) 227 + { 228 + if (hba->vops && hba->vops->reinit_notify) 229 + hba->vops->reinit_notify(hba); 230 + } 231 + 226 232 extern const struct ufs_pm_lvl_states ufs_pm_lvl_states[]; 227 233 228 234 /**
+47 -16
drivers/ufs/core/ufshcd.c
··· 8231 8231 return ret; 8232 8232 } 8233 8233 8234 - /** 8235 - * ufshcd_probe_hba - probe hba to detect device and initialize it 8236 - * @hba: per-adapter instance 8237 - * @init_dev_params: whether or not to call ufshcd_device_params_init(). 8238 - * 8239 - * Execute link-startup and verify device initialization 8240 - */ 8241 - static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params) 8234 + static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params) 8242 8235 { 8243 8236 int ret; 8244 - unsigned long flags; 8245 - ktime_t start = ktime_get(); 8246 8237 8247 8238 hba->ufshcd_state = UFSHCD_STATE_RESET; 8248 8239 8249 8240 ret = ufshcd_link_startup(hba); 8250 8241 if (ret) 8251 - goto out; 8242 + return ret; 8252 8243 8253 8244 if (hba->quirks & UFSHCD_QUIRK_SKIP_PH_CONFIGURATION) 8254 - goto out; 8245 + return ret; 8255 8246 8256 8247 /* Debug counters initialization */ 8257 8248 ufshcd_clear_dbg_ufs_stats(hba); ··· 8253 8262 /* Verify device initialization by sending NOP OUT UPIU */ 8254 8263 ret = ufshcd_verify_dev_init(hba); 8255 8264 if (ret) 8256 - goto out; 8265 + return ret; 8257 8266 8258 8267 /* Initiate UFS initialization, and waiting until completion */ 8259 8268 ret = ufshcd_complete_dev_init(hba); 8260 8269 if (ret) 8261 - goto out; 8270 + return ret; 8262 8271 8263 8272 /* 8264 8273 * Initialize UFS device parameters used by driver, these ··· 8267 8276 if (init_dev_params) { 8268 8277 ret = ufshcd_device_params_init(hba); 8269 8278 if (ret) 8270 - goto out; 8279 + return ret; 8271 8280 } 8272 8281 8273 8282 ufshcd_tune_unipro_params(hba); ··· 8288 8297 if (ret) { 8289 8298 dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", 8290 8299 __func__, ret); 8300 + return ret; 8301 + } 8302 + } 8303 + 8304 + return 0; 8305 + } 8306 + 8307 + /** 8308 + * ufshcd_probe_hba - probe hba to detect device and initialize it 8309 + * @hba: per-adapter instance 8310 + * @init_dev_params: whether or not to call ufshcd_device_params_init(). 8311 + * 8312 + * Execute link-startup and verify device initialization 8313 + */ 8314 + static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params) 8315 + { 8316 + ktime_t start = ktime_get(); 8317 + unsigned long flags; 8318 + int ret; 8319 + 8320 + ret = ufshcd_device_init(hba, init_dev_params); 8321 + if (ret) 8322 + goto out; 8323 + 8324 + if (hba->quirks & UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH) { 8325 + /* Reset the device and controller before doing reinit */ 8326 + ufshcd_device_reset(hba); 8327 + ufshcd_hba_stop(hba); 8328 + ufshcd_vops_reinit_notify(hba); 8329 + ret = ufshcd_hba_enable(hba); 8330 + if (ret) { 8331 + dev_err(hba->dev, "Host controller enable failed\n"); 8332 + ufshcd_print_evt_hist(hba); 8333 + ufshcd_print_host_state(hba); 8291 8334 goto out; 8292 8335 } 8293 - ufshcd_print_pwr_info(hba); 8336 + 8337 + /* Reinit the device */ 8338 + ret = ufshcd_device_init(hba, init_dev_params); 8339 + if (ret) 8340 + goto out; 8294 8341 } 8342 + 8343 + ufshcd_print_pwr_info(hba); 8295 8344 8296 8345 /* 8297 8346 * bActiveICCLevel is volatile for UFS device (as per latest v2.1 spec)
+92 -80
drivers/ufs/host/ufs-qcom.c
··· 101 101 102 102 static int ufs_qcom_enable_lane_clks(struct ufs_qcom_host *host) 103 103 { 104 - int err = 0; 104 + int err; 105 105 struct device *dev = host->hba->dev; 106 106 107 107 if (host->is_lane_clks_enabled) ··· 110 110 err = ufs_qcom_host_clk_enable(dev, "rx_lane0_sync_clk", 111 111 host->rx_l0_sync_clk); 112 112 if (err) 113 - goto out; 113 + return err; 114 114 115 115 err = ufs_qcom_host_clk_enable(dev, "tx_lane0_sync_clk", 116 116 host->tx_l0_sync_clk); ··· 128 128 goto disable_rx_l1; 129 129 130 130 host->is_lane_clks_enabled = true; 131 - goto out; 131 + 132 + return 0; 132 133 133 134 disable_rx_l1: 134 135 clk_disable_unprepare(host->rx_l1_sync_clk); ··· 137 136 clk_disable_unprepare(host->tx_l0_sync_clk); 138 137 disable_rx_l0: 139 138 clk_disable_unprepare(host->rx_l0_sync_clk); 140 - out: 139 + 141 140 return err; 142 141 } 143 142 ··· 152 151 err = ufs_qcom_host_clk_get(dev, "rx_lane0_sync_clk", 153 152 &host->rx_l0_sync_clk, false); 154 153 if (err) 155 - goto out; 154 + return err; 156 155 157 156 err = ufs_qcom_host_clk_get(dev, "tx_lane0_sync_clk", 158 157 &host->tx_l0_sync_clk, false); 159 158 if (err) 160 - goto out; 159 + return err; 161 160 162 161 /* In case of single lane per direction, don't read lane1 clocks */ 163 162 if (host->hba->lanes_per_direction > 1) { 164 163 err = ufs_qcom_host_clk_get(dev, "rx_lane1_sync_clk", 165 164 &host->rx_l1_sync_clk, false); 166 165 if (err) 167 - goto out; 166 + return err; 168 167 169 168 err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk", 170 169 &host->tx_l1_sync_clk, true); 171 170 } 172 - out: 173 - return err; 171 + 172 + return 0; 174 173 } 175 174 176 175 static int ufs_qcom_check_hibern8(struct ufs_hba *hba) ··· 233 232 234 233 if (!host->core_reset) { 235 234 dev_warn(hba->dev, "%s: reset control not set\n", __func__); 236 - goto out; 235 + return 0; 237 236 } 238 237 239 238 reenable_intr = hba->is_irq_enabled; ··· 244 243 if (ret) { 245 244 dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n", 246 245 __func__, ret); 247 - goto out; 246 + return ret; 248 247 } 249 248 250 249 /* ··· 266 265 hba->is_irq_enabled = true; 267 266 } 268 267 269 - out: 270 - return ret; 268 + return 0; 269 + } 270 + 271 + static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba) 272 + { 273 + struct ufs_qcom_host *host = ufshcd_get_variant(hba); 274 + 275 + if (host->hw_ver.major == 0x1) { 276 + /* 277 + * HS-G3 operations may not reliably work on legacy QCOM 278 + * UFS host controller hardware even though capability 279 + * exchange during link startup phase may end up 280 + * negotiating maximum supported gear as G3. 281 + * Hence downgrade the maximum supported gear to HS-G2. 282 + */ 283 + return UFS_HS_G2; 284 + } else if (host->hw_ver.major >= 0x4) { 285 + return UFS_QCOM_MAX_GEAR(ufshcd_readl(hba, REG_UFS_PARAM0)); 286 + } 287 + 288 + /* Default is HS-G3 */ 289 + return UFS_HS_G3; 271 290 } 272 291 273 292 static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) 274 293 { 275 294 struct ufs_qcom_host *host = ufshcd_get_variant(hba); 276 295 struct phy *phy = host->generic_phy; 277 - int ret = 0; 278 - bool is_rate_B = UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B; 296 + int ret; 279 297 280 298 /* Reset UFS Host Controller and PHY */ 281 299 ret = ufs_qcom_host_reset(hba); ··· 302 282 dev_warn(hba->dev, "%s: host reset returned %d\n", 303 283 __func__, ret); 304 284 305 - if (is_rate_B) 306 - phy_set_mode(phy, PHY_MODE_UFS_HS_B); 307 - 308 285 /* phy initialization - calibrate the phy */ 309 286 ret = phy_init(phy); 310 287 if (ret) { 311 288 dev_err(hba->dev, "%s: phy init failed, ret = %d\n", 312 289 __func__, ret); 313 - goto out; 290 + return ret; 314 291 } 292 + 293 + phy_set_mode_ext(phy, PHY_MODE_UFS_HS_B, host->hs_gear); 315 294 316 295 /* power on phy - start serdes and phy's power and clocks */ 317 296 ret = phy_power_on(phy); ··· 326 307 327 308 out_disable_phy: 328 309 phy_exit(phy); 329 - out: 310 + 330 311 return ret; 331 312 } 332 313 ··· 384 365 static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, 385 366 u32 hs, u32 rate, bool update_link_startup_timer) 386 367 { 387 - int ret = 0; 388 368 struct ufs_qcom_host *host = ufshcd_get_variant(hba); 389 369 struct ufs_clk_info *clki; 390 370 u32 core_clk_period_in_ns; ··· 418 400 * Aggregation logic. 419 401 */ 420 402 if (ufs_qcom_cap_qunipro(host) && !ufshcd_is_intr_aggr_allowed(hba)) 421 - goto out; 403 + return 0; 422 404 423 405 if (gear == 0) { 424 406 dev_err(hba->dev, "%s: invalid gear = %d\n", __func__, gear); 425 - goto out_error; 407 + return -EINVAL; 426 408 } 427 409 428 410 list_for_each_entry(clki, &hba->clk_list_head, list) { ··· 445 427 } 446 428 447 429 if (ufs_qcom_cap_qunipro(host)) 448 - goto out; 430 + return 0; 449 431 450 432 core_clk_period_in_ns = NSEC_PER_SEC / core_clk_rate; 451 433 core_clk_period_in_ns <<= OFFSET_CLK_NS_REG; ··· 460 442 "%s: index %d exceeds table size %zu\n", 461 443 __func__, gear, 462 444 ARRAY_SIZE(hs_fr_table_rA)); 463 - goto out_error; 445 + return -EINVAL; 464 446 } 465 447 tx_clk_cycles_per_us = hs_fr_table_rA[gear-1][1]; 466 448 } else if (rate == PA_HS_MODE_B) { ··· 469 451 "%s: index %d exceeds table size %zu\n", 470 452 __func__, gear, 471 453 ARRAY_SIZE(hs_fr_table_rB)); 472 - goto out_error; 454 + return -EINVAL; 473 455 } 474 456 tx_clk_cycles_per_us = hs_fr_table_rB[gear-1][1]; 475 457 } else { 476 458 dev_err(hba->dev, "%s: invalid rate = %d\n", 477 459 __func__, rate); 478 - goto out_error; 460 + return -EINVAL; 479 461 } 480 462 break; 481 463 case SLOWAUTO_MODE: ··· 485 467 "%s: index %d exceeds table size %zu\n", 486 468 __func__, gear, 487 469 ARRAY_SIZE(pwm_fr_table)); 488 - goto out_error; 470 + return -EINVAL; 489 471 } 490 472 tx_clk_cycles_per_us = pwm_fr_table[gear-1][1]; 491 473 break; 492 474 case UNCHANGED: 493 475 default: 494 476 dev_err(hba->dev, "%s: invalid mode = %d\n", __func__, hs); 495 - goto out_error; 477 + return -EINVAL; 496 478 } 497 479 498 480 if (ufshcd_readl(hba, REG_UFS_TX_SYMBOL_CLK_NS_US) != ··· 516 498 */ 517 499 mb(); 518 500 } 519 - goto out; 520 501 521 - out_error: 522 - ret = -EINVAL; 523 - out: 524 - return ret; 502 + return 0; 525 503 } 526 504 527 505 static int ufs_qcom_link_startup_notify(struct ufs_hba *hba, ··· 532 518 0, true)) { 533 519 dev_err(hba->dev, "%s: ufs_qcom_cfg_timers() failed\n", 534 520 __func__); 535 - err = -EINVAL; 536 - goto out; 521 + return -EINVAL; 537 522 } 538 523 539 524 if (ufs_qcom_cap_qunipro(host)) ··· 558 545 break; 559 546 } 560 547 561 - out: 562 548 return err; 563 549 } 564 550 ··· 692 680 struct ufs_dev_params ufs_qcom_cap; 693 681 int ret = 0; 694 682 683 + if (!dev_req_params) { 684 + pr_err("%s: incoming dev_req_params is NULL\n", __func__); 685 + return -EINVAL; 686 + } 687 + 695 688 switch (status) { 696 689 case PRE_CHANGE: 697 690 ufshcd_init_pwr_dev_param(&ufs_qcom_cap); 698 691 ufs_qcom_cap.hs_rate = UFS_QCOM_LIMIT_HS_RATE; 699 692 700 - if (host->hw_ver.major == 0x1) { 701 - /* 702 - * HS-G3 operations may not reliably work on legacy QCOM 703 - * UFS host controller hardware even though capability 704 - * exchange during link startup phase may end up 705 - * negotiating maximum supported gear as G3. 706 - * Hence downgrade the maximum supported gear to HS-G2. 707 - */ 708 - if (ufs_qcom_cap.hs_tx_gear > UFS_HS_G2) 709 - ufs_qcom_cap.hs_tx_gear = UFS_HS_G2; 710 - if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G2) 711 - ufs_qcom_cap.hs_rx_gear = UFS_HS_G2; 712 - } 693 + /* This driver only supports symmetic gear setting i.e., hs_tx_gear == hs_rx_gear */ 694 + ufs_qcom_cap.hs_tx_gear = ufs_qcom_cap.hs_rx_gear = ufs_qcom_get_hs_gear(hba); 713 695 714 696 ret = ufshcd_get_pwr_dev_param(&ufs_qcom_cap, 715 697 dev_max_params, ··· 711 705 if (ret) { 712 706 dev_err(hba->dev, "%s: failed to determine capabilities\n", 713 707 __func__); 714 - goto out; 708 + return ret; 715 709 } 710 + 711 + /* Use the agreed gear */ 712 + host->hs_gear = dev_req_params->gear_tx; 716 713 717 714 /* enable the device ref clock before changing to HS mode */ 718 715 if (!ufshcd_is_hs_mode(&hba->pwr_info) && ··· 755 746 ret = -EINVAL; 756 747 break; 757 748 } 758 - out: 749 + 759 750 return ret; 760 751 } 761 752 ··· 767 758 err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1), 768 759 &pa_vs_config_reg1); 769 760 if (err) 770 - goto out; 761 + return err; 771 762 772 763 /* Allow extension of MSB bits of PA_SaveConfigTime attribute */ 773 - err = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1), 764 + return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1), 774 765 (pa_vs_config_reg1 | (1 << 12))); 775 - 776 - out: 777 - return err; 778 766 } 779 767 780 768 static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba) ··· 830 824 | UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE 831 825 | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP); 832 826 } 827 + 828 + if (host->hw_ver.major > 0x3) 829 + hba->quirks |= UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH; 833 830 } 834 831 835 832 static void ufs_qcom_set_caps(struct ufs_hba *hba) ··· 900 891 { 901 892 struct ufs_qcom_host *host = rcdev_to_ufs_host(rcdev); 902 893 903 - /* Currently this code only knows about a single reset. */ 904 - WARN_ON(id); 905 894 ufs_qcom_assert_reset(host->hba); 906 895 /* provide 1ms delay to let the reset pulse propagate. */ 907 896 usleep_range(1000, 1100); ··· 911 904 { 912 905 struct ufs_qcom_host *host = rcdev_to_ufs_host(rcdev); 913 906 914 - /* Currently this code only knows about a single reset. */ 915 - WARN_ON(id); 916 907 ufs_qcom_deassert_reset(host->hba); 917 908 918 909 /* ··· 947 942 948 943 host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); 949 944 if (!host) { 950 - err = -ENOMEM; 951 945 dev_err(dev, "%s: no memory for qcom ufs host\n", __func__); 952 - goto out; 946 + return -ENOMEM; 953 947 } 954 948 955 949 /* Make a two way bind between the qcom host and the hba */ ··· 969 965 host->rcdev.owner = dev->driver->owner; 970 966 host->rcdev.nr_resets = 1; 971 967 err = devm_reset_controller_register(dev, &host->rcdev); 972 - if (err) { 968 + if (err) 973 969 dev_warn(dev, "Failed to register reset controller\n"); 974 - err = 0; 975 - } 976 970 977 971 if (!has_acpi_companion(dev)) { 978 972 host->generic_phy = devm_phy_get(dev, "ufsphy"); ··· 1035 1033 1036 1034 ufs_qcom_get_default_testbus_cfg(host); 1037 1035 err = ufs_qcom_testbus_config(host); 1038 - if (err) { 1036 + if (err) 1037 + /* Failure is non-fatal */ 1039 1038 dev_warn(dev, "%s: failed to configure the testbus %d\n", 1040 1039 __func__, err); 1041 - err = 0; 1042 - } 1043 1040 1044 - goto out; 1041 + /* 1042 + * Power up the PHY using the minimum supported gear (UFS_HS_G2). 1043 + * Switching to max gear will be performed during reinit if supported. 1044 + */ 1045 + host->hs_gear = UFS_HS_G2; 1046 + 1047 + return 0; 1045 1048 1046 1049 out_variant_clear: 1047 1050 ufshcd_set_variant(hba, NULL); 1048 - out: 1051 + 1049 1052 return err; 1050 1053 } 1051 1054 ··· 1076 1069 UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), 1077 1070 &core_clk_ctrl_reg); 1078 1071 if (err) 1079 - goto out; 1072 + return err; 1080 1073 1081 1074 core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK; 1082 1075 core_clk_ctrl_reg |= clk_cycles; ··· 1084 1077 /* Clear CORE_CLK_DIV_EN */ 1085 1078 core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT; 1086 1079 1087 - err = ufshcd_dme_set(hba, 1080 + return ufshcd_dme_set(hba, 1088 1081 UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL), 1089 1082 core_clk_ctrl_reg); 1090 - out: 1091 - return err; 1092 1083 } 1093 1084 1094 1085 static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba) ··· 1169 1164 1170 1165 if (err || !dev_req_params) { 1171 1166 ufshcd_uic_hibern8_exit(hba); 1172 - goto out; 1167 + return err; 1173 1168 } 1174 1169 1175 1170 ufs_qcom_cfg_timers(hba, ··· 1180 1175 ufshcd_uic_hibern8_exit(hba); 1181 1176 } 1182 1177 1183 - out: 1184 - return err; 1178 + return 0; 1185 1179 } 1186 1180 1187 1181 static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host) ··· 1389 1385 } 1390 1386 #endif 1391 1387 1388 + static void ufs_qcom_reinit_notify(struct ufs_hba *hba) 1389 + { 1390 + struct ufs_qcom_host *host = ufshcd_get_variant(hba); 1391 + 1392 + phy_power_off(host->generic_phy); 1393 + } 1394 + 1392 1395 /* 1393 1396 * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations 1394 1397 * ··· 1419 1408 .device_reset = ufs_qcom_device_reset, 1420 1409 .config_scaling_param = ufs_qcom_config_scaling_param, 1421 1410 .program_key = ufs_qcom_ice_program_key, 1411 + .reinit_notify = ufs_qcom_reinit_notify, 1422 1412 }; 1423 1413 1424 1414 /** ··· 1436 1424 /* Perform generic probe */ 1437 1425 err = ufshcd_pltfrm_init(pdev, &ufs_hba_qcom_vops); 1438 1426 if (err) 1439 - dev_err(dev, "ufshcd_pltfrm_init() failed %d\n", err); 1427 + return dev_err_probe(dev, err, "ufshcd_pltfrm_init() failed\n"); 1440 1428 1441 - return err; 1429 + return 0; 1442 1430 } 1443 1431 1444 1432 /**
+36 -34
drivers/ufs/host/ufs-qcom.h
··· 17 17 #define DEFAULT_CLK_RATE_HZ 1000000 18 18 #define BUS_VECTOR_NAME_LEN 32 19 19 20 - #define UFS_HW_VER_MAJOR_SHFT (28) 21 - #define UFS_HW_VER_MAJOR_MASK (0x000F << UFS_HW_VER_MAJOR_SHFT) 22 - #define UFS_HW_VER_MINOR_SHFT (16) 23 - #define UFS_HW_VER_MINOR_MASK (0x0FFF << UFS_HW_VER_MINOR_SHFT) 24 - #define UFS_HW_VER_STEP_SHFT (0) 25 - #define UFS_HW_VER_STEP_MASK (0xFFFF << UFS_HW_VER_STEP_SHFT) 20 + #define UFS_HW_VER_MAJOR_MASK GENMASK(31, 28) 21 + #define UFS_HW_VER_MINOR_MASK GENMASK(27, 16) 22 + #define UFS_HW_VER_STEP_MASK GENMASK(15, 0) 26 23 27 24 /* vendor specific pre-defined parameters */ 28 25 #define SLOW 1 ··· 33 36 REG_UFS_TX_SYMBOL_CLK_NS_US = 0xC4, 34 37 REG_UFS_LOCAL_PORT_ID_REG = 0xC8, 35 38 REG_UFS_PA_ERR_CODE = 0xCC, 36 - REG_UFS_RETRY_TIMER_REG = 0xD0, 39 + /* On older UFS revisions, this register is called "RETRY_TIMER_REG" */ 40 + REG_UFS_PARAM0 = 0xD0, 37 41 REG_UFS_PA_LINK_STARTUP_TIMER = 0xD8, 38 42 REG_UFS_CFG1 = 0xDC, 39 43 REG_UFS_CFG2 = 0xE0, ··· 74 76 #define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x) 75 77 76 78 /* bit definitions for REG_UFS_CFG1 register */ 77 - #define QUNIPRO_SEL 0x1 78 - #define UTP_DBG_RAMS_EN 0x20000 79 + #define QUNIPRO_SEL BIT(0) 80 + #define UFS_PHY_SOFT_RESET BIT(1) 81 + #define UTP_DBG_RAMS_EN BIT(17) 79 82 #define TEST_BUS_EN BIT(18) 80 83 #define TEST_BUS_SEL GENMASK(22, 19) 81 84 #define UFS_REG_TEST_BUS_EN BIT(30) 82 85 86 + #define UFS_PHY_RESET_ENABLE 1 87 + #define UFS_PHY_RESET_DISABLE 0 88 + 83 89 /* bit definitions for REG_UFS_CFG2 register */ 84 - #define UAWM_HW_CGC_EN (1 << 0) 85 - #define UARM_HW_CGC_EN (1 << 1) 86 - #define TXUC_HW_CGC_EN (1 << 2) 87 - #define RXUC_HW_CGC_EN (1 << 3) 88 - #define DFC_HW_CGC_EN (1 << 4) 89 - #define TRLUT_HW_CGC_EN (1 << 5) 90 - #define TMRLUT_HW_CGC_EN (1 << 6) 91 - #define OCSC_HW_CGC_EN (1 << 7) 90 + #define UAWM_HW_CGC_EN BIT(0) 91 + #define UARM_HW_CGC_EN BIT(1) 92 + #define TXUC_HW_CGC_EN BIT(2) 93 + #define RXUC_HW_CGC_EN BIT(3) 94 + #define DFC_HW_CGC_EN BIT(4) 95 + #define TRLUT_HW_CGC_EN BIT(5) 96 + #define TMRLUT_HW_CGC_EN BIT(6) 97 + #define OCSC_HW_CGC_EN BIT(7) 98 + 99 + /* bit definitions for REG_UFS_PARAM0 */ 100 + #define MAX_HS_GEAR_MASK GENMASK(6, 4) 101 + #define UFS_QCOM_MAX_GEAR(x) FIELD_GET(MAX_HS_GEAR_MASK, (x)) 92 102 93 103 /* bit definition for UFS_UFS_TEST_BUS_CTRL_n */ 94 - #define TEST_BUS_SUB_SEL_MASK 0x1F /* All XXX_SEL fields are 5 bits wide */ 104 + #define TEST_BUS_SUB_SEL_MASK GENMASK(4, 0) /* All XXX_SEL fields are 5 bits wide */ 95 105 96 106 #define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\ 97 107 TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\ ··· 107 101 TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN) 108 102 109 103 /* bit offset */ 110 - enum { 111 - OFFSET_UFS_PHY_SOFT_RESET = 1, 112 - OFFSET_CLK_NS_REG = 10, 113 - }; 104 + #define OFFSET_CLK_NS_REG 0xa 114 105 115 106 /* bit masks */ 116 - enum { 117 - MASK_UFS_PHY_SOFT_RESET = 0x2, 118 - MASK_TX_SYMBOL_CLK_1US_REG = 0x3FF, 119 - MASK_CLK_NS_REG = 0xFFFC00, 120 - }; 107 + #define MASK_TX_SYMBOL_CLK_1US_REG GENMASK(9, 0) 108 + #define MASK_CLK_NS_REG GENMASK(23, 10) 121 109 122 110 /* QUniPro Vendor specific attributes */ 123 111 #define PA_VS_CONFIG_REG1 0x9000 ··· 126 126 { 127 127 u32 ver = ufshcd_readl(hba, REG_UFS_HW_VERSION); 128 128 129 - *major = (ver & UFS_HW_VER_MAJOR_MASK) >> UFS_HW_VER_MAJOR_SHFT; 130 - *minor = (ver & UFS_HW_VER_MINOR_MASK) >> UFS_HW_VER_MINOR_SHFT; 131 - *step = (ver & UFS_HW_VER_STEP_MASK) >> UFS_HW_VER_STEP_SHFT; 129 + *major = FIELD_GET(UFS_HW_VER_MAJOR_MASK, ver); 130 + *minor = FIELD_GET(UFS_HW_VER_MINOR_MASK, ver); 131 + *step = FIELD_GET(UFS_HW_VER_STEP_MASK, ver); 132 132 }; 133 133 134 134 static inline void ufs_qcom_assert_reset(struct ufs_hba *hba) 135 135 { 136 - ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, 137 - 1 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); 136 + ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, FIELD_PREP(UFS_PHY_SOFT_RESET, UFS_PHY_RESET_ENABLE), 137 + REG_UFS_CFG1); 138 138 139 139 /* 140 140 * Make sure assertion of ufs phy reset is written to ··· 145 145 146 146 static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba) 147 147 { 148 - ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, 149 - 0 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); 148 + ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, FIELD_PREP(UFS_PHY_SOFT_RESET, UFS_PHY_RESET_DISABLE), 149 + REG_UFS_CFG1); 150 150 151 151 /* 152 152 * Make sure de-assertion of ufs phy reset is written to ··· 210 210 struct reset_controller_dev rcdev; 211 211 212 212 struct gpio_desc *device_reset; 213 + 214 + u32 hs_gear; 213 215 }; 214 216 215 217 static inline u32
+8
include/ufs/ufshcd.h
··· 298 298 * @config_scaling_param: called to configure clock scaling parameters 299 299 * @program_key: program or evict an inline encryption key 300 300 * @event_notify: called to notify important events 301 + * @reinit_notify: called to notify reinit of UFSHCD during max gear switch 301 302 */ 302 303 struct ufs_hba_variant_ops { 303 304 const char *name; ··· 337 336 const union ufs_crypto_cfg_entry *cfg, int slot); 338 337 void (*event_notify)(struct ufs_hba *hba, 339 338 enum ufs_event_type evt, void *data); 339 + void (*reinit_notify)(struct ufs_hba *); 340 340 }; 341 341 342 342 /* clock gating state */ ··· 596 594 * auto-hibernate capability but it's FASTAUTO only. 597 595 */ 598 596 UFSHCD_QUIRK_HIBERN_FASTAUTO = 1 << 18, 597 + 598 + /* 599 + * This quirk needs to be enabled if the host controller needs 600 + * to reinit the device after switching to maximum gear. 601 + */ 602 + UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH = 1 << 19, 599 603 }; 600 604 601 605 enum ufshcd_caps {