blob: 16e95175bb29f0a62f7bb747586220647887ae12 [file] [log] [blame]
Bhupesh Sharmafff404f2023-08-14 11:29:25 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2023 Bhupesh Sharma <bhupesh.sharma@linaro.org>
4 *
5 * Based on Linux driver
6 */
7
8#include <clk.h>
9#include <clk-uclass.h>
10#include <common.h>
11#include <dm.h>
12#include <dm/device_compat.h>
13#include <dm/devres.h>
14#include <generic-phy.h>
15#include <malloc.h>
16#include <reset.h>
17
18#include <asm/io.h>
19#include <linux/bitops.h>
20#include <linux/clk-provider.h>
21#include <linux/delay.h>
22#include <linux/iopoll.h>
23#include <linux/ioport.h>
24
25#include <dt-bindings/clock/qcom,gcc-sm6115.h>
26
27#include "phy-qcom-qmp.h"
28#include "phy-qcom-qmp-pcs-ufs-v2.h"
29#include "phy-qcom-qmp-pcs-ufs-v3.h"
30#include "phy-qcom-qmp-pcs-ufs-v4.h"
31#include "phy-qcom-qmp-pcs-ufs-v5.h"
32#include "phy-qcom-qmp-pcs-ufs-v6.h"
33
34#include "phy-qcom-qmp-qserdes-com-v4.h"
35#include "phy-qcom-qmp-qserdes-txrx-v4.h"
36#include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h"
37
38/* QPHY_SW_RESET bit */
39#define SW_RESET BIT(0)
40/* QPHY_POWER_DOWN_CONTROL */
41#define SW_PWRDN BIT(0)
42/* QPHY_START_CONTROL bits */
43#define SERDES_START BIT(0)
44#define PCS_START BIT(1)
45/* QPHY_PCS_READY_STATUS bit */
46#define PCS_READY BIT(0)
47
48#define PHY_INIT_COMPLETE_TIMEOUT (200 * 10000)
49
50struct qmp_ufs_init_tbl {
51 unsigned int offset;
52 unsigned int val;
53 /*
54 * mask of lanes for which this register is written
55 * for cases when second lane needs different values
56 */
57 u8 lane_mask;
58};
59
60#define QMP_PHY_INIT_CFG(o, v) \
61 { \
62 .offset = o, \
63 .val = v, \
64 .lane_mask = 0xff, \
65 }
66
67#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
68 { \
69 .offset = o, \
70 .val = v, \
71 .lane_mask = l, \
72 }
73
74enum ufs_hs_gear_tag {
75 UFS_HS_DONT_CHANGE, /* Don't change Gear */
76 UFS_HS_G1, /* HS Gear 1 (default for reset) */
77 UFS_HS_G2, /* HS Gear 2 */
78 UFS_HS_G3, /* HS Gear 3 */
79 UFS_HS_G4, /* HS Gear 4 */
80 UFS_HS_G5 /* HS Gear 5 */
81};
82
83/* set of registers with offsets different per-PHY */
84enum qphy_reg_layout {
85 /* PCS registers */
86 QPHY_SW_RESET,
87 QPHY_START_CTRL,
88 QPHY_PCS_READY_STATUS,
89 QPHY_PCS_POWER_DOWN_CONTROL,
90 /* Keep last to ensure regs_layout arrays are properly initialized */
91 QPHY_LAYOUT_SIZE
92};
93
94static const unsigned int ufsphy_v2_regs_layout[QPHY_LAYOUT_SIZE] = {
95 [QPHY_START_CTRL] = QPHY_V2_PCS_UFS_PHY_START,
96 [QPHY_PCS_READY_STATUS] = QPHY_V2_PCS_UFS_READY_STATUS,
97 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V2_PCS_UFS_POWER_DOWN_CONTROL,
98};
99
100static const unsigned int ufsphy_v3_regs_layout[QPHY_LAYOUT_SIZE] = {
101 [QPHY_START_CTRL] = QPHY_V3_PCS_UFS_PHY_START,
102 [QPHY_PCS_READY_STATUS] = QPHY_V3_PCS_UFS_READY_STATUS,
103 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_UFS_POWER_DOWN_CONTROL,
104};
105
106static const unsigned int ufsphy_v4_regs_layout[QPHY_LAYOUT_SIZE] = {
107 [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START,
108 [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS,
109 [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET,
110 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL,
111};
112
113static const struct qmp_ufs_init_tbl sdm845_ufsphy_serdes[] = {
114 QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
115 QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
116 QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
117 QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
118 QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
119 QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5),
120 QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20),
121 QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
122 QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00),
123 QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01),
124 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00),
125 QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
126 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04),
127 QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05),
128 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff),
129 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00),
130 QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
131 QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
132 QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
133 QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
134 QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
135 QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
136 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda),
137 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
138 QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff),
139 QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c),
140 QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98),
141 QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06),
142 QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16),
143 QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36),
144 QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f),
145 QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
146 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1),
147 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00),
148 QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32),
149 QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f),
150};
151
152static const struct qmp_ufs_init_tbl sdm845_ufsphy_hs_b_serdes[] = {
153 QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44),
154};
155
156static const struct qmp_ufs_init_tbl sdm845_ufsphy_tx[] = {
157 QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06),
158 QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04),
159 QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07),
160};
161
162static const struct qmp_ufs_init_tbl sdm845_ufsphy_rx[] = {
163 QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24),
164 QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f),
165 QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
166 QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40),
167 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
168 QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b),
169 QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
170 QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
171 QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b),
172 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
173 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
174 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04),
175 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
176 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81),
177 QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
178 QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59),
179};
180
181static const struct qmp_ufs_init_tbl sdm845_ufsphy_pcs[] = {
182 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_SIGDET_CTRL2, 0x6e),
183 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a),
184 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
185 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_SYM_RESYNC_CTRL, 0x03),
186 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
187 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_SIGDET_CTRL1, 0x0f),
188 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_RX_MIN_HIBERN8_TIME, 0x9a),
189 QMP_PHY_INIT_CFG(QPHY_V3_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
190};
191
192static const struct qmp_ufs_init_tbl sm6115_ufsphy_serdes[] = {
193 QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e),
194 QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
195 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
196 QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02),
197 QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
198 QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
199 QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
200 QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
201 QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a),
202 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01),
203 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00),
204 QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
205 QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
206 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
207 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
208 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
209 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04),
210 QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05),
211 QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
212 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00),
213 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00),
214 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00),
215 QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
216 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
217 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
218 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
219 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
220 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28),
221 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02),
222 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff),
223 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c),
224 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
225 QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98),
226 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00),
227 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00),
228 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00),
229 QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b),
230 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
231 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28),
232 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80),
233 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
234 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6),
235 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
236 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
237 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f),
238 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00),
239 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
240 QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
241 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff),
242 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00),
243};
244
245static const struct qmp_ufs_init_tbl sm6115_ufsphy_hs_b_serdes[] = {
246 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44),
247};
248
249static const struct qmp_ufs_init_tbl sm6115_ufsphy_tx[] = {
250 QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
251 QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06),
252};
253
254static const struct qmp_ufs_init_tbl sm6115_ufsphy_rx[] = {
255 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24),
256 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F),
257 QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40),
258 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E),
259 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B),
260 QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B),
261 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF),
262 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F),
263 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF),
264 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F),
265 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D),
266 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04),
267 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04),
268 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04),
269 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B),
270};
271
272static const struct qmp_ufs_init_tbl sm6115_ufsphy_pcs[] = {
273 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_PWM_GEAR_BAND, 0x15),
274 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_SIGDET_CTRL2, 0x6d),
275 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
276 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
277 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28),
278 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_SYM_RESYNC_CTRL, 0x03),
279 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_LARGE_AMP_POST_EMP_LVL, 0x12),
280 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_TX_SMALL_AMP_POST_EMP_LVL, 0x0f),
281 QMP_PHY_INIT_CFG(QPHY_V2_PCS_UFS_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */
282};
283
284static const struct qmp_ufs_init_tbl sm8150_ufsphy_serdes[] = {
285 QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9),
286 QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11),
287 QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00),
288 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01),
289 QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
290 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
291 QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00),
292 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
293 QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
294 QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
295 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
296 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
297 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff),
298 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c),
299 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac),
300 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
301 QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98),
302 QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
303 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
304 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
305 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32),
306 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f),
307 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd),
308 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23),
309};
310
311static const struct qmp_ufs_init_tbl sm8150_ufsphy_hs_b_serdes[] = {
312 QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06),
313};
314
315static const struct qmp_ufs_init_tbl sm8150_ufsphy_tx[] = {
316 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06),
317 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03),
318 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01),
319 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00),
320 QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05),
321 QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c),
322};
323
324static const struct qmp_ufs_init_tbl sm8150_ufsphy_rx[] = {
325 QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24),
326 QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f),
327 QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
328 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18),
329 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a),
330 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
331 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1),
332 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
333 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80),
334 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
335 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04),
336 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b),
337 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
338 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
339 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d),
340 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00),
341 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10),
342 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
343 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
344 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36),
345 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36),
346 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6),
347 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b),
348 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d),
349 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0),
350 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8),
351 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8),
352 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b),
353 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1),
354 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0),
355 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8),
356 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8),
357 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b),
358 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1),
359};
360
361static const struct qmp_ufs_init_tbl sm8150_ufsphy_pcs[] = {
362 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d),
363 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a),
364 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
365 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
366 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f),
367 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff),
368 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
369};
370
371static const struct qmp_ufs_init_tbl sm8150_ufsphy_hs_g4_pcs[] = {
372 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x10),
373 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_BIST_FIXED_PAT_CTRL, 0x0a),
374};
375
376static const struct qmp_ufs_init_tbl sm8250_ufsphy_hs_g4_tx[] = {
377 QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xe5),
378};
379
380static const struct qmp_ufs_init_tbl sm8250_ufsphy_hs_g4_rx[] = {
381 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a),
382 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x81),
383 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0e),
384 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x6f),
385 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04),
386 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00),
387 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x09),
388 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07),
389 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17),
390 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x20),
391 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0x80),
392 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x01),
393 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f),
394 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff),
395 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff),
396 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f),
397 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x2c),
398 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x6d),
399 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0x6d),
400 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xed),
401 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x3c),
402};
403
404struct qmp_ufs_offsets {
405 u16 serdes;
406 u16 pcs;
407 u16 tx;
408 u16 rx;
409 /* for PHYs with >= 2 lanes */
410 u16 tx2;
411 u16 rx2;
412};
413
414struct qmp_ufs_cfg_tbls {
415 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
416 const struct qmp_ufs_init_tbl *serdes;
417 int serdes_num;
418 const struct qmp_ufs_init_tbl *tx;
419 int tx_num;
420 const struct qmp_ufs_init_tbl *rx;
421 int rx_num;
422 const struct qmp_ufs_init_tbl *pcs;
423 int pcs_num;
424};
425
426/* struct qmp_ufs_cfg - per-PHY initialization config */
427struct qmp_ufs_cfg {
428 int lanes;
429
430 const struct qmp_ufs_offsets *offsets;
431
432 /* Main init sequence for PHY blocks - serdes, tx, rx, pcs */
433 const struct qmp_ufs_cfg_tbls tbls;
434 /* Additional sequence for HS Series B */
435 const struct qmp_ufs_cfg_tbls tbls_hs_b;
436 /* Additional sequence for HS G4 */
437 const struct qmp_ufs_cfg_tbls tbls_hs_g4;
438
439 /* clock ids to be requested */
440 const char * const *clk_list;
441 int num_clks;
442 /* regulators to be requested */
443 const char * const *vreg_list;
444 int num_vregs;
445 /* resets to be requested */
446 const char * const *reset_list;
447 int num_resets;
448
449 /* array of registers with different offsets */
450 const unsigned int *regs;
451
452 /* true, if PCS block has no separate SW_RESET register */
453 bool no_pcs_sw_reset;
454};
455
456struct qmp_ufs_priv {
457 struct phy *phy;
458
459 void __iomem *serdes;
460 void __iomem *pcs;
461 void __iomem *pcs_misc;
462 void __iomem *tx;
463 void __iomem *rx;
464 void __iomem *tx2;
465 void __iomem *rx2;
466
467 struct clk *clks;
468 unsigned int clk_count;
469
470 struct reset_ctl *resets;
471 unsigned int reset_count;
472
473 const struct qmp_ufs_cfg *cfg;
474
475 struct udevice *dev;
476
477 u32 mode;
478 u32 submode;
479};
480
481static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
482{
483 u32 reg;
484
485 reg = readl(base + offset);
486 reg |= val;
487 writel(reg, base + offset);
488
489 /* ensure that above write is through */
490 readl(base + offset);
491}
492
493static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
494{
495 u32 reg;
496
497 reg = readl(base + offset);
498 reg &= ~val;
499 writel(reg, base + offset);
500
501 /* ensure that above write is through */
502 readl(base + offset);
503}
504
505/* list of clocks required by phy */
506static const char * const sdm845_ufs_phy_clk_l[] = {
507 "ref", "ref_aux",
508};
509
510/* list of regulators */
511static const char * const qmp_ufs_vreg_l[] = {
512 "vdda-phy", "vdda-pll",
513};
514
515/* list of resets */
516static const char * const qmp_ufs_reset_l[] = {
517 "ufsphy",
518};
519
520static const struct qmp_ufs_offsets qmp_ufs_offsets = {
521 .serdes = 0,
522 .pcs = 0xc00,
523 .tx = 0x400,
524 .rx = 0x600,
525 .tx2 = 0x800,
526 .rx2 = 0xa00,
527};
528
529static const struct qmp_ufs_cfg sdm845_ufsphy_cfg = {
530 .lanes = 2,
531
532 .tbls = {
533 .serdes = sdm845_ufsphy_serdes,
534 .serdes_num = ARRAY_SIZE(sdm845_ufsphy_serdes),
535 .tx = sdm845_ufsphy_tx,
536 .tx_num = ARRAY_SIZE(sdm845_ufsphy_tx),
537 .rx = sdm845_ufsphy_rx,
538 .rx_num = ARRAY_SIZE(sdm845_ufsphy_rx),
539 .pcs = sdm845_ufsphy_pcs,
540 .pcs_num = ARRAY_SIZE(sdm845_ufsphy_pcs),
541 },
542 .tbls_hs_b = {
543 .serdes = sdm845_ufsphy_hs_b_serdes,
544 .serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
545 },
546 .clk_list = sdm845_ufs_phy_clk_l,
547 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
548 .vreg_list = qmp_ufs_vreg_l,
549 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
550 .regs = ufsphy_v3_regs_layout,
551
552 .no_pcs_sw_reset = true,
553};
554
555static const struct qmp_ufs_cfg sm6115_ufsphy_cfg = {
556 .lanes = 1,
557
558 .offsets = &qmp_ufs_offsets,
559
560 .tbls = {
561 .serdes = sm6115_ufsphy_serdes,
562 .serdes_num = ARRAY_SIZE(sm6115_ufsphy_serdes),
563 .tx = sm6115_ufsphy_tx,
564 .tx_num = ARRAY_SIZE(sm6115_ufsphy_tx),
565 .rx = sm6115_ufsphy_rx,
566 .rx_num = ARRAY_SIZE(sm6115_ufsphy_rx),
567 .pcs = sm6115_ufsphy_pcs,
568 .pcs_num = ARRAY_SIZE(sm6115_ufsphy_pcs),
569 },
570 .tbls_hs_b = {
571 .serdes = sm6115_ufsphy_hs_b_serdes,
572 .serdes_num = ARRAY_SIZE(sm6115_ufsphy_hs_b_serdes),
573 },
574 .clk_list = sdm845_ufs_phy_clk_l,
575 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
576 .vreg_list = qmp_ufs_vreg_l,
577 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
578 .reset_list = qmp_ufs_reset_l,
579 .num_resets = ARRAY_SIZE(qmp_ufs_reset_l),
580 .regs = ufsphy_v2_regs_layout,
581
582 .no_pcs_sw_reset = true,
583};
584
585static const struct qmp_ufs_cfg sm8250_ufsphy_cfg = {
586 .lanes = 2,
587
588 .tbls = {
589 .serdes = sm8150_ufsphy_serdes,
590 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_serdes),
591 .tx = sm8150_ufsphy_tx,
592 .tx_num = ARRAY_SIZE(sm8150_ufsphy_tx),
593 .rx = sm8150_ufsphy_rx,
594 .rx_num = ARRAY_SIZE(sm8150_ufsphy_rx),
595 .pcs = sm8150_ufsphy_pcs,
596 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_pcs),
597 },
598 .tbls_hs_b = {
599 .serdes = sm8150_ufsphy_hs_b_serdes,
600 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes),
601 },
602 .tbls_hs_g4 = {
603 .tx = sm8250_ufsphy_hs_g4_tx,
604 .tx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_tx),
605 .rx = sm8250_ufsphy_hs_g4_rx,
606 .rx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_rx),
607 .pcs = sm8150_ufsphy_hs_g4_pcs,
608 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
609 },
610 .clk_list = sdm845_ufs_phy_clk_l,
611 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
612 .vreg_list = qmp_ufs_vreg_l,
613 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
614 .reset_list = qmp_ufs_reset_l,
615 .num_resets = ARRAY_SIZE(qmp_ufs_reset_l),
616 .regs = ufsphy_v4_regs_layout,
617
618 .no_pcs_sw_reset = false,
619};
620
621static void qmp_ufs_configure_lane(void __iomem *base,
622 const struct qmp_ufs_init_tbl tbl[],
623 int num,
624 u8 lane_mask)
625{
626 int i;
627 const struct qmp_ufs_init_tbl *t = tbl;
628
629 if (!t)
630 return;
631
632 for (i = 0; i < num; i++, t++) {
633 if (!(t->lane_mask & lane_mask))
634 continue;
635
636 writel(t->val, base + t->offset);
637 }
638}
639
640static void qmp_ufs_configure(void __iomem *base,
641 const struct qmp_ufs_init_tbl tbl[],
642 int num)
643{
644 qmp_ufs_configure_lane(base, tbl, num, 0xff);
645}
646
647static void qmp_ufs_serdes_init(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg_tbls *tbls)
648{
649 void __iomem *serdes = qmp->serdes;
650
651 qmp_ufs_configure(serdes, tbls->serdes, tbls->serdes_num);
652}
653
654static void qmp_ufs_lanes_init(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg_tbls *tbls)
655{
656 const struct qmp_ufs_cfg *cfg = qmp->cfg;
657 void __iomem *tx = qmp->tx;
658 void __iomem *rx = qmp->rx;
659
660 qmp_ufs_configure_lane(tx, tbls->tx, tbls->tx_num, 1);
661 qmp_ufs_configure_lane(rx, tbls->rx, tbls->rx_num, 1);
662
663 if (cfg->lanes >= 2) {
664 qmp_ufs_configure_lane(qmp->tx2, tbls->tx, tbls->tx_num, 2);
665 qmp_ufs_configure_lane(qmp->rx2, tbls->rx, tbls->rx_num, 2);
666 }
667}
668
669static void qmp_ufs_pcs_init(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg_tbls *tbls)
670{
671 void __iomem *pcs = qmp->pcs;
672
673 qmp_ufs_configure(pcs, tbls->pcs, tbls->pcs_num);
674}
675
676static void qmp_ufs_init_registers(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg *cfg)
677{
678 /* We support 'PHY_MODE_UFS_HS_B' mode & 'UFS_HS_G3' submode for now. */
679 qmp_ufs_serdes_init(qmp, &cfg->tbls);
680 qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_b);
681 qmp_ufs_lanes_init(qmp, &cfg->tbls);
682 qmp_ufs_pcs_init(qmp, &cfg->tbls);
683}
684
685static int qmp_ufs_do_reset(struct qmp_ufs_priv *qmp)
686{
687 int i, ret;
688
689 for (i = 0; i < qmp->reset_count; i++) {
690 ret = reset_assert(&qmp->resets[i]);
691 if (ret)
692 return ret;
693 }
694
695 udelay(10);
696
697 for (i = 0; i < qmp->reset_count; i++) {
698 ret = reset_deassert(&qmp->resets[i]);
699 if (ret)
700 return ret;
701 }
702
703 udelay(50);
704
705 return 0;
706}
707
708static int qmp_ufs_power_on(struct phy *phy)
709{
710 struct qmp_ufs_priv *qmp = dev_get_priv(phy->dev);
711 const struct qmp_ufs_cfg *cfg = qmp->cfg;
712 void __iomem *pcs = qmp->pcs;
713 void __iomem *status;
714 unsigned int val;
715 int ret;
716
717 /* Power down PHY */
718 qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
719
720 qmp_ufs_init_registers(qmp, cfg);
721
722 if (cfg->no_pcs_sw_reset) {
723 ret = qmp_ufs_do_reset(qmp);
724 if (ret) {
725 printf("%s: qmp reset failed\n", __func__);
726 return ret;
727 }
728 }
729
730 /* Pull PHY out of reset state */
731 if (!cfg->no_pcs_sw_reset)
732 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
733
734 /* start SerDes */
735 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START);
736
737 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
738 ret = readl_poll_timeout(status, val, (val & PCS_READY), PHY_INIT_COMPLETE_TIMEOUT);
739 if (ret) {
740 printf("%s: phy initialization timed-out\n", __func__);
741 return ret;
742 }
743
744 return 0;
745}
746
747static int qmp_ufs_power_off(struct phy *phy)
748{
749 struct qmp_ufs_priv *qmp = dev_get_priv(phy->dev);
750 const struct qmp_ufs_cfg *cfg = qmp->cfg;
751
752 /* PHY reset */
753 qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
754
755 /* stop SerDes and Phy-Coding-Sublayer */
756 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL],
757 SERDES_START | PCS_START);
758
759 /* Put PHY into POWER DOWN state: active low */
760 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
761 SW_PWRDN);
762
763 clk_release_all(qmp->clks, qmp->clk_count);
764
765 return 0;
766}
767
768static int qmp_ufs_vreg_init(struct udevice *dev, struct qmp_ufs_priv *qmp)
769{
770 // TBD: Add regulator support later - if needed
771 return 0;
772}
773
774static int qmp_ufs_reset_init(struct udevice *dev, struct qmp_ufs_priv *qmp)
775{
776 const struct qmp_ufs_cfg *cfg = qmp->cfg;
777 int num = cfg->num_resets;
778 int i, ret;
779
780 qmp->reset_count = 0;
781 qmp->resets = devm_kcalloc(dev, num, sizeof(*qmp->resets), GFP_KERNEL);
782 if (!qmp->resets)
783 return -ENOMEM;
784
785 for (i = 0; i < num; i++) {
786 ret = reset_get_by_index(dev, i, &qmp->resets[i]);
787 if (ret < 0) {
788 printf("%s: failed to get reset %d\n", __func__, i);
789 goto reset_get_err;
790 }
791
792 ++qmp->reset_count;
793 }
794
795 return 0;
796
797reset_get_err:
798 ret = reset_release_all(qmp->resets, qmp->reset_count);
799 if (ret)
800 printf("%s: failed to disable all resets\n", __func__);
801
802 return ret;
803}
804
805static int qmp_ufs_clk_init(struct udevice *dev, struct qmp_ufs_priv *qmp)
806{
807 const struct qmp_ufs_cfg *cfg = qmp->cfg;
808 int num = cfg->num_clks;
809 int i, ret;
810
811 qmp->clk_count = 0;
812 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
813 if (!qmp->clks)
814 return -ENOMEM;
815
816 for (i = 0; i < num; i++) {
817 ret = clk_get_by_index(dev, i, &qmp->clks[i]);
818 if (ret < 0)
819 goto clk_get_err;
820
821 ret = clk_enable(&qmp->clks[i]);
822 if (ret && ret != -ENOSYS) {
823 printf("%s: failed to enable clock %d\n", __func__, i);
824 clk_free(&qmp->clks[i]);
825 goto clk_get_err;
826 }
827
828 ++qmp->clk_count;
829 }
830
831 return 0;
832
833clk_get_err:
834 ret = clk_release_all(qmp->clks, qmp->clk_count);
835 if (ret)
836 printf("%s: failed to disable all clocks\n", __func__);
837
838 return ret;
839}
840
841static int qmp_ufs_probe_generic_child(struct udevice *dev,
842 ofnode child)
843{
844 struct qmp_ufs_priv *qmp = dev_get_priv(dev);
845 const struct qmp_ufs_cfg *cfg = qmp->cfg;
846 struct resource res;
847 int ret;
848
849 /*
850 * Get memory resources for the PHY:
851 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
852 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
853 * For single lane PHYs: pcs_misc (optional) -> 3.
854 */
855 ret = ofnode_read_resource(child, 0, &res);
856 if (ret) {
857 dev_err(dev, "can't get reg property of child %s\n",
858 ofnode_get_name(child));
859 return ret;
860 }
861
862 qmp->tx = (void __iomem *)res.start;
863
864 ret = ofnode_read_resource(child, 1, &res);
865 if (ret) {
866 dev_err(dev, "can't get reg property of child %s\n",
867 ofnode_get_name(child));
868 return ret;
869 }
870
871 qmp->rx = (void __iomem *)res.start;
872
873 ret = ofnode_read_resource(child, 2, &res);
874 if (ret) {
875 dev_err(dev, "can't get reg property of child %s\n",
876 ofnode_get_name(child));
877 return ret;
878 }
879
880 qmp->pcs = (void __iomem *)res.start;
881
882 if (cfg->lanes >= 2) {
883 ret = ofnode_read_resource(child, 3, &res);
884 if (ret) {
885 dev_err(dev, "can't get reg property of child %s\n",
886 ofnode_get_name(child));
887 return ret;
888 }
889
890 qmp->tx2 = (void __iomem *)res.start;
891
892 ret = ofnode_read_resource(child, 4, &res);
893 if (ret) {
894 dev_err(dev, "can't get reg property of child %s\n",
895 ofnode_get_name(child));
896 return ret;
897 }
898
899 qmp->rx2 = (void __iomem *)res.start;
900
901 ret = ofnode_read_resource(child, 5, &res);
902 if (ret)
903 qmp->pcs_misc = NULL;
904 } else {
905 ret = ofnode_read_resource(child, 3, &res);
906 if (ret)
907 qmp->pcs_misc = NULL;
908 }
909
910 if (!qmp->pcs_misc)
911 dev_warn(qmp->dev, "PHY pcs_misc-reg not used\n");
912
913 return 0;
914}
915
916static int qmp_ufs_probe_dt_children(struct udevice *dev)
917{
918 int ret;
919 ofnode child;
920
921 ofnode_for_each_subnode(child, dev_ofnode(dev)) {
922 ret = qmp_ufs_probe_generic_child(dev, child);
923 if (ret) {
924 dev_err(dev, "Cannot parse child %s:%d\n",
925 ofnode_get_name(child), ret);
926 return ret;
927 }
928 }
929
930 return 0;
931}
932
933static int qmp_ufs_probe(struct udevice *dev)
934{
935 struct qmp_ufs_priv *qmp = dev_get_priv(dev);
936 int ret;
937
938 qmp->serdes = (void __iomem *)dev_read_addr(dev);
939 if (IS_ERR(qmp->serdes))
940 return PTR_ERR(qmp->serdes);
941
942 qmp->cfg = (const struct qmp_ufs_cfg *)dev_get_driver_data(dev);
943 if (!qmp->cfg)
944 return -EINVAL;
945
946 ret = qmp_ufs_clk_init(dev, qmp);
947 if (ret) {
948 printf("%s: failed to get UFS clks\n", __func__);
949 return ret;
950 }
951
952 ret = qmp_ufs_vreg_init(dev, qmp);
953 if (ret) {
954 printf("%s: failed to get UFS voltage regulators\n", __func__);
955 return ret;
956 }
957
958 if (qmp->cfg->no_pcs_sw_reset) {
959 ret = qmp_ufs_reset_init(dev, qmp);
960 if (ret) {
961 printf("%s: failed to get UFS resets\n", __func__);
962 return ret;
963 }
964 }
965
966 qmp->dev = dev;
967
968 ret = qmp_ufs_probe_dt_children(dev);
969 if (ret) {
970 printf("%s: failed to get UFS dt regs\n", __func__);
971 return ret;
972 }
973
974 return 0;
975}
976
977static struct phy_ops qmp_ufs_ops = {
978 .power_on = qmp_ufs_power_on,
979 .power_off = qmp_ufs_power_off,
980};
981
982static const struct udevice_id qmp_ufs_ids[] = {
983 { .compatible = "qcom,sdm845-qmp-ufs-phy", .data = (ulong)&sdm845_ufsphy_cfg },
984 { .compatible = "qcom,sm6115-qmp-ufs-phy", .data = (ulong)&sm6115_ufsphy_cfg },
985 { .compatible = "qcom,sm8250-qmp-ufs-phy", .data = (ulong)&sm8250_ufsphy_cfg },
986 { }
987};
988
989U_BOOT_DRIVER(qcom_qmp_ufs) = {
990 .name = "qcom-qmp-ufs",
991 .id = UCLASS_PHY,
992 .of_match = qmp_ufs_ids,
993 .ops = &qmp_ufs_ops,
994 .probe = qmp_ufs_probe,
995 .priv_auto = sizeof(struct qmp_ufs_priv),
996};