aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorSeungwon Jeon <tgih.jun@samsung.com>2013-08-31 12:10:21 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-06 19:01:41 -0400
commit12b4fdb4f6bccb5459a2f75fbe0eab253bfceab4 (patch)
treeb83139cc18787adc3d8ea552ba41563ac9d4c3e0 /drivers/scsi
parent7d568652d3abc81a6d684d4760571a3ccb6f68d9 (diff)
[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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/ufs/ufshcd.c88
-rw-r--r--drivers/scsi/ufs/ufshcd.h51
-rw-r--r--drivers/scsi/ufs/ufshci.h6
3 files changed, 145 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 46b0754b4b76..a4ce6c462614 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -235,6 +235,18 @@ static inline int ufshcd_get_uic_cmd_result(struct ufs_hba *hba)
235} 235}
236 236
237/** 237/**
238 * ufshcd_get_dme_attr_val - Get the value of attribute returned by UIC command
239 * @hba: Pointer to adapter instance
240 *
241 * This function gets UIC command argument3
242 * Returns 0 on success, non zero value on error
243 */
244static inline u32 ufshcd_get_dme_attr_val(struct ufs_hba *hba)
245{
246 return ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3);
247}
248
249/**
238 * ufshcd_get_req_rsp - returns the TR response transaction type 250 * ufshcd_get_req_rsp - returns the TR response transaction type
239 * @ucd_rsp_ptr: pointer to response UPIU 251 * @ucd_rsp_ptr: pointer to response UPIU
240 */ 252 */
@@ -1374,6 +1386,80 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
1374} 1386}
1375 1387
1376/** 1388/**
1389 * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET
1390 * @hba: per adapter instance
1391 * @attr_sel: uic command argument1
1392 * @attr_set: attribute set type as uic command argument2
1393 * @mib_val: setting value as uic command argument3
1394 * @peer: indicate whether peer or local
1395 *
1396 * Returns 0 on success, non-zero value on failure
1397 */
1398int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
1399 u8 attr_set, u32 mib_val, u8 peer)
1400{
1401 struct uic_command uic_cmd = {0};
1402 static const char *const action[] = {
1403 "dme-set",
1404 "dme-peer-set"
1405 };
1406 const char *set = action[!!peer];
1407 int ret;
1408
1409 uic_cmd.command = peer ?
1410 UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
1411 uic_cmd.argument1 = attr_sel;
1412 uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
1413 uic_cmd.argument3 = mib_val;
1414
1415 ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
1416 if (ret)
1417 dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
1418 set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
1419
1420 return ret;
1421}
1422EXPORT_SYMBOL_GPL(ufshcd_dme_set_attr);
1423
1424/**
1425 * ufshcd_dme_get_attr - UIC command for DME_GET, DME_PEER_GET
1426 * @hba: per adapter instance
1427 * @attr_sel: uic command argument1
1428 * @mib_val: the value of the attribute as returned by the UIC command
1429 * @peer: indicate whether peer or local
1430 *
1431 * Returns 0 on success, non-zero value on failure
1432 */
1433int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
1434 u32 *mib_val, u8 peer)
1435{
1436 struct uic_command uic_cmd = {0};
1437 static const char *const action[] = {
1438 "dme-get",
1439 "dme-peer-get"
1440 };
1441 const char *get = action[!!peer];
1442 int ret;
1443
1444 uic_cmd.command = peer ?
1445 UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
1446 uic_cmd.argument1 = attr_sel;
1447
1448 ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
1449 if (ret) {
1450 dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
1451 get, UIC_GET_ATTR_ID(attr_sel), ret);
1452 goto out;
1453 }
1454
1455 if (mib_val)
1456 *mib_val = uic_cmd.argument3;
1457out:
1458 return ret;
1459}
1460EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr);
1461
1462/**
1377 * ufshcd_complete_dev_init() - checks device readiness 1463 * ufshcd_complete_dev_init() - checks device readiness
1378 * hba: per-adapter instance 1464 * hba: per-adapter instance
1379 * 1465 *
@@ -1908,6 +1994,8 @@ static void ufshcd_uic_cmd_compl(struct ufs_hba *hba)
1908 if (hba->active_uic_cmd) { 1994 if (hba->active_uic_cmd) {
1909 hba->active_uic_cmd->argument2 |= 1995 hba->active_uic_cmd->argument2 |=
1910 ufshcd_get_uic_cmd_result(hba); 1996 ufshcd_get_uic_cmd_result(hba);
1997 hba->active_uic_cmd->argument3 =
1998 ufshcd_get_dme_attr_val(hba);
1911 complete(&hba->active_uic_cmd->done); 1999 complete(&hba->active_uic_cmd->done);
1912 } 2000 }
1913} 2001}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 59c9c4848be1..648ab16d379c 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -263,4 +263,55 @@ static inline void check_upiu_size(void)
263extern int ufshcd_runtime_suspend(struct ufs_hba *hba); 263extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
264extern int ufshcd_runtime_resume(struct ufs_hba *hba); 264extern int ufshcd_runtime_resume(struct ufs_hba *hba);
265extern int ufshcd_runtime_idle(struct ufs_hba *hba); 265extern int ufshcd_runtime_idle(struct ufs_hba *hba);
266extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
267 u8 attr_set, u32 mib_val, u8 peer);
268extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
269 u32 *mib_val, u8 peer);
270
271/* UIC command interfaces for DME primitives */
272#define DME_LOCAL 0
273#define DME_PEER 1
274#define ATTR_SET_NOR 0 /* NORMAL */
275#define ATTR_SET_ST 1 /* STATIC */
276
277static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel,
278 u32 mib_val)
279{
280 return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
281 mib_val, DME_LOCAL);
282}
283
284static inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel,
285 u32 mib_val)
286{
287 return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
288 mib_val, DME_LOCAL);
289}
290
291static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel,
292 u32 mib_val)
293{
294 return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR,
295 mib_val, DME_PEER);
296}
297
298static inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel,
299 u32 mib_val)
300{
301 return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST,
302 mib_val, DME_PEER);
303}
304
305static inline int ufshcd_dme_get(struct ufs_hba *hba,
306 u32 attr_sel, u32 *mib_val)
307{
308 return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL);
309}
310
311static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
312 u32 attr_sel, u32 *mib_val)
313{
314 return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER);
315}
316
266#endif /* End of Header */ 317#endif /* End of Header */
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index 739ae3aade0e..1e1fe2668181 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -191,6 +191,12 @@ enum {
191#define CONFIG_RESULT_CODE_MASK 0xFF 191#define CONFIG_RESULT_CODE_MASK 0xFF
192#define GENERIC_ERROR_CODE_MASK 0xFF 192#define GENERIC_ERROR_CODE_MASK 0xFF
193 193
194#define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\
195 ((sel) & 0xFFFF))
196#define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0)
197#define UIC_ARG_ATTR_TYPE(t) (((t) & 0xFF) << 16)
198#define UIC_GET_ATTR_ID(v) (((v) >> 16) & 0xFFFF)
199
194/* UIC Commands */ 200/* UIC Commands */
195enum { 201enum {
196 UIC_CMD_DME_GET = 0x01, 202 UIC_CMD_DME_GET = 0x01,