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

scsi: ufs-qcom: Add reset control support for host controller

Add reset control for host controller so that host controller can be reset
as required in its power up sequence.

Link: https://lore.kernel.org/r/1573798172-20534-3-git-send-email-cang@codeaurora.org
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Can Guo <cang@codeaurora.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Can Guo and committed by
Martin K. Petersen
870b1279 ebdd1dfd

+56
+53
drivers/scsi/ufs/ufs-qcom.c
··· 246 246 mb(); 247 247 } 248 248 249 + /** 250 + * ufs_qcom_host_reset - reset host controller and PHY 251 + */ 252 + static int ufs_qcom_host_reset(struct ufs_hba *hba) 253 + { 254 + int ret = 0; 255 + struct ufs_qcom_host *host = ufshcd_get_variant(hba); 256 + 257 + if (!host->core_reset) { 258 + dev_warn(hba->dev, "%s: reset control not set\n", __func__); 259 + goto out; 260 + } 261 + 262 + ret = reset_control_assert(host->core_reset); 263 + if (ret) { 264 + dev_err(hba->dev, "%s: core_reset assert failed, err = %d\n", 265 + __func__, ret); 266 + goto out; 267 + } 268 + 269 + /* 270 + * The hardware requirement for delay between assert/deassert 271 + * is at least 3-4 sleep clock (32.7KHz) cycles, which comes to 272 + * ~125us (4/32768). To be on the safe side add 200us delay. 273 + */ 274 + usleep_range(200, 210); 275 + 276 + ret = reset_control_deassert(host->core_reset); 277 + if (ret) 278 + dev_err(hba->dev, "%s: core_reset deassert failed, err = %d\n", 279 + __func__, ret); 280 + 281 + usleep_range(1000, 1100); 282 + 283 + out: 284 + return ret; 285 + } 286 + 249 287 static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) 250 288 { 251 289 struct ufs_qcom_host *host = ufshcd_get_variant(hba); ··· 291 253 int ret = 0; 292 254 bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B) 293 255 ? true : false; 256 + 257 + /* Reset UFS Host Controller and PHY */ 258 + ret = ufs_qcom_host_reset(hba); 259 + if (ret) 260 + dev_warn(hba->dev, "%s: host reset returned %d\n", 261 + __func__, ret); 294 262 295 263 if (is_rate_B) 296 264 phy_set_mode(phy, PHY_MODE_UFS_HS_B); ··· 1144 1100 /* Make a two way bind between the qcom host and the hba */ 1145 1101 host->hba = hba; 1146 1102 ufshcd_set_variant(hba, host); 1103 + 1104 + /* Setup the reset control of HCI */ 1105 + host->core_reset = devm_reset_control_get(hba->dev, "rst"); 1106 + if (IS_ERR(host->core_reset)) { 1107 + err = PTR_ERR(host->core_reset); 1108 + dev_warn(dev, "Failed to get reset control %d\n", err); 1109 + host->core_reset = NULL; 1110 + err = 0; 1111 + } 1147 1112 1148 1113 /* Fire up the reset controller. Failure here is non-fatal. */ 1149 1114 host->rcdev.of_node = dev->of_node;
+3
drivers/scsi/ufs/ufs-qcom.h
··· 6 6 #define UFS_QCOM_H_ 7 7 8 8 #include <linux/reset-controller.h> 9 + #include <linux/reset.h> 9 10 10 11 #define MAX_UFS_QCOM_HOSTS 1 11 12 #define MAX_U32 (~(u32)0) ··· 234 233 u32 dbg_print_en; 235 234 struct ufs_qcom_testbus testbus; 236 235 236 + /* Reset control of HCI */ 237 + struct reset_control *core_reset; 237 238 struct reset_controller_dev rcdev; 238 239 239 240 struct gpio_desc *device_reset;