diff options
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 88 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 51 | ||||
| -rw-r--r-- | drivers/scsi/ufs/ufshci.h | 6 |
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 | */ | ||
| 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 | * 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 | */ | ||
| 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 | * 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) | |||
| 263 | extern int ufshcd_runtime_suspend(struct ufs_hba *hba); | 263 | extern int ufshcd_runtime_suspend(struct ufs_hba *hba); |
| 264 | extern int ufshcd_runtime_resume(struct ufs_hba *hba); | 264 | extern int ufshcd_runtime_resume(struct ufs_hba *hba); |
| 265 | extern int ufshcd_runtime_idle(struct ufs_hba *hba); | 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 | #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 */ |
| 195 | enum { | 201 | enum { |
| 196 | UIC_CMD_DME_GET = 0x01, | 202 | UIC_CMD_DME_GET = 0x01, |
