linux/drivers/phy/samsung/phy-samsung-ufs.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * UFS PHY driver for Samsung EXYNOS SoC
   4 *
   5 * Copyright (C) 2020 Samsung Electronics Co., Ltd.
   6 * Author: Seungwon Jeon <essuuj@gmail.com>
   7 * Author: Alim Akhtar <alim.akhtar@samsung.com>
   8 *
   9 */
  10#ifndef _PHY_SAMSUNG_UFS_
  11#define _PHY_SAMSUNG_UFS_
  12
  13#include <linux/phy/phy.h>
  14#include <linux/regmap.h>
  15
  16#define PHY_COMN_BLK    1
  17#define PHY_TRSV_BLK    2
  18#define END_UFS_PHY_CFG { 0 }
  19#define PHY_TRSV_CH_OFFSET      0x30
  20#define PHY_APB_ADDR(off)       ((off) << 2)
  21
  22#define PHY_COMN_REG_CFG(o, v, d) {     \
  23        .off_0 = PHY_APB_ADDR((o)),     \
  24        .off_1 = 0,             \
  25        .val = (v),             \
  26        .desc = (d),            \
  27        .id = PHY_COMN_BLK,     \
  28}
  29
  30#define PHY_TRSV_REG_CFG_OFFSET(o, v, d, c) {   \
  31        .off_0 = PHY_APB_ADDR((o)),     \
  32        .off_1 = PHY_APB_ADDR((o) + (c)),       \
  33        .val = (v),             \
  34        .desc = (d),            \
  35        .id = PHY_TRSV_BLK,     \
  36}
  37
  38#define PHY_TRSV_REG_CFG(o, v, d)       \
  39        PHY_TRSV_REG_CFG_OFFSET(o, v, d, PHY_TRSV_CH_OFFSET)
  40
  41/* UFS PHY registers */
  42#define PHY_PLL_LOCK_STATUS     0x1e
  43#define PHY_CDR_LOCK_STATUS     0x5e
  44
  45#define PHY_PLL_LOCK_BIT        BIT(5)
  46#define PHY_CDR_LOCK_BIT        BIT(4)
  47
  48/* description for PHY calibration */
  49enum {
  50        /* applicable to any */
  51        PWR_DESC_ANY    = 0,
  52        /* mode */
  53        PWR_DESC_PWM    = 1,
  54        PWR_DESC_HS     = 2,
  55        /* series */
  56        PWR_DESC_SER_A  = 1,
  57        PWR_DESC_SER_B  = 2,
  58        /* gear */
  59        PWR_DESC_G1     = 1,
  60        PWR_DESC_G2     = 2,
  61        PWR_DESC_G3     = 3,
  62        /* field mask */
  63        MD_MASK         = 0x3,
  64        SR_MASK         = 0x3,
  65        GR_MASK         = 0x7,
  66};
  67
  68#define PWR_MODE_HS_G1_ANY      PWR_MODE_HS(PWR_DESC_G1, PWR_DESC_ANY)
  69#define PWR_MODE_HS_G1_SER_A    PWR_MODE_HS(PWR_DESC_G1, PWR_DESC_SER_A)
  70#define PWR_MODE_HS_G1_SER_B    PWR_MODE_HS(PWR_DESC_G1, PWR_DESC_SER_B)
  71#define PWR_MODE_HS_G2_ANY      PWR_MODE_HS(PWR_DESC_G2, PWR_DESC_ANY)
  72#define PWR_MODE_HS_G2_SER_A    PWR_MODE_HS(PWR_DESC_G2, PWR_DESC_SER_A)
  73#define PWR_MODE_HS_G2_SER_B    PWR_MODE_HS(PWR_DESC_G2, PWR_DESC_SER_B)
  74#define PWR_MODE_HS_G3_ANY      PWR_MODE_HS(PWR_DESC_G3, PWR_DESC_ANY)
  75#define PWR_MODE_HS_G3_SER_A    PWR_MODE_HS(PWR_DESC_G3, PWR_DESC_SER_A)
  76#define PWR_MODE_HS_G3_SER_B    PWR_MODE_HS(PWR_DESC_G3, PWR_DESC_SER_B)
  77#define PWR_MODE(g, s, m)       ((((g) & GR_MASK) << 4) |\
  78                                 (((s) & SR_MASK) << 2) | ((m) & MD_MASK))
  79#define PWR_MODE_PWM_ANY        PWR_MODE(PWR_DESC_ANY,\
  80                                         PWR_DESC_ANY, PWR_DESC_PWM)
  81#define PWR_MODE_HS(g, s)       ((((g) & GR_MASK) << 4) |\
  82                                 (((s) & SR_MASK) << 2) | PWR_DESC_HS)
  83#define PWR_MODE_HS_ANY         PWR_MODE(PWR_DESC_ANY,\
  84                                         PWR_DESC_ANY, PWR_DESC_HS)
  85#define PWR_MODE_ANY            PWR_MODE(PWR_DESC_ANY,\
  86                                         PWR_DESC_ANY, PWR_DESC_ANY)
  87/* PHY calibration point/state */
  88enum {
  89        CFG_PRE_INIT,
  90        CFG_POST_INIT,
  91        CFG_PRE_PWR_HS,
  92        CFG_POST_PWR_HS,
  93        CFG_TAG_MAX,
  94};
  95
  96struct samsung_ufs_phy_cfg {
  97        u32 off_0;
  98        u32 off_1;
  99        u32 val;
 100        u8 desc;
 101        u8 id;
 102};
 103
 104struct samsung_ufs_phy_drvdata {
 105        const struct samsung_ufs_phy_cfg **cfg;
 106        struct pmu_isol {
 107                u32 offset;
 108                u32 mask;
 109                u32 en;
 110        } isol;
 111        bool has_symbol_clk;
 112};
 113
 114struct samsung_ufs_phy {
 115        struct device *dev;
 116        void __iomem *reg_pma;
 117        struct regmap *reg_pmu;
 118        struct clk *ref_clk;
 119        struct clk *ref_clk_parent;
 120        struct clk *tx0_symbol_clk;
 121        struct clk *rx0_symbol_clk;
 122        struct clk *rx1_symbol_clk;
 123        const struct samsung_ufs_phy_drvdata *drvdata;
 124        struct samsung_ufs_phy_cfg **cfg;
 125        const struct pmu_isol *isol;
 126        u8 lane_cnt;
 127        int ufs_phy_state;
 128        enum phy_mode mode;
 129};
 130
 131static inline struct samsung_ufs_phy *get_samsung_ufs_phy(struct phy *phy)
 132{
 133        return (struct samsung_ufs_phy *)phy_get_drvdata(phy);
 134}
 135
 136static inline void samsung_ufs_phy_ctrl_isol(
 137                struct samsung_ufs_phy *phy, u32 isol)
 138{
 139        regmap_update_bits(phy->reg_pmu, phy->isol->offset,
 140                           phy->isol->mask, isol ? 0 : phy->isol->en);
 141}
 142
 143extern const struct samsung_ufs_phy_drvdata exynos7_ufs_phy;
 144extern const struct samsung_ufs_phy_drvdata exynosautov9_ufs_phy;
 145
 146#endif /* _PHY_SAMSUNG_UFS_ */
 147