BOARD: EXYNOS9810: ufs: add exynos specific files
authorhgchu <hg.chu@samsung.com>
Fri, 12 Jan 2018 10:19:25 +0000 (19:19 +0900)
committerJaeHun Jung <jh0801.jung@samsung.com>
Tue, 8 May 2018 08:20:49 +0000 (17:20 +0900)
Change-Id: I94018923d8fffc48e4e1e231093ff3ee3bca8c20
Signed-off-by: hgchu <hg.chu@samsung.com>
drivers/scsi/ufs/Makefile
drivers/scsi/ufs/ufs-cal-9810.c [new file with mode: 0644]
drivers/scsi/ufs/ufs-cal-9810.h [new file with mode: 0644]
drivers/scsi/ufs/ufs-exynos-dbg.c [new file with mode: 0644]
drivers/scsi/ufs/ufs-exynos.c [new file with mode: 0644]
drivers/scsi/ufs/ufs-exynos.h [new file with mode: 0644]

index 04691d93ee665cda275fbe299267238a2de68c9e..79955d9d7d581c6d5202aa13be89d6326b8d420f 100644 (file)
@@ -6,4 +6,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
-obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o ufs-exynos-dbg.o
+obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o ufs-exynos-dbg.o ufs-cal-9810.o
diff --git a/drivers/scsi/ufs/ufs-cal-9810.c b/drivers/scsi/ufs/ufs-cal-9810.c
new file mode 100644 (file)
index 0000000..4293d9e
--- /dev/null
@@ -0,0 +1,656 @@
+#if defined(__UFS_CAL_U_BOOT__)
+#include <linux/types.h>
+#include <ufs-cal-9810.h>
+#elif defined(__UFS_CAL_FW__)
+#include <types.h>
+#include <include/ufs-cal-9810.h>
+#else
+#include <linux/types.h>
+#include "ufs-cal-9810.h"
+#endif
+
+#ifndef _UFS_CAL_
+#define _UFS_CAL_
+
+/* UFSHCI */
+#define UIC_ARG_MIB_SEL(attr, sel)     ((((attr) & 0xFFFF) << 16) |\
+                                        ((sel) & 0xFFFF))
+#define UIC_ARG_MIB(attr)              UIC_ARG_MIB_SEL(attr, 0)
+
+/* Unipro.h */
+#define IS_PWR_MODE_HS(m)        (((m) == FAST_MODE) || ((m) == FASTAUTO_MODE))
+#define IS_PWR_MODE_PWM(m)       (((m) == SLOW_MODE) || ((m) == SLOWAUTO_MODE))
+
+enum {
+       PA_HS_MODE_A    = 1,
+       PA_HS_MODE_B    = 2,
+};
+
+enum {
+       FAST_MODE       = 1,
+       SLOW_MODE       = 2,
+       FASTAUTO_MODE   = 4,
+       SLOWAUTO_MODE   = 5,
+       UNCHANGED       = 7,
+};
+
+/* User defined */
+#define UNIPRO_MCLK_PERIOD(p) (1000000000L / p->mclk_rate)
+
+#define PHY_PMA_COMN_ADDR(reg)         (reg)
+#define PHY_PMA_TRSV_ADDR(reg, lane)   ((reg) + (0x140 * (lane)))
+
+#define NUM_OF_UFS_HOST        2
+
+enum {
+       PHY_CFG_NONE = 0,
+       PHY_PCS_COMN,
+       PHY_PCS_RXTX,
+       PHY_PMA_COMN,
+       PHY_PMA_TRSV,
+       PHY_PLL_WAIT,
+       PHY_CDR_WAIT,
+       UNIPRO_STD_MIB,
+       UNIPRO_DBG_MIB,
+       UNIPRO_DBG_APB,
+
+       /* Since exynos8895 */
+       PHY_PCS_RX,
+       PHY_PCS_TX,
+       PHY_PCS_RX_PRD,
+       PHY_PCS_TX_PRD,
+       UNIPRO_DBG_PRD,
+       PHY_PMA_TRSV_LANE1_SQ_OFF,
+       COMMON_WAIT,
+};
+
+enum {
+       TX_LANE_0 = 0,
+       TX_LANE_1 = 1,
+       TX_LANE_2 = 2,
+       TX_LANE_3 = 3,
+       RX_LANE_0 = 4,
+       RX_LANE_1 = 5,
+       RX_LANE_2 = 6,
+       RX_LANE_3 = 7,
+};
+
+enum {
+       __PMD_PWM_G1_L1,
+       __PMD_PWM_G1_L2,
+       __PMD_PWM_G2_L1,
+       __PMD_PWM_G2_L2,
+       __PMD_PWM_G3_L1,
+       __PMD_PWM_G3_L2,
+       __PMD_PWM_G4_L1,
+       __PMD_PWM_G4_L2,
+       __PMD_PWM_G5_L1,
+       __PMD_PWM_G5_L2,
+       __PMD_HS_G1_L1,
+       __PMD_HS_G1_L2,
+       __PMD_HS_G2_L1,
+       __PMD_HS_G2_L2,
+       __PMD_HS_G3_L1,
+       __PMD_HS_G3_L2,
+};
+
+#define PMD_PWM_G1_L1  (1U << __PMD_PWM_G1_L1)
+#define PMD_PWM_G1_L2  (1U << __PMD_PWM_G1_L2)
+#define PMD_PWM_G2_L1  (1U << __PMD_PWM_G2_L1)
+#define PMD_PWM_G2_L2  (1U << __PMD_PWM_G2_L2)
+#define PMD_PWM_G3_L1  (1U << __PMD_PWM_G3_L1)
+#define PMD_PWM_G3_L2  (1U << __PMD_PWM_G3_L2)
+#define PMD_PWM_G4_L1  (1U << __PMD_PWM_G4_L1)
+#define PMD_PWM_G4_L2  (1U << __PMD_PWM_G4_L2)
+#define PMD_PWM_G5_L1  (1U << __PMD_PWM_G5_L1)
+#define PMD_PWM_G5_L2  (1U << __PMD_PWM_G5_L2)
+#define PMD_HS_G1_L1   (1U << __PMD_HS_G1_L1)
+#define PMD_HS_G1_L2   (1U << __PMD_HS_G1_L2)
+#define PMD_HS_G2_L1   (1U << __PMD_HS_G2_L1)
+#define PMD_HS_G2_L2   (1U << __PMD_HS_G2_L2)
+#define PMD_HS_G3_L1   (1U << __PMD_HS_G3_L1)
+#define PMD_HS_G3_L2   (1U << __PMD_HS_G3_L2)
+
+#define PMD_ALL                (PMD_HS_G3_L2 - 1)
+#define PMD_PWM                (PMD_PWM_G4_L2 - 1)
+#define PMD_HS         (PMD_ALL ^ PMD_PWM)
+
+struct ufs_cal_phy_cfg {
+       u32 addr;
+       u32 val;
+       u32 flg;
+       u32 lyr;
+       u8 board;
+};
+
+#define for_each_phy_cfg(cfg) \
+       for (; (cfg)->flg != PHY_CFG_NONE; (cfg)++)
+
+#endif /*_UFS_CAL_ */
+
+static struct ufs_cal_param *ufs_cal[NUM_OF_UFS_HOST];
+static unsigned long ufs_cal_lock_timeout = 0xFFFFFFFF;
+
+static const struct ufs_cal_phy_cfg init_cfg[] = {
+       {0x9514, 0x00, PMD_ALL, UNIPRO_DBG_PRD, 0},
+       {0x200, 0x40, PMD_ALL, PHY_PCS_COMN, 0},
+       {0x12, 0x00, PMD_ALL, PHY_PCS_RX_PRD, 0},
+       {0xAA, 0x00, PMD_ALL, PHY_PCS_TX_PRD, 0},
+       {0x5C, 0x38, PMD_ALL, PHY_PCS_RX, 0},
+       {0x0F, 0x0, PMD_ALL, PHY_PCS_RX, 0},
+       {0x65, 0x01, PMD_ALL, PHY_PCS_RX, 0},
+       {0x69, 0x01, PMD_ALL, PHY_PCS_RX, 0},
+       {0x21, 0x00, PMD_ALL, PHY_PCS_RX, 0},
+       {0x22, 0x00, PMD_ALL, PHY_PCS_RX, 0},
+       {0x84, 0x01, PMD_ALL, PHY_PCS_RX, 0},
+       {0x04, 0x01, PMD_ALL, PHY_PCS_TX, 0},
+       {0x8F, 0x3E, PMD_ALL, PHY_PCS_TX, 0},
+       {0x200, 0x0, PMD_ALL, PHY_PCS_COMN, 0},
+       {0x9536, 0x4E20, PMD_ALL, UNIPRO_DBG_MIB, 0},
+       {0x9564, 0x2e820183, PMD_ALL, UNIPRO_DBG_MIB, 0},
+       {0x155E, 0x0, PMD_ALL, UNIPRO_STD_MIB, 0},
+       {0x3000, 0x0, PMD_ALL, UNIPRO_STD_MIB, 0},
+       {0x3001, 0x1, PMD_ALL, UNIPRO_STD_MIB, 0},
+       {0x4021, 0x1, PMD_ALL, UNIPRO_STD_MIB, 0},
+       {0x4020, 0x1, PMD_ALL, UNIPRO_STD_MIB, 0},
+       {0x8C, 0x80, PMD_ALL, PHY_PMA_COMN, 0},
+       {0x74, 0x10, PMD_ALL, PHY_PMA_COMN, 0},
+       {0x110, 0xB5, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x134, 0x43, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x16C, 0x20, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x178, 0xC0, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0xE0, 0x12, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x164, 0x58, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x1B0, 0x18, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x8C, 0xC0, PMD_ALL, PHY_PMA_COMN, 0},
+       {0x8C, 0x00, PMD_ALL, PHY_PMA_COMN, 0},
+       {0x00, 0xC8, PMD_ALL, COMMON_WAIT, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg post_init_cfg[] = {
+       {0x9529, 0x01, PMD_ALL, UNIPRO_DBG_MIB, 0},
+       {0x15A4, 0xFA, PMD_ALL, UNIPRO_STD_MIB, 0},
+       {0x9529, 0x00, PMD_ALL, UNIPRO_DBG_MIB, 0},
+       {0x200, 0x40, PMD_ALL, PHY_PCS_COMN, 0},
+       {0x35, 0x05, PMD_ALL, PHY_PCS_RX, 0},
+       {0x73, 0x01, PMD_ALL, PHY_PCS_RX, 0},
+       {0x41, 0x02, PMD_ALL, PHY_PCS_RX, 0},
+       {0x42, 0xAC, PMD_ALL, PHY_PCS_RX, 0},
+       {0x200, 0x00, PMD_ALL, PHY_PCS_COMN, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg calib_of_pwm[] = {
+       {0x2041, 8064, PMD_PWM, UNIPRO_STD_MIB, 0},
+       {0x2042, 28224, PMD_PWM, UNIPRO_STD_MIB, 0},
+       {0x2043, 20160, PMD_PWM, UNIPRO_STD_MIB, 0},
+       {0x15B0, 12000, PMD_PWM, UNIPRO_STD_MIB, 0},
+       {0x15B1, 32000, PMD_PWM, UNIPRO_STD_MIB, 0},
+       {0x15B2, 16000, PMD_PWM, UNIPRO_STD_MIB, 0},
+
+       {0x7888, 8064, PMD_PWM, UNIPRO_DBG_APB, 0},
+       {0x788C, 28224, PMD_PWM, UNIPRO_DBG_APB, 0},
+       {0x7890, 20160, PMD_PWM, UNIPRO_DBG_APB, 0},
+       {0x78B8, 12000, PMD_PWM, UNIPRO_DBG_APB, 0},
+       {0x78BC, 32000, PMD_PWM, UNIPRO_DBG_APB, 0},
+       {0x78C0, 16000, PMD_PWM, UNIPRO_DBG_APB, 0},
+
+       //MPHY tuning value
+       {0xC8, 0x40, PMD_PWM, PHY_PMA_TRSV, 0},
+       {0xF0, 0x77, PMD_PWM, PHY_PMA_TRSV, 0},
+       {0x120, 0x80, PMD_PWM, PHY_PMA_TRSV, 0},
+       {0x128, 0x00, PMD_PWM, PHY_PMA_TRSV, 0},
+       {0x12C, 0x00, PMD_PWM, PHY_PMA_TRSV, 0},
+       {0x134, 0x43, PMD_PWM, PHY_PMA_TRSV, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg post_calib_of_pwm[] = {
+       {},
+};
+static struct ufs_cal_phy_cfg calib_of_hs_rate_a[] = {
+       {0x2041, 8064, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x2042, 28224, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x2043, 20160, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x15B0, 12000, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x15B1, 32000, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x15B2, 16000, PMD_HS, UNIPRO_STD_MIB, 0},
+
+       {0x7888, 8064, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x788C, 28224, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x7890, 20160, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x78B8, 12000, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x78BC, 32000, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x78C0, 16000, PMD_HS, UNIPRO_DBG_APB, 0},
+
+       //MPHY tuning value
+       {0xC8, 0xBC, PMD_HS, PHY_PMA_TRSV, 0},
+       {0xF0, 0x7F, PMD_HS, PHY_PMA_TRSV, 0},
+       {0x120, 0xC0, PMD_HS, PHY_PMA_TRSV, 0},
+       {0x128, 0x08, PMD_HS_G1_L2, PHY_PMA_TRSV, 0},
+       {0x128, 0x02, PMD_HS_G2_L2, PHY_PMA_TRSV, 0},
+       {0x128, 0x00, PMD_HS_G3_L2, PHY_PMA_TRSV, 0},
+       {0x12C, 0x00, PMD_HS_G1_L2|PMD_HS_G3_L2, PHY_PMA_TRSV, 1},
+       {0x12C, 0x10, PMD_HS_G1_L2|PMD_HS_G3_L2, PHY_PMA_TRSV, 2},
+       {0x12C, 0x00, PMD_HS_G2_L2, PHY_PMA_TRSV, 0},
+       {0x134, 0xd3, PMD_HS_G1_L2, PHY_PMA_TRSV, 0},
+       {0x134, 0x73, PMD_HS_G2_L2, PHY_PMA_TRSV, 0},
+       {0x134, 0x63, PMD_HS_G3_L2, PHY_PMA_TRSV, 0},
+       {0x108, 0x5D, PMD_HS, PHY_PMA_TRSV, 1},
+       {0x10C, 0x90, PMD_HS, PHY_PMA_TRSV, 1},
+       {},
+};
+
+static struct ufs_cal_phy_cfg post_calib_of_hs_rate_a[] = {
+       {0x1fc, 0x40, PMD_HS, PHY_CDR_WAIT, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg calib_of_hs_rate_b[] = {
+       {0x2041, 8064, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x2042, 28224, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x2043, 20160, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x15B0, 12000, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x15B1, 32000, PMD_HS, UNIPRO_STD_MIB, 0},
+       {0x15B2, 16000, PMD_HS, UNIPRO_STD_MIB, 0},
+
+       {0x7888, 8064, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x788C, 28224, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x7890, 20160, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x78B8, 12000, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x78BC, 32000, PMD_HS, UNIPRO_DBG_APB, 0},
+       {0x78C0, 16000, PMD_HS, UNIPRO_DBG_APB, 0},
+       /*MPHY tuning value*/
+       {0xC8, 0xBC, PMD_HS, PHY_PMA_TRSV, 0},
+       {0xF0, 0x7F, PMD_HS, PHY_PMA_TRSV, 0},
+       {0x120, 0xC0, PMD_HS, PHY_PMA_TRSV, 0},
+       {0x128, 0x08, PMD_HS_G1_L2, PHY_PMA_TRSV, 0},
+       {0x128, 0x02, PMD_HS_G2_L2, PHY_PMA_TRSV, 0},
+       {0x128, 0x00, PMD_HS_G3_L2, PHY_PMA_TRSV, 0},
+       {0x12C, 0x00, PMD_HS_G1_L2|PMD_HS_G3_L2, PHY_PMA_TRSV, 1},
+       {0x12C, 0x10, PMD_HS_G1_L2|PMD_HS_G3_L2, PHY_PMA_TRSV, 2},
+       {0x12C, 0x00, PMD_HS_G2_L2, PHY_PMA_TRSV, 0},
+       {0x134, 0xd3, PMD_HS_G1_L2, PHY_PMA_TRSV, 0},
+       {0x134, 0x73, PMD_HS_G2_L2, PHY_PMA_TRSV, 0},
+       {0x134, 0x63, PMD_HS_G3_L2, PHY_PMA_TRSV, 0},
+       {0x108, 0x5D, PMD_HS, PHY_PMA_TRSV, 1},
+       {0x10C, 0x90, PMD_HS, PHY_PMA_TRSV, 1},
+       {},
+};
+
+static struct ufs_cal_phy_cfg post_calib_of_hs_rate_b[] = {
+       {0x1fc, 0x40, PMD_HS, PHY_CDR_WAIT, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg lane1_sq_off[] = {
+       {0x0C4, 0x19, PMD_ALL, PHY_PMA_TRSV_LANE1_SQ_OFF, 0},
+       {0x0E8, 0xFF, PMD_ALL, PHY_PMA_TRSV_LANE1_SQ_OFF, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg post_h8_enter[] = {
+       {0x0C4, 0x99, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x0E8, 0x7F, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x004, 0x02, PMD_ALL, PHY_PMA_COMN, 0},
+       {},
+};
+
+static struct ufs_cal_phy_cfg pre_h8_exit[] = {
+       {0x004, 0x00, PMD_ALL, PHY_PMA_COMN, 0},
+       {0x0C4, 0xD9, PMD_ALL, PHY_PMA_TRSV, 0},
+       {0x0E8, 0x77, PMD_ALL, PHY_PMA_TRSV, 0},
+       {},
+};
+
+static inline ufs_cal_errno __match_board_by_cfg(u8 board, u8 cfg_board)
+{
+       ufs_cal_errno match = UFS_CAL_ERROR;
+
+       if (cfg_board == 0)
+               match = UFS_CAL_NO_ERROR;
+       else if (board == cfg_board)
+               match = UFS_CAL_NO_ERROR;
+
+       return match;
+}
+
+static inline ufs_cal_errno __match_mode_by_cfg(struct uic_pwr_mode *pmd,
+                                                               int mode)
+{
+       ufs_cal_errno match = UFS_CAL_ERROR;
+       u8 _m, _l, _g;
+
+       _m = pmd->mode;
+       _g = pmd->gear;
+       _l = pmd->lane;
+
+       if (mode == PMD_ALL)
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && mode == PMD_HS)
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && mode == PMD_PWM)
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && _g == 1 && _l == 1
+               && (mode & (PMD_HS_G1_L1|PMD_HS_G1_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && _g == 1 && _l == 2
+               && (mode & (PMD_HS_G1_L1|PMD_HS_G1_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && _g == 2 && _l == 1
+               && (mode & (PMD_HS_G2_L1|PMD_HS_G2_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && _g == 2 && _l == 2
+               && (mode & (PMD_HS_G2_L1|PMD_HS_G2_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && _g == 3 && _l == 1
+               && (mode & (PMD_HS_G3_L1|PMD_HS_G3_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_HS(_m) && _g == 3 && _l == 2
+               && (mode & (PMD_HS_G3_L1|PMD_HS_G3_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 1 && _l == 1
+               && (mode & (PMD_PWM_G1_L1|PMD_PWM_G1_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 1 && _l == 2
+               && (mode & (PMD_PWM_G1_L1|PMD_PWM_G1_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 2 && _l == 1
+               && (mode & (PMD_PWM_G2_L1|PMD_PWM_G2_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 2 && _l == 2
+               && (mode & (PMD_PWM_G2_L1|PMD_PWM_G2_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 3 && _l == 1
+               && (mode & (PMD_PWM_G3_L1|PMD_PWM_G3_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 3 && _l == 2
+               && (mode & (PMD_PWM_G3_L1|PMD_PWM_G3_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 4 && _l == 1
+               && (mode & (PMD_PWM_G4_L1|PMD_PWM_G4_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 4 && _l == 2
+               && (mode & (PMD_PWM_G4_L1|PMD_PWM_G4_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 5 && _l == 1
+               && (mode & (PMD_PWM_G5_L1|PMD_PWM_G5_L2)))
+               match = UFS_CAL_NO_ERROR;
+       else if (IS_PWR_MODE_PWM(_m) && _g == 5 && _l == 2
+               && (mode & (PMD_PWM_G5_L1|PMD_PWM_G5_L2)))
+               match = UFS_CAL_NO_ERROR;
+
+       return match;
+}
+
+static inline ufs_cal_errno ufs_cal_wait_pll_lock(void *hba,
+                                       u32 addr, u32 mask)
+{
+       u32 delay_us = 1;
+       u32 period_ms = 1;
+       u32 reg;
+       unsigned long timeout = ufs_lld_get_time_count(0) + ufs_cal_lock_timeout;
+
+       do {
+               reg = ufs_lld_pma_read(hba, PHY_PMA_COMN_ADDR(addr));
+               if (mask == (reg & mask))
+                       return UFS_CAL_NO_ERROR;
+               ufs_lld_usleep_delay(delay_us, delay_us);
+       } while ((long)(ufs_lld_get_time_count(period_ms) - timeout) >= 0);
+
+       return UFS_CAL_ERROR;
+}
+
+static inline ufs_cal_errno ufs_cal_wait_cdr_lock(void *hba,
+                                       u32 addr, u32 mask, int lane)
+{
+       u32 delay_us = 1;
+       u32 period_ms = 1;
+       u32 reg;
+       unsigned long timeout = ufs_lld_get_time_count(0) + ufs_cal_lock_timeout;
+
+       do {
+               reg = ufs_lld_pma_read(hba, PHY_PMA_TRSV_ADDR(addr, lane));
+               if (mask == (reg & mask))
+                       return UFS_CAL_NO_ERROR;
+               ufs_lld_usleep_delay(delay_us, delay_us);
+       } while ((long)(ufs_lld_get_time_count(period_ms) - timeout) >= 0);
+
+       return UFS_CAL_ERROR;
+
+}
+
+static ufs_cal_errno ufs_cal_config_uic(struct ufs_cal_param *p,
+                                 const struct ufs_cal_phy_cfg *cfg,
+                                 struct uic_pwr_mode *pmd)
+{
+       void *hba = p->host;
+       u8 i = 0;
+
+       if (!cfg)
+               return UFS_CAL_INV_ARG;
+
+       for_each_phy_cfg(cfg) {
+               for (i = 0; i < p->target_lane; i++) {
+                       if (UFS_CAL_ERROR ==
+                                       __match_board_by_cfg(p->board, cfg->board))
+                               continue;
+                       if (pmd && UFS_CAL_ERROR ==
+                                       __match_mode_by_cfg(pmd, cfg->flg))
+                               continue;
+
+                       switch (cfg->lyr) {
+                       case PHY_PCS_COMN:
+                       case UNIPRO_STD_MIB:
+                       case UNIPRO_DBG_MIB:
+                               if (i == 0)
+                                       ufs_lld_dme_set(hba, UIC_ARG_MIB(cfg->addr),
+                                               cfg->val);
+                               break;
+                       case PHY_PCS_RXTX:
+                               ufs_lld_dme_set(hba, UIC_ARG_MIB_SEL(cfg->addr, i),
+                                               cfg->val);
+                               break;
+                       case UNIPRO_DBG_PRD:
+                               if (i == 0)
+                                       ufs_lld_dme_set(hba, UIC_ARG_MIB(cfg->addr),
+                                               UNIPRO_MCLK_PERIOD(p));
+                               break;
+                       case PHY_PCS_RX:
+                               ufs_lld_dme_set(hba, UIC_ARG_MIB_SEL(cfg->addr,
+                                       RX_LANE_0+i), cfg->val);
+                               break;
+                       case PHY_PCS_TX:
+                               ufs_lld_dme_set(hba, UIC_ARG_MIB_SEL(cfg->addr,
+                                       TX_LANE_0+i), cfg->val);
+                               break;
+                       case PHY_PCS_RX_PRD:
+                               ufs_lld_dme_set(hba, UIC_ARG_MIB_SEL(cfg->addr,
+                                       RX_LANE_0+i), UNIPRO_MCLK_PERIOD(p));
+                               break;
+
+                       case PHY_PCS_TX_PRD:
+                               ufs_lld_dme_set(hba, UIC_ARG_MIB_SEL(cfg->addr,
+                                       TX_LANE_0+i), UNIPRO_MCLK_PERIOD(p));
+                               break;
+                       case PHY_PMA_COMN:
+                               if (i == 0)
+                                       ufs_lld_pma_write(hba, cfg->val,
+                                               PHY_PMA_COMN_ADDR(cfg->addr));
+                               break;
+                       case PHY_PMA_TRSV:
+                               ufs_lld_pma_write(hba, cfg->val,
+                                               PHY_PMA_TRSV_ADDR(cfg->addr, i));
+                               break;
+                       case PHY_PMA_TRSV_LANE1_SQ_OFF:
+                               if (i == 1)
+                                       ufs_lld_pma_write(hba, cfg->val,
+                                               PHY_PMA_TRSV_ADDR(cfg->addr, i));
+                               break;
+                       case UNIPRO_DBG_APB:
+                               ufs_lld_unipro_write(hba, cfg->val, cfg->addr);
+                               break;
+                       case PHY_PLL_WAIT:
+                               if (i == 0) {
+                                       if (ufs_cal_wait_pll_lock(hba,
+                                               cfg->addr, cfg->val) ==
+                                                               UFS_CAL_ERROR)
+                                               return UFS_CAL_TIMEOUT;
+                               }
+                               break;
+                       case PHY_CDR_WAIT:
+                               if (ufs_cal_wait_cdr_lock(hba,
+                                               cfg->addr, cfg->val, i) ==
+                                                               UFS_CAL_ERROR)
+                                       return UFS_CAL_TIMEOUT;
+                               break;
+                       case COMMON_WAIT:
+                               if (i == 0)
+                                       ufs_lld_udelay(cfg->val);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+       }
+
+       return UFS_CAL_NO_ERROR;
+}
+
+/*
+ * This is a recommendation from Samsung UFS device vendor.
+ *
+ * Activate time: host < device
+ * Hibern time: host > device
+ */
+static void ufs_cal_calib_hibern8_values(void *hba)
+{
+       u32 hw_cap_min_tactivate;
+       u32 peer_rx_min_actv_time_cap;
+       u32 max_rx_hibern8_time_cap;
+
+       ufs_lld_dme_get(hba, UIC_ARG_MIB_SEL(0x8F, RX_LANE_0),
+                       &hw_cap_min_tactivate); /* HW Capability of MIN_TACTIVATE */
+
+       ufs_lld_dme_get(hba, UIC_ARG_MIB(0x15A8),
+                       &peer_rx_min_actv_time_cap);    /* PA_TActivate */
+       ufs_lld_dme_get(hba, UIC_ARG_MIB(0x15A7),
+                       &max_rx_hibern8_time_cap);      /* PA_Hibern8Time */
+
+       if (peer_rx_min_actv_time_cap >= hw_cap_min_tactivate)
+               ufs_lld_dme_peer_set(hba, UIC_ARG_MIB(0x15A8),
+                               peer_rx_min_actv_time_cap + 1);
+       ufs_lld_dme_set(hba, UIC_ARG_MIB(0x15A7), max_rx_hibern8_time_cap + 1);
+}
+
+ufs_cal_errno ufs_cal_post_h8_enter(struct ufs_cal_param *p)
+{
+       ufs_cal_errno ret = UFS_CAL_NO_ERROR;
+
+       ret = ufs_cal_config_uic(p, post_h8_enter, p->pmd);
+
+       return ret;
+}
+
+ufs_cal_errno ufs_cal_pre_h8_exit(struct ufs_cal_param *p)
+{
+       ufs_cal_errno ret = UFS_CAL_NO_ERROR;
+
+       ret = ufs_cal_config_uic(p, pre_h8_exit, p->pmd);
+
+       return ret;
+}
+
+/*
+ * This currently uses only SLOW_MODE and FAST_MODE.
+ * If you want others, you should modify this function.
+ */
+ufs_cal_errno ufs_cal_pre_pmc(struct ufs_cal_param *p)
+{
+       ufs_cal_errno ret = UFS_CAL_NO_ERROR;
+       struct ufs_cal_phy_cfg *cfg;
+
+       if ((p->pmd->mode == SLOW_MODE) || (p->pmd->mode == SLOWAUTO_MODE))
+               cfg = calib_of_pwm;
+       else if (p->pmd->hs_series == PA_HS_MODE_B)
+               cfg = calib_of_hs_rate_b;
+       else if (p->pmd->hs_series == PA_HS_MODE_A)
+               cfg = calib_of_hs_rate_a;
+       else
+               return UFS_CAL_INV_ARG;
+
+       /*
+        * If a number of target lanes is 1 and a host's
+        * a number of available lanes is 2,
+        * you should turn off phy power of lane #1.
+        *
+        * This must be modified when a number of avaiable lanes
+        * would grow in the future.
+        */
+       if ((p->available_lane == 2) && (p->target_lane == 1))
+               ret = ufs_cal_config_uic(p, lane1_sq_off, NULL);
+
+       ret = ufs_cal_config_uic(p, cfg, p->pmd);
+
+       return ret;
+}
+
+/*
+ * This currently uses only SLOW_MODE and FAST_MODE.
+ * If you want others, you should modify this function.
+ */
+ufs_cal_errno ufs_cal_post_pmc(struct ufs_cal_param *p)
+{
+       ufs_cal_errno ret = UFS_CAL_NO_ERROR;
+       struct ufs_cal_phy_cfg *cfg;
+
+       if ((p->pmd->mode == SLOWAUTO_MODE) || (p->pmd->mode == SLOW_MODE))
+               cfg = post_calib_of_pwm;
+       else if (p->pmd->hs_series == PA_HS_MODE_B)
+               cfg = post_calib_of_hs_rate_b;
+       else if (p->pmd->hs_series == PA_HS_MODE_A)
+               cfg = post_calib_of_hs_rate_a;
+       else
+               return UFS_CAL_INV_ARG;
+
+       ret = ufs_cal_config_uic(p, cfg, p->pmd);
+
+       return ret;
+}
+
+ufs_cal_errno ufs_cal_post_link(struct ufs_cal_param *p)
+{
+       ufs_cal_errno ret = UFS_CAL_NO_ERROR;
+
+       ufs_cal_calib_hibern8_values(p->host);
+
+       ret = ufs_cal_config_uic(p, post_init_cfg, NULL);
+
+       return ret;
+}
+
+ufs_cal_errno ufs_cal_pre_link(struct ufs_cal_param *p)
+{
+       ufs_cal_errno ret = UFS_CAL_NO_ERROR;
+
+       ret = ufs_cal_config_uic(p, init_cfg, NULL);
+
+       return ret;
+}
+
+ufs_cal_errno ufs_cal_init(struct ufs_cal_param *p, int idx)
+{
+       /*
+        * Return if innput index is greater than
+        * the maximum that cal supports
+        */
+       if (idx >= NUM_OF_UFS_HOST)
+               return UFS_CAL_INV_ARG;
+
+       ufs_cal[idx] = p;
+
+       ufs_cal_lock_timeout = ufs_lld_calc_timeout(100);
+
+       return UFS_CAL_NO_ERROR;
+}
diff --git a/drivers/scsi/ufs/ufs-cal-9810.h b/drivers/scsi/ufs/ufs-cal-9810.h
new file mode 100644 (file)
index 0000000..4645450
--- /dev/null
@@ -0,0 +1,52 @@
+struct uic_pwr_mode {
+       u8 lane;
+       u8 gear;
+       u8 mode;
+       u8 hs_series;
+};
+
+struct ufs_cal_param {
+       void *host;             /* Host adaptor */
+       u8 available_lane;
+       u8 target_lane;
+       u32 mclk_rate;
+       u8 board;
+       struct uic_pwr_mode *pmd;
+};
+
+typedef enum {
+       UFS_CAL_NO_ERROR = 0,
+       UFS_CAL_TIMEOUT,
+       UFS_CAL_ERROR,
+       UFS_CAL_INV_ARG,
+} ufs_cal_errno;
+
+enum {
+       __BRD_COMMON,
+       __BRD_UNIV,
+       __BRD_SMDK,
+};
+#define BRD_COMMON     (1U << __BRD_COMMON)
+#define BRD_UNIV       (1U << __BRD_UNIV)
+#define BRD_SMDK       (1U << __BRD_SMDK)
+
+/* UFS CAL interface */
+ufs_cal_errno ufs_cal_post_h8_enter(struct ufs_cal_param *p);
+ufs_cal_errno ufs_cal_pre_h8_exit(struct ufs_cal_param *p);
+ufs_cal_errno ufs_cal_post_pmc(struct ufs_cal_param *p);
+ufs_cal_errno ufs_cal_pre_pmc(struct ufs_cal_param *p);
+ufs_cal_errno ufs_cal_post_link(struct ufs_cal_param *p);
+ufs_cal_errno ufs_cal_pre_link(struct ufs_cal_param *p);
+ufs_cal_errno ufs_cal_init(struct ufs_cal_param *p, int idx);
+
+/* Adaptor for UFS CAL */
+void ufs_lld_dme_set(void *h, u32 addr, u32 val);
+void ufs_lld_dme_get(void *h, u32 addr, u32 *val);
+void ufs_lld_dme_peer_set(void *h, u32 addr, u32 val);
+void ufs_lld_pma_write(void *h, u32 val, u32 addr);
+u32 ufs_lld_pma_read(void *h, u32 addr);
+void ufs_lld_unipro_write(void *h, u32 val, u32 addr);
+void ufs_lld_udelay(u32 val);
+void ufs_lld_usleep_delay(u32 min, u32 max);
+unsigned long ufs_lld_get_time_count(unsigned long offset);
+unsigned long ufs_lld_calc_timeout(const unsigned int ms);
diff --git a/drivers/scsi/ufs/ufs-exynos-dbg.c b/drivers/scsi/ufs/ufs-exynos-dbg.c
new file mode 100644 (file)
index 0000000..c06e9e7
--- /dev/null
@@ -0,0 +1,1193 @@
+/*
+ * UFS debugging functions for Exynos specific extensions
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Authors:
+ *     Kiwoong <kwmad.kim@samsung.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/smc.h>
+
+#include "ufshcd.h"
+#include "unipro.h"
+#include "mphy.h"
+#include "ufs-exynos.h"
+
+#if !defined(CONFIG_SOC_EXYNOS7420) && !defined(CONFIG_SOC_EXYNOS8890)
+/*
+ * This is a list for latest SoC.
+ */
+static struct exynos_ufs_sfr_log ufs_log_sfr[] = {
+       {"STD HCI SFR"                  ,       LOG_STD_HCI_SFR,                0},
+
+       {"INTERRUPT STATUS"             ,       REG_INTERRUPT_STATUS,           0},
+       {"INTERRUPT ENABLE"             ,       REG_INTERRUPT_ENABLE,           0},
+       {"CONTROLLER STATUS"            ,       REG_CONTROLLER_STATUS,          0},
+       {"CONTROLLER ENABLE"            ,       REG_CONTROLLER_ENABLE,          0},
+       {"UTP TRANSF REQ INT AGG CNTRL" ,       REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL,           0},
+       {"UTP TRANSF REQ LIST BASE L"   ,       REG_UTP_TRANSFER_REQ_LIST_BASE_L,               0},
+       {"UTP TRANSF REQ LIST BASE H"   ,       REG_UTP_TRANSFER_REQ_LIST_BASE_H,               0},
+       {"UTP TRANSF REQ DOOR BELL"     ,       REG_UTP_TRANSFER_REQ_DOOR_BELL,         0},
+       {"UTP TRANSF REQ LIST CLEAR"    ,       REG_UTP_TRANSFER_REQ_LIST_CLEAR,                0},
+       {"UTP TRANSF REQ LIST RUN STOP" ,       REG_UTP_TRANSFER_REQ_LIST_RUN_STOP,             0},
+       {"UTP TRANSF REQ LIST CNR"      ,       REG_UTP_TRANSFER_REQ_LIST_CNR,          0},
+       {"UTP TASK REQ LIST BASE L"     ,       REG_UTP_TASK_REQ_LIST_BASE_L,           0},
+       {"UTP TASK REQ LIST BASE H"     ,       REG_UTP_TASK_REQ_LIST_BASE_H,           0},
+       {"UTP TASK REQ DOOR BELL"       ,       REG_UTP_TASK_REQ_DOOR_BELL,             0},
+       {"UTP TASK REQ LIST CLEAR"      ,       REG_UTP_TASK_REQ_LIST_CLEAR,            0},
+       {"UTP TASK REQ LIST RUN STOP"   ,       REG_UTP_TASK_REQ_LIST_RUN_STOP,         0},
+       {"UIC COMMAND"                  ,       REG_UIC_COMMAND,                0},
+       {"UIC COMMAND ARG1"             ,       REG_UIC_COMMAND_ARG_1,          0},
+       {"UIC COMMAND ARG2"             ,       REG_UIC_COMMAND_ARG_2,          0},
+       {"UIC COMMAND ARG3"             ,       REG_UIC_COMMAND_ARG_3,          0},
+       {"CCAP"                         ,       REG_CRYPTO_CAPABILITY,          0},
+
+
+       {"VS HCI SFR"                   ,       LOG_VS_HCI_SFR,                 0},
+
+       {"TXPRDT ENTRY SIZE"            ,       HCI_TXPRDT_ENTRY_SIZE,          0},
+       {"RXPRDT ENTRY SIZE"            ,       HCI_RXPRDT_ENTRY_SIZE,          0},
+       {"TO CNT DIV VAL"               ,       HCI_TO_CNT_DIV_VAL,             0},
+       {"1US TO CNT VAL"               ,       HCI_1US_TO_CNT_VAL,             0},
+       {"INVALID UPIU CTRL"            ,       HCI_INVALID_UPIU_CTRL,          0},
+       {"INVALID UPIU BADDR"           ,       HCI_INVALID_UPIU_BADDR,         0},
+       {"INVALID UPIU UBADDR"          ,       HCI_INVALID_UPIU_UBADDR,                0},
+       {"INVALID UTMR OFFSET ADDR"     ,       HCI_INVALID_UTMR_OFFSET_ADDR,           0},
+       {"INVALID UTR OFFSET ADDR"      ,       HCI_INVALID_UTR_OFFSET_ADDR,            0},
+       {"INVALID DIN OFFSET ADDR"      ,       HCI_INVALID_DIN_OFFSET_ADDR,            0},
+       {"VENDOR SPECIFIC IS"           ,       HCI_VENDOR_SPECIFIC_IS,         0},
+       {"VENDOR SPECIFIC IE"           ,       HCI_VENDOR_SPECIFIC_IE,         0},
+       {"UTRL NEXUS TYPE"              ,       HCI_UTRL_NEXUS_TYPE,            0},
+       {"UTMRL NEXUS TYPE"             ,       HCI_UTMRL_NEXUS_TYPE,           0},
+       {"SW RST"                       ,       HCI_SW_RST,             0},
+       {"RX UPIU MATCH ERROR CODE"     ,       HCI_RX_UPIU_MATCH_ERROR_CODE,           0},
+       {"DATA REORDER"                 ,       HCI_DATA_REORDER,               0},
+       {"AXIDMA RWDATA BURST LEN"      ,       HCI_AXIDMA_RWDATA_BURST_LEN,            0},
+       {"WRITE DMA CTRL"               ,       HCI_WRITE_DMA_CTRL,             0},
+       {"V2P1 CTRL"                    ,       HCI_UFSHCI_V2P1_CTRL,           0},
+       {"CLKSTOP CTRL"                 ,       HCI_CLKSTOP_CTRL,               0},
+       {"FORCE HCS"                    ,       HCI_FORCE_HCS,          0},
+       {"FSM MONITOR"                  ,       HCI_FSM_MONITOR,                0},
+       {"DMA0 MONITOR STATE"           ,       HCI_DMA0_MONITOR_STATE,         0},
+       {"DMA0 MONITOR CNT"             ,       HCI_DMA0_MONITOR_CNT,           0},
+       {"DMA1 MONITOR STATE"           ,       HCI_DMA1_MONITOR_STATE,         0},
+       {"DMA1 MONITOR CNT"             ,       HCI_DMA1_MONITOR_CNT,           0},
+       {"AXI DMA IF CTRL"              ,       HCI_UFS_AXI_DMA_IF_CTRL,        0},
+       {"UFS ACG DISABLE"              ,       HCI_UFS_ACG_DISABLE,            0},
+       {"MPHY REFCLK SEL"              ,       HCI_MPHY_REFCLK_SEL,            0},
+       {"SMU ABORT MATCH INFO"         ,       HCI_SMU_ABORT_MATCH_INFO,       0},
+       {"DBR DUPLICATION INFO"         ,       HCI_DBR_DUPLICATION_INFO,       0},
+       {"DBR TIMER CONFIG"             ,       HCI_DBR_TIMER_CONFIG,           0},
+       {"DBR TIMER ENABLE"             ,       HCI_DBR_TIMER_ENABLE,           0},
+       {"DBR TIMER STATUS"             ,       HCI_DBR_TIMER_STATUS,           0},
+       {"UTRL DBR 3 0 TIMER EXPIRED VALUE"             ,       HCI_UTRL_DBR_3_0_TIMER_EXPIRED_VALUE,           0},
+       {"UTRL DBR 7 4 TIMER EXPIRED VALUE"             ,       HCI_UTRL_DBR_7_4_TIMER_EXPIRED_VALUE,   0},
+       {"UTRL DBR 11 8 TIMER EXPIRED VALUE"            ,       HCI_UTRL_DBR_11_8_TIMER_EXPIRED_VALUE,  0},
+       {"UTRL DBR 15 12 TIMER EXPIRED VALUE"           ,       HCI_UTRL_DBR_15_12_TIMER_EXPIRED_VALUE,         0},
+       {"UTMRL DBR 3 0 TIMER EXPIRED VALUE"            ,       HCI_UTMRL_DBR_3_0_TIMER_EXPIRED_VALUE,          0},
+
+       {"FMP SFR"                      ,       LOG_FMP_SFR,                    0},
+
+       {"UFSPRCTRL"                    ,       UFSPRCTRL,                      0},
+       {"UFSPRSTAT"                    ,       UFSPRSTAT,                      0},
+       {"UFSPRSECURITY"                ,       UFSPRSECURITY,                  0},
+       {"UFSPWCTRL"                    ,       UFSPWCTRL,                      0},
+       {"UFSPWSTAT"                    ,       UFSPWSTAT,                      0},
+       {"UFSPSBEGIN0"                  ,       UFSPSBEGIN0,                    0},
+       {"UFSPSEND0"                    ,       UFSPSEND0,                      0},
+       {"UFSPSLUN0"                    ,       UFSPSLUN0,                      0},
+       {"UFSPSCTRL0"                   ,       UFSPSCTRL0,                     0},
+       {"UFSPSBEGIN1"                  ,       UFSPSBEGIN1,                    0},
+       {"UFSPSEND1"                    ,       UFSPSEND1,                      0},
+       {"UFSPSLUN1"                    ,       UFSPSLUN1,                      0},
+       {"UFSPSCTRL1"                   ,       UFSPSCTRL1,                     0},
+       {"UFSPSBEGIN2"                  ,       UFSPSBEGIN2,                    0},
+       {"UFSPSEND2"                    ,       UFSPSEND2,                      0},
+       {"UFSPSLUN2"                    ,       UFSPSLUN2,                      0},
+       {"UFSPSCTRL2"                   ,       UFSPSCTRL2,                     0},
+       {"UFSPSBEGIN3"                  ,       UFSPSBEGIN3,                    0},
+       {"UFSPSEND3"                    ,       UFSPSEND3,                      0},
+       {"UFSPSLUN3"                    ,       UFSPSLUN3,                      0},
+       {"UFSPSCTRL3"                   ,       UFSPSCTRL3,                     0},
+       {"UFSPSBEGIN4"                  ,       UFSPSBEGIN4,                    0},
+       {"UFSPSLUN4"                    ,       UFSPSLUN4,                      0},
+       {"UFSPSCTRL4"                   ,       UFSPSCTRL4,                     0},
+       {"UFSPSBEGIN5"                  ,       UFSPSBEGIN5,                    0},
+       {"UFSPSEND5"                    ,       UFSPSEND5,                      0},
+       {"UFSPSLUN5"                    ,       UFSPSLUN5,                      0},
+       {"UFSPSCTRL5"                   ,       UFSPSCTRL5,                     0},
+       {"UFSPSBEGIN6"                  ,       UFSPSBEGIN6,                    0},
+       {"UFSPSEND6"                    ,       UFSPSEND6,                      0},
+       {"UFSPSLUN6"                    ,       UFSPSLUN6,                      0},
+       {"UFSPSCTRL6"                   ,       UFSPSCTRL6,                     0},
+       {"UFSPSBEGIN7"                  ,       UFSPSBEGIN7,                    0},
+       {"UFSPSEND7"                    ,       UFSPSEND7,                      0},
+       {"UFSPSLUN7"                    ,       UFSPSLUN7,                      0},
+       {"UFSPSCTRL7"                   ,       UFSPSCTRL7,                     0},
+
+       {"UNIPRO SFR"                   ,       LOG_UNIPRO_SFR,                 0},
+
+       {"DME_LINKSTARTUP_CNF_RESULT"   ,       UNIP_DME_LINKSTARTUP_CNF_RESULT ,       0},
+       {"DME_HIBERN8_ENTER_CNF_RESULT" ,       UNIP_DME_HIBERN8_ENTER_CNF_RESULT,      0},
+       {"DME_HIBERN8_ENTER_IND_RESULT" ,       UNIP_DME_HIBERN8_ENTER_IND_RESULT,      0},
+       {"DME_HIBERN8_EXIT_CNF_RESULT"  ,       UNIP_DME_HIBERN8_EXIT_CNF_RESULT,       0},
+       {"DME_HIBERN8_EXIT_IND_RESULT"  ,       UNIP_DME_HIBERN8_EXIT_IND_RESULT,       0},
+       {"DME_PWR_IND_RESULT"           ,       UNIP_DME_PWR_IND_RESULT ,       0},
+       {"DME_INTR_STATUS_LSB"          ,       UNIP_DME_INTR_STATUS_LSB,       0},
+       {"DME_INTR_STATUS_MSB"          ,       UNIP_DME_INTR_STATUS_MSB,       0},
+       {"DME_INTR_ERROR_CODE"          ,       UNIP_DME_INTR_ERROR_CODE,       0},
+       {"DME_DISCARD_PORT_ID"          ,       UNIP_DME_DISCARD_PORT_ID,       0},
+       {"DME_DBG_OPTION_SUITE"         ,       UNIP_DME_DBG_OPTION_SUITE,      0},
+       {"DME_DBG_CTRL_FSM"             ,       UNIP_DME_DBG_CTRL_FSM,  0},
+       {"DME_DBG_FLAG_STATUS"          ,       UNIP_DME_DBG_FLAG_STATUS,       0},
+       {"DME_DBG_LINKCFG_FSM"          ,       UNIP_DME_DBG_LINKCFG_FSM,       0},
+
+       {"PMA SFR"                      ,       LOG_PMA_SFR,                    0},
+
+       {"COMN 0x2f"                    ,       (0x00BC),                       0},
+       {"TRSV_L0 0x4b"                 ,       (0x01EC),                       0},
+       {"TRSV_L0 0x4f"                 ,       (0x01FC),                       0},
+       {"TRSV_L1 0x4b"                 ,       (0x032C),                       0},
+       {"TRSV_L1 0x4f"                 ,       (0x033C),                       0},
+
+       {},
+};
+
+static struct exynos_ufs_attr_log ufs_log_attr[] = {
+       /* PA Standard */
+       {UIC_ARG_MIB(0x1520),   0, 0},
+       {UIC_ARG_MIB(0x1540),   0, 0},
+       {UIC_ARG_MIB(0x1543),   0, 0},
+       {UIC_ARG_MIB(0x155C),   0, 0},
+       {UIC_ARG_MIB(0x155D),   0, 0},
+       {UIC_ARG_MIB(0x155E),   0, 0},
+       {UIC_ARG_MIB(0x155F),   0, 0},
+       {UIC_ARG_MIB(0x1560),   0, 0},
+       {UIC_ARG_MIB(0x1561),   0, 0},
+       {UIC_ARG_MIB(0x1564),   0, 0},
+       {UIC_ARG_MIB(0x1567),   0, 0},
+       {UIC_ARG_MIB(0x1568),   0, 0},
+       {UIC_ARG_MIB(0x1569),   0, 0},
+       {UIC_ARG_MIB(0x156A),   0, 0},
+       {UIC_ARG_MIB(0x1571),   0, 0},
+       {UIC_ARG_MIB(0x1580),   0, 0},
+       {UIC_ARG_MIB(0x1581),   0, 0},
+       {UIC_ARG_MIB(0x1582),   0, 0},
+       {UIC_ARG_MIB(0x1583),   0, 0},
+       {UIC_ARG_MIB(0x1584),   0, 0},
+       {UIC_ARG_MIB(0x1585),   0, 0},
+       {UIC_ARG_MIB(0x1590),   0, 0},
+       {UIC_ARG_MIB(0x1591),   0, 0},
+       {UIC_ARG_MIB(0x15A1),   0, 0},
+       {UIC_ARG_MIB(0x15A2),   0, 0},
+       {UIC_ARG_MIB(0x15A3),   0, 0},
+       {UIC_ARG_MIB(0x15A4),   0, 0},
+       {UIC_ARG_MIB(0x15A7),   0, 0},
+       {UIC_ARG_MIB(0x15A8),   0, 0},
+       {UIC_ARG_MIB(0x15C0),   0, 0},
+       {UIC_ARG_MIB(0x15C1),   0, 0},
+       /* PA Debug */
+       {UIC_ARG_MIB(0x9514),   0, 0},
+       {UIC_ARG_MIB(0x9536),   0, 0},
+       {UIC_ARG_MIB(0x9556),   0, 0},
+       {UIC_ARG_MIB(0x9564),   0, 0},
+       {UIC_ARG_MIB(0x9566),   0, 0},
+       {UIC_ARG_MIB(0x9567),   0, 0},
+       {UIC_ARG_MIB(0x9568),   0, 0},
+       {UIC_ARG_MIB(0x956A),   0, 0},
+       {UIC_ARG_MIB(0x9595),   0, 0},
+       {UIC_ARG_MIB(0x9596),   0, 0},
+       {UIC_ARG_MIB(0x9597),   0, 0},
+       /* DL Standard */
+       {UIC_ARG_MIB(0x2046),   0, 0},
+       {UIC_ARG_MIB(0x2047),   0, 0},
+       {UIC_ARG_MIB(0x2066),   0, 0},
+       {UIC_ARG_MIB(0x2067),   0, 0},
+       /* DL Debug */
+       {UIC_ARG_MIB(0xA000),   0, 0},
+       {UIC_ARG_MIB(0xA005),   0, 0},
+       {UIC_ARG_MIB(0xA007),   0, 0},
+       {UIC_ARG_MIB(0xA010),   0, 0},
+       {UIC_ARG_MIB(0xA011),   0, 0},
+       {UIC_ARG_MIB(0xA020),   0, 0},
+       {UIC_ARG_MIB(0xA021),   0, 0},
+       {UIC_ARG_MIB(0xA022),   0, 0},
+       {UIC_ARG_MIB(0xA023),   0, 0},
+       {UIC_ARG_MIB(0xA024),   0, 0},
+       {UIC_ARG_MIB(0xA025),   0, 0},
+       {UIC_ARG_MIB(0xA026),   0, 0},
+       {UIC_ARG_MIB(0xA027),   0, 0},
+       {UIC_ARG_MIB(0xA028),   0, 0},
+       {UIC_ARG_MIB(0xA029),   0, 0},
+       {UIC_ARG_MIB(0xA02A),   0, 0},
+       {UIC_ARG_MIB(0xA02B),   0, 0},
+       {UIC_ARG_MIB(0xA100),   0, 0},
+       {UIC_ARG_MIB(0xA101),   0, 0},
+       {UIC_ARG_MIB(0xA102),   0, 0},
+       {UIC_ARG_MIB(0xA103),   0, 0},
+       {UIC_ARG_MIB(0xA114),   0, 0},
+       {UIC_ARG_MIB(0xA115),   0, 0},
+       {UIC_ARG_MIB(0xA116),   0, 0},
+       {UIC_ARG_MIB(0xA120),   0, 0},
+       {UIC_ARG_MIB(0xA121),   0, 0},
+       {UIC_ARG_MIB(0xA122),   0, 0},
+       /* NL Standard */
+       {UIC_ARG_MIB(0x3000),   0, 0},
+       {UIC_ARG_MIB(0x3001),   0, 0},
+       /* NL Debug */
+       {UIC_ARG_MIB(0xB010),   0, 0},
+       {UIC_ARG_MIB(0xB011),   0, 0},
+       /* TL Standard */
+       {UIC_ARG_MIB(0x4020),   0, 0},
+       {UIC_ARG_MIB(0x4021),   0, 0},
+       {UIC_ARG_MIB(0x4022),   0, 0},
+       {UIC_ARG_MIB(0x4023),   0, 0},
+       {UIC_ARG_MIB(0x4025),   0, 0},
+       {UIC_ARG_MIB(0x402B),   0, 0},
+       /* TL Debug */
+       {UIC_ARG_MIB(0xC001),   0, 0},
+       {UIC_ARG_MIB(0xC024),   0, 0},
+       {UIC_ARG_MIB(0xC025),   0, 0},
+       {UIC_ARG_MIB(0xC026),   0, 0},
+       /* MPHY PCS Lane 0*/
+       {UIC_ARG_MIB_SEL(0x0021, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0022, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0023, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0024, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0028, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0029, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002A, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002B, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002C, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002D, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0033, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0035, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0036, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0041, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A1, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A2, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A3, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A4, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A7, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00C1, RX_LANE_0+0),  0, 0},
+       /* MPHY PCS Lane 1*/
+       {UIC_ARG_MIB_SEL(0x0021, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0022, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0023, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0024, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0028, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0029, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002A, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002B, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002C, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002D, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0033, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0035, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0036, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0041, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A1, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A2, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A3, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A4, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A7, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00C1, RX_LANE_0+1),  0, 0},
+       {},
+};
+
+static struct exynos_ufs_sfr_log ufs_show_sfr[] = {
+       {"STD HCI SFR"                  ,       LOG_STD_HCI_SFR,                0},
+
+       {"INTERRUPT STATUS"             ,       REG_INTERRUPT_STATUS,           0},
+       {"CONTROLLER STATUS"            ,       REG_CONTROLLER_STATUS,          0},
+       {"UTP TRANSF REQ DOOR BELL"     ,       REG_UTP_TRANSFER_REQ_DOOR_BELL,         0},
+       {"UTP TASK REQ DOOR BELL"       ,       REG_UTP_TASK_REQ_DOOR_BELL,             0},
+
+       {"VS HCI SFR"                   ,       LOG_VS_HCI_SFR,                 0},
+
+       {"VENDOR SPECIFIC IS"           ,       HCI_VENDOR_SPECIFIC_IS,         0},
+       {"RX UPIU MATCH ERROR CODE"     ,       HCI_RX_UPIU_MATCH_ERROR_CODE,           0},
+       {"CLKSTOP CTRL",                        HCI_CLKSTOP_CTRL,               0},
+       {"FORCE HCS",                           HCI_FORCE_HCS,          0},
+       {"DMA0 MONITOR STATE"           ,       HCI_DMA0_MONITOR_STATE,         0},
+       {"DMA1 MONITOR STATE"           ,       HCI_DMA1_MONITOR_STATE,         0},
+       {"SMU ABORT MATCH INFO"         ,       HCI_SMU_ABORT_MATCH_INFO,       0},
+
+       {"FMP SFR"                      ,       LOG_FMP_SFR,                    0},
+
+       {"UFSPRSECURITY"                ,       UFSPRSECURITY,                  0},
+
+
+       {"UNIPRO SFR"                   ,       LOG_UNIPRO_SFR,                 0},
+
+       {"DME_HIBERN8_ENTER_IND_RESULT" ,       UNIP_DME_HIBERN8_ENTER_IND_RESULT       ,       0},
+       {"DME_HIBERN8_EXIT_IND_RESULT"  ,       UNIP_DME_HIBERN8_EXIT_IND_RESULT        ,       0},
+       {"DME_PWR_IND_RESULT"           ,       UNIP_DME_PWR_IND_RESULT                 ,       0},
+       {"DME_DBG_CTRL_FSM"             ,       UNIP_DME_DBG_CTRL_FSM                   ,       0},
+
+       {"PMA SFR"                      ,       LOG_PMA_SFR,                    0},
+
+       {"COMN 0x2f"                    ,       (0x00BC),                       0},
+       {"TRSV_L0 0x4b"                 ,       (0x01EC),                       0},
+       {"TRSV_L0 0x4f"                 ,       (0x01FC),                       0},
+       {"TRSV_L1 0x4b"                 ,       (0x032C),                       0},
+       {"TRSV_L1 0x4f"                 ,       (0x033C),                       0},
+       {},
+};
+
+static struct exynos_ufs_attr_log ufs_show_attr[] = {
+       /* PA Standard */
+       {UIC_ARG_MIB(0x1560),   0, 0},
+       {UIC_ARG_MIB(0x1571),   0, 0},
+       {UIC_ARG_MIB(0x1580),   0, 0},
+       /* PA Debug */
+       {UIC_ARG_MIB(0x9595),   0, 0},
+       {UIC_ARG_MIB(0x9597),   0, 0},
+       /* DL Debug */
+       {UIC_ARG_MIB(0xA000),   0, 0},
+       {UIC_ARG_MIB(0xA005),   0, 0},
+       {UIC_ARG_MIB(0xA010),   0, 0},
+       {UIC_ARG_MIB(0xA114),   0, 0},
+       {UIC_ARG_MIB(0xA116),   0, 0},
+       /* MPHY PCS Lane 0*/
+       {UIC_ARG_MIB_SEL(0x0021, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0022, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0023, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0024, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0028, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0029, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002A, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002B, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002C, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002D, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0033, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0035, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0036, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0041, TX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A1, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A2, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A3, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A4, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A7, RX_LANE_0+0),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00C1, RX_LANE_0+0),  0, 0},
+       /* MPHY PCS Lane 1*/
+       {UIC_ARG_MIB_SEL(0x0021, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0022, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0023, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0024, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0028, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0029, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002A, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002B, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002C, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x002D, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0033, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0035, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0036, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x0041, TX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A1, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A2, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A3, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A4, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00A7, RX_LANE_0+1),  0, 0},
+       {UIC_ARG_MIB_SEL(0x00C1, RX_LANE_0+1),  0, 0},
+       {},
+};
+#else
+static struct exynos_ufs_sfr_log ufs_log_sfr[] = {
+       {"STD HCI SFR"                  ,       LOG_STD_HCI_SFR,                0},
+
+       {"CAPABILITIES"                 ,       REG_CONTROLLER_CAPABILITIES,    0},
+       {"UFS VERSION"                  ,       REG_UFS_VERSION,                0},
+       {"PRODUCT ID"                   ,       REG_CONTROLLER_DEV_ID,          0},
+       {"MANUFACTURE ID"               ,       REG_CONTROLLER_PROD_ID,         0},
+       {"INTERRUPT STATUS"             ,       REG_INTERRUPT_STATUS,           0},
+       {"INTERRUPT ENABLE"             ,       REG_INTERRUPT_ENABLE,           0},
+       {"CONTROLLER STATUS"            ,       REG_CONTROLLER_STATUS,          0},
+       {"CONTROLLER ENABLE"            ,       REG_CONTROLLER_ENABLE,          0},
+       {"UTP TRANSF REQ INT AGG CNTRL" ,       REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL,           0},
+       {"UTP TRANSF REQ LIST BASE L"   ,       REG_UTP_TRANSFER_REQ_LIST_BASE_L,               0},
+       {"UTP TRANSF REQ LIST BASE H"   ,       REG_UTP_TRANSFER_REQ_LIST_BASE_H,               0},
+       {"UTP TRANSF REQ DOOR BELL"     ,       REG_UTP_TRANSFER_REQ_DOOR_BELL,         0},
+       {"UTP TRANSF REQ LIST CLEAR"    ,       REG_UTP_TRANSFER_REQ_LIST_CLEAR,                0},
+       {"UTP TRANSF REQ LIST RUN STOP" ,       REG_UTP_TRANSFER_REQ_LIST_RUN_STOP,             0},
+       {"UTP TASK REQ LIST BASE L"     ,       REG_UTP_TASK_REQ_LIST_BASE_L,           0},
+       {"UTP TASK REQ LIST BASE H"     ,       REG_UTP_TASK_REQ_LIST_BASE_H,           0},
+       {"UTP TASK REQ DOOR BELL"       ,       REG_UTP_TASK_REQ_DOOR_BELL,             0},
+       {"UTP TASK REQ LIST CLEAR"      ,       REG_UTP_TASK_REQ_LIST_CLEAR,            0},
+       {"UTP TASK REQ LIST RUN STOP"   ,       REG_UTP_TASK_REQ_LIST_RUN_STOP,         0},
+       {"UIC COMMAND"                  ,       REG_UIC_COMMAND,                0},
+       {"UIC COMMAND ARG1"             ,       REG_UIC_COMMAND_ARG_1,          0},
+       {"UIC COMMAND ARG2"             ,       REG_UIC_COMMAND_ARG_2,          0},
+       {"UIC COMMAND ARG3"             ,       REG_UIC_COMMAND_ARG_3,          0},
+
+       {"VS HCI SFR"                   ,       LOG_VS_HCI_SFR,                 0},
+
+       {"TXPRDT ENTRY SIZE"            ,       HCI_TXPRDT_ENTRY_SIZE,          0},
+       {"RXPRDT ENTRY SIZE"            ,       HCI_RXPRDT_ENTRY_SIZE,          0},
+       {"TO CNT DIV VAL"               ,       HCI_TO_CNT_DIV_VAL,             0},
+       {"1US TO CNT VAL"               ,       HCI_1US_TO_CNT_VAL,             0},
+       {"INVALID UPIU CTRL"            ,       HCI_INVALID_UPIU_CTRL,          0},
+       {"INVALID UPIU BADDR"           ,       HCI_INVALID_UPIU_BADDR,         0},
+       {"INVALID UPIU UBADDR"          ,       HCI_INVALID_UPIU_UBADDR,                0},
+       {"INVALID UTMR OFFSET ADDR"     ,       HCI_INVALID_UTMR_OFFSET_ADDR,           0},
+       {"INVALID UTR OFFSET ADDR"      ,       HCI_INVALID_UTR_OFFSET_ADDR,            0},
+       {"INVALID DIN OFFSET ADDR"      ,       HCI_INVALID_DIN_OFFSET_ADDR,            0},
+       {"DBR TIMER CONFIG"             ,       HCI_DBR_TIMER_CONFIG,           0},
+       {"DBR TIMER STATUS"             ,       HCI_DBR_TIMER_STATUS,           0},
+       {"VENDOR SPECIFIC IS"           ,       HCI_VENDOR_SPECIFIC_IS,         0},
+       {"VENDOR SPECIFIC IE"           ,       HCI_VENDOR_SPECIFIC_IE,         0},
+       {"UTRL NEXUS TYPE"              ,       HCI_UTRL_NEXUS_TYPE,            0},
+       {"UTMRL NEXUS TYPE"             ,       HCI_UTMRL_NEXUS_TYPE,           0},
+       {"E2EFC CTRL"                   ,       HCI_E2EFC_CTRL,         0},
+       {"SW RST"                       ,       HCI_SW_RST,             0},
+       {"LINK VERSION"                 ,       HCI_LINK_VERSION,               0},
+       {"IDLE TIMER CONFIG"            ,       HCI_IDLE_TIMER_CONFIG,          0},
+       {"RX UPIU MATCH ERROR CODE"     ,       HCI_RX_UPIU_MATCH_ERROR_CODE,           0},
+       {"DATA REORDER"                 ,       HCI_DATA_REORDER,               0},
+       {"MAX DOUT DATA SIZE"           ,       HCI_MAX_DOUT_DATA_SIZE,         0},
+       {"UNIPRO APB CLK CTRL"          ,       HCI_UNIPRO_APB_CLK_CTRL,                0},
+       {"AXIDMA RWDATA BURST LEN"      ,       HCI_AXIDMA_RWDATA_BURST_LEN,            0},
+       {"GPIO OUT"                     ,       HCI_GPIO_OUT,           0},
+       {"WRITE DMA CTRL"               ,       HCI_WRITE_DMA_CTRL,             0},
+       {"ERROR EN PA LAYER"            ,       HCI_ERROR_EN_PA_LAYER,          0},
+       {"ERROR EN DL LAYER"            ,       HCI_ERROR_EN_DL_LAYER,          0},
+       {"ERROR EN N LAYER"             ,       HCI_ERROR_EN_N_LAYER,           0},
+       {"ERROR EN T LAYER"             ,       HCI_ERROR_EN_T_LAYER,           0},
+       {"ERROR EN DME LAYER"           ,       HCI_ERROR_EN_DME_LAYER,         0},
+       {"REQ HOLD EN"                  ,       HCI_REQ_HOLD_EN,                0},
+       {"CLKSTOP CTRL"                 ,       HCI_CLKSTOP_CTRL,               0},
+       {"FORCE HCS"                    ,       HCI_FORCE_HCS,          0},
+       {"FSM MONITOR"                  ,       HCI_FSM_MONITOR,                0},
+       {"PRDT HIT RATIO"               ,       HCI_PRDT_HIT_RATIO,             0},
+       {"DMA0 MONITOR STATE"           ,       HCI_DMA0_MONITOR_STATE,         0},
+       {"DMA0 MONITOR CNT"             ,       HCI_DMA0_MONITOR_CNT,           0},
+       {"DMA1 MONITOR STATE"           ,       HCI_DMA1_MONITOR_STATE,         0},
+       {"DMA1 MONITOR CNT"             ,       HCI_DMA1_MONITOR_CNT,           0},
+
+       {"FMP SFR"                      ,       LOG_FMP_SFR,                    0},
+
+       {"UFSPRCTRL"                    ,       UFSPRCTRL,                      0},
+       {"UFSPRSTAT"                    ,       UFSPRSTAT,                      0},
+       {"UFSPRSECURITY"                ,       UFSPRSECURITY,                  0},
+       {"UFSPVERSION"                  ,       UFSPVERSION,                    0},
+       {"UFSPWCTRL"                    ,       UFSPWCTRL,                      0},
+       {"UFSPWSTAT"                    ,       UFSPWSTAT,                      0},
+       {"UFSPSBEGIN0"                  ,       UFSPSBEGIN0,                    0},
+       {"UFSPSEND0"                    ,       UFSPSEND0,                      0},
+       {"UFSPSLUN0"                    ,       UFSPSLUN0,                      0},
+       {"UFSPSCTRL0"                   ,       UFSPSCTRL0,                     0},
+       {"UFSPSBEGIN1"                  ,       UFSPSBEGIN1,                    0},
+       {"UFSPSEND1"                    ,       UFSPSEND1,                      0},
+       {"UFSPSLUN1"                    ,       UFSPSLUN1,                      0},
+       {"UFSPSCTRL1"                   ,       UFSPSCTRL1,                     0},
+       {"UFSPSBEGIN2"                  ,       UFSPSBEGIN2,                    0},
+       {"UFSPSEND2"                    ,       UFSPSEND2,                      0},
+       {"UFSPSLUN2"                    ,       UFSPSLUN2,                      0},
+       {"UFSPSCTRL2"                   ,       UFSPSCTRL2,                     0},
+       {"UFSPSBEGIN3"                  ,       UFSPSBEGIN3,                    0},
+       {"UFSPSEND3"                    ,       UFSPSEND3,                      0},
+       {"UFSPSLUN3"                    ,       UFSPSLUN3,                      0},
+       {"UFSPSCTRL3"                   ,       UFSPSCTRL3,                     0},
+       {"UFSPSBEGIN4"                  ,       UFSPSBEGIN4,                    0},
+       {"UFSPSLUN4"                    ,       UFSPSLUN4,                      0},
+       {"UFSPSCTRL4"                   ,       UFSPSCTRL4,                     0},
+       {"UFSPSBEGIN5"                  ,       UFSPSBEGIN5,                    0},
+       {"UFSPSEND5"                    ,       UFSPSEND5,                      0},
+       {"UFSPSLUN5"                    ,       UFSPSLUN5,                      0},
+       {"UFSPSCTRL5"                   ,       UFSPSCTRL5,                     0},
+       {"UFSPSBEGIN6"                  ,       UFSPSBEGIN6,                    0},
+       {"UFSPSEND6"                    ,       UFSPSEND6,                      0},
+       {"UFSPSLUN6"                    ,       UFSPSLUN6,                      0},
+       {"UFSPSCTRL6"                   ,       UFSPSCTRL6,                     0},
+       {"UFSPSBEGIN7"                  ,       UFSPSBEGIN7,                    0},
+       {"UFSPSEND7"                    ,       UFSPSEND7,                      0},
+       {"UFSPSLUN7"                    ,       UFSPSLUN7,                      0},
+       {"UFSPSCTRL7"                   ,       UFSPSCTRL7,                     0},
+
+       {"UNIPRO SFR"                   ,       LOG_UNIPRO_SFR,                 0},
+
+       {"COMP_VERSION"                 ,       UNIP_COMP_VERSION                       ,       0},
+       {"COMP_INFO"                    ,       UNIP_COMP_INFO                          ,       0},
+       {"COMP_RESET"                   ,       UNIP_COMP_RESET                         ,       0},
+       {"DME_POWERON_REQ"              ,       UNIP_DME_POWERON_REQ                    ,       0},
+       {"DME_POWERON_CNF_RESULT"       ,       UNIP_DME_POWERON_CNF_RESULT             ,       0},
+       {"DME_POWEROFF_REQ"             ,       UNIP_DME_POWEROFF_REQ                   ,       0},
+       {"DME_POWEROFF_CNF_RESULT"      ,       UNIP_DME_POWEROFF_CNF_RESULT            ,       0},
+       {"DME_RESET_REQ"                ,       UNIP_DME_RESET_REQ                      ,       0},
+       {"DME_RESET_REQ_LEVEL"          ,       UNIP_DME_RESET_REQ_LEVEL                ,       0},
+       {"DME_ENABLE_REQ"               ,       UNIP_DME_ENABLE_REQ                     ,       0},
+       {"DME_ENABLE_CNF_RESULT"        ,       UNIP_DME_ENABLE_CNF_RESULT              ,       0},
+       {"DME_ENDPOINTRESET_REQ"        ,       UNIP_DME_ENDPOINTRESET_REQ              ,       0},
+       {"DME_ENDPOINTRESET_CNF_RESULT" ,       UNIP_DME_ENDPOINTRESET_CNF_RESULT       ,       0},
+       {"DME_LINKSTARTUP_REQ"          ,       UNIP_DME_LINKSTARTUP_REQ                ,       0},
+       {"DME_LINKSTARTUP_CNF_RESULT"   ,       UNIP_DME_LINKSTARTUP_CNF_RESULT         ,       0},
+       {"DME_HIBERN8_ENTER_REQ"        ,       UNIP_DME_HIBERN8_ENTER_REQ              ,       0},
+       {"DME_HIBERN8_ENTER_CNF_RESULT" ,       UNIP_DME_HIBERN8_ENTER_CNF_RESULT       ,       0},
+       {"DME_HIBERN8_ENTER_IND_RESULT" ,       UNIP_DME_HIBERN8_ENTER_IND_RESULT       ,       0},
+       {"DME_HIBERN8_EXIT_REQ"         ,       UNIP_DME_HIBERN8_EXIT_REQ               ,       0},
+       {"DME_HIBERN8_EXIT_CNF_RESULT"  ,       UNIP_DME_HIBERN8_EXIT_CNF_RESULT        ,       0},
+       {"DME_HIBERN8_EXIT_IND_RESULT"  ,       UNIP_DME_HIBERN8_EXIT_IND_RESULT        ,       0},
+       {"DME_PWR_REQ"                  ,       UNIP_DME_PWR_REQ                        ,       0},
+       {"DME_PWR_REQ_POWERMODE "       ,       UNIP_DME_PWR_REQ_POWERMODE              ,       0},
+       {"DME_PWR_REQ_LOCALL2TIMER0"    ,       UNIP_DME_PWR_REQ_LOCALL2TIMER0          ,       0},
+       {"DME_PWR_REQ_LOCALL2TIMER1"    ,       UNIP_DME_PWR_REQ_LOCALL2TIMER1          ,       0},
+       {"DME_PWR_REQ_LOCALL2TIMER2"    ,       UNIP_DME_PWR_REQ_LOCALL2TIMER2          ,       0},
+       {"DME_PWR_REQ_REMOTEL2TIMER0"   ,       UNIP_DME_PWR_REQ_REMOTEL2TIMER0         ,       0},
+       {"DME_PWR_REQ_REMOTEL2TIMER1"   ,       UNIP_DME_PWR_REQ_REMOTEL2TIMER1         ,       0},
+       {"DME_PWR_REQ_REMOTEL2TIMER2"   ,       UNIP_DME_PWR_REQ_REMOTEL2TIMER2         ,       0},
+       {"DME_PWR_CNF_RESULT"           ,       UNIP_DME_PWR_CNF_RESULT                 ,       0},
+       {"DME_PWR_IND_RESULT"           ,       UNIP_DME_PWR_IND_RESULT                 ,       0},
+       {"DME_TEST_MODE_REQ"            ,       UNIP_DME_TEST_MODE_REQ                  ,       0},
+       {"DME_TEST_MODE_CNF_RESULT"     ,       UNIP_DME_TEST_MODE_CNF_RESULT           ,       0},
+       {"DME_ERROR_IND_LAYER"          ,       UNIP_DME_ERROR_IND_LAYER                ,       0},
+       {"DME_ERROR_IND_ERRCODE"        ,       UNIP_DME_ERROR_IND_ERRCODE              ,       0},
+       {"DME_PACP_CNFBIT"              ,       UNIP_DME_PACP_CNFBIT                    ,       0},
+       {"DME_DL_FRAME_IND"             ,       UNIP_DME_DL_FRAME_IND                   ,       0},
+       {"DME_INTR_STATUS"              ,       UNIP_DME_INTR_STATUS                    ,       0},
+       {"DME_INTR_ENABLE"              ,       UNIP_DME_INTR_ENABLE                    ,       0},
+       {"DME_GETSET_ADDR"              ,       UNIP_DME_GETSET_ADDR                    ,       0},
+       {"DME_GETSET_WDATA"             ,       UNIP_DME_GETSET_WDATA                   ,       0},
+       {"DME_GETSET_RDATA"             ,       UNIP_DME_GETSET_RDATA                   ,       0},
+       {"DME_GETSET_CONTROL"           ,       UNIP_DME_GETSET_CONTROL                 ,       0},
+       {"DME_GETSET_RESULT"            ,       UNIP_DME_GETSET_RESULT                  ,       0},
+       {"DME_PEER_GETSET_ADDR"         ,       UNIP_DME_PEER_GETSET_ADDR               ,       0},
+       {"DME_PEER_GETSET_WDATA"        ,       UNIP_DME_PEER_GETSET_WDATA              ,       0},
+       {"DME_PEER_GETSET_RDATA"        ,       UNIP_DME_PEER_GETSET_RDATA              ,       0},
+       {"DME_PEER_GETSET_CONTROL"      ,       UNIP_DME_PEER_GETSET_CONTROL            ,       0},
+       {"DME_PEER_GETSET_RESULT"       ,       UNIP_DME_PEER_GETSET_RESULT             ,       0},
+       {"DME_DIRECT_GETSET_BASE"       ,       UNIP_DME_DIRECT_GETSET_BASE             ,       0},
+       {"DME_DIRECT_GETSET_ERR_ADDR"   ,       UNIP_DME_DIRECT_GETSET_ERR_ADDR         ,       0},
+       {"DME_DIRECT_GETSET_ERR_CODE"   ,       UNIP_DME_DIRECT_GETSET_ERR_CODE         ,       0},
+       {"DME_INTR_ERROR_CODE"          ,       UNIP_DME_INTR_ERROR_CODE                ,       0},
+       {"DME_DEEPSTALL_ENTER_REQ"      ,       UNIP_DME_DEEPSTALL_ENTER_REQ            ,       0},
+       {"DME_DISCARD_CPORT_ID"         ,       UNIP_DME_DISCARD_CPORT_ID               ,       0},
+       {"DBG_DME_CTRL_STATE"           ,       UNIP_DBG_DME_CTRL_STATE                 ,       0},
+       {"DBG_FORCE_DME_CTRL_STATE"     ,       UNIP_DBG_FORCE_DME_CTRL_STATE           ,       0},
+       {"DBG_AUTO_DME_LINKSTARTUP"     ,       UNIP_DBG_AUTO_DME_LINKSTARTUP,                  0},
+       {"DBG_PA_CTRLSTATE"             ,       UNIP_DBG_PA_CTRLSTATE                   ,       0},
+       {"DBG_PA_TX_STATE"              ,       UNIP_DBG_PA_TX_STATE                    ,       0},
+       {"DBG_BREAK_DME_CTRL_STATE"     ,       UNIP_DBG_BREAK_DME_CTRL_STATE           ,       0},
+       {"DBG_STEP_DME_CTRL_STATE"      ,       UNIP_DBG_STEP_DME_CTRL_STATE            ,       0},
+       {"DBG_NEXT_DME_CTRL_STATE"      ,       UNIP_DBG_NEXT_DME_CTRL_STATE            ,       0},
+
+       {"PMA SFR"                      ,       LOG_PMA_SFR,                    0},
+
+       {"COMN 0x00"                    ,       (0x00<<2),                      0},
+       {"COMN 0x01"                    ,       (0x01<<2),                      0},
+       {"COMN 0x02"                    ,       (0x02<<2),                      0},
+       {"COMN 0x03"                    ,       (0x03<<2),                      0},
+       {"COMN 0x04"                    ,       (0x04<<2),                      0},
+       {"COMN 0x05"                    ,       (0x05<<2),                      0},
+       {"COMN 0x06"                    ,       (0x06<<2),                      0},
+       {"COMN 0x07"                    ,       (0x07<<2),                      0},
+       {"COMN 0x08"                    ,       (0x08<<2),                      0},
+       {"COMN 0x0a"                    ,       (0x0a<<2),                      0},
+       {"COMN 0x0b"                    ,       (0x0b<<2),                      0},
+       {"COMN 0x0c"                    ,       (0x0c<<2),                      0},
+       {"COMN 0x0d"                    ,       (0x0d<<2),                      0},
+       {"COMN 0x0e"                    ,       (0x0e<<2),                      0},
+       {"COMN 0x0f"                    ,       (0x0f<<2),                      0},
+       {"COMN 0x10"                    ,       (0x10<<2),                      0},
+       {"COMN 0x11"                    ,       (0x11<<2),                      0},
+       {"COMN 0x12"                    ,       (0x12<<2),                      0},
+       {"COMN 0x13"                    ,       (0x13<<2),                      0},
+       {"COMN 0x14"                    ,       (0x14<<2),                      0},
+       {"COMN 0x15"                    ,       (0x15<<2),                      0},
+       {"COMN 0x16"                    ,       (0x16<<2),                      0},
+       {"COMN 0x17"                    ,       (0x17<<2),                      0},
+       {"COMN 0x18"                    ,       (0x18<<2),                      0},
+       {"COMN 0x19"                    ,       (0x19<<2),                      0},
+       {"COMN 0x1a"                    ,       (0x1a<<2),                      0},
+       {"COMN 0x1b"                    ,       (0x1b<<2),                      0},
+       {"COMN 0x1c"                    ,       (0x1c<<2),                      0},
+       {"COMN 0x1d"                    ,       (0x1d<<2),                      0},
+       {"COMN 0x1e"                    ,       (0x1e<<2),                      0},
+       {"COMN 0x1f"                    ,       (0x1f<<2),                      0},
+       {"COMN 0x20"                    ,       (0x20<<2),                      0},
+       {"COMN 0x21"                    ,       (0x21<<2),                      0},
+       {"COMN 0x22"                    ,       (0x22<<2),                      0},
+       {"COMN 0x23"                    ,       (0x23<<2),                      0},
+       {"COMN 0x24"                    ,       (0x24<<2),                      0},
+       {"COMN 0x25"                    ,       (0x25<<2),                      0},
+       {"COMN 0x26"                    ,       (0x26<<2),                      0},
+       {"COMN 0x27"                    ,       (0x27<<2),                      0},
+       {"COMN 0x28"                    ,       (0x28<<2),                      0},
+       {"COMN 0x29"                    ,       (0x29<<2),                      0},
+       {"COMN 0x2a"                    ,       (0x2a<<2),                      0},
+       {"COMN 0x2b"                    ,       (0x2b<<2),                      0},
+       {"COMN 0x2c"                    ,       (0x2c<<2),                      0},
+       {"COMN 0x2d"                    ,       (0x2d<<2),                      0},
+       {"COMN 0x2e"                    ,       (0x2e<<2),                      0},
+       {"COMN 0x2f"                    ,       (0x2f<<2),                      0},
+       {"COMN 0x30"                    ,       (0x30<<2),                      0},
+       {"TRSV 0x31"                    ,       (0x31<<2),                      0},
+       {"TRSV 0x32"                    ,       (0x32<<2),                      0},
+       {"TRSV 0x33"                    ,       (0x33<<2),                      0},
+       {"TRSV 0x34"                    ,       (0x34<<2),                      0},
+       {"TRSV 0x35"                    ,       (0x35<<2),                      0},
+       {"TRSV 0x36"                    ,       (0x36<<2),                      0},
+       {"TRSV 0x37"                    ,       (0x37<<2),                      0},
+       {"TRSV 0x38"                    ,       (0x38<<2),                      0},
+       {"TRSV 0x3a"                    ,       (0x3a<<2),                      0},
+       {"TRSV 0x3b"                    ,       (0x3b<<2),                      0},
+       {"TRSV 0x3c"                    ,       (0x3c<<2),                      0},
+       {"TRSV 0x3d"                    ,       (0x3d<<2),                      0},
+       {"TRSV 0x3e"                    ,       (0x3e<<2),                      0},
+       {"TRSV 0x3f"                    ,       (0x3f<<2),                      0},
+       {"TRSV 0x40"                    ,       (0x40<<2),                      0},
+       {"TRSV 0x41"                    ,       (0x41<<2),                      0},
+       {"TRSV 0x42"                    ,       (0x42<<2),                      0},
+       {"TRSV 0x43"                    ,       (0x43<<2),                      0},
+       {"TRSV 0x44"                    ,       (0x44<<2),                      0},
+       {"TRSV 0x45"                    ,       (0x45<<2),                      0},
+       {"TRSV 0x46"                    ,       (0x46<<2),                      0},
+       {"TRSV 0x47"                    ,       (0x47<<2),                      0},
+       {"TRSV 0x48"                    ,       (0x48<<2),                      0},
+       {"TRSV 0x49"                    ,       (0x49<<2),                      0},
+       {"TRSV 0x4a"                    ,       (0x4a<<2),                      0},
+       {"TRSV 0x4b"                    ,       (0x4b<<2),                      0},
+       {"TRSV 0x4c"                    ,       (0x4c<<2),                      0},
+       {"TRSV 0x4d"                    ,       (0x4d<<2),                      0},
+       {"TRSV 0x4e"                    ,       (0x4e<<2),                      0},
+       {"TRSV 0x4f"                    ,       (0x4f<<2),                      0},
+       {"TRSV 0x50"                    ,       (0x50<<2),                      0},
+       {"TRSV 0x51"                    ,       (0x51<<2),                      0},
+       {"TRSV 0x52"                    ,       (0x52<<2),                      0},
+       {"TRSV 0x53"                    ,       (0x53<<2),                      0},
+       {"TRSV 0x54"                    ,       (0x54<<2),                      0},
+       {"TRSV 0x55"                    ,       (0x55<<2),                      0},
+       {"TRSV 0x56"                    ,       (0x56<<2),                      0},
+       {"TRSV 0x57"                    ,       (0x57<<2),                      0},
+       {"TRSV 0x58"                    ,       (0x58<<2),                      0},
+       {"TRSV 0x59"                    ,       (0x59<<2),                      0},
+       {"TRSV 0x5a"                    ,       (0x5a<<2),                      0},
+       {"TRSV 0x5b"                    ,       (0x5b<<2),                      0},
+       {"TRSV 0x5c"                    ,       (0x5c<<2),                      0},
+       {"TRSV 0x5d"                    ,       (0x5d<<2),                      0},
+       {"TRSV 0x5e"                    ,       (0x5e<<2),                      0},
+       {"TRSV 0x5f"                    ,       (0x5f<<2),                      0},
+       {"TRSV 0x60"                    ,       (0x60<<2),                      0},
+       {"TRSV 0x61"                    ,       (0x61<<2),                      0},
+       {"TRSV 0x62"                    ,       (0x62<<2),                      0},
+       {"TRSV 0x63"                    ,       (0x63<<2),                      0},
+       {"TRSV 0x64"                    ,       (0x64<<2),                      0},
+       {"TRSV 0x65"                    ,       (0x65<<2),                      0},
+       {"TRSV 0x66"                    ,       (0x66<<2),                      0},
+       {"TRSV 0x67"                    ,       (0x67<<2),                      0},
+       {"TRSV 0x68"                    ,       (0x68<<2),                      0},
+       {"TRSV 0x6a"                    ,       (0x6a<<2),                      0},
+       {"TRSV 0x6b"                    ,       (0x6b<<2),                      0},
+       {"TRSV 0x6c"                    ,       (0x6c<<2),                      0},
+       {"TRSV 0x6d"                    ,       (0x6d<<2),                      0},
+       {"TRSV 0x6e"                    ,       (0x6e<<2),                      0},
+       {"TRSV 0x6f"                    ,       (0x6f<<2),                      0},
+       {"TRSV 0x70"                    ,       (0x70<<2),                      0},
+       {"TRSV 0x71"                    ,       (0x71<<2),                      0},
+       {"TRSV 0x72"                    ,       (0x72<<2),                      0},
+       {"TRSV 0x73"                    ,       (0x73<<2),                      0},
+       {"TRSV 0x74"                    ,       (0x74<<2),                      0},
+       {"TRSV 0x75"                    ,       (0x75<<2),                      0},
+       {"TRSV 0x76"                    ,       (0x76<<2),                      0},
+       {"TRSV 0x77"                    ,       (0x77<<2),                      0},
+       {"TRSV 0x78"                    ,       (0x78<<2),                      0},
+       {"TRSV 0x79"                    ,       (0x79<<2),                      0},
+       {"TRSV 0x7a"                    ,       (0x7a<<2),                      0},
+       {"TRSV 0x7b"                    ,       (0x7b<<2),                      0},
+       {"TRSV 0x7c"                    ,       (0x7c<<2),                      0},
+       {"TRSV 0x7d"                    ,       (0x7d<<2),                      0},
+       {"TRSV 0x7e"                    ,       (0x7e<<2),                      0},
+       {"TRSV 0x7f"                    ,       (0x7f<<2),                      0},
+
+       {},
+};
+
+static struct exynos_ufs_attr_log ufs_log_attr[] = {
+       /* PA Standard */
+       {UIC_ARG_MIB(0x1520),   0, 0},
+       {UIC_ARG_MIB(0x1540),   0, 0},
+       {UIC_ARG_MIB(0x1543),   0, 0},
+       {UIC_ARG_MIB(0x155C),   0, 0},
+       {UIC_ARG_MIB(0x155D),   0, 0},
+       {UIC_ARG_MIB(0x155E),   0, 0},
+       {UIC_ARG_MIB(0x155F),   0, 0},
+       {UIC_ARG_MIB(0x1560),   0, 0},
+       {UIC_ARG_MIB(0x1561),   0, 0},
+       {UIC_ARG_MIB(0x1564),   0, 0},
+       {UIC_ARG_MIB(0x1567),   0, 0},
+       {UIC_ARG_MIB(0x1568),   0, 0},
+       {UIC_ARG_MIB(0x1569),   0, 0},
+       {UIC_ARG_MIB(0x156A),   0, 0},
+       {UIC_ARG_MIB(0x1571),   0, 0},
+       {UIC_ARG_MIB(0x1580),   0, 0},
+       {UIC_ARG_MIB(0x1581),   0, 0},
+       {UIC_ARG_MIB(0x1582),   0, 0},
+       {UIC_ARG_MIB(0x1583),   0, 0},
+       {UIC_ARG_MIB(0x1584),   0, 0},
+       {UIC_ARG_MIB(0x1585),   0, 0},
+       {UIC_ARG_MIB(0x1590),   0, 0},
+       {UIC_ARG_MIB(0x1591),   0, 0},
+       {UIC_ARG_MIB(0x15A1),   0, 0},
+       {UIC_ARG_MIB(0x15A2),   0, 0},
+       {UIC_ARG_MIB(0x15A3),   0, 0},
+       {UIC_ARG_MIB(0x15A4),   0, 0},
+       {UIC_ARG_MIB(0x15A7),   0, 0},
+       {UIC_ARG_MIB(0x15A8),   0, 0},
+       {UIC_ARG_MIB(0x15C0),   0, 0},
+       {UIC_ARG_MIB(0x15C1),   0, 0},
+       /* PA Debug */
+       {UIC_ARG_MIB(0x9500),   0, 0},
+       {UIC_ARG_MIB(0x9501),   0, 0},
+       {UIC_ARG_MIB(0x9502),   0, 0},
+       {UIC_ARG_MIB(0x9503),   0, 0},
+       {UIC_ARG_MIB(0x9510),   0, 0},
+       {UIC_ARG_MIB(0x9511),   0, 0},
+       {UIC_ARG_MIB(0x9514),   0, 0},
+       {UIC_ARG_MIB(0x9515),   0, 0},
+       {UIC_ARG_MIB(0x9516),   0, 0},
+       {UIC_ARG_MIB(0x9517),   0, 0},
+       {UIC_ARG_MIB(0x9520),   0, 0},
+       {UIC_ARG_MIB(0x9521),   0, 0},
+       {UIC_ARG_MIB(0x9522),   0, 0},
+       {UIC_ARG_MIB(0x9523),   0, 0},
+       {UIC_ARG_MIB(0x9525),   0, 0},
+       {UIC_ARG_MIB(0x9528),   0, 0},
+       {UIC_ARG_MIB(0x9529),   0, 0},
+       {UIC_ARG_MIB(0x952A),   0, 0},
+       {UIC_ARG_MIB(0x952B),   0, 0},
+       {UIC_ARG_MIB(0x952C),   0, 0},
+       {UIC_ARG_MIB(0x9534),   0, 0},
+       {UIC_ARG_MIB(0x9535),   0, 0},
+       {UIC_ARG_MIB(0x9536),   0, 0},
+       {UIC_ARG_MIB(0x9539),   0, 0},
+       {UIC_ARG_MIB(0x9540),   0, 0},
+       {UIC_ARG_MIB(0x9541),   0, 0},
+       {UIC_ARG_MIB(0x9542),   0, 0},
+       {UIC_ARG_MIB(0x9543),   0, 0},
+       {UIC_ARG_MIB(0x9546),   0, 0},
+       {UIC_ARG_MIB(0x9551),   0, 0},
+       {UIC_ARG_MIB(0x9552),   0, 0},
+       {UIC_ARG_MIB(0x9554),   0, 0},
+       {UIC_ARG_MIB(0x9556),   0, 0},
+       {UIC_ARG_MIB(0x9557),   0, 0},
+       {UIC_ARG_MIB(0x9558),   0, 0},
+       {UIC_ARG_MIB(0x9559),   0, 0},
+       {UIC_ARG_MIB(0x9560),   0, 0},
+       {UIC_ARG_MIB(0x9561),   0, 0},
+       {UIC_ARG_MIB(0x9562),   0, 0},
+       {UIC_ARG_MIB(0x9563),   0, 0},
+       {UIC_ARG_MIB(0x9564),   0, 0},
+       {UIC_ARG_MIB(0x9565),   0, 0},
+       {UIC_ARG_MIB(0x9566),   0, 0},
+       {UIC_ARG_MIB(0x9567),   0, 0},
+       {UIC_ARG_MIB(0x9568),   0, 0},
+       {UIC_ARG_MIB(0x9569),   0, 0},
+       {UIC_ARG_MIB(0x9570),   0, 0},
+       {UIC_ARG_MIB(0x9571),   0, 0},
+       {UIC_ARG_MIB(0x9572),   0, 0},
+       {UIC_ARG_MIB(0x9573),   0, 0},
+       /* DL Standard */
+       {UIC_ARG_MIB(0x2002),   0, 0},
+       {UIC_ARG_MIB(0x2003),   0, 0},
+       {UIC_ARG_MIB(0x2004),   0, 0},
+       {UIC_ARG_MIB(0x2005),   0, 0},
+       {UIC_ARG_MIB(0x2006),   0, 0},
+       {UIC_ARG_MIB(0x2040),   0, 0},
+       {UIC_ARG_MIB(0x2041),   0, 0},
+       {UIC_ARG_MIB(0x2042),   0, 0},
+       {UIC_ARG_MIB(0x2043),   0, 0},
+       {UIC_ARG_MIB(0x2044),   0, 0},
+       {UIC_ARG_MIB(0x2045),   0, 0},
+       {UIC_ARG_MIB(0x2046),   0, 0},
+       {UIC_ARG_MIB(0x2047),   0, 0},
+       {UIC_ARG_MIB(0x2060),   0, 0},
+       {UIC_ARG_MIB(0x2061),   0, 0},
+       {UIC_ARG_MIB(0x2062),   0, 0},
+       {UIC_ARG_MIB(0x2063),   0, 0},
+       {UIC_ARG_MIB(0x2064),   0, 0},
+       {UIC_ARG_MIB(0x2065),   0, 0},
+       {UIC_ARG_MIB(0x2066),   0, 0},
+       {UIC_ARG_MIB(0x2067),   0, 0},
+       /* DL Debug */
+       {UIC_ARG_MIB(0xA000),   0, 0},
+       {UIC_ARG_MIB(0xA003),   0, 0},
+       {UIC_ARG_MIB(0xA004),   0, 0},
+       {UIC_ARG_MIB(0xA005),   0, 0},
+       {UIC_ARG_MIB(0xA006),   0, 0},
+       {UIC_ARG_MIB(0xA007),   0, 0},
+       {UIC_ARG_MIB(0xA009),   0, 0},
+       {UIC_ARG_MIB(0xA010),   0, 0},
+       {UIC_ARG_MIB(0xA011),   0, 0},
+       {UIC_ARG_MIB(0xA012),   0, 0},
+       {UIC_ARG_MIB(0xA013),   0, 0},
+       {UIC_ARG_MIB(0xA014),   0, 0},
+       {UIC_ARG_MIB(0xA015),   0, 0},
+       {UIC_ARG_MIB(0xA016),   0, 0},
+       {UIC_ARG_MIB(0xA020),   0, 0},
+       {UIC_ARG_MIB(0xA021),   0, 0},
+       {UIC_ARG_MIB(0xA022),   0, 0},
+       {UIC_ARG_MIB(0xA023),   0, 0},
+       {UIC_ARG_MIB(0xA024),   0, 0},
+       {UIC_ARG_MIB(0xA025),   0, 0},
+       {UIC_ARG_MIB(0xA026),   0, 0},
+       {UIC_ARG_MIB(0xA027),   0, 0},
+       {UIC_ARG_MIB(0xA028),   0, 0},
+       {UIC_ARG_MIB(0xA029),   0, 0},
+       {UIC_ARG_MIB(0xA02A),   0, 0},
+       {UIC_ARG_MIB(0xA02B),   0, 0},
+       {UIC_ARG_MIB(0xA02C),   0, 0},
+       {UIC_ARG_MIB(0xA02D),   0, 0},
+       {UIC_ARG_MIB(0xA02E),   0, 0},
+       {UIC_ARG_MIB(0xA02F),   0, 0},
+       {UIC_ARG_MIB(0xA030),   0, 0},
+       {UIC_ARG_MIB(0xA031),   0, 0},
+       {UIC_ARG_MIB(0xA041),   0, 0},
+       {UIC_ARG_MIB(0xA042),   0, 0},
+       {UIC_ARG_MIB(0xA043),   0, 0},
+       {UIC_ARG_MIB(0xA044),   0, 0},
+       {UIC_ARG_MIB(0xA045),   0, 0},
+       {UIC_ARG_MIB(0xA046),   0, 0},
+       {UIC_ARG_MIB(0xA047),   0, 0},
+       {UIC_ARG_MIB(0xA060),   0, 0},
+       {UIC_ARG_MIB(0xA061),   0, 0},
+       {UIC_ARG_MIB(0xA062),   0, 0},
+       {UIC_ARG_MIB(0xA063),   0, 0},
+       {UIC_ARG_MIB(0xA064),   0, 0},
+       {UIC_ARG_MIB(0xA065),   0, 0},
+       {UIC_ARG_MIB(0xA066),   0, 0},
+       {UIC_ARG_MIB(0xA067),   0, 0},
+       {UIC_ARG_MIB(0xA068),   0, 0},
+       {UIC_ARG_MIB(0xA069),   0, 0},
+       {UIC_ARG_MIB(0xA06A),   0, 0},
+       {UIC_ARG_MIB(0xA06B),   0, 0},
+       {UIC_ARG_MIB(0xA06C),   0, 0},
+       {UIC_ARG_MIB(0xA080),   0, 0},
+       /* NL Standard */
+       {UIC_ARG_MIB(0x3000),   0, 0},
+       {UIC_ARG_MIB(0x3001),   0, 0},
+       {UIC_ARG_MIB(0x4020),   0, 0},
+       {UIC_ARG_MIB(0x4021),   0, 0},
+       {UIC_ARG_MIB(0x4022),   0, 0},
+       {UIC_ARG_MIB(0x4023),   0, 0},
+       {UIC_ARG_MIB(0x4025),   0, 0},
+       {UIC_ARG_MIB(0x402B),   0, 0},
+       /* MPHY */
+       {UIC_ARG_MIB(0x0021),   0, 0},
+       {UIC_ARG_MIB(0x0022),   0, 0},
+       {UIC_ARG_MIB(0x0023),   0, 0},
+       {UIC_ARG_MIB(0x0024),   0, 0},
+       {UIC_ARG_MIB(0x0028),   0, 0},
+       {UIC_ARG_MIB(0x0029),   0, 0},
+       {UIC_ARG_MIB(0x002A),   0, 0},
+       {UIC_ARG_MIB(0x002B),   0, 0},
+       {UIC_ARG_MIB(0x002C),   0, 0},
+       {UIC_ARG_MIB(0x002D),   0, 0},
+       {UIC_ARG_MIB(0x0033),   0, 0},
+       {UIC_ARG_MIB(0x0035),   0, 0},
+       {UIC_ARG_MIB(0x0036),   0, 0},
+       {UIC_ARG_MIB(0x0041),   0, 0},
+       {UIC_ARG_MIB(0x00A1),   0, 0},
+       {UIC_ARG_MIB(0x00A2),   0, 0},
+       {UIC_ARG_MIB(0x00A3),   0, 0},
+       {UIC_ARG_MIB(0x00A4),   0, 0},
+       {UIC_ARG_MIB(0x00A7),   0, 0},
+       {UIC_ARG_MIB(0x00C1),   0, 0},
+       {UIC_ARG_MIB(0x029b),   0, 0},
+       {UIC_ARG_MIB(0x035d),   0, 0},
+       {UIC_ARG_MIB(0x028B),   0, 0},
+       {UIC_ARG_MIB(0x029A),   0, 0},
+       {UIC_ARG_MIB(0x0277),   0, 0},
+
+       {},
+};
+
+static struct exynos_ufs_sfr_log ufs_show_sfr[] = {
+       {},
+};
+
+static struct exynos_ufs_attr_log ufs_show_attr[] = {
+       {},
+};
+
+#endif
+static void exynos_ufs_get_misc(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct exynos_ufs_clk_info *clki;
+       struct list_head *head = &ufs->debug.misc.clk_list_head;
+
+       list_for_each_entry(clki, head, list) {
+               if (!IS_ERR_OR_NULL(clki->clk))
+                       clki->freq = clk_get_rate(clki->clk);
+       }
+       ufs->debug.misc.isolation = readl(ufs->phy.reg_pmu);
+}
+
+static void exynos_ufs_get_sfr(struct ufs_hba *hba,
+                                       struct exynos_ufs_sfr_log* cfg)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       int sel_api = 0;
+
+       while(cfg) {
+               if (!cfg->name)
+                       break;
+
+               if (cfg->offset >= LOG_STD_HCI_SFR) {
+                       /* Select an API to get SFRs */
+                       sel_api = cfg->offset;
+               } else {
+                       /* Fetch value */
+                       if (sel_api == LOG_STD_HCI_SFR)
+                               cfg->val = ufshcd_readl(hba, cfg->offset);
+                       else if (sel_api == LOG_VS_HCI_SFR)
+                               cfg->val = hci_readl(ufs, cfg->offset);
+//                     else if (sel_api == LOG_FMP_SFR)
+//                             cfg->val = exynos_smc(SMC_CMD_FMP_DUMP, 0, 0, cfg->offset);
+                       else if (sel_api == LOG_UNIPRO_SFR)
+                               cfg->val = unipro_readl(ufs, cfg->offset);
+                       else if (sel_api == LOG_PMA_SFR)
+                               cfg->val = phy_pma_readl(ufs, cfg->offset);
+                       else
+                               cfg->val = 0xFFFFFFFF;
+               }
+
+               /* Next SFR */
+               cfg++;
+       }
+}
+
+static void exynos_ufs_get_attr(struct ufs_hba *hba,
+                                       struct exynos_ufs_attr_log* cfg)
+{
+       u32 i;
+       u32 intr_enable;
+
+       /* Disable and backup interrupts */
+       intr_enable = ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+       ufshcd_writel(hba, 0, REG_INTERRUPT_ENABLE);
+
+       while(cfg) {
+               if (cfg->offset == 0)
+                       break;
+
+               /* Send DME_GET */
+               ufshcd_writel(hba, cfg->offset, REG_UIC_COMMAND_ARG_1);
+               ufshcd_writel(hba, UIC_CMD_DME_GET, REG_UIC_COMMAND);
+
+               i = 0;
+               while(!(ufshcd_readl(hba, REG_INTERRUPT_STATUS) &
+                                       UIC_COMMAND_COMPL)) {
+                       if (i++ > 20000) {
+                               dev_err(hba->dev,
+                                       "Failed to fetch a value of %x",
+                                       cfg->offset);
+                               goto out;
+                       }
+               }
+
+               /* Clear UIC command completion */
+               ufshcd_writel(hba, UIC_COMMAND_COMPL, REG_INTERRUPT_STATUS);
+
+               /* Fetch result and value */
+               cfg->res = ufshcd_readl(hba, REG_UIC_COMMAND_ARG_2 &
+                               MASK_UIC_COMMAND_RESULT);
+               cfg->val = ufshcd_readl(hba, REG_UIC_COMMAND_ARG_3);
+
+               /* Next attribute */
+               cfg++;
+       }
+
+out:
+       /* Restore and enable interrupts */
+       ufshcd_writel(hba, intr_enable, REG_INTERRUPT_ENABLE);
+}
+
+static void exynos_ufs_dump_misc(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct exynos_ufs_misc_log* cfg = &ufs->debug.misc;
+       struct exynos_ufs_clk_info *clki;
+       struct list_head *head = &cfg->clk_list_head;
+
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+       dev_err(hba->dev, ": \t\tMISC DUMP\n");
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+
+       list_for_each_entry(clki, head, list) {
+               if (!IS_ERR_OR_NULL(clki->clk)) {
+                       dev_err(hba->dev, "%s: %lu\n",
+                                       clki->name, clki->freq);
+               }
+       }
+       dev_err(hba->dev, "iso: %d\n", ufs->debug.misc.isolation);
+}
+
+static void exynos_ufs_dump_sfr(struct ufs_hba *hba,
+                                       struct exynos_ufs_sfr_log* cfg)
+{
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+       dev_err(hba->dev, ": \t\tREGISTER DUMP\n");
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+
+       while(cfg) {
+               if (!cfg->name)
+                       break;
+
+               /* Dump */
+               dev_err(hba->dev, ": %s(0x%04x):\t\t\t\t0x%08x\n",
+                               cfg->name, cfg->offset, cfg->val);
+
+               /* Next SFR */
+               cfg++;
+       }
+}
+
+static void exynos_ufs_dump_attr(struct ufs_hba *hba,
+                                       struct exynos_ufs_attr_log* cfg)
+{
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+       dev_err(hba->dev, ": \t\tATTRIBUTE DUMP\n");
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+
+       while(cfg) {
+               if (!cfg->offset)
+                       break;
+
+               /* Dump */
+               dev_err(hba->dev, ": 0x%04x:\t\t0x%08x\t\t0x%08x\n",
+                               cfg->offset, cfg->val, cfg->res);
+
+               /* Next SFR */
+               cfg++;
+       }
+}
+
+/*
+ * Functions to be provied externally
+ *
+ * There are two classes that are to initialize data structures for debug
+ * and to define actual behavior.
+ */
+void exynos_ufs_get_uic_info(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+
+       if (!(ufs->misc_flags & EXYNOS_UFS_MISC_TOGGLE_LOG))
+               return;
+
+       exynos_ufs_get_sfr(hba, ufs->debug.sfr);
+       exynos_ufs_get_attr(hba, ufs->debug.attr);
+       exynos_ufs_get_misc(hba);
+
+       ufs->misc_flags &= ~(EXYNOS_UFS_MISC_TOGGLE_LOG);
+}
+
+void exynos_ufs_dump_uic_info(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+
+//     /* secure log */
+//     exynos_smc(SMC_CMD_UFS_LOG, 1, 0, hba->secure_log.paddr);
+
+       exynos_ufs_get_sfr(hba, ufs->debug.sfr);
+       exynos_ufs_get_attr(hba, ufs->debug.attr);
+       exynos_ufs_get_misc(hba);
+
+       exynos_ufs_dump_sfr(hba, ufs->debug.sfr);
+       exynos_ufs_dump_attr(hba, ufs->debug.attr);
+       exynos_ufs_dump_misc(hba);
+}
+
+void exynos_ufs_show_uic_info(struct ufs_hba *hba)
+{
+       exynos_ufs_get_sfr(hba, ufs_show_sfr);
+       exynos_ufs_get_attr(hba, ufs_show_attr);
+
+       exynos_ufs_dump_sfr(hba, ufs_show_sfr);
+       exynos_ufs_dump_attr(hba, ufs_show_attr);
+}
+
+
+int exynos_ufs_init_dbg(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct list_head *head = &hba->clk_list_head;
+       struct ufs_clk_info *clki;
+       struct exynos_ufs_clk_info *exynos_clki;
+
+       ufs->debug.sfr = ufs_log_sfr;
+       ufs->debug.attr = ufs_log_attr;
+       INIT_LIST_HEAD(&ufs->debug.misc.clk_list_head);
+
+       if (!head || list_empty(head))
+               return 0;
+
+       list_for_each_entry(clki, head, list) {
+               exynos_clki = devm_kzalloc(hba->dev, sizeof(*exynos_clki), GFP_KERNEL);
+               if (!exynos_clki) {
+                       return -ENOMEM;
+               }
+               exynos_clki->clk = clki->clk;
+               exynos_clki->name = clki->name;
+               exynos_clki->freq = 0;
+               list_add_tail(&exynos_clki->list, &ufs->debug.misc.clk_list_head);
+       }
+
+//     hba->secure_log.paddr = exynos_ss_get_spare_paddr(0);
+//     hba->secure_log.vaddr = (u32 *)exynos_ss_get_spare_vaddr(0);
+
+       return 0;
+}
+
+static struct ufs_cmd_info   ufs_cmd_queue;
+static struct ufs_cmd_logging_category ufs_cmd_log;
+
+static void exynos_ufs_putItem_start(struct ufs_cmd_info *cmdQueue, struct ufs_cmd_logging_category *cmdData)
+{
+       cmdQueue->addr_per_tag[cmdData->tag] = &cmdQueue->data[cmdQueue->last];
+       cmdQueue->data[cmdQueue->last].cmd_opcode = cmdData->cmd_opcode;
+       cmdQueue->data[cmdQueue->last].tag = cmdData->tag;
+       cmdQueue->data[cmdQueue->last].lba = cmdData->lba;
+       cmdQueue->data[cmdQueue->last].sct = cmdData->sct;
+       cmdQueue->data[cmdQueue->last].retries = cmdData->retries;
+       cmdQueue->data[cmdQueue->last].start_time = cmdData->start_time;
+       cmdQueue->data[cmdQueue->last].outstanding_reqs = cmdData->outstanding_reqs;
+       cmdQueue->last = (cmdQueue->last + 1) % MAX_CMD_LOGS;
+}
+
+
+
+void exynos_ufs_cmd_log_start(struct ufs_hba *hba, struct scsi_cmnd *cmd)
+{
+       int cpu = raw_smp_processor_id();
+
+       unsigned long lba = (cmd->cmnd[2] << 24) |
+                                       (cmd->cmnd[3] << 16) |
+                                       (cmd->cmnd[4] << 8) |
+                                       (cmd->cmnd[5] << 0);
+       unsigned int sct = (cmd->cmnd[7] << 8) |
+                                       (cmd->cmnd[8] << 0);
+
+       ufs_cmd_log.start_time = cpu_clock(cpu);
+       ufs_cmd_log.cmd_opcode = cmd->cmnd[0];
+       ufs_cmd_log.tag = cmd->request->tag;
+       ufs_cmd_log.outstanding_reqs = hba->outstanding_reqs;
+
+       if(cmd->cmnd[0] != UNMAP)
+               ufs_cmd_log.lba = lba;
+
+       ufs_cmd_log.sct = sct;
+       ufs_cmd_log.retries = cmd->allowed;
+
+       exynos_ufs_putItem_start(&ufs_cmd_queue, &ufs_cmd_log);
+}
+
+
+void exynos_ufs_cmd_log_end(struct ufs_hba *hba, int tag)
+{
+       int cpu = raw_smp_processor_id();
+
+       ufs_cmd_queue.addr_per_tag[tag]->end_time = cpu_clock(cpu);
+}
diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c
new file mode 100644 (file)
index 0000000..d7124a4
--- /dev/null
@@ -0,0 +1,1237 @@
+/*
+ * UFS Host Controller driver for Exynos specific extensions
+ *
+ * Copyright (C) 2013-2014 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/smc.h>
+//#include <soc/samsung/exynos-pm.h>
+//#include <soc/samsung/exynos-powermode.h>
+#include "ufshcd.h"
+#include "unipro.h"
+#include "mphy.h"
+#include "ufshcd-pltfrm.h"
+#include "ufs-exynos.h"
+
+
+/*
+ * Unipro attribute value
+ */
+#define TXTRAILINGCLOCKS       0x10
+#define TACTIVATE_10_USEC      400     /* unit: 10us */
+
+/* Device ID */
+#define DEV_ID 0x00
+#define PEER_DEV_ID    0x01
+#define PEER_CPORT_ID  0x00
+#define TRAFFIC_CLASS  0x00
+
+#define IATOVAL_NSEC           20000   /* unit: ns */
+
+/* UFS CAL interface */
+
+/*
+ * Debugging information, SFR/attributes/misc
+ */
+static struct exynos_ufs *ufs_host_backup[1];
+static int ufs_host_index = 0;
+
+static struct exynos_ufs_sfr_log ufs_log_std_sfr[] = {
+       {"CAPABILITIES"                 ,       REG_CONTROLLER_CAPABILITIES,    0},
+       {"UFS VERSION"                  ,       REG_UFS_VERSION,                0},
+       {"PRODUCT ID"                   ,       REG_CONTROLLER_DEV_ID,          0},
+       {"MANUFACTURE ID"               ,       REG_CONTROLLER_PROD_ID,         0},
+       {"INTERRUPT STATUS"             ,       REG_INTERRUPT_STATUS,           0},
+       {"INTERRUPT ENABLE"             ,       REG_INTERRUPT_ENABLE,           0},
+       {"CONTROLLER STATUS"            ,       REG_CONTROLLER_STATUS,          0},
+       {"CONTROLLER ENABLE"            ,       REG_CONTROLLER_ENABLE,          0},
+       {"UTP TRANSF REQ INT AGG CNTRL" ,       REG_UTP_TRANSFER_REQ_INT_AGG_CONTROL,           0},
+       {"UTP TRANSF REQ LIST BASE L"   ,       REG_UTP_TRANSFER_REQ_LIST_BASE_L,               0},
+       {"UTP TRANSF REQ LIST BASE H"   ,       REG_UTP_TRANSFER_REQ_LIST_BASE_H,               0},
+       {"UTP TRANSF REQ DOOR BELL"     ,       REG_UTP_TRANSFER_REQ_DOOR_BELL,         0},
+       {"UTP TRANSF REQ LIST CLEAR"    ,       REG_UTP_TRANSFER_REQ_LIST_CLEAR,                0},
+       {"UTP TRANSF REQ LIST RUN STOP" ,       REG_UTP_TRANSFER_REQ_LIST_RUN_STOP,             0},
+       {"UTP TASK REQ LIST BASE L"     ,       REG_UTP_TASK_REQ_LIST_BASE_L,           0},
+       {"UTP TASK REQ LIST BASE H"     ,       REG_UTP_TASK_REQ_LIST_BASE_H,           0},
+       {"UTP TASK REQ DOOR BELL"       ,       REG_UTP_TASK_REQ_DOOR_BELL,             0},
+       {"UTP TASK REQ LIST CLEAR"      ,       REG_UTP_TASK_REQ_LIST_CLEAR,            0},
+       {"UTP TASK REQ LIST RUN STOP"   ,       REG_UTP_TASK_REQ_LIST_RUN_STOP,         0},
+       {"UIC COMMAND"                  ,       REG_UIC_COMMAND,                0},
+       {"UIC COMMAND ARG1"             ,       REG_UIC_COMMAND_ARG_1,          0},
+       {"UIC COMMAND ARG2"             ,       REG_UIC_COMMAND_ARG_2,          0},
+       {"UIC COMMAND ARG3"             ,       REG_UIC_COMMAND_ARG_3,          0},
+
+       {},
+};
+
+/* Helper for UFS CAL interface */
+static inline int ufs_init_cal(struct exynos_ufs *ufs, int idx,
+                                       struct platform_device *pdev)
+{
+       int ret = 0;
+       struct device *dev = &pdev->dev;
+       struct ufs_cal_param *p = NULL;
+
+       p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               dev_err(ufs->dev, "cannot allocate mem for cal param\n");
+               return -ENOMEM;
+       }
+       ufs->cal_param = p;
+
+       p->host = ufs;
+       p->board = 0;   /* ken: need a dt node for board */
+       if ((ret = ufs_cal_init(p, idx)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_init_cal = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+static inline int ufs_pre_link(struct exynos_ufs *ufs)
+{
+       int ret = 0;
+       struct ufs_cal_param *p = ufs->cal_param;
+
+       p->mclk_rate = ufs->mclk_rate;
+       p->target_lane = ufs->num_rx_lanes;
+       p->available_lane = ufs->num_rx_lanes;
+
+       if ((ret = ufs_cal_pre_link(p)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_pre_link = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+static inline int ufs_post_link(struct exynos_ufs *ufs)
+{
+       int ret = 0;
+
+       if ((ret = ufs_cal_post_link(ufs->cal_param)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_post_link = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+static inline int ufs_pre_gear_change(struct exynos_ufs *ufs,
+                               struct uic_pwr_mode *pmd)
+{
+       struct ufs_cal_param *p = ufs->cal_param;
+       int ret = 0;
+
+       p->pmd = pmd;
+       p->target_lane = pmd->lane;
+       if ((ret = ufs_cal_pre_pmc(p)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_pre_gear_change = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+static inline int ufs_post_gear_change(struct exynos_ufs *ufs)
+{
+       int ret = 0;
+
+       if ((ret = ufs_cal_post_pmc(ufs->cal_param)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_post_gear_change = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+static inline int ufs_post_h8_enter(struct exynos_ufs *ufs)
+{
+       int ret = 0;
+
+       if ((ret = ufs_cal_post_h8_enter(ufs->cal_param)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_post_h8_enter = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+static inline int ufs_pre_h8_exit(struct exynos_ufs *ufs)
+{
+       int ret = 0;
+
+       if ((ret = ufs_cal_pre_h8_exit(ufs->cal_param)) != UFS_CAL_NO_ERROR) {
+               dev_err(ufs->dev, "ufs_pre_h8_exit = %d!!!\n", ret);
+               return -EPERM;
+       }
+
+       return 0;
+}
+
+/* Adaptor for UFS CAL */
+void ufs_lld_dme_set(void *h, u32 addr, u32 val)
+{
+       ufshcd_dme_set(((struct exynos_ufs *)h)->hba, addr, val);
+}
+
+void ufs_lld_dme_get(void *h, u32 addr, u32 *val)
+{
+       ufshcd_dme_get(((struct exynos_ufs *)h)->hba, addr, val);
+}
+
+void ufs_lld_dme_peer_set(void *h, u32 addr, u32 val)
+{
+       ufshcd_dme_peer_set(((struct exynos_ufs *)h)->hba, addr, val);
+}
+
+void ufs_lld_pma_write(void *h, u32 val, u32 addr)
+{
+       phy_pma_writel((struct exynos_ufs *)h, val, addr);
+}
+
+u32 ufs_lld_pma_read(void *h, u32 addr)
+{
+       return phy_pma_readl((struct exynos_ufs *)h, addr);
+}
+
+void ufs_lld_unipro_write(void *h, u32 val, u32 addr)
+{
+       unipro_writel((struct exynos_ufs *)h, val, addr);
+}
+
+void ufs_lld_udelay(u32 val)
+{
+       udelay(val);
+}
+
+void ufs_lld_usleep_delay(u32 min, u32 max)
+{
+       usleep_range(min, max);
+}
+
+unsigned long ufs_lld_get_time_count(unsigned long offset)
+{
+       return jiffies;
+}
+
+unsigned long ufs_lld_calc_timeout(const unsigned int ms)
+{
+       return msecs_to_jiffies(ms);
+}
+
+static inline void exynos_ufs_ctrl_phy_pwr(struct exynos_ufs *ufs, bool en)
+{
+       u32 reg;
+
+       reg = readl(ufs->phy.reg_pmu);
+
+       if (en)
+               writel(reg | BIT(0), ufs->phy.reg_pmu);
+       else
+               writel(reg & ~(BIT(0)), ufs->phy.reg_pmu);
+}
+
+#ifndef __EXYNOS_UFS_VS_DEBUG__
+static void exynos_ufs_dump_std_sfr(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct exynos_ufs_sfr_log* cfg = ufs->debug.std_sfr;
+
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+       dev_err(hba->dev, ": \t\tREGISTER DUMP\n");
+       dev_err(hba->dev, ": --------------------------------------------------- \n");
+
+       while(cfg) {
+               if (!cfg->name)
+                       break;
+               cfg->val = ufshcd_readl(hba, cfg->offset);
+
+               /* Dump */
+               dev_err(hba->dev, ": %s(0x%04x):\t\t\t\t0x%08x\n",
+                               cfg->name, cfg->offset, cfg->val);
+
+               /* Next SFR */
+               cfg++;
+       }
+}
+#endif
+
+/*
+ * Exynos debugging main function
+ */
+static void exynos_ufs_dump_debug_info(struct ufs_hba *hba)
+{
+#ifdef __EXYNOS_UFS_VS_DEBUG__
+       exynos_ufs_get_uic_info(hba);
+#else
+       exynos_ufs_dump_std_sfr(hba);
+#endif
+}
+
+static void exynos_ufs_select_refclk(struct exynos_ufs *ufs, bool en)
+{
+       u32 reg;
+       if (ufs->hw_rev != UFS_VER_0004)
+               return;
+
+       /*
+        * true : alternative clock path, false : active clock path
+        */
+       reg = hci_readl(ufs, HCI_MPHY_REFCLK_SEL);
+       if (en)
+               hci_writel(ufs, reg | MPHY_REFCLK_SEL, HCI_MPHY_REFCLK_SEL);
+       else
+               hci_writel(ufs, reg & ~MPHY_REFCLK_SEL, HCI_MPHY_REFCLK_SEL);
+}
+
+inline void exynos_ufs_set_hwacg_control(struct exynos_ufs *ufs, bool en)
+{
+       u32 reg;
+       if ((ufs->hw_rev != UFS_VER_0004) && (ufs->hw_rev != UFS_VER_0005))
+               return;
+
+       /*
+        * default value 1->0 at KC. so,
+        * need to set "1(disable HWACG)" during UFS init
+        */
+       reg = hci_readl(ufs, HCI_UFS_ACG_DISABLE);
+       if (en)
+               hci_writel(ufs, reg & (~HCI_UFS_ACG_DISABLE_EN), HCI_UFS_ACG_DISABLE);
+       else
+               hci_writel(ufs, reg | HCI_UFS_ACG_DISABLE_EN, HCI_UFS_ACG_DISABLE);
+
+}
+
+inline void exynos_ufs_ctrl_auto_hci_clk(struct exynos_ufs *ufs, bool en)
+{
+       u32 reg = hci_readl(ufs, HCI_FORCE_HCS);
+
+       if (en)
+               hci_writel(ufs, reg | HCI_CORECLK_STOP_EN, HCI_FORCE_HCS);
+       else
+               hci_writel(ufs, reg & ~HCI_CORECLK_STOP_EN, HCI_FORCE_HCS);
+}
+
+static inline void exynos_ufs_ctrl_clk(struct exynos_ufs *ufs, bool en)
+{
+       u32 reg = hci_readl(ufs, HCI_FORCE_HCS);
+
+       if (en)
+               hci_writel(ufs, reg | CLK_STOP_CTRL_EN_ALL, HCI_FORCE_HCS);
+       else
+               hci_writel(ufs, reg & ~CLK_STOP_CTRL_EN_ALL, HCI_FORCE_HCS);
+}
+
+static inline void exynos_ufs_gate_clk(struct exynos_ufs *ufs, bool en)
+{
+
+       u32 reg = hci_readl(ufs, HCI_CLKSTOP_CTRL);
+
+       if (en)
+               hci_writel(ufs, reg | CLK_STOP_ALL, HCI_CLKSTOP_CTRL);
+       else
+               hci_writel(ufs, reg & ~CLK_STOP_ALL, HCI_CLKSTOP_CTRL);
+}
+
+static void exynos_ufs_set_unipro_mclk(struct exynos_ufs *ufs)
+{
+       ufs->mclk_rate = (u32)clk_get_rate(ufs->clk_unipro);
+}
+
+static void exynos_ufs_fit_aggr_timeout(struct exynos_ufs *ufs)
+{
+       u32 cnt_val;
+       unsigned long nVal;
+
+       /* IA_TICK_SEL : 1(1us_TO_CNT_VAL) */
+       nVal = hci_readl(ufs, HCI_UFSHCI_V2P1_CTRL);
+       nVal |= IA_TICK_SEL;
+       hci_writel(ufs, nVal, HCI_UFSHCI_V2P1_CTRL);
+
+       cnt_val = ufs->mclk_rate / 1000000 ;
+       hci_writel(ufs, cnt_val & CNT_VAL_1US_MASK, HCI_1US_TO_CNT_VAL);
+}
+
+static void exynos_ufs_init_pmc_req(struct ufs_hba *hba,
+               struct ufs_pa_layer_attr *pwr_max,
+               struct ufs_pa_layer_attr *pwr_req)
+{
+
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct uic_pwr_mode *req_pmd = &ufs->req_pmd_parm;
+       struct uic_pwr_mode *act_pmd = &ufs->act_pmd_parm;
+
+       /* update lane variable after link */
+       ufs->num_rx_lanes = pwr_max->lane_rx;
+       ufs->num_tx_lanes = pwr_max->lane_tx;
+
+       pwr_req->gear_rx
+               = act_pmd->gear= min_t(u8, pwr_max->gear_rx, req_pmd->gear);
+       pwr_req->gear_tx
+               = act_pmd->gear = min_t(u8, pwr_max->gear_tx, req_pmd->gear);
+       pwr_req->lane_rx
+               = act_pmd->lane = min_t(u8, pwr_max->lane_rx, req_pmd->lane);
+       pwr_req->lane_tx
+               = act_pmd->lane = min_t(u8, pwr_max->lane_tx, req_pmd->lane);
+       pwr_req->pwr_rx = act_pmd->mode = req_pmd->mode;
+       pwr_req->pwr_tx = act_pmd->mode = req_pmd->mode;
+       pwr_req->hs_rate = act_pmd->hs_series = req_pmd->hs_series;
+}
+
+static void exynos_ufs_config_intr(struct exynos_ufs *ufs, u32 errs, u8 index)
+{
+       switch(index) {
+       case UNIP_PA_LYR:
+               hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERROR_EN_PA_LAYER);
+               break;
+       case UNIP_DL_LYR:
+               hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERROR_EN_DL_LAYER);
+               break;
+       case UNIP_N_LYR:
+               hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERROR_EN_N_LAYER);
+               break;
+       case UNIP_T_LYR:
+               hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERROR_EN_T_LAYER);
+               break;
+       case UNIP_DME_LYR:
+               hci_writel(ufs, DFES_ERR_EN | errs, HCI_ERROR_EN_DME_LAYER);
+               break;
+       }
+}
+
+static void exynos_ufs_dev_hw_reset(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+
+       /* bit[1] for resetn */
+       hci_writel(ufs, 0 << 0, HCI_GPIO_OUT);
+       udelay(5);
+       hci_writel(ufs, 1 << 0, HCI_GPIO_OUT);
+}
+
+static void exynos_ufs_init_host(struct exynos_ufs *ufs)
+{
+       u32 reg;
+
+       /* internal clock control */
+       exynos_ufs_ctrl_auto_hci_clk(ufs, false);
+       exynos_ufs_set_unipro_mclk(ufs);
+
+       /* period for interrupt aggregation */
+       exynos_ufs_fit_aggr_timeout(ufs);
+
+       /* misc HCI configurations */
+       hci_writel(ufs, 0xA, HCI_DATA_REORDER);
+       hci_writel(ufs, PRDT_PREFECT_EN | PRDT_SET_SIZE(12),
+                       HCI_TXPRDT_ENTRY_SIZE);
+       hci_writel(ufs, PRDT_SET_SIZE(12), HCI_RXPRDT_ENTRY_SIZE);
+       hci_writel(ufs, 0xFFFFFFFF, HCI_UTRL_NEXUS_TYPE);
+       hci_writel(ufs, 0xFFFFFFFF, HCI_UTMRL_NEXUS_TYPE);
+
+       reg = hci_readl(ufs, HCI_AXIDMA_RWDATA_BURST_LEN) &
+                                       ~BURST_LEN(0);
+       hci_writel(ufs, WLU_EN | BURST_LEN(3),
+                                       HCI_AXIDMA_RWDATA_BURST_LEN);
+
+       /*
+        * Enable HWAGC control by IOP
+        *
+        * default value 1->0 at KC.
+        * always "0"(controlled by UFS_ACG_DISABLE)
+        */
+       reg = hci_readl(ufs, HCI_IOP_ACG_DISABLE);
+       hci_writel(ufs, reg & (~HCI_IOP_ACG_DISABLE_EN), HCI_IOP_ACG_DISABLE);
+}
+
+static void exynos_ufs_pre_hibern8(struct ufs_hba *hba, u8 enter)
+{
+}
+
+static void exynos_ufs_post_hibern8(struct ufs_hba *hba, u8 enter)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+
+       if (!enter) {
+               struct uic_pwr_mode *act_pmd = &ufs->act_pmd_parm;
+               u32 mode = 0;
+
+               ufshcd_dme_get(hba, UIC_ARG_MIB(PA_PWRMODE), &mode);
+               if (mode != (act_pmd->mode << 4 | act_pmd->mode)) {
+                       dev_warn(hba->dev, "%s: power mode not matched, mode : 0x%x, act_mode : 0x%x\n",
+                                       __func__, mode, act_pmd->mode);
+                       hba->pwr_info.pwr_rx = (mode >> 4) & 0xf;
+                       hba->pwr_info.pwr_tx = mode & 0xf;
+                       ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info);
+               }
+       }
+}
+
+static void exynos_ufs_modify_sysreg(struct exynos_ufs *ufs, int index)
+{
+       struct exynos_ufs_sys *sys = &ufs->sys;
+       void __iomem *reg_sys = sys->reg_sys[index];
+       const char *const name[NUM_OF_SYSREG] = {
+               "ufs-io-coherency",
+       };
+       u32 reg;
+
+       if (!of_get_child_by_name(ufs->dev->of_node, name[index]))
+               return;
+
+       reg = readl(reg_sys);
+       writel((reg & ~(sys->mask[index])) | sys->bits[index], reg_sys);
+}
+
+static int exynos_ufs_init_system(struct exynos_ufs *ufs)
+{
+       struct device *dev = ufs->dev;
+       int ret = 0;
+
+       /* PHY isolation bypass */
+       exynos_ufs_ctrl_phy_pwr(ufs, true);
+
+       /* IO cohernecy */
+       if (!of_get_child_by_name(dev->of_node, "ufs-io-coherency")) {
+               dev_err(dev, "Not configured to use IO coherency\n");
+       } else {
+               if (!of_find_property(dev->of_node, "dma-coherent", NULL))
+                       BUG();
+
+               exynos_ufs_modify_sysreg(ufs, 0);
+       }
+
+       return ret;
+}
+
+static int exynos_ufs_get_clks(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct list_head *head = &hba->clk_list_head;
+       struct ufs_clk_info *clki;
+
+       ufs_host_backup[ufs_host_index++] = ufs;
+       ufs->debug.std_sfr = ufs_log_std_sfr;
+
+       if (!head || list_empty(head))
+               goto out;
+
+       list_for_each_entry(clki, head, list) {
+               if (!IS_ERR_OR_NULL(clki->clk)) {
+                       if (!strcmp(clki->name, "GATE_UFS_EMBD"))
+                               ufs->clk_hci = clki->clk;
+                       if (!strcmp(clki->name, "UFS_EMBD")) {
+                               ufs->clk_unipro = clki->clk;
+                       }
+               }
+       }
+out:
+       if (!ufs->clk_hci || !ufs->clk_unipro)
+               return -EINVAL;
+
+       return 0;
+}
+
+static void exynos_ufs_set_features(struct ufs_hba *hba, u32 hw_rev)
+{
+       /* caps */
+       hba->caps = UFSHCD_CAP_CLK_GATING |
+                       UFSHCD_CAP_HIBERN8_WITH_CLK_GATING |
+                       UFSHCD_CAP_INTR_AGGR;
+
+       /* quirks of common driver */
+       hba->quirks = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
+                       UFSHCI_QUIRK_SKIP_INTR_AGGR |
+                       UFSHCD_QUIRK_UNRESET_INTR_AGGR |
+                       UFSHCD_QUIRK_BROKEN_REQ_LIST_CLR;
+
+       hba->quirks |= UFSHCD_QUIRK_GET_UPMCRS_DIRECT |
+               UFSHCD_QUIRK_GET_GENERRCODE_DIRECT;
+
+       /* quirks of exynos-specific driver */
+}
+
+/*
+ * Exynos-specific callback functions
+ *
+ * init                        | Pure SW init & system-related init
+ * host_reset          | Host SW reset & init
+ * pre_setup_clocks    | specific power down
+ * setup_clocks                | specific power up
+ * ...
+ *
+ * Initializations for software, host controller and system
+ * should be contained only in ->host_reset() as possible.
+ */
+
+static int exynos_ufs_init(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       int ret;
+
+       /* set features, such as caps or quirks */
+       exynos_ufs_set_features(hba, ufs->hw_rev);
+
+       /* get some clock sources and debug infomation structures */
+       ret = exynos_ufs_get_clks(hba);
+       if (ret)
+               return ret;
+
+       /* system init */
+       ret = exynos_ufs_init_system(ufs);
+       if (ret)
+               return ret;
+
+
+       /* Enable log */
+       ret =  exynos_ufs_init_dbg(hba);
+
+       if (ret)
+               return ret;
+
+       ufs->misc_flags = EXYNOS_UFS_MISC_TOGGLE_LOG;
+
+       return 0;
+}
+
+static void exynos_ufs_host_reset(struct ufs_hba *hba)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+       exynos_ufs_ctrl_auto_hci_clk(ufs, false);
+
+       hci_writel(ufs, UFS_SW_RST_MASK, HCI_SW_RST);
+
+       do {
+               if (!(hci_readl(ufs, HCI_SW_RST) & UFS_SW_RST_MASK))
+                       goto success;
+       } while (time_before(jiffies, timeout));
+
+       dev_err(ufs->dev, "timeout host sw-reset\n");
+
+       exynos_ufs_dump_uic_info(hba);
+
+       goto out;
+
+success:
+       /* host init */
+       exynos_ufs_init_host(ufs);
+
+       /* device reset */
+       exynos_ufs_dev_hw_reset(hba);
+
+       /* secure log */
+//     exynos_smc(SMC_CMD_LOG, 0, 0, 2);
+out:
+       return;
+}
+
+static inline void exynos_ufs_dev_reset_ctrl(struct exynos_ufs *ufs, bool en)
+{
+
+       if (en)
+               hci_writel(ufs, 1 << 0, HCI_GPIO_OUT);
+       else
+               hci_writel(ufs, 0 << 0, HCI_GPIO_OUT);
+}
+
+static int exynos_ufs_pre_setup_clocks(struct ufs_hba *hba, bool on)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       int ret = 0;
+
+       if (on) {
+#ifdef CONFIG_CPU_IDLE
+               exynos_update_ip_idle_status(ufs->idle_ip_index, 0);
+#endif
+               /*
+                * Now all used blocks would not be turned off in a host.
+                */
+               exynos_ufs_ctrl_auto_hci_clk(ufs, false);
+               exynos_ufs_gate_clk(ufs, false);
+
+               /* HWAGC disable */
+               exynos_ufs_set_hwacg_control(ufs, false);
+       } else {
+//             pm_qos_update_request(&ufs->pm_qos_int, 0);
+
+               /*
+                * BG/SQ off
+                */
+               ret = ufs_post_h8_enter(ufs);
+       }
+
+       return ret;
+}
+
+static int exynos_ufs_setup_clocks(struct ufs_hba *hba, bool on)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       int ret = 0;
+
+       if (on) {
+               /*
+                * BG/SQ on
+                */
+               ret = ufs_pre_h8_exit(ufs);
+
+//             pm_qos_update_request(&ufs->pm_qos_int, ufs->pm_qos_int_value);
+
+       } else {
+               /*
+                * Now all used blocks would be turned off in a host.
+                */
+               exynos_ufs_gate_clk(ufs, true);
+               exynos_ufs_ctrl_auto_hci_clk(ufs, true);
+
+               /* HWAGC enable */
+               exynos_ufs_set_hwacg_control(ufs, true);
+
+#ifdef CONFIG_CPU_IDLE
+               exynos_update_ip_idle_status(ufs->idle_ip_index, 1);
+#endif
+       }
+
+       return ret;
+}
+
+static int exynos_ufs_link_startup_notify(struct ufs_hba *hba,
+                                       enum ufs_notify_change_status status)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       int ret = 0;
+
+       switch (status) {
+       case PRE_CHANGE:
+               /* refer to hba */
+               ufs->hba = hba;
+
+               /* hci */
+               exynos_ufs_config_intr(ufs, DFES_DEF_DL_ERRS, UNIP_DL_LYR);
+               exynos_ufs_config_intr(ufs, DFES_DEF_N_ERRS, UNIP_N_LYR);
+               exynos_ufs_config_intr(ufs, DFES_DEF_T_ERRS, UNIP_T_LYR);
+
+               exynos_ufs_ctrl_clk(ufs, true);
+               exynos_ufs_select_refclk(ufs, true);
+               exynos_ufs_gate_clk(ufs, false);
+               exynos_ufs_set_hwacg_control(ufs, false);
+
+               if (ufs->num_rx_lanes == 0 || ufs->num_tx_lanes == 0) {
+                       ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES),
+                                       &ufs->num_rx_lanes);
+                       ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES),
+                                       &ufs->num_tx_lanes);
+                       WARN(ufs->num_rx_lanes != ufs->num_tx_lanes,
+                                       "available data lane is not equal(rx:%d, tx:%d)\n",
+                                       ufs->num_rx_lanes, ufs->num_tx_lanes);
+               }
+
+               ufs->mclk_rate = clk_get_rate(ufs->clk_unipro);
+
+               ret = ufs_pre_link(ufs);
+               break;
+       case POST_CHANGE:
+               /* UIC configuration table after link startup */
+               ret = ufs_post_link(ufs);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int exynos_ufs_pwr_change_notify(struct ufs_hba *hba,
+                                       enum ufs_notify_change_status status,
+                                       struct ufs_pa_layer_attr *pwr_max,
+                                       struct ufs_pa_layer_attr *pwr_req)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       struct uic_pwr_mode *act_pmd = &ufs->act_pmd_parm;
+       int ret = 0;
+
+       switch (status) {
+       case PRE_CHANGE:
+
+               /* Set PMC parameters to be requested */
+               exynos_ufs_init_pmc_req(hba, pwr_max, pwr_req);
+
+               /* UIC configuration table before power mode change */
+               ret = ufs_pre_gear_change(ufs, act_pmd);
+
+               break;
+       case POST_CHANGE:
+               /* UIC configuration table after power mode change */
+               ret = ufs_post_gear_change(ufs);
+
+               dev_info(ufs->dev,
+                               "Power mode change(%d): M(%d)G(%d)L(%d)HS-series(%d)\n",
+                               ret, act_pmd->mode, act_pmd->gear,
+                               act_pmd->lane, act_pmd->hs_series);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static void exynos_ufs_set_nexus_t_xfer_req(struct ufs_hba *hba,
+                               int tag, struct scsi_cmnd *cmd)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       u32 type;
+
+       type =  hci_readl(ufs, HCI_UTRL_NEXUS_TYPE);
+
+       if (cmd)
+               type |= (1 << tag);
+       else
+               type &= ~(1 << tag);
+
+       hci_writel(ufs, type, HCI_UTRL_NEXUS_TYPE);
+}
+
+static void exynos_ufs_set_nexus_t_task_mgmt(struct ufs_hba *hba, int tag, u8 tm_func)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       u32 type;
+
+       type =  hci_readl(ufs, HCI_UTMRL_NEXUS_TYPE);
+
+       switch (tm_func) {
+       case UFS_ABORT_TASK:
+       case UFS_QUERY_TASK:
+               type |= (1 << tag);
+               break;
+       case UFS_ABORT_TASK_SET:
+       case UFS_CLEAR_TASK_SET:
+       case UFS_LOGICAL_RESET:
+       case UFS_QUERY_TASK_SET:
+               type &= ~(1 << tag);
+               break;
+       }
+
+       hci_writel(ufs, type, HCI_UTMRL_NEXUS_TYPE);
+}
+
+static void exynos_ufs_hibern8_notify(struct ufs_hba *hba,
+                               u8 enter, bool notify)
+{
+       switch (notify) {
+       case PRE_CHANGE:
+               exynos_ufs_pre_hibern8(hba, enter);
+               break;
+       case POST_CHANGE:
+               exynos_ufs_post_hibern8(hba, enter);
+               break;
+       default:
+               break;
+       }
+}
+
+static int __exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+
+//     pm_qos_update_request(&ufs->pm_qos_int, 0);
+
+       exynos_ufs_dev_reset_ctrl(ufs, false);
+
+       exynos_ufs_ctrl_phy_pwr(ufs, false);
+
+       return 0;
+}
+
+static int __exynos_ufs_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+{
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+       int ret = 0;
+
+       exynos_ufs_ctrl_phy_pwr(ufs, true);
+
+       /* system init */
+       ret = exynos_ufs_init_system(ufs);
+       if (ret)
+               return ret;
+
+       if (ufshcd_is_clkgating_allowed(hba))
+               clk_prepare_enable(ufs->clk_hci);
+       exynos_ufs_ctrl_auto_hci_clk(ufs, false);
+       /* secure log */
+//     exynos_smc(SMC_CMD_LOG, 0, 0, 2);
+
+       if (ufshcd_is_clkgating_allowed(hba))
+               clk_disable_unprepare(ufs->clk_hci);
+
+       return 0;
+}
+
+static u8 exynos_ufs_get_unipro_direct(struct ufs_hba *hba, int num)
+{
+       u32 offset[] = {
+               UNIP_DME_LINKSTARTUP_CNF_RESULT,
+               UNIP_DME_HIBERN8_ENTER_CNF_RESULT,
+               UNIP_DME_HIBERN8_EXIT_CNF_RESULT,
+               UNIP_DME_PWR_IND_RESULT,
+               UNIP_DME_HIBERN8_ENTER_IND_RESULT,
+               UNIP_DME_HIBERN8_EXIT_IND_RESULT
+       };
+
+       struct exynos_ufs *ufs = to_exynos_ufs(hba);
+
+       return unipro_readl(ufs, offset[num]);
+}
+
+static struct ufs_hba_variant_ops exynos_ufs_ops = {
+       .init = exynos_ufs_init,
+       .host_reset = exynos_ufs_host_reset,
+       .pre_setup_clocks = exynos_ufs_pre_setup_clocks,
+       .setup_clocks = exynos_ufs_setup_clocks,
+       .link_startup_notify = exynos_ufs_link_startup_notify,
+       .pwr_change_notify = exynos_ufs_pwr_change_notify,
+       .set_nexus_t_xfer_req = exynos_ufs_set_nexus_t_xfer_req,
+       .set_nexus_t_task_mgmt = exynos_ufs_set_nexus_t_task_mgmt,
+       .hibern8_notify = exynos_ufs_hibern8_notify,
+       .dbg_register_dump = exynos_ufs_dump_debug_info,
+       .suspend = __exynos_ufs_suspend,
+       .resume = __exynos_ufs_resume,
+       .get_unipro_result = exynos_ufs_get_unipro_direct,
+};
+
+static int exynos_ufs_populate_dt_sys_per_feature(struct device *dev,
+                               struct exynos_ufs *ufs, int index)
+{
+       struct device_node *np;
+       struct exynos_ufs_sys *sys = &ufs->sys;
+       struct resource io_res;
+       int ret;
+       const char *const name[NUM_OF_SYSREG] = {
+               "ufs-io-coherency",
+       };
+
+       np = of_get_child_by_name(dev->of_node, name[index]);
+       if (!np) {
+               dev_err(dev, "failed to get ufs-sys node\n");
+               return -ENODEV;
+       }
+
+       ret = of_address_to_resource(np, 0, &io_res);
+       if (ret) {
+               dev_err(dev, "failed to get i/o address %s\n", name[index]);
+               if (ret == -EINVAL)
+                       ret = 0;
+       } else {
+               sys->reg_sys[index] = devm_ioremap_resource(dev, &io_res);
+               if (IS_ERR(sys->reg_sys[index])) {
+                       dev_err(dev, "failed to ioremap sysreg\n");
+                       ret = -ENOMEM;
+               } else {
+                       ret = of_property_read_u32(np, "mask",
+                                               &sys->mask[index]);
+                       ret = of_property_read_u32(np, "bits",
+                                               &sys->bits[index]);
+                       if (ret)
+                               ret = -EINVAL;
+               }
+       }
+
+       of_node_put(np);
+
+       return ret;
+}
+
+static int exynos_ufs_populate_dt_sys(struct device *dev, struct exynos_ufs *ufs)
+{
+       int i = 0;
+       int ret;
+
+       for (i = 0 ; i < NUM_OF_SYSREG ; i++) {
+               ret = exynos_ufs_populate_dt_sys_per_feature(dev, ufs, i);
+               if (ret && ret != -ENODEV)
+                       break;
+       }
+
+       return ret;
+}
+
+static int exynos_ufs_populate_dt_phy(struct device *dev, struct exynos_ufs *ufs)
+{
+       struct device_node *ufs_phy, *phy_sys;
+       struct exynos_ufs_phy *phy = &ufs->phy;
+       struct resource io_res;
+       int ret;
+
+       ufs_phy = of_get_child_by_name(dev->of_node, "ufs-phy");
+       if (!ufs_phy) {
+               dev_err(dev, "failed to get ufs-phy node\n");
+               return -ENODEV;
+       }
+
+       ret = of_address_to_resource(ufs_phy, 0, &io_res);
+       if (ret) {
+               dev_err(dev, "failed to get i/o address phy pma\n");
+               goto err_0;
+       }
+
+       phy->reg_pma = devm_ioremap_resource(dev, &io_res);
+       if (!phy->reg_pma) {
+               dev_err(dev, "failed to ioremap for phy pma\n");
+               ret = -ENOMEM;
+               goto err_0;
+       }
+
+       phy_sys = of_get_child_by_name(ufs_phy, "ufs-phy-sys");
+       if (!phy_sys) {
+               dev_err(dev, "failed to get ufs-phy-sys node\n");
+               ret = -ENODEV;
+               goto err_0;
+       }
+
+       ret = of_address_to_resource(phy_sys, 0, &io_res);
+       if (ret) {
+               dev_err(dev, "failed to get i/o address ufs-phy pmu\n");
+               goto err_1;
+       }
+
+       phy->reg_pmu = devm_ioremap_resource(dev, &io_res);
+       if (!phy->reg_pmu) {
+               dev_err(dev, "failed to ioremap for ufs-phy pmu\n");
+               ret = -ENOMEM;
+       }
+
+err_1:
+       of_node_put(phy_sys);
+err_0:
+       of_node_put(ufs_phy);
+
+       return ret;
+}
+
+static int exynos_ufs_get_pwr_mode(struct device_node *np,
+                               struct exynos_ufs *ufs)
+{
+       struct uic_pwr_mode *pmd = &ufs->req_pmd_parm;
+
+       pmd->mode = FAST_MODE;
+
+       if (of_property_read_u8(np, "ufs,pmd-attr-lane", &pmd->lane))
+               pmd->lane = 1;
+
+       if (of_property_read_u8(np, "ufs,pmd-attr-gear", &pmd->gear))
+               pmd->gear = 1;
+
+       pmd->hs_series = PA_HS_MODE_B;
+
+       return 0;
+}
+
+static int exynos_ufs_populate_dt(struct device *dev, struct exynos_ufs *ufs)
+{
+       struct device_node *np = dev->of_node;
+       int ret;
+
+       /* Get exynos-specific version for featuring */
+       if (of_property_read_u32(np, "hw-rev", &ufs->hw_rev))
+               ufs->hw_rev = UFS_VER_0004;
+
+       ret = exynos_ufs_populate_dt_phy(dev, ufs);
+       if (ret) {
+               dev_err(dev, "failed to populate dt-phy\n");
+               goto out;
+       }
+
+       ret = exynos_ufs_populate_dt_sys(dev, ufs);
+       if (ret)
+               dev_err(dev, "failed to populate ufs-sys\n");
+
+       exynos_ufs_get_pwr_mode(np, ufs);
+
+       if (of_property_read_u8(np, "brd-for-cal", &ufs->cal_param->board))
+               ufs->cal_param->board = 0;
+
+       if (of_property_read_u32(np, "ufs-pm-qos-int", &ufs->pm_qos_int_value))
+               ufs->pm_qos_int_value = 0;
+
+       if (of_property_read_u32(np, "ufs-pm-qos-fsys0", &ufs->pm_qos_fsys0_value))
+               ufs->pm_qos_fsys0_value = 0;
+
+
+out:
+       return ret;
+}
+
+static u64 exynos_ufs_dma_mask = DMA_BIT_MASK(32);
+
+static int exynos_ufs_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct exynos_ufs *ufs;
+       struct resource *res;
+       int ret;
+
+       ufs = devm_kzalloc(dev, sizeof(*ufs), GFP_KERNEL);
+       if (!ufs) {
+               dev_err(dev, "cannot allocate mem for exynos-ufs\n");
+               return -ENOMEM;
+       }
+
+       /* exynos-specific hci */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       ufs->reg_hci = devm_ioremap_resource(dev, res);
+       if (!ufs->reg_hci) {
+               dev_err(dev, "cannot ioremap for hci vendor register\n");
+               return -ENOMEM;
+       }
+
+       /* unipro */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+       ufs->reg_unipro = devm_ioremap_resource(dev, res);
+       if (!ufs->reg_unipro) {
+               dev_err(dev, "cannot ioremap for unipro register\n");
+               return -ENOMEM;
+       }
+
+       /* ufs protector */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+       ufs->reg_ufsp = devm_ioremap_resource(dev, res);
+       if (!ufs->reg_ufsp) {
+               dev_err(dev, "cannot ioremap for ufs protector register\n");
+               return -ENOMEM;
+       }
+
+       /* This must be before calling exynos_ufs_populate_dt */
+       ret = ufs_init_cal(ufs, ufs_host_index, pdev);
+       if (ret)
+               return ret;
+
+       ret = exynos_ufs_populate_dt(dev, ufs);
+       if (ret) {
+               dev_err(dev, "failed to get dt info.\n");
+               return ret;
+       }
+
+#ifdef CONFIG_CPU_IDLE
+       ufs->idle_ip_index = exynos_get_idle_ip_index(dev_name(&pdev->dev));
+       exynos_update_ip_idle_status(ufs->idle_ip_index, 0);
+#endif
+
+       ufs->dev = dev;
+       dev->platform_data = ufs;
+       dev->dma_mask = &exynos_ufs_dma_mask;
+
+//     pm_qos_add_request(&ufs->pm_qos_int, PM_QOS_DEVICE_THROUGHPUT, 0);
+
+       ret = ufshcd_pltfrm_init(pdev, &exynos_ufs_ops);
+
+       return ret;
+}
+
+static int exynos_ufs_remove(struct platform_device *pdev)
+{
+       struct exynos_ufs *ufs = dev_get_platdata(&pdev->dev);
+
+       ufshcd_pltfrm_exit(pdev);
+
+       pm_qos_remove_request(&ufs->pm_qos_fsys0);
+
+       ufs->misc_flags = EXYNOS_UFS_MISC_TOGGLE_LOG;
+
+       exynos_ufs_ctrl_phy_pwr(ufs, false);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int exynos_ufs_suspend(struct device *dev)
+{
+       struct ufs_hba *hba = dev_get_drvdata(dev);
+
+       return ufshcd_system_suspend(hba);
+}
+
+static int exynos_ufs_resume(struct device *dev)
+{
+       struct ufs_hba *hba = dev_get_drvdata(dev);
+
+       return ufshcd_system_resume(hba);
+}
+#else
+#define exynos_ufs_suspend     NULL
+#define exynos_ufs_resume      NULL
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int exynos_ufs_runtime_suspend(struct device *dev)
+{
+       return ufshcd_system_suspend(dev_get_drvdata(dev));
+}
+
+static int exynos_ufs_runtime_resume(struct device *dev)
+{
+       return ufshcd_system_resume(dev_get_drvdata(dev));
+}
+
+static int exynos_ufs_runtime_idle(struct device *dev)
+{
+       return ufshcd_runtime_idle(dev_get_drvdata(dev));
+}
+
+#else
+#define exynos_ufs_runtime_suspend     NULL
+#define exynos_ufs_runtime_resume      NULL
+#define exynos_ufs_runtime_idle                NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static void exynos_ufs_shutdown(struct platform_device *pdev)
+{
+       ufshcd_shutdown((struct ufs_hba *)platform_get_drvdata(pdev));
+}
+
+static const struct dev_pm_ops exynos_ufs_dev_pm_ops = {
+       .suspend                = exynos_ufs_suspend,
+       .resume                 = exynos_ufs_resume,
+       .runtime_suspend        = exynos_ufs_runtime_suspend,
+       .runtime_resume         = exynos_ufs_runtime_resume,
+       .runtime_idle           = exynos_ufs_runtime_idle,
+};
+
+static const struct ufs_hba_variant exynos_ufs_drv_data = {
+       .ops            = &exynos_ufs_ops,
+};
+
+static const struct of_device_id exynos_ufs_match[] = {
+       { .compatible = "samsung,exynos-ufs", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_ufs_match);
+
+static struct platform_driver exynos_ufs_driver = {
+       .driver = {
+               .name = "exynos-ufs",
+               .owner = THIS_MODULE,
+               .pm = &exynos_ufs_dev_pm_ops,
+               .of_match_table = exynos_ufs_match,
+               .suppress_bind_attrs = true,
+       },
+       .probe = exynos_ufs_probe,
+       .remove = exynos_ufs_remove,
+       .shutdown = exynos_ufs_shutdown,
+};
+
+module_platform_driver(exynos_ufs_driver);
+MODULE_DESCRIPTION("Exynos Specific UFSHCI driver");
+MODULE_AUTHOR("Seungwon Jeon <tgih.jun@samsung.com>");
+MODULE_AUTHOR("Kiwoong Kim <kwmad.kim@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/ufs/ufs-exynos.h b/drivers/scsi/ufs/ufs-exynos.h
new file mode 100644 (file)
index 0000000..4f24951
--- /dev/null
@@ -0,0 +1,666 @@
+/*
+ * UFS Host Controller driver for Exynos specific extensions
+ *
+ * Copyright (C) 2013-2014 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef _UFS_EXYNOS_H_
+#define _UFS_EXYNOS_H_
+
+#include <linux/pm_qos.h>
+#include "ufs-cal-9810.h"
+
+#define UFS_VER_0004   4
+#define UFS_VER_0005   5
+
+/*
+ * Exynos's Vendor specific registers for UFSHCI
+ */
+#define HCI_TXPRDT_ENTRY_SIZE          0x00
+#define HCI_RXPRDT_ENTRY_SIZE          0x04
+#define HCI_TO_CNT_DIV_VAL              0x08
+#define HCI_1US_TO_CNT_VAL             0x0C
+ #define CNT_VAL_1US_MASK      0x3ff
+#define HCI_INVALID_UPIU_CTRL          0x10
+#define HCI_INVALID_UPIU_BADDR         0x14
+#define HCI_INVALID_UPIU_UBADDR                0x18
+#define HCI_INVALID_UTMR_OFFSET_ADDR   0x1C
+#define HCI_INVALID_UTR_OFFSET_ADDR    0x20
+#define HCI_INVALID_DIN_OFFSET_ADDR    0x24
+#define HCI_VENDOR_SPECIFIC_IS         0x38
+#define HCI_VENDOR_SPECIFIC_IE         0x3C
+#define HCI_UTRL_NEXUS_TYPE            0x40
+#define HCI_UTMRL_NEXUS_TYPE           0x44
+#define HCI_E2EFC_CTRL                 0x48
+#define HCI_SW_RST                     0x50
+ #define UFS_LINK_SW_RST       (1 << 0)
+ #define UFS_UNIPRO_SW_RST     (1 << 1)
+ #define UFS_SW_RST_MASK       (UFS_UNIPRO_SW_RST | UFS_LINK_SW_RST)
+#define HCI_LINK_VERSION               0x54
+#define HCI_IDLE_TIMER_CONFIG          0x58
+#define HCI_RX_UPIU_MATCH_ERROR_CODE   0x5C
+#define HCI_DATA_REORDER               0x60
+#define HCI_MAX_DOUT_DATA_SIZE         0x64
+#define HCI_UNIPRO_APB_CLK_CTRL                0x68
+#define HCI_AXIDMA_RWDATA_BURST_LEN    0x6C
+ #define BURST_LEN(x)                  ((x) << 27 | (x))
+ #define WLU_EN                                (1 << 31)
+ #define AXIDMA_RWDATA_BURST_LEN       (0xF)
+#define HCI_GPIO_OUT                   0x70
+#define HCI_WRITE_DMA_CTRL             0x74
+#define HCI_ERROR_EN_PA_LAYER          0x78
+#define HCI_ERROR_EN_DL_LAYER          0x7C
+#define HCI_ERROR_EN_N_LAYER           0x80
+#define HCI_ERROR_EN_T_LAYER           0x84
+#define HCI_ERROR_EN_DME_LAYER         0x88
+#define HCI_UFSHCI_V2P1_CTRL                   0X8C
+#define IA_TICK_SEL                            BIT(16)
+#define HCI_REQ_HOLD_EN                        0xAC
+
+#define HCI_CLKSTOP_CTRL               0xB0
+ #define REFCLKOUT_STOP                        BIT(4)
+ #define MPHY_APBCLK_STOP              BIT(3)
+ #define REFCLK_STOP                   BIT(2)
+ #define UNIPRO_MCLK_STOP              BIT(1)
+ #define UNIPRO_PCLK_STOP              BIT(0)
+ #define CLK_STOP_ALL          (REFCLKOUT_STOP |\
+                                       REFCLK_STOP |\
+                                       UNIPRO_MCLK_STOP |\
+                                       UNIPRO_PCLK_STOP)
+
+#define HCI_FORCE_HCS                  0xB4
+ #define REFCLKOUT_STOP_EN     BIT(11)
+ #define MPHY_APBCLK_STOP_EN   BIT(10)
+ #define UFSP_DRCG_EN          BIT(8)   //FMP
+ #define REFCLK_STOP_EN                BIT(7)
+ #define UNIPRO_PCLK_STOP_EN   BIT(6)
+ #define UNIPRO_MCLK_STOP_EN   BIT(5)
+ #define HCI_CORECLK_STOP_EN   BIT(4)
+ #define CLK_STOP_CTRL_EN_ALL  (UFSP_DRCG_EN |\
+                                       MPHY_APBCLK_STOP_EN |\
+                                       REFCLKOUT_STOP_EN |\
+                                       REFCLK_STOP_EN |\
+                                       UNIPRO_PCLK_STOP_EN |\
+                                       UNIPRO_MCLK_STOP_EN)
+
+#define HCI_FSM_MONITOR                        0xC0
+#define HCI_PRDT_HIT_RATIO             0xC4
+#define HCI_DMA0_MONITOR_STATE         0xC8
+#define HCI_DMA0_MONITOR_CNT           0xCC
+#define HCI_DMA1_MONITOR_STATE         0xD0
+#define HCI_DMA1_MONITOR_CNT           0xD4
+
+#define HCI_UFS_AXI_DMA_IF_CTRL                0xF8
+#define HCI_UFS_ACG_DISABLE            0xFC
+ #define HCI_UFS_ACG_DISABLE_EN                BIT(0)
+#define HCI_IOP_ACG_DISABLE            0x100
+ #define HCI_IOP_ACG_DISABLE_EN                BIT(0)
+#define HCI_MPHY_REFCLK_SEL            0x108
+ #define MPHY_REFCLK_SEL               BIT(0)
+#define HCI_SMU_ABORT_MATCH_INFO               0x10C
+#define HCI_DBR_DUPLICATION_INFO               0x120
+
+#define HCI_DBR_TIMER_CONFIG           0x140
+#define HCI_DBR_TIMER_ENABLE           0x144
+#define HCI_DBR_TIMER_STATUS           0x148
+
+#define HCI_UTRL_DBR_3_0_TIMER_EXPIRED_VALUE           0x150
+#define HCI_UTRL_DBR_7_4_TIMER_EXPIRED_VALUE           0x154
+#define HCI_UTRL_DBR_11_8_TIMER_EXPIRED_VALUE          0x158
+#define HCI_UTRL_DBR_15_12_TIMER_EXPIRED_VALUE         0x15C
+#define HCI_UTMRL_DBR_3_0_TIMER_EXPIRED_VALUE          0x160
+
+/* Device fatal error */
+#define DFES_ERR_EN    BIT(31)
+#define DFES_DEF_DL_ERRS       (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF |\
+                                UIC_DATA_LINK_LAYER_ERROR_PA_INIT)
+#define DFES_DEF_N_ERRS                (UIC_NETWORK_UNSUPPORTED_HEADER_TYPE |\
+                                UIC_NETWORK_BAD_DEVICEID_ENC |\
+                                UIC_NETWORK_LHDR_TRAP_PACKET_DROPPING)
+#define DFES_DEF_T_ERRS                (UIC_TRANSPORT_UNSUPPORTED_HEADER_TYPE |\
+                                UIC_TRANSPORT_UNKNOWN_CPORTID |\
+                                UIC_TRANSPORT_NO_CONNECTION_RX |\
+                                UIC_TRANSPORT_BAD_TC)
+
+/* TXPRDT defines */
+#define PRDT_PREFECT_EN                BIT(31)
+#define PRDT_SET_SIZE(x)       ((x) & 0x1F)
+
+enum {
+       UNIP_PA_LYR = 0,
+       UNIP_DL_LYR,
+       UNIP_N_LYR,
+       UNIP_T_LYR,
+       UNIP_DME_LYR,
+};
+
+/*
+ * UNIPRO registers
+ */
+#define UNIP_COMP_VERSION                      0x000
+#define UNIP_COMP_INFO                         0x004
+#define UNIP_COMP_RESET                                0x010
+
+#define UNIP_DME_POWERON_REQ                   0x7800
+#define UNIP_DME_POWERON_CNF_RESULT            0x7804
+#define UNIP_DME_POWEROFF_REQ                  0x7810
+#define UNIP_DME_POWEROFF_CNF_RESULT           0x7814
+#define UNIP_DME_RESET_REQ                     0x7820
+#define UNIP_DME_RESET_REQ_LEVEL               0x7824
+#define UNIP_DME_ENABLE_REQ                    0x7830
+#define UNIP_DME_ENABLE_CNF_RESULT             0x7834
+#define UNIP_DME_ENDPOINTRESET_REQ             0x7840
+#define UNIP_DME_ENDPOINTRESET_CNF_RESULT      0x7844
+#define UNIP_DME_LINKSTARTUP_REQ               0x7850
+#define UNIP_DME_LINKSTARTUP_CNF_RESULT                0x7854
+#define UNIP_DME_HIBERN8_ENTER_REQ             0x7860
+#define UNIP_DME_HIBERN8_ENTER_CNF_RESULT      0x7864
+#define UNIP_DME_HIBERN8_ENTER_IND_RESULT      0x7868
+#define UNIP_DME_HIBERN8_EXIT_REQ              0x7870
+#define UNIP_DME_HIBERN8_EXIT_CNF_RESULT       0x7874
+#define UNIP_DME_HIBERN8_EXIT_IND_RESULT       0x7878
+#define UNIP_DME_PWR_REQ                       0x7880
+#define UNIP_DME_PWR_REQ_POWERMODE             0x7884
+#define UNIP_DME_PWR_REQ_LOCALL2TIMER0                 0x7888
+#define UNIP_DME_PWR_REQ_LOCALL2TIMER1                 0x788C
+#define UNIP_DME_PWR_REQ_LOCALL2TIMER2                 0x7890
+#define UNIP_DME_PWR_REQ_REMOTEL2TIMER0                0x78B8
+#define UNIP_DME_PWR_REQ_REMOTEL2TIMER1                0x78BC
+#define UNIP_DME_PWR_REQ_REMOTEL2TIMER2                0x78C0
+#define UNIP_DME_PWR_CNF_RESULT                        0x78E8
+#define UNIP_DME_PWR_IND_RESULT                        0x78EC
+#define UNIP_DME_TEST_MODE_REQ                         0x7900
+#define UNIP_DME_TEST_MODE_CNF_RESULT          0x7904
+
+#define UNIP_DME_ERROR_IND_LAYER               0x0C0
+#define UNIP_DME_ERROR_IND_ERRCODE             0x0C4
+#define UNIP_DME_PACP_CNFBIT                   0x0C8
+#define UNIP_DME_DL_FRAME_IND                  0x0D0
+#define UNIP_DME_INTR_STATUS                   0x0E0
+#define UNIP_DME_INTR_ENABLE                   0x0E4
+
+#define UNIP_DME_GETSET_CONTROL                0x7A00
+#define UNIP_DME_GETSET_ADDR                   0x7A04
+#define UNIP_DME_GETSET_WDATA                  0x7A08
+#define UNIP_DME_GETSET_RDATA                  0x7A0C
+#define UNIP_DME_GETSET_RESULT                 0x7A10
+#define UNIP_DME_PEER_GETSET_CONTROL           0x7A20
+#define UNIP_DME_PEER_GETSET_ADDR              0x7A24
+#define UNIP_DME_PEER_GETSET_WDATA             0x7A28
+#define UNIP_DME_PEER_GETSET_RDATA             0x7A2C
+#define UNIP_DME_PEER_GETSET_RESULT            0x7A30
+
+#define UNIP_DME_INTR_STATUS_LSB                          0x7B00
+#define UNIP_DME_INTR_STATUS_MSB                  0x7B04
+#define UNIP_DME_INTR_ERROR_CODE                          0x7B20
+#define UNIP_DME_DISCARD_PORT_ID                  0x7B24
+#define UNIP_DME_DBG_OPTION_SUITE                         0x7C00
+#define UNIP_DME_DBG_CTRL_FSM                     0x7D00
+#define UNIP_DME_DBG_FLAG_STATUS                          0x7D14
+#define UNIP_DME_DBG_LINKCFG_FSM                  0x7D18
+
+#define UNIP_DME_INTR_ERROR_CODE               0x7B20
+#define UNIP_DME_DEEPSTALL_ENTER_REQ           0x7910
+#define UNIP_DME_DISCARD_CPORT_ID              0x7B24
+
+#define UNIP_DBG_FORCE_DME_CTRL_STATE          0x150
+#define UNIP_DBG_AUTO_DME_LINKSTARTUP          0x158
+#define UNIP_DBG_PA_CTRLSTATE                  0x15C
+#define UNIP_DBG_PA_TX_STATE                   0x160
+#define UNIP_DBG_BREAK_DME_CTRL_STATE          0x164
+#define UNIP_DBG_STEP_DME_CTRL_STATE           0x168
+#define UNIP_DBG_NEXT_DME_CTRL_STATE           0x16C
+
+/*
+ * UFS Protector registers
+ */
+#define UFSPRCTRL      0x000
+#define UFSPRSTAT      0x008
+#define UFSPRSECURITY  0x010
+ #define NSSMU         BIT(14)
+#define DESCTYPE(type)         ((type & 0x3) << 19)
+#define ARPROTPRDT(type)       ((type & 0x3) << 16)
+#define ARPROTDESC(type)       ((type & 0x3) << 9)
+#define ARPROTDATA(type)       ((type & 0x3) << 6)
+#define AWPROTDESC(type)       ((type & 0x3) << 3)
+#define AWPROTDATA(type)       ((type & 0x3))
+#define CFG_AXPROT(type)       (ARPROTPRDT(type) | ARPROTDESC(type) | \
+                               ARPROTDATA(type) | AWPROTDESC(type) | \
+                               AWPROTDATA(type))
+#define UFSPVERSION    0x01C
+#define UFSPRENCKEY0   0x020
+#define UFSPRENCKEY1   0x024
+#define UFSPRENCKEY2   0x028
+#define UFSPRENCKEY3   0x02C
+#define UFSPRENCKEY4   0x030
+#define UFSPRENCKEY5   0x034
+#define UFSPRENCKEY6   0x038
+#define UFSPRENCKEY7   0x03C
+#define UFSPRTWKEY0    0x040
+#define UFSPRTWKEY1    0x044
+#define UFSPRTWKEY2    0x048
+#define UFSPRTWKEY3    0x04C
+#define UFSPRTWKEY4    0x050
+#define UFSPRTWKEY5    0x054
+#define UFSPRTWKEY6    0x058
+#define UFSPRTWKEY7    0x05C
+#define UFSPWCTRL      0x100
+#define UFSPWSTAT      0x108
+#define UFSPWSECURITY  0x110
+#define UFSPWENCKEY0   0x120
+#define UFSPWENCKEY1   0x124
+#define UFSPWENCKEY2   0x128
+#define UFSPWENCKEY3   0x12C
+#define UFSPWENCKEY4   0x130
+#define UFSPWENCKEY5   0x134
+#define UFSPWENCKEY6   0x138
+#define UFSPWENCKEY7   0x13C
+#define UFSPWTWKEY0    0x140
+#define UFSPWTWKEY1    0x144
+#define UFSPWTWKEY2    0x148
+#define UFSPWTWKEY3    0x14C
+#define UFSPWTWKEY4    0x150
+#define UFSPWTWKEY5    0x154
+#define UFSPWTWKEY6    0x158
+#define UFSPWTWKEY7    0x15C
+#define UFSPSBEGIN0    0x200
+#define UFSPSEND0      0x204
+#define UFSPSLUN0      0x208
+#define UFSPSCTRL0     0x20C
+#define UFSPSBEGIN1    0x210
+#define UFSPSEND1      0x214
+#define UFSPSLUN1      0x218
+#define UFSPSCTRL1     0x21C
+#define UFSPSBEGIN2    0x220
+#define UFSPSEND2      0x224
+#define UFSPSLUN2      0x228
+#define UFSPSCTRL2     0x22C
+#define UFSPSBEGIN3    0x230
+#define UFSPSEND3      0x234
+#define UFSPSLUN3      0x238
+#define UFSPSCTRL3     0x23C
+#define UFSPSBEGIN4    0x240
+#define UFSPSEND4      0x244
+#define UFSPSLUN4      0x248
+#define UFSPSCTRL4     0x24C
+#define UFSPSBEGIN5    0x250
+#define UFSPSEND5      0x254
+#define UFSPSLUN5      0x258
+#define UFSPSCTRL5     0x25C
+#define UFSPSBEGIN6    0x260
+#define UFSPSEND6      0x264
+#define UFSPSLUN6      0x268
+#define UFSPSCTRL6     0x26C
+#define UFSPSBEGIN7    0x270
+#define UFSPSEND7      0x274
+#define UFSPSLUN7      0x278
+#define UFSPSCTRL7     0x27C
+
+/*
+ * MIBs for PA debug registers
+ */
+#define PA_DBG_CLK_PERIOD              0x9514
+#define PA_DBG_RXPHY_CFGUPDT           0x9519
+#define PA_DBG_MODE                    0x9529
+#define PA_DBG_AUTOMODE_THLD           0x9536
+#define PA_DBG_OV_TM                   0x200
+#define PA_DBG_RESUME_HIBERN8          0x9550
+#define PA_DBG_OPTION_SUITE            0x9564
+
+/*
+ * MIBs for Transport Layer debug registers
+ */
+#define T_DBG_SKIP_INIT_HIBERN8_EXIT   0xc001
+
+/*
+ * Exynos MPHY attributes
+ */
+#define TX_LINERESET_N_VAL             0x0277
+ #define TX_LINERESET_N(v)     (((v) >> 10) & 0xff)
+#define TX_LINERESET_P_VAL             0x027D
+ #define TX_LINERESET_P(v)     (((v) >> 12) & 0xff)
+#define TX_OV_SLEEP_CNT_TIMER          0x028E
+ #define TX_OV_H8_ENTER_EN             (1 << 7)
+ #define TX_OV_SLEEP_CNT(v)    (((v) >> 5) & 0x7f)
+
+#define TX_HIGH_Z_CNT_11_08            0x028c
+ #define TX_HIGH_Z_CNT_H(v)    (((v) >> 8) & 0xf)
+#define TX_HIGH_Z_CNT_07_00            0x028d
+ #define TX_HIGH_Z_CNT_L(v)    ((v) & 0xff)
+#define TX_BASE_NVAL_07_00             0x0293
+ #define TX_BASE_NVAL_L(v)     ((v) & 0xff)
+#define TX_BASE_NVAL_15_08             0x0294
+ #define TX_BASE_NVAL_H(v)     (((v) >> 8) & 0xff)
+#define TX_GRAN_NVAL_07_00             0x0295
+ #define TX_GRAN_NVAL_L(v)     ((v) & 0xff)
+#define TX_GRAN_NVAL_10_08             0x0296
+ #define TX_GRAN_NVAL_H(v)     (((v) >> 8) & 0x3)
+
+#define RX_FILLER_ENABLE               0x0316
+ #define RX_FILLER_EN          (1 << 1)
+#define RX_LCC_IGNORE                  0x0318
+#define RX_LINERESET_VAL               0x0317
+ #define RX_LINERESET(v)       (((v) >> 12) & 0xff)
+#define RX_SYNC_MASK_LENGTH            0x0321
+#define RX_HIBERN8_WAIT_VAL_BIT_20_16  0x0331
+#define RX_HIBERN8_WAIT_VAL_BIT_15_08  0x0332
+#define RX_HIBERN8_WAIT_VAL_BIT_07_00  0x0333
+
+#define RX_OV_SLEEP_CNT_TIMER          0x0340
+ #define RX_OV_SLEEP_CNT(v)    (((v) >> 6) & 0x1f)
+#define RX_OV_STALL_CNT_TIMER          0x0341
+ #define RX_OV_STALL_CNT(v)    (((v) >> 4) & 0xff)
+#define RX_BASE_NVAL_07_00             0x0355
+ #define RX_BASE_NVAL_L(v)     ((v) & 0xff)
+#define RX_BASE_NVAL_15_08             0x0354
+ #define RX_BASE_NVAL_H(v)     (((v) >> 8) & 0xff)
+#define RX_GRAN_NVAL_07_00             0x0353
+ #define RX_GRAN_NVAL_L(v)     ((v) & 0xff)
+#define RX_GRAN_NVAL_10_08             0x0352
+ #define RX_GRAN_NVAL_H(v)     (((v) >> 8) & 0x3)
+
+#define CMN_PWM_CMN_CTRL               0x0402
+ #define PWM_CMN_CTRL_MASK     0x3
+#define CMN_REFCLK_PLL_LOCK            0x0406
+#define CMN_REFCLK_STREN               0x044C
+#define CMN_REFCLK_OUT                 0x044E
+#define CMN_REFCLK_SEL_PLL             0x044F
+
+#define PHY_PMA_COMN_ADDR(reg)         (reg)
+#define PHY_PMA_TRSV_ADDR(reg, lane)   ((reg) + (0x140 * (lane)))
+
+/*
+ * Driver specific definitions
+ */
+
+enum {
+       PHY_CFG_NONE = 0,
+       PHY_PCS_COMN,
+       PHY_PCS_RXTX,
+       PHY_PMA_COMN,
+       PHY_PMA_TRSV,
+       PHY_PLL_WAIT,
+       PHY_CDR_WAIT,
+       UNIPRO_STD_MIB,
+       UNIPRO_DBG_MIB,
+       UNIPRO_DBG_APB,
+
+       // Since exynos8895
+       PHY_PCS_RX,
+       PHY_PCS_TX,
+       PHY_PCS_RX_PRD,
+       PHY_PCS_TX_PRD,
+       UNIPRO_DBG_PRD,
+       PHY_PMA_TRSV_LANE1_SQ_OFF,
+       COMMON_WAIT,
+};
+
+enum {
+       TX_LANE_0 = 0,
+       TX_LANE_1 = 1,
+       TX_LANE_2 = 2,
+       TX_LANE_3 = 3,
+       RX_LANE_0 = 4,
+       RX_LANE_1 = 5,
+       RX_LANE_2 = 6,
+       RX_LANE_3 = 7,
+};
+
+enum {
+       __PMD_PWM_G1_L1,
+       __PMD_PWM_G1_L2,
+       __PMD_PWM_G2_L1,
+       __PMD_PWM_G2_L2,
+       __PMD_PWM_G3_L1,
+       __PMD_PWM_G3_L2,
+       __PMD_PWM_G4_L1,
+       __PMD_PWM_G4_L2,
+       __PMD_PWM_G5_L1,
+       __PMD_PWM_G5_L2,
+       __PMD_HS_G1_L1,
+       __PMD_HS_G1_L2,
+       __PMD_HS_G2_L1,
+       __PMD_HS_G2_L2,
+       __PMD_HS_G3_L1,
+       __PMD_HS_G3_L2,
+};
+
+#define PMD_PWM_G1_L1  (1U << __PMD_PWM_G1_L1)
+#define PMD_PWM_G1_L2  (1U << __PMD_PWM_G1_L2)
+#define PMD_PWM_G2_L1  (1U << __PMD_PWM_G2_L1)
+#define PMD_PWM_G2_L2  (1U << __PMD_PWM_G2_L2)
+#define PMD_PWM_G3_L1  (1U << __PMD_PWM_G3_L1)
+#define PMD_PWM_G3_L2  (1U << __PMD_PWM_G3_L2)
+#define PMD_PWM_G4_L1  (1U << __PMD_PWM_G4_L1)
+#define PMD_PWM_G4_L2  (1U << __PMD_PWM_G4_L2)
+#define PMD_PWM_G5_L1  (1U << __PMD_PWM_G5_L1)
+#define PMD_PWM_G5_L2  (1U << __PMD_PWM_G5_L2)
+#define PMD_HS_G1_L1   (1U << __PMD_HS_G1_L1)
+#define PMD_HS_G1_L2   (1U << __PMD_HS_G1_L2)
+#define PMD_HS_G2_L1   (1U << __PMD_HS_G2_L1)
+#define PMD_HS_G2_L2   (1U << __PMD_HS_G2_L2)
+#define PMD_HS_G3_L1   (1U << __PMD_HS_G3_L1)
+#define PMD_HS_G3_L2   (1U << __PMD_HS_G3_L2)
+
+#define PMD_ALL                (PMD_HS_G3_L2 - 1)
+#define PMD_PWM                (PMD_PWM_G4_L2 - 1)
+#define PMD_HS         (PMD_ALL ^ PMD_PWM)
+
+struct ufs_phy_cfg {
+       u32 addr;
+       u32 val;
+       u32 flg;
+       u32 lyr;
+};
+
+struct exynos_ufs_soc {
+       struct ufs_phy_cfg *tbl_phy_init;
+       struct ufs_phy_cfg *tbl_post_phy_init;
+       struct ufs_phy_cfg *tbl_calib_of_pwm;
+       struct ufs_phy_cfg *tbl_calib_of_hs_rate_a;
+       struct ufs_phy_cfg *tbl_calib_of_hs_rate_b;
+       struct ufs_phy_cfg *tbl_post_calib_of_pwm;
+       struct ufs_phy_cfg *tbl_post_calib_of_hs_rate_a;
+       struct ufs_phy_cfg *tbl_post_calib_of_hs_rate_b;
+       struct ufs_phy_cfg *tbl_lpa_restore;
+       struct ufs_phy_cfg *tbl_pre_clk_off;
+       struct ufs_phy_cfg *tbl_post_clk_on;
+       struct ufs_phy_cfg *tbl_lane1_sq_off;
+};
+
+struct exynos_ufs_phy {
+       void __iomem *reg_pma;
+       void __iomem *reg_pmu;
+       struct exynos_ufs_soc *soc;
+};
+
+#define NUM_OF_SYSREG 1
+struct exynos_ufs_sys {
+       void __iomem *reg_sys[NUM_OF_SYSREG];
+       u32 mask[NUM_OF_SYSREG];
+       u32 bits[NUM_OF_SYSREG];
+};
+
+struct exynos_ufs_clk_info {
+       struct list_head list;
+       struct clk *clk;
+       const char *name;
+       unsigned long freq;
+};
+
+struct exynos_ufs_misc_log {
+       struct list_head clk_list_head;
+       bool isolation;
+};
+
+struct exynos_ufs_sfr_log {
+       const char* name;
+       const u32 offset;
+#define LOG_STD_HCI_SFR                0xFFFFFFF0
+#define LOG_VS_HCI_SFR         0xFFFFFFF1
+#define LOG_FMP_SFR            0xFFFFFFF2
+#define LOG_UNIPRO_SFR         0xFFFFFFF3
+#define LOG_PMA_SFR            0xFFFFFFF4
+       u32 val;
+};
+
+struct exynos_ufs_attr_log {
+       const u32 offset;
+       u32 res;
+       u32 val;
+};
+
+struct exynos_ufs_debug {
+       struct exynos_ufs_sfr_log* std_sfr;
+       struct exynos_ufs_sfr_log* sfr;
+       struct exynos_ufs_attr_log* attr;
+       struct exynos_ufs_misc_log misc;
+};
+
+struct exynos_smu_data {
+       struct exynos_smu_variant_ops *vops;
+       struct platform_device *pdev;
+};
+
+struct exynos_fmp_data {
+       struct exynos_fmp_variant_ops *vops;
+       struct platform_device *pdev;
+};
+
+struct exynos_ufs {
+       struct device *dev;
+       struct ufs_hba *hba;
+
+       void __iomem *reg_hci;
+       void __iomem *reg_unipro;
+       void __iomem *reg_ufsp;
+
+       struct clk *clk_hci;
+       struct clk *pclk;
+       struct clk *clk_unipro;
+       struct clk *clk_refclk_1;
+       struct clk *clk_refclk_2;
+       struct clk *clk_phy_symb[4];
+       u32 mclk_rate;
+       u32 pwm_freq;
+
+       int num_rx_lanes;
+       int num_tx_lanes;
+
+       struct exynos_ufs_phy phy;
+       struct exynos_ufs_sys sys;
+       struct uic_pwr_mode req_pmd_parm;
+       struct uic_pwr_mode act_pmd_parm;
+
+       struct exynos_smu_data smu;
+       struct exynos_fmp_data fmp;
+
+       u32 rx_min_actv_time_cap;
+       u32 rx_hibern8_time_cap;
+       u32 tx_hibern8_time_cap;
+
+       u32 opts;
+#define EXYNOS_UFS_OPTS_SET_LINE_INIT_PREP_LEN BIT(1)
+
+       /* for miscellaneous control */
+       unsigned long misc_flags;
+#define EXYNOS_UFS_MISC_TOGGLE_LOG     BIT(0)
+
+       struct exynos_ufs_debug debug;
+
+       /* Support system power mode */
+       int idle_ip_index;
+
+       u32 hw_rev;
+
+       struct pm_qos_request   pm_qos_int;
+       s32                     pm_qos_int_value;
+       struct pm_qos_request   pm_qos_fsys0;
+       s32                     pm_qos_fsys0_value;
+       bool lane1_poweroff;
+       struct ufs_cal_param    *cal_param;
+};
+
+static inline struct exynos_ufs *to_exynos_ufs(struct ufs_hba *hba)
+{
+       return dev_get_platdata(hba->dev);
+}
+
+#ifndef __EXYNOS_UFS_MMIO_FUNC__
+#define __EXYNOS_UFS_MMIO_FUNC__
+#define EXYNOS_UFS_MMIO_FUNC(name)                                             \
+static inline void name##_writel(struct exynos_ufs *ufs, u32 val, u32 reg)     \
+{                                                                              \
+       writel(val, ufs->reg_##name + reg);                                     \
+}                                                                              \
+                                                                               \
+static inline u32 name##_readl(struct exynos_ufs *ufs, u32 reg)                        \
+{                                                                              \
+       return readl(ufs->reg_##name + reg);                                    \
+}
+
+EXYNOS_UFS_MMIO_FUNC(hci);
+EXYNOS_UFS_MMIO_FUNC(unipro);
+EXYNOS_UFS_MMIO_FUNC(ufsp);
+
+static inline void phy_pma_writel(struct exynos_ufs *ufs, u32 val, u32 reg)
+{
+       u32 reg1 = hci_readl(ufs, HCI_CLKSTOP_CTRL);
+
+       hci_writel(ufs, reg1 & ~MPHY_APBCLK_STOP, HCI_CLKSTOP_CTRL);
+       writel(val, ufs->phy.reg_pma + reg);
+       hci_writel(ufs, reg1 | MPHY_APBCLK_STOP, HCI_CLKSTOP_CTRL);
+}
+
+static inline u32 phy_pma_readl(struct exynos_ufs *ufs, u32 reg)
+{
+       u32 reg1 = hci_readl(ufs, HCI_CLKSTOP_CTRL);
+
+       hci_writel(ufs, reg1 & ~MPHY_APBCLK_STOP, HCI_CLKSTOP_CTRL);
+       reg = readl(ufs->phy.reg_pma + reg);
+       hci_writel(ufs, reg1 | MPHY_APBCLK_STOP, HCI_CLKSTOP_CTRL);
+
+       return reg;
+}
+#endif
+
+/* Structure for ufs cmd logging */
+#define MAX_CMD_LOGS    128
+
+struct ufs_cmd_logging_category {
+       unsigned char cmd_opcode;
+       unsigned int tag;
+       unsigned long lba;
+       unsigned int sct;
+       int retries;
+       u64     start_time;
+       u64     end_time;
+       unsigned long outstanding_reqs;
+
+};
+
+struct ufs_cmd_info {
+       int     first;
+       int     last;
+       struct ufs_cmd_logging_category *addr_per_tag[16];
+       struct ufs_cmd_logging_category  data[MAX_CMD_LOGS];
+
+};
+
+extern void exynos_ufs_get_uic_info(struct ufs_hba *hba);
+extern void exynos_ufs_dump_uic_info(struct ufs_hba *hba);
+extern int exynos_ufs_init_dbg(struct ufs_hba *hba);
+extern void exynos_ufs_show_uic_info(struct ufs_hba *hba);
+extern void exynos_ufs_cmd_log_start(struct ufs_hba *hba, struct scsi_cmnd *cmd);
+extern void exynos_ufs_cmd_log_end(struct ufs_hba *hba, int tag);
+
+#ifndef __EXYNOS_UFS_VS_DEBUG__
+#define __EXYNOS_UFS_VS_DEBUG__
+#endif
+
+#endif /* _UFS_EXYNOS_H_ */