mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
ufs: Add Micron UFS HID support
As Micron said, Micron UFS HID could reuse SamSung HID driver, but need change some flags and attibutes definitions. Change-Id: If485cd01b6b69f1f14947fe84520c190262d966f Reviewed-on: https://gerrit.mot.com/2085180 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Dongliang Yue <yuedl1@motorola.com> Reviewed-by: Huosheng Liao <liaohs@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
f1fe70af8c
commit
f04f8628d3
4 changed files with 192 additions and 53 deletions
|
|
@ -269,10 +269,16 @@ config SCSI_SKHID
|
|||
bool "UFS Host Initiated Defrag supportr"
|
||||
depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI)
|
||||
help
|
||||
Activate or deactive SKHPB driver
|
||||
Activate or deactive SKHID driver
|
||||
|
||||
config MICRON_HPB
|
||||
bool "Activate micron HPB Host-aware Performance Booster"
|
||||
depends on SCSI_UFSHCD && UFSFEATURE && UFSHPB
|
||||
help
|
||||
Activate or deactive micron HPB driver
|
||||
|
||||
config MICRON_UFSHID
|
||||
bool "UFS Host Initiated Defrag supportr"
|
||||
depends on (SCSI_UFSHCD || SCSI_UFSHCD_QTI)
|
||||
help
|
||||
Activate or deactive micron hid driver
|
||||
|
|
|
|||
|
|
@ -160,6 +160,9 @@ enum flag_idn {
|
|||
QUERY_FLAG_IDN_TW_BUF_FLUSH_EN = 0x0F,
|
||||
QUERY_FLAG_IDN_TW_FLUSH_DURING_HIBERN = 0x10,
|
||||
#endif
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
QUERY_FLAG_IDN_HID_EN = 0x13
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Attribute idn for Query requests */
|
||||
|
|
@ -210,6 +213,10 @@ enum attr_idn {
|
|||
#if defined(CONFIG_UFSFEATURE)
|
||||
QUERY_ATTR_IDN_SUP_VENDOR_OPTIONS = 0xFF,
|
||||
#endif
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
QUERY_ATTR_IDN_HID_FRAG_STATUS = 0x31,
|
||||
QUERY_ATTR_IDN_HID_PROGRESS = 0x32,
|
||||
#endif
|
||||
};
|
||||
|
||||
#define QUERY_ATTR_IDN_BOOT_LU_EN_MAX 0x02
|
||||
|
|
|
|||
|
|
@ -113,6 +113,54 @@ err_out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
static int ufshid_set_flag(struct ufshid_dev *hid, u8 idn)
|
||||
{
|
||||
struct ufs_hba *hba = hid->ufsf->hba;
|
||||
int ret = 0;
|
||||
bool flag_result;
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
|
||||
ret = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_SET_FLAG, idn, 0,
|
||||
&flag_result);
|
||||
|
||||
if (ret) {
|
||||
ERR_MSG("set flag [0x%.2X] fail. (%d)", idn, ret);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
HID_DEBUG(hid, "hid_flag set [0x%.2X] result [0x%.2X] ", idn, flag_result);
|
||||
err_out:
|
||||
pm_runtime_mark_last_busy(hba->dev);
|
||||
pm_runtime_put_noidle(hba->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ufshid_clear_flag(struct ufshid_dev *hid, u8 idn)
|
||||
{
|
||||
struct ufs_hba *hba = hid->ufsf->hba;
|
||||
int ret = 0;
|
||||
|
||||
pm_runtime_get_sync(hba->dev);
|
||||
|
||||
ret = ufsf_query_flag_retry(hba, UPIU_QUERY_OPCODE_CLEAR_FLAG, idn, 0,
|
||||
NULL);
|
||||
if (ret) {
|
||||
ERR_MSG("clear flag [0x%.2X] fail. (%d)", idn, ret);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
HID_DEBUG(hid, "hid_flag set [0x%.2X] ", idn);
|
||||
err_out:
|
||||
pm_runtime_mark_last_busy(hba->dev);
|
||||
pm_runtime_put_noidle(hba->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static inline int ufshid_version_check(int spec_version)
|
||||
{
|
||||
INFO_MSG("Support HID Spec : Driver = (%.4x), Device = (%.4x)",
|
||||
|
|
@ -133,18 +181,27 @@ void ufshid_get_dev_info(struct ufsf_feature *ufsf, u8 *desc_buf)
|
|||
|
||||
ufsf->hid_dev = NULL;
|
||||
|
||||
if (!(LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP]) &
|
||||
UFS_FEATURE_SUPPORT_HID_BIT)) {
|
||||
INFO_MSG("bUFSExFeaturesSupport: HID not support");
|
||||
goto err_out;
|
||||
if(IS_SAMSUNG_DEVICE(storage_mfrid)) {
|
||||
if (!(LI_EN_32(&desc_buf[DEVICE_DESC_PARAM_EX_FEAT_SUP]) &
|
||||
UFS_FEATURE_SUPPORT_HID_BIT)) {
|
||||
INFO_MSG("bUFSExFeaturesSupport: HID not support");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
INFO_MSG("bUFSExFeaturesSupport: HID support");
|
||||
spec_version =
|
||||
LI_EN_16(&desc_buf[DEVICE_DESC_PARAM_HID_VER]);
|
||||
ret = ufshid_version_check(spec_version);
|
||||
if (ret)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
INFO_MSG("bUFSExFeaturesSupport: HID support");
|
||||
spec_version =
|
||||
LI_EN_16(&desc_buf[DEVICE_DESC_PARAM_HID_VER]);
|
||||
ret = ufshid_version_check(spec_version);
|
||||
if (ret)
|
||||
#ifndef CONFIG_MICRON_UFSHID
|
||||
if(IS_MICRON_DEVICE(storage_mfrid)){
|
||||
INFO_MSG("micron: HID not support");
|
||||
goto err_out;
|
||||
}
|
||||
#endif
|
||||
|
||||
ufsf->hid_dev = kzalloc(sizeof(struct ufshid_dev), GFP_KERNEL);
|
||||
if (!ufsf->hid_dev) {
|
||||
|
|
@ -163,39 +220,79 @@ static int ufshid_get_analyze_and_issue_execute(struct ufshid_dev *hid)
|
|||
u32 attr_val;
|
||||
int frag_level;
|
||||
|
||||
if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION,
|
||||
HID_OP_EXECUTE))
|
||||
if(IS_MICRON_DEVICE(storage_mfrid)) {
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
//get micron ufs frag level
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_STATUS, &frag_level))
|
||||
return -EINVAL;
|
||||
//get micron ufs hid execution progress
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_PROGRESS, &attr_val))
|
||||
return -EINVAL;
|
||||
HID_DEBUG(hid, "micron frag_level= %d attr_val= %d",frag_level,attr_val);
|
||||
|
||||
if (attr_val != HID_PROG_ONGOING) {
|
||||
if(frag_level!= HID_LEV_GREEN_MICRON) {
|
||||
ufshid_set_flag(hid, QUERY_FLAG_IDN_HID_EN);
|
||||
return HID_REQUIRED;
|
||||
} else {
|
||||
return HID_NOT_REQUIRED;
|
||||
}
|
||||
} else {
|
||||
return HID_REQUIRED;
|
||||
}
|
||||
#else
|
||||
return HID_NOT_REQUIRED;
|
||||
#endif
|
||||
} else if(IS_SAMSUNG_DEVICE(storage_mfrid)) {
|
||||
if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION,
|
||||
HID_OP_EXECUTE))
|
||||
return -EINVAL;
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val))
|
||||
return -EINVAL;
|
||||
|
||||
frag_level = attr_val & HID_FRAG_LEVEL_MASK;
|
||||
HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d",
|
||||
frag_level, HID_FRAG_UPDATE_STAT(attr_val),
|
||||
HID_EXECUTE_REQ_STAT(attr_val));
|
||||
|
||||
if (frag_level == HID_LEV_GRAY)
|
||||
return -EAGAIN;
|
||||
|
||||
return (HID_EXECUTE_REQ_STAT(attr_val)) ?
|
||||
HID_REQUIRED : HID_NOT_REQUIRED;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val))
|
||||
return -EINVAL;
|
||||
|
||||
frag_level = attr_val & HID_FRAG_LEVEL_MASK;
|
||||
HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d",
|
||||
frag_level, HID_FRAG_UPDATE_STAT(attr_val),
|
||||
HID_EXECUTE_REQ_STAT(attr_val));
|
||||
|
||||
if (frag_level == HID_LEV_GRAY)
|
||||
return -EAGAIN;
|
||||
|
||||
return (HID_EXECUTE_REQ_STAT(attr_val)) ?
|
||||
HID_REQUIRED : HID_NOT_REQUIRED;
|
||||
}
|
||||
}
|
||||
|
||||
static int ufshid_issue_disable(struct ufshid_dev *hid)
|
||||
{
|
||||
u32 attr_val;
|
||||
|
||||
if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION,
|
||||
HID_OP_DISABLE))
|
||||
return -EINVAL;
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val))
|
||||
return -EINVAL;
|
||||
if(IS_MICRON_DEVICE(storage_mfrid)) {
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
//get micron ufs hid execution progress
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_PROGRESS, &attr_val))
|
||||
return -EINVAL;
|
||||
HID_DEBUG(hid, "micron hid progress = %d",attr_val);
|
||||
|
||||
HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d",
|
||||
attr_val & HID_FRAG_LEVEL_MASK,
|
||||
HID_FRAG_UPDATE_STAT(attr_val),
|
||||
HID_EXECUTE_REQ_STAT(attr_val));
|
||||
if(attr_val == HID_PROG_ONGOING) {
|
||||
if (ufshid_clear_flag(hid, QUERY_FLAG_IDN_HID_EN))
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
}else if(IS_SAMSUNG_DEVICE(storage_mfrid)) {
|
||||
if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION,
|
||||
HID_OP_DISABLE))
|
||||
return -EINVAL;
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val))
|
||||
return -EINVAL;
|
||||
|
||||
HID_DEBUG(hid, "Frag_lv %d Freg_stat %d HID_need_exec %d",
|
||||
attr_val & HID_FRAG_LEVEL_MASK,
|
||||
HID_FRAG_UPDATE_STAT(attr_val),
|
||||
HID_EXECUTE_REQ_STAT(attr_val));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -706,27 +803,42 @@ static ssize_t ufshid_sysfs_show_color(struct ufshid_dev *hid, char *buf)
|
|||
u32 attr_val;
|
||||
int frag_level;
|
||||
|
||||
if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION,
|
||||
HID_OP_ANALYZE)) {
|
||||
ERR_MSG("query HID_OPERATION fail");
|
||||
return -EINVAL;
|
||||
if(IS_MICRON_DEVICE(storage_mfrid)){
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_STATUS, &attr_val))
|
||||
return -EINVAL;
|
||||
frag_level = attr_val;
|
||||
/*Micron only has two levels RED & GREEN*/
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
((frag_level == HID_LEV_GREEN_MICRON)) ? "GREEN" :
|
||||
((frag_level ==HID_LEV_RED_MICRON))?"RED":"UNKNOWN");
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n","Error.");
|
||||
#endif
|
||||
} else if(IS_SAMSUNG_DEVICE(storage_mfrid)) {
|
||||
if (ufshid_write_attr(hid, QUERY_ATTR_IDN_HID_OPERATION,
|
||||
HID_OP_ANALYZE)) {
|
||||
ERR_MSG("query HID_OPERATION fail");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) {
|
||||
ERR_MSG("query HID_FRAG_LEVEL fail");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
frag_level = attr_val & HID_FRAG_LEVEL_MASK;
|
||||
INFO_MSG("Frag_lv %d Freg_stat %d HID_need_exec %d", frag_level,
|
||||
HID_FRAG_UPDATE_STAT(attr_val),
|
||||
HID_EXECUTE_REQ_STAT(attr_val));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
frag_level == HID_LEV_RED ? "RED" :
|
||||
frag_level == HID_LEV_YELLOW ? "YELLOW" :
|
||||
frag_level == HID_LEV_GREEN ? "GREEN" :
|
||||
frag_level == HID_LEV_GRAY ? "GRAY" : "UNKNOWN");
|
||||
}
|
||||
|
||||
if (ufshid_read_attr(hid, QUERY_ATTR_IDN_HID_FRAG_LEVEL, &attr_val)) {
|
||||
ERR_MSG("query HID_FRAG_LEVEL fail");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
frag_level = attr_val & HID_FRAG_LEVEL_MASK;
|
||||
INFO_MSG("Frag_lv %d Freg_stat %d HID_need_exec %d", frag_level,
|
||||
HID_FRAG_UPDATE_STAT(attr_val),
|
||||
HID_EXECUTE_REQ_STAT(attr_val));
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
frag_level == HID_LEV_RED ? "RED" :
|
||||
frag_level == HID_LEV_YELLOW ? "YELLOW" :
|
||||
frag_level == HID_LEV_GREEN ? "GREEN" :
|
||||
frag_level == HID_LEV_GRAY ? "GRAY" : "UNKNOWN");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_UFSHID_POC)
|
||||
|
|
|
|||
|
|
@ -103,6 +103,20 @@ enum {
|
|||
HID_LEV_RED = 3,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MICRON_UFSHID)
|
||||
enum {
|
||||
HID_LEV_GREEN_MICRON = 0,
|
||||
HID_LEV_RED_MICRON = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
HID_PROG_IDLE = 0,
|
||||
HID_PROG_ONGOING = 1,
|
||||
HID_PROG_STOP = 2, //stopped by Host
|
||||
HID_PROG_COMPLETE = 3,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct ufshid_dev {
|
||||
struct ufsf_feature *ufsf;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue