0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _PHY_SAMSUNG_UFS_
0011 #define _PHY_SAMSUNG_UFS_
0012
0013 #include <linux/phy/phy.h>
0014 #include <linux/regmap.h>
0015
0016 #define PHY_COMN_BLK 1
0017 #define PHY_TRSV_BLK 2
0018 #define END_UFS_PHY_CFG { 0 }
0019 #define PHY_TRSV_CH_OFFSET 0x30
0020 #define PHY_APB_ADDR(off) ((off) << 2)
0021
0022 #define PHY_COMN_REG_CFG(o, v, d) { \
0023 .off_0 = PHY_APB_ADDR((o)), \
0024 .off_1 = 0, \
0025 .val = (v), \
0026 .desc = (d), \
0027 .id = PHY_COMN_BLK, \
0028 }
0029
0030 #define PHY_TRSV_REG_CFG_OFFSET(o, v, d, c) { \
0031 .off_0 = PHY_APB_ADDR((o)), \
0032 .off_1 = PHY_APB_ADDR((o) + (c)), \
0033 .val = (v), \
0034 .desc = (d), \
0035 .id = PHY_TRSV_BLK, \
0036 }
0037
0038 #define PHY_TRSV_REG_CFG(o, v, d) \
0039 PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_TRSV_CH_OFFSET)
0040
0041
0042 #define PHY_PLL_LOCK_STATUS 0x1e
0043
0044 #define PHY_PLL_LOCK_BIT BIT(5)
0045 #define PHY_CDR_LOCK_BIT BIT(4)
0046
0047
0048 enum {
0049
0050 PWR_DESC_ANY = 0,
0051
0052 PWR_DESC_PWM = 1,
0053 PWR_DESC_HS = 2,
0054
0055 PWR_DESC_SER_A = 1,
0056 PWR_DESC_SER_B = 2,
0057
0058 PWR_DESC_G1 = 1,
0059 PWR_DESC_G2 = 2,
0060 PWR_DESC_G3 = 3,
0061
0062 MD_MASK = 0x3,
0063 SR_MASK = 0x3,
0064 GR_MASK = 0x7,
0065 };
0066
0067 #define PWR_MODE_HS_G1_ANY PWR_MODE_HS(PWR_DESC_G1, PWR_DESC_ANY)
0068 #define PWR_MODE_HS_G1_SER_A PWR_MODE_HS(PWR_DESC_G1, PWR_DESC_SER_A)
0069 #define PWR_MODE_HS_G1_SER_B PWR_MODE_HS(PWR_DESC_G1, PWR_DESC_SER_B)
0070 #define PWR_MODE_HS_G2_ANY PWR_MODE_HS(PWR_DESC_G2, PWR_DESC_ANY)
0071 #define PWR_MODE_HS_G2_SER_A PWR_MODE_HS(PWR_DESC_G2, PWR_DESC_SER_A)
0072 #define PWR_MODE_HS_G2_SER_B PWR_MODE_HS(PWR_DESC_G2, PWR_DESC_SER_B)
0073 #define PWR_MODE_HS_G3_ANY PWR_MODE_HS(PWR_DESC_G3, PWR_DESC_ANY)
0074 #define PWR_MODE_HS_G3_SER_A PWR_MODE_HS(PWR_DESC_G3, PWR_DESC_SER_A)
0075 #define PWR_MODE_HS_G3_SER_B PWR_MODE_HS(PWR_DESC_G3, PWR_DESC_SER_B)
0076 #define PWR_MODE(g, s, m) ((((g) & GR_MASK) << 4) |\
0077 (((s) & SR_MASK) << 2) | ((m) & MD_MASK))
0078 #define PWR_MODE_PWM_ANY PWR_MODE(PWR_DESC_ANY,\
0079 PWR_DESC_ANY, PWR_DESC_PWM)
0080 #define PWR_MODE_HS(g, s) ((((g) & GR_MASK) << 4) |\
0081 (((s) & SR_MASK) << 2) | PWR_DESC_HS)
0082 #define PWR_MODE_HS_ANY PWR_MODE(PWR_DESC_ANY,\
0083 PWR_DESC_ANY, PWR_DESC_HS)
0084 #define PWR_MODE_ANY PWR_MODE(PWR_DESC_ANY,\
0085 PWR_DESC_ANY, PWR_DESC_ANY)
0086
0087 enum {
0088 CFG_PRE_INIT,
0089 CFG_POST_INIT,
0090 CFG_PRE_PWR_HS,
0091 CFG_POST_PWR_HS,
0092 CFG_TAG_MAX,
0093 };
0094
0095 struct samsung_ufs_phy_cfg {
0096 u32 off_0;
0097 u32 off_1;
0098 u32 val;
0099 u8 desc;
0100 u8 id;
0101 };
0102
0103 struct samsung_ufs_phy_pmu_isol {
0104 u32 offset;
0105 u32 mask;
0106 u32 en;
0107 };
0108
0109 struct samsung_ufs_phy_drvdata {
0110 const struct samsung_ufs_phy_cfg **cfgs;
0111 struct samsung_ufs_phy_pmu_isol isol;
0112 const char * const *clk_list;
0113 int num_clks;
0114 u32 cdr_lock_status_offset;
0115 };
0116
0117 struct samsung_ufs_phy {
0118 struct device *dev;
0119 void __iomem *reg_pma;
0120 struct regmap *reg_pmu;
0121 struct clk_bulk_data *clks;
0122 const struct samsung_ufs_phy_drvdata *drvdata;
0123 const struct samsung_ufs_phy_cfg * const *cfgs;
0124 struct samsung_ufs_phy_pmu_isol isol;
0125 u8 lane_cnt;
0126 int ufs_phy_state;
0127 enum phy_mode mode;
0128 };
0129
0130 static inline struct samsung_ufs_phy *get_samsung_ufs_phy(struct phy *phy)
0131 {
0132 return (struct samsung_ufs_phy *)phy_get_drvdata(phy);
0133 }
0134
0135 static inline void samsung_ufs_phy_ctrl_isol(
0136 struct samsung_ufs_phy *phy, u32 isol)
0137 {
0138 regmap_update_bits(phy->reg_pmu, phy->isol.offset,
0139 phy->isol.mask, isol ? 0 : phy->isol.en);
0140 }
0141
0142 extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy;
0143 extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy;
0144 extern const struct samsung_ufs_phy_drvdata fsd_ufs_phy;
0145
0146 #endif