scsi: ufs: add quirk to handle broken UFS HCI version
authorYaniv Gardi <ygardi@codeaurora.org>
Sun, 17 May 2015 15:55:05 +0000 (18:55 +0300)
committerJames Bottomley <JBottomley@Odin.com>
Tue, 2 Jun 2015 20:20:14 +0000 (13:20 -0700)
Some host controller hardware controllers may not advertise correct
version in UFS HCI VER register. To workaround this, add new quirk
and call the host controller hardware vendor specific callback to
get the correct UFS HCI version register value.

Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
Reviewed-by: Akinobu Mita <akinobu.mita@gmail.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
drivers/scsi/ufs/ufshcd.c
drivers/scsi/ufs/ufshcd.h
drivers/scsi/ufs/ufshci.h

index 014f1c0f843abff2d014aee5117bfa3673db7152..b0ade73f8c6a66a6a5f4d32fcbc4ac266b43d7eb 100644 (file)
@@ -271,6 +271,11 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba *hba)
  */
 static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
 {
+       if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) {
+               if (hba->vops && hba->vops->get_ufs_hci_version)
+                       return hba->vops->get_ufs_hci_version(hba);
+       }
+
        return ufshcd_readl(hba, REG_UFS_VERSION);
 }
 
index eb6831db15484e5f7ba4a359f3d0b8dd9531e573..c40a0e78a6c4298cf437dc312f0a136dd78abfa9 100644 (file)
@@ -246,6 +246,7 @@ struct ufs_pwr_mode_info {
  * @name: variant name
  * @init: called when the driver is initialized
  * @exit: called to cleanup everything done in init
+ * @get_ufs_hci_version: called to get UFS HCI version
  * @clk_scale_notify: notifies that clks are scaled up/down
  * @setup_clocks: called before touching any of the controller registers
  * @setup_regulators: called before accessing the host controller
@@ -263,6 +264,7 @@ struct ufs_hba_variant_ops {
        const char *name;
        int     (*init)(struct ufs_hba *);
        void    (*exit)(struct ufs_hba *);
+       u32     (*get_ufs_hci_version)(struct ufs_hba *);
        void    (*clk_scale_notify)(struct ufs_hba *);
        int     (*setup_clocks)(struct ufs_hba *, bool);
        int     (*setup_regulators)(struct ufs_hba *, bool);
@@ -449,6 +451,14 @@ struct ufs_hba {
         */
        #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE          UFS_BIT(4)
 
+       /*
+        * This quirk needs to be enabled if the host contoller doesn't
+        * advertise the correct version in UFS_VER register. If this quirk
+        * is enabled, standard UFS host driver will call the vendor specific
+        * ops (get_ufs_hci_version) to get the correct version.
+        */
+       #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION             UFS_BIT(5)
+
        unsigned int quirks;    /* Deviations from standard UFSHCI spec. */
 
        wait_queue_head_t tm_wq;
index f8909ece217179bcf42a344439c4590a55a69405..0ae0967aaed8c651830d138cc7e3adc40a6f826b 100644 (file)
@@ -89,8 +89,9 @@ enum {
 
 /* Controller UFSHCI version */
 enum {
-       UFSHCI_VERSION_10 = 0x00010000,
-       UFSHCI_VERSION_11 = 0x00010100,
+       UFSHCI_VERSION_10 = 0x00010000, /* 1.0 */
+       UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */
+       UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */
 };
 
 /*