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