aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSubhash Jadavani <subhashj@codeaurora.org>2016-12-05 22:25:32 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-12-08 17:00:11 -0500
commit56d4a1866d748732fd8d690b2c2156bbc9c9eb02 (patch)
tree330f2d414d6d0afc8a390165f48999941c4ab32f
parentab436706e4a86719595012424ecefbdf4a84cc30 (diff)
scsi: ufs: add quirk to increase host PA_SaveConfigTime
The maximum value PA_SaveConfigTime is 250 (10us) but this is not enough for some vendors. Gear switch from PWM to HS may fail even with this max. PA_SaveConfigTime. Gear switch can be issued by host controller as an error recovery and any software delay will not help on this case so we need to increase PA_SaveConfigTime to >32us as per vendor recommendation. This change adds a quirk to increase the PA_SaveConfigTime parameter. Reviewed-by: Venkat Gopalakrishnan <venkatg@codeaurora.org> Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c30
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h1
-rw-r--r--drivers/scsi/ufs/ufs_quirks.h30
-rw-r--r--drivers/scsi/ufs/ufshcd.c26
-rw-r--r--drivers/scsi/ufs/ufshcd.h12
5 files changed, 76 insertions, 23 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index ff614613bf89..2943a68b6d69 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -23,6 +23,7 @@
23#include "unipro.h" 23#include "unipro.h"
24#include "ufs-qcom.h" 24#include "ufs-qcom.h"
25#include "ufshci.h" 25#include "ufshci.h"
26#include "ufs_quirks.h"
26#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \ 27#define UFS_QCOM_DEFAULT_DBG_PRINT_EN \
27 (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN) 28 (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
28 29
@@ -1031,6 +1032,34 @@ out:
1031 return ret; 1032 return ret;
1032} 1033}
1033 1034
1035static int ufs_qcom_quirk_host_pa_saveconfigtime(struct ufs_hba *hba)
1036{
1037 int err;
1038 u32 pa_vs_config_reg1;
1039
1040 err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1),
1041 &pa_vs_config_reg1);
1042 if (err)
1043 goto out;
1044
1045 /* Allow extension of MSB bits of PA_SaveConfigTime attribute */
1046 err = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_VS_CONFIG_REG1),
1047 (pa_vs_config_reg1 | (1 << 12)));
1048
1049out:
1050 return err;
1051}
1052
1053static int ufs_qcom_apply_dev_quirks(struct ufs_hba *hba)
1054{
1055 int err = 0;
1056
1057 if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME)
1058 err = ufs_qcom_quirk_host_pa_saveconfigtime(hba);
1059
1060 return err;
1061}
1062
1034static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba) 1063static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
1035{ 1064{
1036 struct ufs_qcom_host *host = ufshcd_get_variant(hba); 1065 struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -1618,6 +1647,7 @@ static struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
1618 .hce_enable_notify = ufs_qcom_hce_enable_notify, 1647 .hce_enable_notify = ufs_qcom_hce_enable_notify,
1619 .link_startup_notify = ufs_qcom_link_startup_notify, 1648 .link_startup_notify = ufs_qcom_link_startup_notify,
1620 .pwr_change_notify = ufs_qcom_pwr_change_notify, 1649 .pwr_change_notify = ufs_qcom_pwr_change_notify,
1650 .apply_dev_quirks = ufs_qcom_apply_dev_quirks,
1621 .suspend = ufs_qcom_suspend, 1651 .suspend = ufs_qcom_suspend,
1622 .resume = ufs_qcom_resume, 1652 .resume = ufs_qcom_resume,
1623 .dbg_register_dump = ufs_qcom_dump_dbg_regs, 1653 .dbg_register_dump = ufs_qcom_dump_dbg_regs,
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index a19307a57ce2..fe517cd7dac3 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -142,6 +142,7 @@ enum ufs_qcom_phy_init_type {
142 UFS_QCOM_DBG_PRINT_TEST_BUS_EN) 142 UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
143 143
144/* QUniPro Vendor specific attributes */ 144/* QUniPro Vendor specific attributes */
145#define PA_VS_CONFIG_REG1 0x9000
145#define DME_VS_CORE_CLK_CTRL 0xD002 146#define DME_VS_CORE_CLK_CTRL 0xD002
146/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */ 147/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
147#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8) 148#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index f7983058f3f7..08b799d4efcc 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -134,29 +134,17 @@ struct ufs_dev_fix {
134 */ 134 */
135#define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 7) 135#define UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE (1 << 7)
136 136
137/*
138 * The max. value PA_SaveConfigTime is 250 (10us) but this is not enough for
139 * some vendors.
140 * Gear switch from PWM to HS may fail even with this max. PA_SaveConfigTime.
141 * Gear switch can be issued by host controller as an error recovery and any
142 * software delay will not help on this case so we need to increase
143 * PA_SaveConfigTime to >32us as per vendor recommendation.
144 */
145#define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME (1 << 8)
137 146
138struct ufs_hba; 147struct ufs_hba;
139void ufs_advertise_fixup_device(struct ufs_hba *hba); 148void ufs_advertise_fixup_device(struct ufs_hba *hba);
140 149
141static struct ufs_dev_fix ufs_fixups[] = {
142 /* UFS cards deviations table */
143 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
144 UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
145 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
146 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
147 UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
148 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
149 UFS_DEVICE_NO_FASTAUTO),
150 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
151 UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
152 UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
153 UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
154 UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
155 UFS_DEVICE_QUIRK_PA_TACTIVATE),
156 UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
157 UFS_DEVICE_QUIRK_PA_TACTIVATE),
158 UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
159
160 END_FIX
161};
162#endif /* UFS_QUIRKS_H_ */ 150#endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7af70aa0b750..af7e0285f004 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -185,6 +185,30 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl)
185 return ufs_pm_lvl_states[lvl].link_state; 185 return ufs_pm_lvl_states[lvl].link_state;
186} 186}
187 187
188static struct ufs_dev_fix ufs_fixups[] = {
189 /* UFS cards deviations table */
190 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
191 UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
192 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
193 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
194 UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS),
195 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
196 UFS_DEVICE_NO_FASTAUTO),
197 UFS_FIX(UFS_VENDOR_SAMSUNG, UFS_ANY_MODEL,
198 UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE),
199 UFS_FIX(UFS_VENDOR_TOSHIBA, UFS_ANY_MODEL,
200 UFS_DEVICE_QUIRK_DELAY_BEFORE_LPM),
201 UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9C8KBADG",
202 UFS_DEVICE_QUIRK_PA_TACTIVATE),
203 UFS_FIX(UFS_VENDOR_TOSHIBA, "THGLF2G9D8KBADG",
204 UFS_DEVICE_QUIRK_PA_TACTIVATE),
205 UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
206 UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
207 UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
208
209 END_FIX
210};
211
188static void ufshcd_tmc_handler(struct ufs_hba *hba); 212static void ufshcd_tmc_handler(struct ufs_hba *hba);
189static void ufshcd_async_scan(void *data, async_cookie_t cookie); 213static void ufshcd_async_scan(void *data, async_cookie_t cookie);
190static int ufshcd_reset_and_restore(struct ufs_hba *hba); 214static int ufshcd_reset_and_restore(struct ufs_hba *hba);
@@ -5213,6 +5237,8 @@ static void ufshcd_tune_unipro_params(struct ufs_hba *hba)
5213 5237
5214 if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE) 5238 if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_PA_TACTIVATE)
5215 ufshcd_quirk_tune_host_pa_tactivate(hba); 5239 ufshcd_quirk_tune_host_pa_tactivate(hba);
5240
5241 ufshcd_vops_apply_dev_quirks(hba);
5216} 5242}
5217 5243
5218/** 5244/**
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 7d9ff22acfea..08cd26ed2382 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -266,7 +266,7 @@ struct ufs_pwr_mode_info {
266 * @setup_task_mgmt: called before any task management request is issued 266 * @setup_task_mgmt: called before any task management request is issued
267 * to set some things 267 * to set some things
268 * @hibern8_notify: called around hibern8 enter/exit 268 * @hibern8_notify: called around hibern8 enter/exit
269 * to configure some things 269 * @apply_dev_quirks: called to apply device specific quirks
270 * @suspend: called during host controller PM callback 270 * @suspend: called during host controller PM callback
271 * @resume: called during host controller PM callback 271 * @resume: called during host controller PM callback
272 * @dbg_register_dump: used to dump controller debug information 272 * @dbg_register_dump: used to dump controller debug information
@@ -293,7 +293,8 @@ struct ufs_hba_variant_ops {
293 void (*setup_xfer_req)(struct ufs_hba *, int, bool); 293 void (*setup_xfer_req)(struct ufs_hba *, int, bool);
294 void (*setup_task_mgmt)(struct ufs_hba *, int, u8); 294 void (*setup_task_mgmt)(struct ufs_hba *, int, u8);
295 void (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme, 295 void (*hibern8_notify)(struct ufs_hba *, enum uic_cmd_dme,
296 enum ufs_notify_change_status); 296 enum ufs_notify_change_status);
297 int (*apply_dev_quirks)(struct ufs_hba *);
297 int (*suspend)(struct ufs_hba *, enum ufs_pm_op); 298 int (*suspend)(struct ufs_hba *, enum ufs_pm_op);
298 int (*resume)(struct ufs_hba *, enum ufs_pm_op); 299 int (*resume)(struct ufs_hba *, enum ufs_pm_op);
299 void (*dbg_register_dump)(struct ufs_hba *hba); 300 void (*dbg_register_dump)(struct ufs_hba *hba);
@@ -839,6 +840,13 @@ static inline void ufshcd_vops_hibern8_notify(struct ufs_hba *hba,
839 return hba->vops->hibern8_notify(hba, cmd, status); 840 return hba->vops->hibern8_notify(hba, cmd, status);
840} 841}
841 842
843static inline int ufshcd_vops_apply_dev_quirks(struct ufs_hba *hba)
844{
845 if (hba->vops && hba->vops->apply_dev_quirks)
846 return hba->vops->apply_dev_quirks(hba);
847 return 0;
848}
849
842static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) 850static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op)
843{ 851{
844 if (hba->vops && hba->vops->suspend) 852 if (hba->vops && hba->vops->suspend)