blob: 8908a34df548340556d92ac8ca488dbbbd0e293a [file] [log] [blame]
Bhupesh Sharmaf0cbbc92024-09-10 11:11:58 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2023-2024 Linaro Limited
5 * Authors:
6 * - Bhupesh Sharma <bhupesh.sharma@linaro.org>
7 * - Neil Armstrong <neil.armstrong@linaro.org>
8 *
9 * Based on Linux driver
10 */
11
12#include <clk.h>
13#include <clk-uclass.h>
14#include <dm.h>
15#include <dm/device_compat.h>
16#include <dm/devres.h>
17#include <generic-phy.h>
18#include <malloc.h>
19#include <reset.h>
20
21#include <asm/io.h>
22#include <linux/bitops.h>
23#include <linux/clk-provider.h>
24#include <linux/delay.h>
25#include <linux/iopoll.h>
26#include <linux/ioport.h>
27
28#include "phy-qcom-qmp.h"
29#include "phy-qcom-qmp-pcs-ufs-v2.h"
30#include "phy-qcom-qmp-pcs-ufs-v3.h"
31#include "phy-qcom-qmp-pcs-ufs-v4.h"
32#include "phy-qcom-qmp-pcs-ufs-v5.h"
33#include "phy-qcom-qmp-pcs-ufs-v6.h"
34
35#include "phy-qcom-qmp-qserdes-com-v4.h"
36#include "phy-qcom-qmp-qserdes-com-v6.h"
37#include "phy-qcom-qmp-qserdes-txrx-v4.h"
38#include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h"
39
40/* QPHY_SW_RESET bit */
41#define SW_RESET BIT(0)
42/* QPHY_POWER_DOWN_CONTROL */
43#define SW_PWRDN BIT(0)
44/* QPHY_START_CONTROL bits */
45#define SERDES_START BIT(0)
46#define PCS_START BIT(1)
47/* QPHY_PCS_READY_STATUS bit */
48#define PCS_READY BIT(0)
49
50#define PHY_INIT_COMPLETE_TIMEOUT (200 * 10000)
51
52struct qmp_ufs_init_tbl {
53 unsigned int offset;
54 unsigned int val;
55 /*
56 * mask of lanes for which this register is written
57 * for cases when second lane needs different values
58 */
59 u8 lane_mask;
60};
61
62#define QMP_PHY_INIT_CFG(o, v) \
63 { \
64 .offset = o, \
65 .val = v, \
66 .lane_mask = 0xff, \
67 }
68
69#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
70 { \
71 .offset = o, \
72 .val = v, \
73 .lane_mask = l, \
74 }
75
76/* set of registers with offsets different per-PHY */
77enum qphy_reg_layout {
78 /* PCS registers */
79 QPHY_SW_RESET,
80 QPHY_START_CTRL,
81 QPHY_PCS_READY_STATUS,
82 QPHY_PCS_POWER_DOWN_CONTROL,
83 /* Keep last to ensure regs_layout arrays are properly initialized */
84 QPHY_LAYOUT_SIZE
85};
86
87static const unsigned int ufsphy_v2_regs_layout[QPHY_LAYOUT_SIZE] = {
88 [QPHY_START_CTRL] = QPHY_V2_PCS_UFS_PHY_START,
89 [QPHY_PCS_READY_STATUS] = QPHY_V2_PCS_UFS_READY_STATUS,
90 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V2_PCS_UFS_POWER_DOWN_CONTROL,
91};
92
93static const unsigned int ufsphy_v3_regs_layout[QPHY_LAYOUT_SIZE] = {
94 [QPHY_START_CTRL] = QPHY_V3_PCS_UFS_PHY_START,
95 [QPHY_PCS_READY_STATUS] = QPHY_V3_PCS_UFS_READY_STATUS,
96 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_UFS_POWER_DOWN_CONTROL,
97};
98
99static const unsigned int ufsphy_v4_regs_layout[QPHY_LAYOUT_SIZE] = {
100 [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START,
101 [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS,
102 [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET,
103 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL,
104};
105
106static const unsigned int ufsphy_v6_regs_layout[QPHY_LAYOUT_SIZE] = {
107 [QPHY_START_CTRL] = QPHY_V6_PCS_UFS_PHY_START,
108 [QPHY_PCS_READY_STATUS] = QPHY_V6_PCS_UFS_READY_STATUS,
109 [QPHY_SW_RESET] = QPHY_V6_PCS_UFS_SW_RESET,
110 [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_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 sm8150_ufsphy_serdes[] = {
193 QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9),
194 QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11),
195 QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00),
196 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01),
197 QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02),
198 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f),
199 QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00),
200 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
201 QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82),
202 QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06),
203 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16),
204 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36),
205 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff),
206 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c),
207 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac),
208 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e),
209 QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98),
210 QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06),
211 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16),
212 QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36),
213 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32),
214 QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f),
215 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd),
216 QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23),
217};
218
219static const struct qmp_ufs_init_tbl sm8150_ufsphy_hs_b_serdes[] = {
220 QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06),
221};
222
223static const struct qmp_ufs_init_tbl sm8150_ufsphy_tx[] = {
224 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06),
225 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03),
226 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01),
227 QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00),
228 QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05),
229 QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c),
230};
231
232static const struct qmp_ufs_init_tbl sm8150_ufsphy_rx[] = {
233 QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24),
234 QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f),
235 QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e),
236 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18),
237 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a),
238 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
239 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1),
240 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80),
241 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80),
242 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c),
243 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04),
244 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b),
245 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06),
246 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04),
247 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d),
248 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00),
249 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10),
250 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0),
251 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00),
252 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36),
253 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36),
254 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6),
255 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b),
256 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d),
257 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0),
258 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8),
259 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8),
260 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b),
261 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1),
262 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0),
263 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8),
264 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8),
265 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b),
266 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1),
267};
268
269static const struct qmp_ufs_init_tbl sm8150_ufsphy_pcs[] = {
270 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d),
271 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a),
272 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02),
273 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
274 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f),
275 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff),
276 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
277};
278
279static const struct qmp_ufs_init_tbl sm8150_ufsphy_hs_g4_pcs[] = {
280 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x10),
281 QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_BIST_FIXED_PAT_CTRL, 0x0a),
282};
283
284static const struct qmp_ufs_init_tbl sm8250_ufsphy_hs_g4_tx[] = {
285 QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xe5),
286};
287
288static const struct qmp_ufs_init_tbl sm8250_ufsphy_hs_g4_rx[] = {
289 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a),
290 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x81),
291 QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0e),
292 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x6f),
293 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04),
294 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00),
295 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x09),
296 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07),
297 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17),
298 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x20),
299 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0x80),
300 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x01),
301 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f),
302 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff),
303 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff),
304 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f),
305 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x2c),
306 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x6d),
307 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0x6d),
308 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xed),
309 QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x3c),
310};
311
312static const struct qmp_ufs_init_tbl sm8550_ufsphy_serdes[] = {
313 QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
314 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
315 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
316 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
317 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
318 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
319 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f),
320 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
321 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
322 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x0a),
323 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
324 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14),
325 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f),
326 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06),
327 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c),
328 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x0a),
329 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
330 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x14),
331 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x99),
332 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x07),
333};
334
335static const struct qmp_ufs_init_tbl sm8550_ufsphy_hs_b_serdes[] = {
336 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x44),
337};
338
339static const struct qmp_ufs_init_tbl sm8550_ufsphy_tx[] = {
340 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x05),
341 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
342 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_FR_DCC_CTRL, 0x4c),
343};
344
345static const struct qmp_ufs_init_tbl sm8550_ufsphy_rx[] = {
346 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c),
347 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x0e),
348
349 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xc2),
350 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xc2),
351 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3, 0x1a),
352 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6, 0x60),
353
354 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B3, 0x9e),
355 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B6, 0x60),
356
357 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B3, 0x9e),
358 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B4, 0x0e),
359 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B5, 0x36),
360 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02),
361
362};
363
364static const struct qmp_ufs_init_tbl sm8550_ufsphy_pcs[] = {
365 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x69),
366 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
367 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
368 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
369 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x2b),
370 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
371 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
372 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
373 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4f),
374 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e),
375};
376
377static const struct qmp_ufs_init_tbl sm8650_ufsphy_serdes[] = {
378 QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0xd9),
379 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16),
380 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x11),
381 QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00),
382 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x01),
383 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x1f),
384 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO_MODE1, 0x1f),
385 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IETRIM, 0x0a),
386 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_IPTRIM, 0x17),
387 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x04),
388 QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_INITVAL2, 0x00),
389 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41),
390 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06),
391 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x18),
392 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x14),
393 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x7f),
394 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x06),
395 QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x4c),
396 QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06),
397 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x18),
398 QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x14),
399 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x99),
400 QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x07),
401};
402
403static const struct qmp_ufs_init_tbl sm8650_ufsphy_tx[] = {
404 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_LANE_MODE_1, 0x01),
405 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x07),
406 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x0e),
407};
408
409static const struct qmp_ufs_init_tbl sm8650_ufsphy_rx[] = {
410 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE2, 0x0c),
411 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FO_GAIN_RATE4, 0x0c),
412 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_GAIN_RATE4, 0x04),
413 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x14),
414 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CONTROLS, 0x07),
415 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_OFFSET_ADAPTOR_CNTRL3, 0x0e),
416 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_COUNT_HIGH_RATE4, 0x02),
417 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_FO_GAIN_RATE4, 0x1c),
418 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_FASTLOCK_SO_GAIN_RATE4, 0x06),
419 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_VGA_CAL_MAN_VAL, 0x3e),
420 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f),
421 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B0, 0xce),
422 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B1, 0xce),
423 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B2, 0x18),
424 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B3, 0x1a),
425 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B4, 0x0f),
426 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE_0_1_B6, 0x60),
427 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B3, 0x9e),
428 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE2_B6, 0x60),
429 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B3, 0x9e),
430 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B4, 0x0e),
431 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B5, 0x36),
432 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE3_B8, 0x02),
433 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B0, 0x24),
434 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B1, 0x24),
435 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B2, 0x20),
436 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B3, 0xb9),
437 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_MODE_RATE4_B4, 0x4f),
438 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_SO_SATURATION, 0x1f),
439 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_UCDR_PI_CTRL1, 0x94),
440 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_RX_TERM_BW_CTRL0, 0xfa),
441 QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30),
442};
443
444static const struct qmp_ufs_init_tbl sm8650_ufsphy_pcs[] = {
445 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02),
446 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43),
447 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PCS_CTRL1, 0xc1),
448 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0f),
449 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_SIGDET_CTRL2, 0x68),
450 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S4, 0x0e),
451 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S5, 0x12),
452 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S6, 0x15),
453 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_POST_EMP_LVL_S7, 0x19),
454 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x13),
455 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x04),
456 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x04),
457 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_PLL_CNTL, 0x33),
458 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x05),
459 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x05),
460 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HS_G5_SYNC_LENGTH_CAPABILITY, 0x4d),
461 QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_RX_HSG5_SYNC_WAIT_TIME, 0x9e),
462};
463
464struct qmp_ufs_offsets {
465 u16 serdes;
466 u16 pcs;
467 u16 tx;
468 u16 rx;
469 /* for PHYs with >= 2 lanes */
470 u16 tx2;
471 u16 rx2;
472};
473
474struct qmp_ufs_cfg_tbls {
475 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
476 const struct qmp_ufs_init_tbl *serdes;
477 int serdes_num;
478 const struct qmp_ufs_init_tbl *tx;
479 int tx_num;
480 const struct qmp_ufs_init_tbl *rx;
481 int rx_num;
482 const struct qmp_ufs_init_tbl *pcs;
483 int pcs_num;
484};
485
486/* struct qmp_ufs_cfg - per-PHY initialization config */
487struct qmp_ufs_cfg {
488 int lanes;
489
490 const struct qmp_ufs_offsets *offsets;
491
492 /* Main init sequence for PHY blocks - serdes, tx, rx, pcs */
493 const struct qmp_ufs_cfg_tbls tbls;
494 /* Additional sequence for HS Series B */
495 const struct qmp_ufs_cfg_tbls tbls_hs_b;
496 /* Additional sequence for HS G4 */
497 const struct qmp_ufs_cfg_tbls tbls_hs_g4;
498
499 /* clock ids to be requested */
500 const char * const *clk_list;
501 int num_clks;
502 /* regulators to be requested */
503 const char * const *vreg_list;
504 int num_vregs;
505 /* resets to be requested */
506 const char * const *reset_list;
507 int num_resets;
508
509 /* array of registers with different offsets */
510 const unsigned int *regs;
511
512 /* true, if PCS block has no separate SW_RESET register */
513 bool no_pcs_sw_reset;
514};
515
516struct qmp_ufs_priv {
517 struct phy *phy;
518
519 void __iomem *serdes;
520 void __iomem *pcs;
521 void __iomem *pcs_misc;
522 void __iomem *tx;
523 void __iomem *rx;
524 void __iomem *tx2;
525 void __iomem *rx2;
526
527 struct clk *clks;
528 unsigned int clk_count;
529
530 struct reset_ctl *resets;
531 unsigned int reset_count;
532
533 const struct qmp_ufs_cfg *cfg;
534
535 struct udevice *dev;
536
537 u32 mode;
538 u32 submode;
539};
540
541static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
542{
543 u32 reg;
544
545 reg = readl(base + offset);
546 reg |= val;
547 writel(reg, base + offset);
548
549 /* ensure that above write is through */
550 readl(base + offset);
551}
552
553static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
554{
555 u32 reg;
556
557 reg = readl(base + offset);
558 reg &= ~val;
559 writel(reg, base + offset);
560
561 /* ensure that above write is through */
562 readl(base + offset);
563}
564
565/* list of clocks required by phy */
566static const char * const sdm845_ufs_phy_clk_l[] = {
567 "ref", "ref_aux",
568};
569
570/* list of regulators */
571static const char * const qmp_ufs_vreg_l[] = {
572 "vdda-phy", "vdda-pll",
573};
574
575/* list of resets */
576static const char * const qmp_ufs_reset_l[] = {
577 "ufsphy",
578};
579
580static const struct qmp_ufs_offsets qmp_ufs_offsets = {
581 .serdes = 0,
582 .pcs = 0xc00,
583 .tx = 0x400,
584 .rx = 0x600,
585 .tx2 = 0x800,
586 .rx2 = 0xa00,
587};
588
589static const struct qmp_ufs_offsets qmp_ufs_offsets_v6 = {
590 .serdes = 0,
591 .pcs = 0x0400,
592 .tx = 0x1000,
593 .rx = 0x1200,
594 .tx2 = 0x1800,
595 .rx2 = 0x1a00,
596};
597
598static const struct qmp_ufs_cfg sdm845_ufsphy_cfg = {
599 .lanes = 2,
600
601 .offsets = &qmp_ufs_offsets,
602
603 .tbls = {
604 .serdes = sdm845_ufsphy_serdes,
605 .serdes_num = ARRAY_SIZE(sdm845_ufsphy_serdes),
606 .tx = sdm845_ufsphy_tx,
607 .tx_num = ARRAY_SIZE(sdm845_ufsphy_tx),
608 .rx = sdm845_ufsphy_rx,
609 .rx_num = ARRAY_SIZE(sdm845_ufsphy_rx),
610 .pcs = sdm845_ufsphy_pcs,
611 .pcs_num = ARRAY_SIZE(sdm845_ufsphy_pcs),
612 },
613 .tbls_hs_b = {
614 .serdes = sdm845_ufsphy_hs_b_serdes,
615 .serdes_num = ARRAY_SIZE(sdm845_ufsphy_hs_b_serdes),
616 },
617 .clk_list = sdm845_ufs_phy_clk_l,
618 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
619 .vreg_list = qmp_ufs_vreg_l,
620 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
621 .regs = ufsphy_v3_regs_layout,
622
623 .no_pcs_sw_reset = true,
624};
625
626static const struct qmp_ufs_cfg sm8250_ufsphy_cfg = {
627 .lanes = 2,
628
629 .offsets = &qmp_ufs_offsets,
630
631 .tbls = {
632 .serdes = sm8150_ufsphy_serdes,
633 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_serdes),
634 .tx = sm8150_ufsphy_tx,
635 .tx_num = ARRAY_SIZE(sm8150_ufsphy_tx),
636 .rx = sm8150_ufsphy_rx,
637 .rx_num = ARRAY_SIZE(sm8150_ufsphy_rx),
638 .pcs = sm8150_ufsphy_pcs,
639 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_pcs),
640 },
641 .tbls_hs_b = {
642 .serdes = sm8150_ufsphy_hs_b_serdes,
643 .serdes_num = ARRAY_SIZE(sm8150_ufsphy_hs_b_serdes),
644 },
645 .tbls_hs_g4 = {
646 .tx = sm8250_ufsphy_hs_g4_tx,
647 .tx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_tx),
648 .rx = sm8250_ufsphy_hs_g4_rx,
649 .rx_num = ARRAY_SIZE(sm8250_ufsphy_hs_g4_rx),
650 .pcs = sm8150_ufsphy_hs_g4_pcs,
651 .pcs_num = ARRAY_SIZE(sm8150_ufsphy_hs_g4_pcs),
652 },
653 .clk_list = sdm845_ufs_phy_clk_l,
654 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
655 .vreg_list = qmp_ufs_vreg_l,
656 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
657 .reset_list = qmp_ufs_reset_l,
658 .num_resets = ARRAY_SIZE(qmp_ufs_reset_l),
659 .regs = ufsphy_v4_regs_layout,
660
661 .no_pcs_sw_reset = false,
662};
663
664static const struct qmp_ufs_cfg sm8550_ufsphy_cfg = {
665 .lanes = 2,
666
667 .offsets = &qmp_ufs_offsets_v6,
668
669 .tbls = {
670 .serdes = sm8550_ufsphy_serdes,
671 .serdes_num = ARRAY_SIZE(sm8550_ufsphy_serdes),
672 .tx = sm8550_ufsphy_tx,
673 .tx_num = ARRAY_SIZE(sm8550_ufsphy_tx),
674 .rx = sm8550_ufsphy_rx,
675 .rx_num = ARRAY_SIZE(sm8550_ufsphy_rx),
676 .pcs = sm8550_ufsphy_pcs,
677 .pcs_num = ARRAY_SIZE(sm8550_ufsphy_pcs),
678 },
679 .tbls_hs_b = {
680 .serdes = sm8550_ufsphy_hs_b_serdes,
681 .serdes_num = ARRAY_SIZE(sm8550_ufsphy_hs_b_serdes),
682 },
683 .clk_list = sdm845_ufs_phy_clk_l,
684 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
685 .vreg_list = qmp_ufs_vreg_l,
686 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
687 .regs = ufsphy_v6_regs_layout,
688
689 .no_pcs_sw_reset = false,
690};
691
692static const struct qmp_ufs_cfg sm8650_ufsphy_cfg = {
693 .lanes = 2,
694
695 .offsets = &qmp_ufs_offsets_v6,
696
697 .tbls = {
698 .serdes = sm8650_ufsphy_serdes,
699 .serdes_num = ARRAY_SIZE(sm8650_ufsphy_serdes),
700 .tx = sm8650_ufsphy_tx,
701 .tx_num = ARRAY_SIZE(sm8650_ufsphy_tx),
702 .rx = sm8650_ufsphy_rx,
703 .rx_num = ARRAY_SIZE(sm8650_ufsphy_rx),
704 .pcs = sm8650_ufsphy_pcs,
705 .pcs_num = ARRAY_SIZE(sm8650_ufsphy_pcs),
706 },
707 .clk_list = sdm845_ufs_phy_clk_l,
708 .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l),
709 .vreg_list = qmp_ufs_vreg_l,
710 .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l),
711 .regs = ufsphy_v6_regs_layout,
712
713 .no_pcs_sw_reset = false,
714};
715
716static void qmp_ufs_configure_lane(void __iomem *base,
717 const struct qmp_ufs_init_tbl tbl[],
718 int num,
719 u8 lane_mask)
720{
721 int i;
722 const struct qmp_ufs_init_tbl *t = tbl;
723
724 if (!t)
725 return;
726
727 for (i = 0; i < num; i++, t++) {
728 if (!(t->lane_mask & lane_mask))
729 continue;
730
731 writel(t->val, base + t->offset);
732 }
733}
734
735static void qmp_ufs_configure(void __iomem *base,
736 const struct qmp_ufs_init_tbl tbl[],
737 int num)
738{
739 qmp_ufs_configure_lane(base, tbl, num, 0xff);
740}
741
742static void qmp_ufs_serdes_init(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg_tbls *tbls)
743{
744 void __iomem *serdes = qmp->serdes;
745
746 qmp_ufs_configure(serdes, tbls->serdes, tbls->serdes_num);
747}
748
749static void qmp_ufs_lanes_init(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg_tbls *tbls)
750{
751 const struct qmp_ufs_cfg *cfg = qmp->cfg;
752 void __iomem *tx = qmp->tx;
753 void __iomem *rx = qmp->rx;
754
755 qmp_ufs_configure_lane(tx, tbls->tx, tbls->tx_num, 1);
756 qmp_ufs_configure_lane(rx, tbls->rx, tbls->rx_num, 1);
757
758 if (cfg->lanes >= 2) {
759 qmp_ufs_configure_lane(qmp->tx2, tbls->tx, tbls->tx_num, 2);
760 qmp_ufs_configure_lane(qmp->rx2, tbls->rx, tbls->rx_num, 2);
761 }
762}
763
764static void qmp_ufs_pcs_init(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg_tbls *tbls)
765{
766 void __iomem *pcs = qmp->pcs;
767
768 qmp_ufs_configure(pcs, tbls->pcs, tbls->pcs_num);
769}
770
771static void qmp_ufs_init_registers(struct qmp_ufs_priv *qmp, const struct qmp_ufs_cfg *cfg)
772{
773 /* We support 'PHY_MODE_UFS_HS_B' mode & 'UFS_HS_G3' submode for now. */
774 qmp_ufs_serdes_init(qmp, &cfg->tbls);
775 qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_b);
776 qmp_ufs_serdes_init(qmp, &cfg->tbls_hs_g4);
777 qmp_ufs_lanes_init(qmp, &cfg->tbls);
778 qmp_ufs_pcs_init(qmp, &cfg->tbls);
779}
780
781static int qmp_ufs_do_reset(struct qmp_ufs_priv *qmp)
782{
783 int i, ret;
784
785 for (i = 0; i < qmp->reset_count; i++) {
786 ret = reset_assert(&qmp->resets[i]);
787 if (ret)
788 return ret;
789 }
790
791 udelay(10);
792
793 for (i = 0; i < qmp->reset_count; i++) {
794 ret = reset_deassert(&qmp->resets[i]);
795 if (ret)
796 return ret;
797 }
798
799 udelay(50);
800
801 return 0;
802}
803
804static int qmp_ufs_power_on(struct phy *phy)
805{
806 struct qmp_ufs_priv *qmp = dev_get_priv(phy->dev);
807 const struct qmp_ufs_cfg *cfg = qmp->cfg;
808 void __iomem *pcs = qmp->pcs;
809 void __iomem *status;
810 unsigned int val;
811 int ret;
812
813 /* Power down PHY */
814 qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
815
816 qmp_ufs_init_registers(qmp, cfg);
817
818 if (cfg->no_pcs_sw_reset) {
819 ret = qmp_ufs_do_reset(qmp);
820 if (ret) {
821 dev_err(phy->dev, "qmp reset failed\n");
822 return ret;
823 }
824 }
825
826 /* Pull PHY out of reset state */
827 if (!cfg->no_pcs_sw_reset)
828 qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
829
830 /* start SerDes */
831 qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START);
832
833 status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
834 ret = readl_poll_timeout(status, val, (val & PCS_READY), PHY_INIT_COMPLETE_TIMEOUT);
835 if (ret) {
836 dev_err(phy->dev, "phy initialization timed-out\n");
837 return ret;
838 }
839
840 return 0;
841}
842
843static int qmp_ufs_power_off(struct phy *phy)
844{
845 struct qmp_ufs_priv *qmp = dev_get_priv(phy->dev);
846 const struct qmp_ufs_cfg *cfg = qmp->cfg;
847
848 /* PHY reset */
849 qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
850
851 /* stop SerDes and Phy-Coding-Sublayer */
852 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL],
853 SERDES_START | PCS_START);
854
855 /* Put PHY into POWER DOWN state: active low */
856 qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
857 SW_PWRDN);
858
859 clk_release_all(qmp->clks, qmp->clk_count);
860
861 return 0;
862}
863
864static int qmp_ufs_vreg_init(struct udevice *dev, struct qmp_ufs_priv *qmp)
865{
866 /* TOFIX: Add regulator support, but they should be voted at boot time already */
867
868 return 0;
869}
870
871static int qmp_ufs_reset_init(struct udevice *dev, struct qmp_ufs_priv *qmp)
872{
873 const struct qmp_ufs_cfg *cfg = qmp->cfg;
874 int num = cfg->num_resets;
875 int i, ret;
876
877 qmp->reset_count = 0;
878 qmp->resets = devm_kcalloc(dev, num, sizeof(*qmp->resets), GFP_KERNEL);
879 if (!qmp->resets)
880 return -ENOMEM;
881
882 for (i = 0; i < num; i++) {
883 ret = reset_get_by_index(dev, i, &qmp->resets[i]);
884 if (ret < 0) {
885 dev_err(dev, "failed to get reset %d\n", i);
886 goto reset_get_err;
887 }
888
889 ++qmp->reset_count;
890 }
891
892 return 0;
893
894reset_get_err:
895 ret = reset_release_all(qmp->resets, qmp->reset_count);
896 if (ret)
897 dev_warn(dev, "failed to disable all resets\n");
898
899 return ret;
900}
901
902static int qmp_ufs_clk_init(struct udevice *dev, struct qmp_ufs_priv *qmp)
903{
904 const struct qmp_ufs_cfg *cfg = qmp->cfg;
905 int num = cfg->num_clks;
906 int i, ret;
907
908 qmp->clk_count = 0;
909 qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
910 if (!qmp->clks)
911 return -ENOMEM;
912
913 for (i = 0; i < num; i++) {
914 ret = clk_get_by_index(dev, i, &qmp->clks[i]);
915 if (ret < 0)
916 goto clk_get_err;
917
918 ret = clk_enable(&qmp->clks[i]);
919 if (ret && ret != -ENOSYS) {
920 dev_err(dev, "failed to enable clock %d\n", i);
921 goto clk_get_err;
922 }
923
924 ++qmp->clk_count;
925 }
926
927 return 0;
928
929clk_get_err:
930 ret = clk_release_all(qmp->clks, qmp->clk_count);
931 if (ret)
932 dev_warn(dev, "failed to disable all clocks\n");
933
934 return ret;
935}
936
937static int qmp_ufs_probe_generic_child(struct udevice *dev,
938 ofnode child)
939{
940 struct qmp_ufs_priv *qmp = dev_get_priv(dev);
941 const struct qmp_ufs_cfg *cfg = qmp->cfg;
942 struct resource res;
943 int ret;
944
945 /*
946 * Get memory resources for the PHY:
947 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
948 * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
949 * For single lane PHYs: pcs_misc (optional) -> 3.
950 */
951 ret = ofnode_read_resource(child, 0, &res);
952 if (ret) {
953 dev_err(dev, "can't get reg property of child %s\n",
954 ofnode_get_name(child));
955 return ret;
956 }
957
958 qmp->tx = (void __iomem *)res.start;
959
960 ret = ofnode_read_resource(child, 1, &res);
961 if (ret) {
962 dev_err(dev, "can't get reg property of child %s\n",
963 ofnode_get_name(child));
964 return ret;
965 }
966
967 qmp->rx = (void __iomem *)res.start;
968
969 ret = ofnode_read_resource(child, 2, &res);
970 if (ret) {
971 dev_err(dev, "can't get reg property of child %s\n",
972 ofnode_get_name(child));
973 return ret;
974 }
975
976 qmp->pcs = (void __iomem *)res.start;
977
978 if (cfg->lanes >= 2) {
979 ret = ofnode_read_resource(child, 3, &res);
980 if (ret) {
981 dev_err(dev, "can't get reg property of child %s\n",
982 ofnode_get_name(child));
983 return ret;
984 }
985
986 qmp->tx2 = (void __iomem *)res.start;
987
988 ret = ofnode_read_resource(child, 4, &res);
989 if (ret) {
990 dev_err(dev, "can't get reg property of child %s\n",
991 ofnode_get_name(child));
992 return ret;
993 }
994
995 qmp->rx2 = (void __iomem *)res.start;
996
997 ret = ofnode_read_resource(child, 5, &res);
998 if (ret)
999 qmp->pcs_misc = NULL;
1000 } else {
1001 ret = ofnode_read_resource(child, 3, &res);
1002 if (ret)
1003 qmp->pcs_misc = NULL;
1004 }
1005
1006 return 0;
1007}
1008
1009static int qmp_ufs_probe_dt_children(struct udevice *dev)
1010{
1011 int ret;
1012 ofnode child;
1013
1014 ofnode_for_each_subnode(child, dev_ofnode(dev)) {
1015 ret = qmp_ufs_probe_generic_child(dev, child);
1016 if (ret) {
1017 dev_err(dev, "Cannot parse child %s:%d\n",
1018 ofnode_get_name(child), ret);
1019 return ret;
1020 }
1021 }
1022
1023 return 0;
1024}
1025
1026static int qmp_ufs_probe(struct udevice *dev)
1027{
1028 struct qmp_ufs_priv *qmp = dev_get_priv(dev);
1029 int ret;
1030
1031 qmp->serdes = (void __iomem *)dev_read_addr(dev);
1032 if (IS_ERR(qmp->serdes))
1033 return PTR_ERR(qmp->serdes);
1034
1035 qmp->cfg = (const struct qmp_ufs_cfg *)dev_get_driver_data(dev);
1036 if (!qmp->cfg)
1037 return -EINVAL;
1038
1039 ret = qmp_ufs_clk_init(dev, qmp);
1040 if (ret) {
1041 dev_err(dev, "failed to get UFS clks\n");
1042 return ret;
1043 }
1044
1045 ret = qmp_ufs_vreg_init(dev, qmp);
1046 if (ret) {
1047 dev_err(dev, "failed to get UFS voltage regulators\n");
1048 return ret;
1049 }
1050
1051 if (qmp->cfg->no_pcs_sw_reset) {
1052 ret = qmp_ufs_reset_init(dev, qmp);
1053 if (ret) {
1054 dev_err(dev, "failed to get UFS resets\n");
1055 return ret;
1056 }
1057 }
1058
1059 qmp->dev = dev;
1060
1061 if (ofnode_get_child_count(dev_ofnode(dev))) {
1062 ret = qmp_ufs_probe_dt_children(dev);
1063 if (ret) {
1064 dev_err(dev, "failed to get UFS dt regs\n");
1065 return ret;
1066 }
1067 } else {
1068 const struct qmp_ufs_offsets *offs = qmp->cfg->offsets;
1069 struct resource res;
1070
1071 if (!qmp->cfg->offsets) {
1072 dev_err(dev, "missing UFS offsets\n");
1073 return -EINVAL;
1074 }
1075
1076 ret = ofnode_read_resource(dev_ofnode(dev), 0, &res);
1077 if (ret) {
1078 dev_err(dev, "can't get reg property\n");
1079 return ret;
1080 }
1081
1082 qmp->serdes = (void __iomem *)res.start + offs->serdes;
1083 qmp->pcs = (void __iomem *)res.start + offs->pcs;
1084 qmp->tx = (void __iomem *)res.start + offs->tx;
1085 qmp->rx = (void __iomem *)res.start + offs->rx;
1086
1087 if (qmp->cfg->lanes >= 2) {
1088 qmp->tx2 = (void __iomem *)res.start + offs->tx2;
1089 qmp->rx2 = (void __iomem *)res.start + offs->rx2;
1090 }
1091 }
1092
1093 return 0;
1094}
1095
1096static struct phy_ops qmp_ufs_ops = {
1097 .power_on = qmp_ufs_power_on,
1098 .power_off = qmp_ufs_power_off,
1099};
1100
1101static const struct udevice_id qmp_ufs_ids[] = {
1102 { .compatible = "qcom,sdm845-qmp-ufs-phy", .data = (ulong)&sdm845_ufsphy_cfg },
1103 { .compatible = "qcom,sm8250-qmp-ufs-phy", .data = (ulong)&sm8250_ufsphy_cfg },
1104 { .compatible = "qcom,sm8550-qmp-ufs-phy", .data = (ulong)&sm8550_ufsphy_cfg },
1105 { .compatible = "qcom,sm8650-qmp-ufs-phy", .data = (ulong)&sm8650_ufsphy_cfg },
1106 { }
1107};
1108
1109U_BOOT_DRIVER(qcom_qmp_ufs) = {
1110 .name = "qcom-qmp-ufs",
1111 .id = UCLASS_PHY,
1112 .of_match = qmp_ufs_ids,
1113 .ops = &qmp_ufs_ops,
1114 .probe = qmp_ufs_probe,
1115 .priv_auto = sizeof(struct qmp_ufs_priv),
1116};