[SCSI] ufs: add dme configuration primitives
Implements to support GET and SET operations of the DME. These operations are used to configure the behavior of the UNIPRO. Along with basic operation, {Peer/AttrSetType} can be mixed. Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com> Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org> Tested-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Santosh Y <santoshsy@gmail.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
7d568652d3
commit
12b4fdb4f6
3 changed files with 145 additions and 0 deletions
|
@ -234,6 +234,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
|
|||
MASK_UIC_COMMAND_RESULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command
|
||||
* @hba: Pointer to adapter instance
|
||||
*
|
||||
* This function gets UIC command argument3
|
||||
* Returns 0 on success, non zero value on error
|
||||
*/
|
||||
static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba)
|
||||
{
|
||||
return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3);
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_get_req_rsp - returns the TR response transaction type
|
||||
* @ucd_rsp_ptr: pointer to response UPIU
|
||||
|
@ -1373,6 +1385,80 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
|
||||
* @hba: per adapter instance
|
||||
* @attr_sel: uic command argument1
|
||||
* @attr_set: attribute set type as uic command argument2
|
||||
* @mib_val: setting value as uic command argument3
|
||||
* @peer: indicate whether peer or local
|
||||
*
|
||||
* Returns 0 on success, non-zero value on failure
|
||||
*/
|
||||
int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
|
||||
u8 attr_set, u32 mib_val, u8 peer)
|
||||
{
|
||||
struct uic_command uic_cmd = {0};
|
||||
static const char *const action[] = {
|
||||
"dme-set",
|
||||
"dme-peer-set"
|
||||
};
|
||||
const char *set = action[!!peer];
|
||||
int ret;
|
||||
|
||||
uic_cmd.command = peer ?
|
||||
UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
|
||||
uic_cmd.argument1 = attr_sel;
|
||||
uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
|
||||
uic_cmd.argument3 = mib_val;
|
||||
|
||||
ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
|
||||
if (ret)
|
||||
dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
|
||||
set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_dme_set_attr);
|
||||
|
||||
/**
|
||||
* ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET
|
||||
* @hba: per adapter instance
|
||||
* @attr_sel: uic command argument1
|
||||
* @mib_val: the value of the attribute as returned by the UIC command
|
||||
* @peer: indicate whether peer or local
|
||||
*
|
||||
* Returns 0 on success, non-zero value on failure
|
||||
*/
|
||||
int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
|
||||
u32 *mib_val, u8 peer)
|
||||
{
|
||||
struct uic_command uic_cmd = {0};
|
||||
static const char *const action[] = {
|
||||
"dme-get",
|
||||
"dme-peer-get"
|
||||
};
|
||||
const char *get = action[!!peer];
|
||||
int ret;
|
||||
|
||||
uic_cmd.command = peer ?
|
||||
UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
|
||||
uic_cmd.argument1 = attr_sel;
|
||||
|
||||
ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
|
||||
if (ret) {
|
||||
dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
|
||||
get, UIC_GET_ATTR_ID(attr_sel), ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mib_val)
|
||||
*mib_val = uic_cmd.argument3;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
|
||||
|
||||
/**
|
||||
* ufshcd_complete_dev_init() - checks device readiness
|
||||
* hba: per-adapter instance
|
||||
|
@ -1908,6 +1994,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
|
|||
if (hba->active_uic_cmd) {
|
||||
hba->active_uic_cmd->argument2 |=
|
||||
ufshcd_get_uic_cmd_result(hba);
|
||||
hba->active_uic_cmd->argument3 =
|
||||
ufshcd_get_dme_attr_val(hba);
|
||||
complete(&hba->active_uic_cmd->done);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,4 +263,55 @@ static inline void check_upiu_size(void)
|
|||
extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
|
||||
extern int ufshcd_runtime_resume(struct ufs_hba *hba);
|
||||
extern int ufshcd_runtime_idle(struct ufs_hba *hba);
|
||||
extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
|
||||
u8 attr_set, u32 mib_val, u8 peer);
|
||||
extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
|
||||
u32 *mib_val, u8 peer);
|
||||
|
||||
/* UIC command interfaces for DME primitives */
|
||||
#define DME_LOCAL 0
|
||||
#define DME_PEER 1
|
||||
#define ATTR_SET_NOR 0 /* NORMAL */
|
||||
#define ATTR_SET_ST 1 /* STATIC */
|
||||
|
||||
static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
|
||||
u32 mib_val)
|
||||
{
|
||||
return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
|
||||
mib_val, DME_LOCAL);
|
||||
}
|
||||
|
||||
static inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel,
|
||||
u32 mib_val)
|
||||
{
|
||||
return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
|
||||
mib_val, DME_LOCAL);
|
||||
}
|
||||
|
||||
static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
|
||||
u32 mib_val)
|
||||
{
|
||||
return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
|
||||
mib_val, DME_PEER);
|
||||
}
|
||||
|
||||
static inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel,
|
||||
u32 mib_val)
|
||||
{
|
||||
return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
|
||||
mib_val, DME_PEER);
|
||||
}
|
||||
|
||||
static inline int ufshcd_dme_get(struct ufs_hba *hba,
|
||||
u32 attr_sel, u32 *mib_val)
|
||||
{
|
||||
return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL);
|
||||
}
|
||||
|
||||
static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
|
||||
u32 attr_sel, u32 *mib_val)
|
||||
{
|
||||
return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
|
||||
}
|
||||
|
||||
#endif /* End of Header */
|
||||
|
|
|
@ -191,6 +191,12 @@ enum {
|
|||
#define CONFIG_RESULT_CODE_MASK 0xFF
|
||||
#define GENERIC_ERROR_CODE_MASK 0xFF
|
||||
|
||||
#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\
|
||||
((sel) & 0xFFFF))
|
||||
#define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0)
|
||||
#define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16)
|
||||
#define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF)
|
||||
|
||||
/* UIC Commands */
|
||||
enum {
|
||||
UIC_CMD_DME_GET = 0x01,
|
||||
|
|
Loading…
Add table
Reference in a new issue