From 014e61878ad7a06497caefd6c7a3b1b6a60a4ae3 Mon Sep 17 00:00:00 2001 From: Yaniv Gardi Date: Wed, 30 Oct 2013 08:38:16 +0200 Subject: [PATCH] scsi: ufs: read the device bRefClkFreq attribute Device reference clock is a crucial parameter, as it would fail to work in HS, if its value is different than 19.2 MHz. This is why we should read its value upon start-up and notify its value as a debug message. We don't want to "blindly" configure this attribute as well, as this is a one-time-programmable parameter and should be considered carefully before setting it. Change-Id: Ia2cc0f18fae1189949c30b5b2a65b763c1c46fb1 Signed-off-by: Yaniv Gardi --- drivers/scsi/ufs/ufshcd.c | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2737ff3b858d..c402f0116810 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4413,6 +4413,41 @@ out: return ret; } +/** + * ufshcd_get_device_ref_clk - get the device bRefClkFreq + * @hba: per-adapter instance + * + * Returns zero on success, non-zero error value on failure. + */ +static int ufshcd_get_device_ref_clk(struct ufs_hba *hba) +{ + int err = 0; + int val = -1; + int retries; + char *arr[] = {"19.2 MHz", "26 MHz", "38.4 MHz", "52 MHz"}; + + for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) { + /* write attribute */ + err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &val); + if (!err) + break; + + dev_dbg(hba->dev, "%s: failed with error %d\n", __func__, err); + } + + if (err || val >= sizeof(arr) || val < 0) { + dev_err(hba->dev, "%s: err = %d, val = %d", + __func__, err, val); + goto out; + } + + dev_info(hba->dev, "%s: bRefClkFreq = %s", __func__, arr[val]); + +out: + return err; +} + /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance @@ -4440,6 +4475,14 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) if (ret) goto out; + ret = ufshcd_get_device_ref_clk(hba); + if (ret) { + dev_err(hba->dev, + "%s: Failed reading bRefClkFreq attribute\n", + __func__); + ret = 0; + } + /* UFS device is also active now */ ufshcd_set_ufs_dev_active(hba); ufshcd_force_reset_auto_bkops(hba);