Commit 12b4fdb4f6bccb5459a2f75fbe0eab253bfceab4
Committed by
James Bottomley
1 parent
7d568652d3
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
[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>
Showing 3 changed files with 145 additions and 0 deletions Side-by-side Diff
drivers/scsi/ufs/ufshcd.c
... | ... | @@ -235,6 +235,18 @@ |
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 | + */ | |
244 | +static 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 | 250 | * ufshcd_get_req_rsp - returns the TR response transaction type |
239 | 251 | * @ucd_rsp_ptr: pointer to response UPIU |
240 | 252 | */ |
... | ... | @@ -1374,6 +1386,80 @@ |
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 | + */ | |
1398 | +int 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 | +} | |
1422 | +EXPORT_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 | + */ | |
1433 | +int 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; | |
1457 | +out: | |
1458 | + return ret; | |
1459 | +} | |
1460 | +EXPORT_SYMBOL_GPL(ufshcd_dme_get_attr); | |
1461 | + | |
1462 | +/** | |
1377 | 1463 | * ufshcd_complete_dev_init() - checks device readiness |
1378 | 1464 | * hba: per-adapter instance |
1379 | 1465 | * |
... | ... | @@ -1908,6 +1994,8 @@ |
1908 | 1994 | if (hba->active_uic_cmd) { |
1909 | 1995 | hba->active_uic_cmd->argument2 |= |
1910 | 1996 | ufshcd_get_uic_cmd_result(hba); |
1997 | + hba->active_uic_cmd->argument3 = | |
1998 | + ufshcd_get_dme_attr_val(hba); | |
1911 | 1999 | complete(&hba->active_uic_cmd->done); |
1912 | 2000 | } |
1913 | 2001 | } |
drivers/scsi/ufs/ufshcd.h
... | ... | @@ -263,5 +263,56 @@ |
263 | 263 | extern int ufshcd_runtime_suspend(struct ufs_hba *hba); |
264 | 264 | extern int ufshcd_runtime_resume(struct ufs_hba *hba); |
265 | 265 | extern int ufshcd_runtime_idle(struct ufs_hba *hba); |
266 | +extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, | |
267 | + u8 attr_set, u32 mib_val, u8 peer); | |
268 | +extern 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 | + | |
277 | +static 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 | + | |
284 | +static 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 | + | |
291 | +static 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 | + | |
298 | +static 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 | + | |
305 | +static 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 | + | |
311 | +static 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 | 317 | #endif /* End of Header */ |
drivers/scsi/ufs/ufshci.h
... | ... | @@ -191,6 +191,12 @@ |
191 | 191 | #define CONFIG_RESULT_CODE_MASK 0xFF |
192 | 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 | 200 | /* UIC Commands */ |
195 | 201 | enum { |
196 | 202 | UIC_CMD_DME_GET = 0x01, |