diff options
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 42 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 8 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshci.h | 3 |
3 files changed, 53 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9641bcb90cd2..3e57cca1ef33 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -2640,6 +2640,42 @@ static int ufshcd_hba_enable(struct ufs_hba *hba) | |||
2640 | return 0; | 2640 | return 0; |
2641 | } | 2641 | } |
2642 | 2642 | ||
2643 | static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) | ||
2644 | { | ||
2645 | int tx_lanes, i, err = 0; | ||
2646 | |||
2647 | if (!peer) | ||
2648 | ufshcd_dme_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), | ||
2649 | &tx_lanes); | ||
2650 | else | ||
2651 | ufshcd_dme_peer_get(hba, UIC_ARG_MIB(PA_CONNECTEDTXDATALANES), | ||
2652 | &tx_lanes); | ||
2653 | for (i = 0; i < tx_lanes; i++) { | ||
2654 | if (!peer) | ||
2655 | err = ufshcd_dme_set(hba, | ||
2656 | UIC_ARG_MIB_SEL(TX_LCC_ENABLE, | ||
2657 | UIC_ARG_MPHY_TX_GEN_SEL_INDEX(i)), | ||
2658 | 0); | ||
2659 | else | ||
2660 | err = ufshcd_dme_peer_set(hba, | ||
2661 | UIC_ARG_MIB_SEL(TX_LCC_ENABLE, | ||
2662 | UIC_ARG_MPHY_TX_GEN_SEL_INDEX(i)), | ||
2663 | 0); | ||
2664 | if (err) { | ||
2665 | dev_err(hba->dev, "%s: TX LCC Disable failed, peer = %d, lane = %d, err = %d", | ||
2666 | __func__, peer, i, err); | ||
2667 | break; | ||
2668 | } | ||
2669 | } | ||
2670 | |||
2671 | return err; | ||
2672 | } | ||
2673 | |||
2674 | static inline int ufshcd_disable_device_tx_lcc(struct ufs_hba *hba) | ||
2675 | { | ||
2676 | return ufshcd_disable_tx_lcc(hba, true); | ||
2677 | } | ||
2678 | |||
2643 | /** | 2679 | /** |
2644 | * ufshcd_link_startup - Initialize unipro link startup | 2680 | * ufshcd_link_startup - Initialize unipro link startup |
2645 | * @hba: per adapter instance | 2681 | * @hba: per adapter instance |
@@ -2677,6 +2713,12 @@ static int ufshcd_link_startup(struct ufs_hba *hba) | |||
2677 | /* failed to get the link up... retire */ | 2713 | /* failed to get the link up... retire */ |
2678 | goto out; | 2714 | goto out; |
2679 | 2715 | ||
2716 | if (hba->quirks & UFSHCD_QUIRK_BROKEN_LCC) { | ||
2717 | ret = ufshcd_disable_device_tx_lcc(hba); | ||
2718 | if (ret) | ||
2719 | goto out; | ||
2720 | } | ||
2721 | |||
2680 | /* Include any host controller configuration via UIC commands */ | 2722 | /* Include any host controller configuration via UIC commands */ |
2681 | if (hba->vops && hba->vops->link_startup_notify) { | 2723 | if (hba->vops && hba->vops->link_startup_notify) { |
2682 | ret = hba->vops->link_startup_notify(hba, POST_CHANGE); | 2724 | ret = hba->vops->link_startup_notify(hba, POST_CHANGE); |
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index fc8bec9960b1..b845f1535f29 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h | |||
@@ -426,6 +426,14 @@ struct ufs_hba { | |||
426 | */ | 426 | */ |
427 | #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS UFS_BIT(1) | 427 | #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS UFS_BIT(1) |
428 | 428 | ||
429 | /* | ||
430 | * If UFS host controller is having issue in processing LCC (Line | ||
431 | * Control Command) coming from device then enable this quirk. | ||
432 | * When this quirk is enabled, host controller driver should disable | ||
433 | * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE | ||
434 | * attribute of device to 0). | ||
435 | */ | ||
436 | #define UFSHCD_QUIRK_BROKEN_LCC UFS_BIT(2) | ||
429 | 437 | ||
430 | unsigned int quirks; /* Deviations from standard UFSHCI spec. */ | 438 | unsigned int quirks; /* Deviations from standard UFSHCI spec. */ |
431 | 439 | ||
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index d5721199e9cc..f8909ece2171 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h | |||
@@ -206,6 +206,9 @@ enum { | |||
206 | #define CONFIG_RESULT_CODE_MASK 0xFF | 206 | #define CONFIG_RESULT_CODE_MASK 0xFF |
207 | #define GENERIC_ERROR_CODE_MASK 0xFF | 207 | #define GENERIC_ERROR_CODE_MASK 0xFF |
208 | 208 | ||
209 | /* GenSelectorIndex calculation macros for M-PHY attributes */ | ||
210 | #define UIC_ARG_MPHY_TX_GEN_SEL_INDEX(lane) (lane) | ||
211 | |||
209 | #define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\ | 212 | #define UIC_ARG_MIB_SEL(attr, sel) ((((attr) & 0xFFFF) << 16) |\ |
210 | ((sel) & 0xFFFF)) | 213 | ((sel) & 0xFFFF)) |
211 | #define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0) | 214 | #define UIC_ARG_MIB(attr) UIC_ARG_MIB_SEL(attr, 0) |