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