2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include <linux/clk.h>
16 #include <linux/clk-provider.h>
17 #include <linux/delay.h>
18 #include <linux/err.h>
20 #include <linux/iopoll.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
24 #include <linux/of_device.h>
25 #include <linux/of_address.h>
26 #include <linux/phy/phy.h>
27 #include <linux/platform_device.h>
28 #include <linux/regulator/consumer.h>
29 #include <linux/reset.h>
30 #include <linux/slab.h>
32 #include <dt-bindings/phy/phy.h>
34 /* QMP PHY QSERDES COM registers */
35 #define QSERDES_COM_BG_TIMER 0x00c
36 #define QSERDES_COM_SSC_EN_CENTER 0x010
37 #define QSERDES_COM_SSC_ADJ_PER1 0x014
38 #define QSERDES_COM_SSC_ADJ_PER2 0x018
39 #define QSERDES_COM_SSC_PER1 0x01c
40 #define QSERDES_COM_SSC_PER2 0x020
41 #define QSERDES_COM_SSC_STEP_SIZE1 0x024
42 #define QSERDES_COM_SSC_STEP_SIZE2 0x028
43 #define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034
44 #define QSERDES_COM_CLK_ENABLE1 0x038
45 #define QSERDES_COM_SYS_CLK_CTRL 0x03c
46 #define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040
47 #define QSERDES_COM_PLL_IVCO 0x048
48 #define QSERDES_COM_LOCK_CMP1_MODE0 0x04c
49 #define QSERDES_COM_LOCK_CMP2_MODE0 0x050
50 #define QSERDES_COM_LOCK_CMP3_MODE0 0x054
51 #define QSERDES_COM_LOCK_CMP1_MODE1 0x058
52 #define QSERDES_COM_LOCK_CMP2_MODE1 0x05c
53 #define QSERDES_COM_LOCK_CMP3_MODE1 0x060
54 #define QSERDES_COM_BG_TRIM 0x070
55 #define QSERDES_COM_CLK_EP_DIV 0x074
56 #define QSERDES_COM_CP_CTRL_MODE0 0x078
57 #define QSERDES_COM_CP_CTRL_MODE1 0x07c
58 #define QSERDES_COM_PLL_RCTRL_MODE0 0x084
59 #define QSERDES_COM_PLL_RCTRL_MODE1 0x088
60 #define QSERDES_COM_PLL_CCTRL_MODE0 0x090
61 #define QSERDES_COM_PLL_CCTRL_MODE1 0x094
62 #define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
63 #define QSERDES_COM_RESETSM_CNTRL 0x0b4
64 #define QSERDES_COM_RESTRIM_CTRL 0x0bc
65 #define QSERDES_COM_RESCODE_DIV_NUM 0x0c4
66 #define QSERDES_COM_LOCK_CMP_EN 0x0c8
67 #define QSERDES_COM_LOCK_CMP_CFG 0x0cc
68 #define QSERDES_COM_DEC_START_MODE0 0x0d0
69 #define QSERDES_COM_DEC_START_MODE1 0x0d4
70 #define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc
71 #define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0
72 #define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4
73 #define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8
74 #define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec
75 #define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0
76 #define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108
77 #define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c
78 #define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110
79 #define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114
80 #define QSERDES_COM_VCO_TUNE_CTRL 0x124
81 #define QSERDES_COM_VCO_TUNE_MAP 0x128
82 #define QSERDES_COM_VCO_TUNE1_MODE0 0x12c
83 #define QSERDES_COM_VCO_TUNE2_MODE0 0x130
84 #define QSERDES_COM_VCO_TUNE1_MODE1 0x134
85 #define QSERDES_COM_VCO_TUNE2_MODE1 0x138
86 #define QSERDES_COM_VCO_TUNE_TIMER1 0x144
87 #define QSERDES_COM_VCO_TUNE_TIMER2 0x148
88 #define QSERDES_COM_BG_CTRL 0x170
89 #define QSERDES_COM_CLK_SELECT 0x174
90 #define QSERDES_COM_HSCLK_SEL 0x178
91 #define QSERDES_COM_CORECLK_DIV 0x184
92 #define QSERDES_COM_CORE_CLK_EN 0x18c
93 #define QSERDES_COM_C_READY_STATUS 0x190
94 #define QSERDES_COM_CMN_CONFIG 0x194
95 #define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c
96 #define QSERDES_COM_DEBUG_BUS0 0x1a0
97 #define QSERDES_COM_DEBUG_BUS1 0x1a4
98 #define QSERDES_COM_DEBUG_BUS2 0x1a8
99 #define QSERDES_COM_DEBUG_BUS3 0x1ac
100 #define QSERDES_COM_DEBUG_BUS_SEL 0x1b0
101 #define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc
103 /* QMP PHY TX registers */
104 #define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054
105 #define QSERDES_TX_DEBUG_BUS_SEL 0x064
106 #define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068
107 #define QSERDES_TX_LANE_MODE 0x094
108 #define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac
110 /* QMP PHY RX registers */
111 #define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
112 #define QSERDES_RX_UCDR_SO_GAIN 0x01c
113 #define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
114 #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
115 #define QSERDES_RX_RX_TERM_BW 0x090
116 #define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4
117 #define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8
118 #define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc
119 #define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0
120 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8
121 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc
122 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0
123 #define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108
124 #define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c
125 #define QSERDES_RX_SIGDET_ENABLES 0x110
126 #define QSERDES_RX_SIGDET_CNTRL 0x114
127 #define QSERDES_RX_SIGDET_LVL 0x118
128 #define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c
129 #define QSERDES_RX_RX_BAND 0x120
130 #define QSERDES_RX_RX_INTERFACE_MODE 0x12c
132 /* QMP PHY PCS registers */
133 #define QPHY_POWER_DOWN_CONTROL 0x04
134 #define QPHY_TXDEEMPH_M6DB_V0 0x24
135 #define QPHY_TXDEEMPH_M3P5DB_V0 0x28
136 #define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
137 #define QPHY_RX_IDLE_DTCT_CNTRL 0x58
138 #define QPHY_POWER_STATE_CONFIG1 0x60
139 #define QPHY_POWER_STATE_CONFIG2 0x64
140 #define QPHY_POWER_STATE_CONFIG4 0x6c
141 #define QPHY_LOCK_DETECT_CONFIG1 0x80
142 #define QPHY_LOCK_DETECT_CONFIG2 0x84
143 #define QPHY_LOCK_DETECT_CONFIG3 0x88
144 #define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
145 #define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
147 /* QPHY_SW_RESET bit */
148 #define SW_RESET BIT(0)
149 /* QPHY_POWER_DOWN_CONTROL */
150 #define SW_PWRDN BIT(0)
151 #define REFCLK_DRV_DSBL BIT(1)
152 /* QPHY_START_CONTROL bits */
153 #define SERDES_START BIT(0)
154 #define PCS_START BIT(1)
155 #define PLL_READY_GATE_EN BIT(3)
156 /* QPHY_PCS_STATUS bit */
157 #define PHYSTATUS BIT(6)
158 /* QPHY_COM_PCS_READY_STATUS bit */
159 #define PCS_READY BIT(0)
161 #define PHY_INIT_COMPLETE_TIMEOUT 1000
162 #define POWER_DOWN_DELAY_US_MIN 10
163 #define POWER_DOWN_DELAY_US_MAX 11
165 #define MAX_PROP_NAME 32
167 struct qmp_phy_init_tbl
{
171 * register part of layout ?
172 * if yes, then offset gives index in the reg-layout
177 #define QMP_PHY_INIT_CFG(o, v) \
183 #define QMP_PHY_INIT_CFG_L(o, v) \
190 /* set of registers with offsets different per-PHY */
191 enum qphy_reg_layout
{
192 /* Common block control registers */
194 QPHY_COM_POWER_DOWN_CONTROL
,
195 QPHY_COM_START_CONTROL
,
196 QPHY_COM_PCS_READY_STATUS
,
198 QPHY_PLL_LOCK_CHK_DLY_TIME
,
202 QPHY_FLL_CNT_VAL_H_TOL
,
206 QPHY_PCS_READY_STATUS
,
209 static const unsigned int pciephy_regs_layout
[] = {
210 [QPHY_COM_SW_RESET
] = 0x400,
211 [QPHY_COM_POWER_DOWN_CONTROL
] = 0x404,
212 [QPHY_COM_START_CONTROL
] = 0x408,
213 [QPHY_COM_PCS_READY_STATUS
] = 0x448,
214 [QPHY_PLL_LOCK_CHK_DLY_TIME
] = 0xa8,
215 [QPHY_FLL_CNTRL1
] = 0xc4,
216 [QPHY_FLL_CNTRL2
] = 0xc8,
217 [QPHY_FLL_CNT_VAL_L
] = 0xcc,
218 [QPHY_FLL_CNT_VAL_H_TOL
] = 0xd0,
219 [QPHY_FLL_MAN_CODE
] = 0xd4,
220 [QPHY_SW_RESET
] = 0x00,
221 [QPHY_START_CTRL
] = 0x08,
222 [QPHY_PCS_READY_STATUS
] = 0x174,
225 static const unsigned int usb3phy_regs_layout
[] = {
226 [QPHY_FLL_CNTRL1
] = 0xc0,
227 [QPHY_FLL_CNTRL2
] = 0xc4,
228 [QPHY_FLL_CNT_VAL_L
] = 0xc8,
229 [QPHY_FLL_CNT_VAL_H_TOL
] = 0xcc,
230 [QPHY_FLL_MAN_CODE
] = 0xd0,
231 [QPHY_SW_RESET
] = 0x00,
232 [QPHY_START_CTRL
] = 0x08,
233 [QPHY_PCS_READY_STATUS
] = 0x17c,
236 static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl
[] = {
237 QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN
, 0x1c),
238 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1
, 0x10),
239 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT
, 0x33),
240 QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG
, 0x06),
241 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN
, 0x42),
242 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP
, 0x00),
243 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1
, 0xff),
244 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2
, 0x1f),
245 QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL
, 0x01),
246 QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL
, 0x01),
247 QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN
, 0x00),
248 QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV
, 0x0a),
249 QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER
, 0x09),
250 QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0
, 0x82),
251 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0
, 0x03),
252 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0
, 0x55),
253 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0
, 0x55),
254 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0
, 0x00),
255 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0
, 0x1a),
256 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0
, 0x0a),
257 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT
, 0x33),
258 QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL
, 0x02),
259 QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE
, 0x1f),
260 QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL
, 0x04),
261 QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0
, 0x0b),
262 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0
, 0x16),
263 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0
, 0x28),
264 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0
, 0x00),
265 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0
, 0x80),
266 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER
, 0x01),
267 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1
, 0x31),
268 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2
, 0x01),
269 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1
, 0x02),
270 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2
, 0x00),
271 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1
, 0x2f),
272 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2
, 0x19),
273 QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM
, 0x15),
274 QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM
, 0x0f),
275 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO
, 0x0f),
276 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV
, 0x19),
277 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1
, 0x10),
278 QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL
, 0x00),
279 QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM
, 0x40),
282 static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl
[] = {
283 QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN
, 0x45),
284 QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE
, 0x06),
287 static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl
[] = {
288 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES
, 0x1c),
289 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2
, 0x01),
290 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3
, 0x00),
291 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4
, 0xdb),
292 QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND
, 0x18),
293 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN
, 0x04),
294 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF
, 0x04),
295 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE
, 0x4b),
296 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL
, 0x14),
297 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL
, 0x19),
300 static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl
[] = {
301 QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL
, 0x4c),
302 QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK
, 0x00),
303 QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK
, 0x01),
305 QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME
, 0x05),
307 QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE
, 0x05),
308 QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL
, 0x02),
309 QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4
, 0x00),
310 QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1
, 0xa3),
311 QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0
, 0x0e),
314 static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl
[] = {
315 QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL
, 0x14),
316 QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN
, 0x08),
317 QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT
, 0x30),
318 QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG
, 0x06),
319 QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL
, 0x01),
320 QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL
, 0x00),
321 QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM
, 0x0f),
322 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO
, 0x0f),
323 QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL
, 0x04),
324 /* PLL and Loop filter settings */
325 QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0
, 0x82),
326 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0
, 0x55),
327 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0
, 0x55),
328 QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0
, 0x03),
329 QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0
, 0x0b),
330 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0
, 0x16),
331 QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0
, 0x28),
332 QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0
, 0x80),
333 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL
, 0x00),
334 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0
, 0x15),
335 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0
, 0x34),
336 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0
, 0x00),
337 QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN
, 0x00),
338 QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG
, 0x00),
339 QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP
, 0x00),
340 QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER
, 0x0a),
342 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER
, 0x01),
343 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1
, 0x31),
344 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2
, 0x01),
345 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1
, 0x00),
346 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2
, 0x00),
347 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1
, 0xde),
348 QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2
, 0x07),
351 static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl
[] = {
352 QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN
, 0x45),
353 QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2
, 0x12),
354 QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE
, 0x06),
357 static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl
[] = {
358 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN
, 0x0b),
359 QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN
, 0x04),
360 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2
, 0x02),
361 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3
, 0x4c),
362 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4
, 0xbb),
363 QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1
, 0x77),
364 QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2
, 0x80),
365 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL
, 0x03),
366 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL
, 0x18),
367 QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL
, 0x16),
370 static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl
[] = {
372 QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2
, 0x03),
373 QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1
, 0x02),
374 QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L
, 0x09),
375 QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL
, 0x42),
376 QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE
, 0x85),
378 /* Lock Det settings */
379 QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1
, 0xd1),
380 QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2
, 0x1f),
381 QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3
, 0x47),
382 QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2
, 0x08),
385 /* struct qmp_phy_cfg - per-PHY initialization config */
387 /* phy-type - PCIE/UFS/USB */
389 /* number of lanes provided by phy */
392 /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
393 const struct qmp_phy_init_tbl
*serdes_tbl
;
395 const struct qmp_phy_init_tbl
*tx_tbl
;
397 const struct qmp_phy_init_tbl
*rx_tbl
;
399 const struct qmp_phy_init_tbl
*pcs_tbl
;
402 /* clock ids to be requested */
403 const char * const *clk_list
;
405 /* resets to be requested */
406 const char * const *reset_list
;
408 /* regulators to be requested */
409 const char * const *vreg_list
;
412 /* array of registers with different offsets */
413 const unsigned int *regs
;
415 unsigned int start_ctrl
;
416 unsigned int pwrdn_ctrl
;
417 unsigned int mask_pcs_ready
;
418 unsigned int mask_com_pcs_ready
;
420 /* true, if PHY has a separate PHY_COM control block */
421 bool has_phy_com_ctrl
;
422 /* true, if PHY has a reset for individual lanes */
424 /* true, if PHY needs delay after POWER_DOWN */
425 bool has_pwrdn_delay
;
426 /* power_down delay in usec */
432 * struct qmp_phy - per-lane phy descriptor
435 * @tx: iomapped memory space for lane's tx
436 * @rx: iomapped memory space for lane's rx
437 * @pcs: iomapped memory space for lane's pcs
438 * @pipe_clk: pipe lock
440 * @qmp: QMP phy to which this lane belongs
441 * @lane_rst: lane's reset controller
448 struct clk
*pipe_clk
;
450 struct qcom_qmp
*qmp
;
451 struct reset_control
*lane_rst
;
455 * struct qcom_qmp - structure holding QMP phy block attributes
458 * @serdes: iomapped memory space for phy's serdes
460 * @clks: array of clocks required by phy
461 * @resets: array of resets required by phy
462 * @vregs: regulator supplies bulk data
464 * @cfg: phy specific configuration
465 * @phys: array of per-lane phy descriptors
466 * @phy_mutex: mutex lock for PHY common block initialization
467 * @init_count: phy common block initialization count
471 void __iomem
*serdes
;
474 struct reset_control
**resets
;
475 struct regulator_bulk_data
*vregs
;
477 const struct qmp_phy_cfg
*cfg
;
478 struct qmp_phy
**phys
;
480 struct mutex phy_mutex
;
484 static inline void qphy_setbits(void __iomem
*base
, u32 offset
, u32 val
)
488 reg
= readl(base
+ offset
);
490 writel(reg
, base
+ offset
);
492 /* ensure that above write is through */
493 readl(base
+ offset
);
496 static inline void qphy_clrbits(void __iomem
*base
, u32 offset
, u32 val
)
500 reg
= readl(base
+ offset
);
502 writel(reg
, base
+ offset
);
504 /* ensure that above write is through */
505 readl(base
+ offset
);
508 /* list of clocks required by phy */
509 static const char * const msm8996_phy_clk_l
[] = {
510 "aux", "cfg_ahb", "ref",
514 static const char * const msm8996_pciephy_reset_l
[] = {
515 "phy", "common", "cfg",
518 static const char * const msm8996_usb3phy_reset_l
[] = {
522 /* list of regulators */
523 static const char * const msm8996_phy_vreg_l
[] = {
524 "vdda-phy", "vdda-pll",
527 static const struct qmp_phy_cfg msm8996_pciephy_cfg
= {
528 .type
= PHY_TYPE_PCIE
,
531 .serdes_tbl
= msm8996_pcie_serdes_tbl
,
532 .serdes_tbl_num
= ARRAY_SIZE(msm8996_pcie_serdes_tbl
),
533 .tx_tbl
= msm8996_pcie_tx_tbl
,
534 .tx_tbl_num
= ARRAY_SIZE(msm8996_pcie_tx_tbl
),
535 .rx_tbl
= msm8996_pcie_rx_tbl
,
536 .rx_tbl_num
= ARRAY_SIZE(msm8996_pcie_rx_tbl
),
537 .pcs_tbl
= msm8996_pcie_pcs_tbl
,
538 .pcs_tbl_num
= ARRAY_SIZE(msm8996_pcie_pcs_tbl
),
539 .clk_list
= msm8996_phy_clk_l
,
540 .num_clks
= ARRAY_SIZE(msm8996_phy_clk_l
),
541 .reset_list
= msm8996_pciephy_reset_l
,
542 .num_resets
= ARRAY_SIZE(msm8996_pciephy_reset_l
),
543 .vreg_list
= msm8996_phy_vreg_l
,
544 .num_vregs
= ARRAY_SIZE(msm8996_phy_vreg_l
),
545 .regs
= pciephy_regs_layout
,
547 .start_ctrl
= PCS_START
| PLL_READY_GATE_EN
,
548 .pwrdn_ctrl
= SW_PWRDN
| REFCLK_DRV_DSBL
,
549 .mask_com_pcs_ready
= PCS_READY
,
551 .has_phy_com_ctrl
= true,
552 .has_lane_rst
= true,
553 .has_pwrdn_delay
= true,
554 .pwrdn_delay_min
= POWER_DOWN_DELAY_US_MIN
,
555 .pwrdn_delay_max
= POWER_DOWN_DELAY_US_MAX
,
558 static const struct qmp_phy_cfg msm8996_usb3phy_cfg
= {
559 .type
= PHY_TYPE_USB3
,
562 .serdes_tbl
= msm8996_usb3_serdes_tbl
,
563 .serdes_tbl_num
= ARRAY_SIZE(msm8996_usb3_serdes_tbl
),
564 .tx_tbl
= msm8996_usb3_tx_tbl
,
565 .tx_tbl_num
= ARRAY_SIZE(msm8996_usb3_tx_tbl
),
566 .rx_tbl
= msm8996_usb3_rx_tbl
,
567 .rx_tbl_num
= ARRAY_SIZE(msm8996_usb3_rx_tbl
),
568 .pcs_tbl
= msm8996_usb3_pcs_tbl
,
569 .pcs_tbl_num
= ARRAY_SIZE(msm8996_usb3_pcs_tbl
),
570 .clk_list
= msm8996_phy_clk_l
,
571 .num_clks
= ARRAY_SIZE(msm8996_phy_clk_l
),
572 .reset_list
= msm8996_usb3phy_reset_l
,
573 .num_resets
= ARRAY_SIZE(msm8996_usb3phy_reset_l
),
574 .vreg_list
= msm8996_phy_vreg_l
,
575 .num_vregs
= ARRAY_SIZE(msm8996_phy_vreg_l
),
576 .regs
= usb3phy_regs_layout
,
578 .start_ctrl
= SERDES_START
| PCS_START
,
579 .pwrdn_ctrl
= SW_PWRDN
,
580 .mask_pcs_ready
= PHYSTATUS
,
583 static void qcom_qmp_phy_configure(void __iomem
*base
,
584 const unsigned int *regs
,
585 const struct qmp_phy_init_tbl tbl
[],
589 const struct qmp_phy_init_tbl
*t
= tbl
;
594 for (i
= 0; i
< num
; i
++, t
++) {
596 writel(t
->val
, base
+ regs
[t
->offset
]);
598 writel(t
->val
, base
+ t
->offset
);
602 static int qcom_qmp_phy_poweron(struct phy
*phy
)
604 struct qmp_phy
*qphy
= phy_get_drvdata(phy
);
605 struct qcom_qmp
*qmp
= qphy
->qmp
;
606 int num
= qmp
->cfg
->num_vregs
;
609 dev_vdbg(&phy
->dev
, "Powering on QMP phy\n");
611 /* turn on regulator supplies */
612 ret
= regulator_bulk_enable(num
, qmp
->vregs
);
614 dev_err(qmp
->dev
, "failed to enable regulators, err=%d\n", ret
);
618 ret
= clk_prepare_enable(qphy
->pipe_clk
);
620 dev_err(qmp
->dev
, "pipe_clk enable failed, err=%d\n", ret
);
621 regulator_bulk_disable(num
, qmp
->vregs
);
628 static int qcom_qmp_phy_poweroff(struct phy
*phy
)
630 struct qmp_phy
*qphy
= phy_get_drvdata(phy
);
631 struct qcom_qmp
*qmp
= qphy
->qmp
;
633 clk_disable_unprepare(qphy
->pipe_clk
);
635 regulator_bulk_disable(qmp
->cfg
->num_vregs
, qmp
->vregs
);
640 static int qcom_qmp_phy_com_init(struct qcom_qmp
*qmp
)
642 const struct qmp_phy_cfg
*cfg
= qmp
->cfg
;
643 void __iomem
*serdes
= qmp
->serdes
;
646 mutex_lock(&qmp
->phy_mutex
);
647 if (qmp
->init_count
++) {
648 mutex_unlock(&qmp
->phy_mutex
);
652 for (i
= 0; i
< cfg
->num_resets
; i
++) {
653 ret
= reset_control_deassert(qmp
->resets
[i
]);
655 dev_err(qmp
->dev
, "%s reset deassert failed\n",
656 qmp
->cfg
->reset_list
[i
]);
658 reset_control_assert(qmp
->resets
[i
]);
663 if (cfg
->has_phy_com_ctrl
)
664 qphy_setbits(serdes
, cfg
->regs
[QPHY_COM_POWER_DOWN_CONTROL
],
667 /* Serdes configuration */
668 qcom_qmp_phy_configure(serdes
, cfg
->regs
, cfg
->serdes_tbl
,
669 cfg
->serdes_tbl_num
);
671 if (cfg
->has_phy_com_ctrl
) {
672 void __iomem
*status
;
673 unsigned int mask
, val
;
675 qphy_clrbits(serdes
, cfg
->regs
[QPHY_COM_SW_RESET
], SW_RESET
);
676 qphy_setbits(serdes
, cfg
->regs
[QPHY_COM_START_CONTROL
],
677 SERDES_START
| PCS_START
);
679 status
= serdes
+ cfg
->regs
[QPHY_COM_PCS_READY_STATUS
];
680 mask
= cfg
->mask_com_pcs_ready
;
682 ret
= readl_poll_timeout(status
, val
, (val
& mask
), 10,
683 PHY_INIT_COMPLETE_TIMEOUT
);
686 "phy common block init timed-out\n");
691 mutex_unlock(&qmp
->phy_mutex
);
697 reset_control_assert(qmp
->resets
[i
]);
699 mutex_unlock(&qmp
->phy_mutex
);
703 static int qcom_qmp_phy_com_exit(struct qcom_qmp
*qmp
)
705 const struct qmp_phy_cfg
*cfg
= qmp
->cfg
;
706 void __iomem
*serdes
= qmp
->serdes
;
707 int i
= cfg
->num_resets
;
709 mutex_lock(&qmp
->phy_mutex
);
710 if (--qmp
->init_count
) {
711 mutex_unlock(&qmp
->phy_mutex
);
715 if (cfg
->has_phy_com_ctrl
) {
716 qphy_setbits(serdes
, cfg
->regs
[QPHY_COM_START_CONTROL
],
717 SERDES_START
| PCS_START
);
718 qphy_clrbits(serdes
, cfg
->regs
[QPHY_COM_SW_RESET
],
720 qphy_setbits(serdes
, cfg
->regs
[QPHY_COM_POWER_DOWN_CONTROL
],
725 reset_control_assert(qmp
->resets
[i
]);
727 mutex_unlock(&qmp
->phy_mutex
);
732 /* PHY Initialization */
733 static int qcom_qmp_phy_init(struct phy
*phy
)
735 struct qmp_phy
*qphy
= phy_get_drvdata(phy
);
736 struct qcom_qmp
*qmp
= qphy
->qmp
;
737 const struct qmp_phy_cfg
*cfg
= qmp
->cfg
;
738 void __iomem
*tx
= qphy
->tx
;
739 void __iomem
*rx
= qphy
->rx
;
740 void __iomem
*pcs
= qphy
->pcs
;
741 void __iomem
*status
;
742 unsigned int mask
, val
;
745 dev_vdbg(qmp
->dev
, "Initializing QMP phy\n");
747 for (i
= 0; i
< qmp
->cfg
->num_clks
; i
++) {
748 ret
= clk_prepare_enable(qmp
->clks
[i
]);
750 dev_err(qmp
->dev
, "failed to enable %s clk, err=%d\n",
751 qmp
->cfg
->clk_list
[i
], ret
);
753 clk_disable_unprepare(qmp
->clks
[i
]);
757 ret
= qcom_qmp_phy_com_init(qmp
);
761 if (cfg
->has_lane_rst
) {
762 ret
= reset_control_deassert(qphy
->lane_rst
);
764 dev_err(qmp
->dev
, "lane%d reset deassert failed\n",
770 /* Tx, Rx, and PCS configurations */
771 qcom_qmp_phy_configure(tx
, cfg
->regs
, cfg
->tx_tbl
, cfg
->tx_tbl_num
);
772 qcom_qmp_phy_configure(rx
, cfg
->regs
, cfg
->rx_tbl
, cfg
->rx_tbl_num
);
773 qcom_qmp_phy_configure(pcs
, cfg
->regs
, cfg
->pcs_tbl
, cfg
->pcs_tbl_num
);
776 * Pull out PHY from POWER DOWN state.
777 * This is active low enable signal to power-down PHY.
779 qphy_setbits(pcs
, QPHY_POWER_DOWN_CONTROL
, cfg
->pwrdn_ctrl
);
781 if (cfg
->has_pwrdn_delay
)
782 usleep_range(cfg
->pwrdn_delay_min
, cfg
->pwrdn_delay_max
);
784 /* start SerDes and Phy-Coding-Sublayer */
785 qphy_setbits(pcs
, cfg
->regs
[QPHY_START_CTRL
], cfg
->start_ctrl
);
787 /* Pull PHY out of reset state */
788 qphy_clrbits(pcs
, cfg
->regs
[QPHY_SW_RESET
], SW_RESET
);
790 status
= pcs
+ cfg
->regs
[QPHY_PCS_READY_STATUS
];
791 mask
= cfg
->mask_pcs_ready
;
793 ret
= readl_poll_timeout(status
, val
, !(val
& mask
), 1,
794 PHY_INIT_COMPLETE_TIMEOUT
);
796 dev_err(qmp
->dev
, "phy initialization timed-out\n");
803 if (cfg
->has_lane_rst
)
804 reset_control_assert(qphy
->lane_rst
);
806 qcom_qmp_phy_com_exit(qmp
);
809 clk_disable_unprepare(qmp
->clks
[i
]);
814 static int qcom_qmp_phy_exit(struct phy
*phy
)
816 struct qmp_phy
*qphy
= phy_get_drvdata(phy
);
817 struct qcom_qmp
*qmp
= qphy
->qmp
;
818 const struct qmp_phy_cfg
*cfg
= qmp
->cfg
;
819 int i
= cfg
->num_clks
;
822 qphy_setbits(qphy
->pcs
, cfg
->regs
[QPHY_SW_RESET
], SW_RESET
);
824 /* stop SerDes and Phy-Coding-Sublayer */
825 qphy_clrbits(qphy
->pcs
, cfg
->regs
[QPHY_START_CTRL
], cfg
->start_ctrl
);
827 /* Put PHY into POWER DOWN state: active low */
828 qphy_clrbits(qphy
->pcs
, QPHY_POWER_DOWN_CONTROL
, cfg
->pwrdn_ctrl
);
830 if (cfg
->has_lane_rst
)
831 reset_control_assert(qphy
->lane_rst
);
833 qcom_qmp_phy_com_exit(qmp
);
836 clk_disable_unprepare(qmp
->clks
[i
]);
841 static int qcom_qmp_phy_vreg_init(struct device
*dev
)
843 struct qcom_qmp
*qmp
= dev_get_drvdata(dev
);
844 int num
= qmp
->cfg
->num_vregs
;
847 qmp
->vregs
= devm_kcalloc(dev
, num
, sizeof(qmp
->vregs
), GFP_KERNEL
);
851 for (i
= 0; i
< num
; i
++)
852 qmp
->vregs
[i
].supply
= qmp
->cfg
->vreg_list
[i
];
854 return devm_regulator_bulk_get(dev
, num
, qmp
->vregs
);
857 static int qcom_qmp_phy_reset_init(struct device
*dev
)
859 struct qcom_qmp
*qmp
= dev_get_drvdata(dev
);
862 qmp
->resets
= devm_kcalloc(dev
, qmp
->cfg
->num_resets
,
863 sizeof(*qmp
->resets
), GFP_KERNEL
);
867 for (i
= 0; i
< qmp
->cfg
->num_resets
; i
++) {
868 struct reset_control
*rst
;
869 const char *name
= qmp
->cfg
->reset_list
[i
];
871 rst
= devm_reset_control_get(dev
, name
);
873 dev_err(dev
, "failed to get %s reset\n", name
);
876 qmp
->resets
[i
] = rst
;
882 static int qcom_qmp_phy_clk_init(struct device
*dev
)
884 struct qcom_qmp
*qmp
= dev_get_drvdata(dev
);
887 qmp
->clks
= devm_kcalloc(dev
, qmp
->cfg
->num_clks
,
888 sizeof(*qmp
->clks
), GFP_KERNEL
);
892 for (i
= 0; i
< qmp
->cfg
->num_clks
; i
++) {
894 const char *name
= qmp
->cfg
->clk_list
[i
];
896 _clk
= devm_clk_get(dev
, name
);
899 if (ret
!= -EPROBE_DEFER
)
900 dev_err(dev
, "failed to get %s clk, %d\n",
911 * Register a fixed rate pipe clock.
913 * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
914 * controls it. The <s>_pipe_clk coming out of the GCC is requested
915 * by the PHY driver for its operations.
916 * We register the <s>_pipe_clksrc here. The gcc driver takes care
917 * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
918 * Below picture shows this relationship.
921 * | PHY block |<<---------------------------------------+
923 * | +-------+ | +-----+ |
924 * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
925 * clk | +-------+ | +-----+
928 static int phy_pipe_clk_register(struct qcom_qmp
*qmp
, int id
)
931 struct clk_fixed_rate
*fixed
;
932 struct clk_init_data init
= { };
934 switch (qmp
->cfg
->type
) {
936 snprintf(name
, sizeof(name
), "usb3_phy_pipe_clk_src");
939 snprintf(name
, sizeof(name
), "pcie_%d_pipe_clk_src", id
);
942 /* not all phys register pipe clocks, so return success */
946 fixed
= devm_kzalloc(qmp
->dev
, sizeof(*fixed
), GFP_KERNEL
);
951 init
.ops
= &clk_fixed_rate_ops
;
953 /* controllers using QMP phys use 125MHz pipe clock interface */
954 fixed
->fixed_rate
= 125000000;
955 fixed
->hw
.init
= &init
;
957 return devm_clk_hw_register(qmp
->dev
, &fixed
->hw
);
960 static const struct phy_ops qcom_qmp_phy_gen_ops
= {
961 .init
= qcom_qmp_phy_init
,
962 .exit
= qcom_qmp_phy_exit
,
963 .power_on
= qcom_qmp_phy_poweron
,
964 .power_off
= qcom_qmp_phy_poweroff
,
965 .owner
= THIS_MODULE
,
969 int qcom_qmp_phy_create(struct device
*dev
, struct device_node
*np
, int id
)
971 struct qcom_qmp
*qmp
= dev_get_drvdata(dev
);
972 struct phy
*generic_phy
;
973 struct qmp_phy
*qphy
;
974 char prop_name
[MAX_PROP_NAME
];
977 qphy
= devm_kzalloc(dev
, sizeof(*qphy
), GFP_KERNEL
);
982 * Get memory resources for each phy lane:
983 * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
985 qphy
->tx
= of_iomap(np
, 0);
986 if (IS_ERR(qphy
->tx
))
987 return PTR_ERR(qphy
->tx
);
989 qphy
->rx
= of_iomap(np
, 1);
990 if (IS_ERR(qphy
->rx
))
991 return PTR_ERR(qphy
->rx
);
993 qphy
->pcs
= of_iomap(np
, 2);
994 if (IS_ERR(qphy
->pcs
))
995 return PTR_ERR(qphy
->pcs
);
998 * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
999 * based phys, so they essentially have pipe clock. So,
1000 * we return error in case phy is USB3 or PIPE type.
1001 * Otherwise, we initialize pipe clock to NULL for
1002 * all phys that don't need this.
1004 snprintf(prop_name
, sizeof(prop_name
), "pipe%d", id
);
1005 qphy
->pipe_clk
= of_clk_get_by_name(np
, prop_name
);
1006 if (IS_ERR(qphy
->pipe_clk
)) {
1007 if (qmp
->cfg
->type
== PHY_TYPE_PCIE
||
1008 qmp
->cfg
->type
== PHY_TYPE_USB3
) {
1009 ret
= PTR_ERR(qphy
->pipe_clk
);
1010 if (ret
!= -EPROBE_DEFER
)
1012 "failed to get lane%d pipe_clk, %d\n",
1016 qphy
->pipe_clk
= NULL
;
1019 /* Get lane reset, if any */
1020 if (qmp
->cfg
->has_lane_rst
) {
1021 snprintf(prop_name
, sizeof(prop_name
), "lane%d", id
);
1022 qphy
->lane_rst
= of_reset_control_get(np
, prop_name
);
1023 if (IS_ERR(qphy
->lane_rst
)) {
1024 dev_err(dev
, "failed to get lane%d reset\n", id
);
1025 return PTR_ERR(qphy
->lane_rst
);
1029 generic_phy
= devm_phy_create(dev
, np
, &qcom_qmp_phy_gen_ops
);
1030 if (IS_ERR(generic_phy
)) {
1031 ret
= PTR_ERR(generic_phy
);
1032 dev_err(dev
, "failed to create qphy %d\n", ret
);
1036 qphy
->phy
= generic_phy
;
1039 qmp
->phys
[id
] = qphy
;
1040 phy_set_drvdata(generic_phy
, qphy
);
1045 static const struct of_device_id qcom_qmp_phy_of_match_table
[] = {
1047 .compatible
= "qcom,msm8996-qmp-pcie-phy",
1048 .data
= &msm8996_pciephy_cfg
,
1050 .compatible
= "qcom,msm8996-qmp-usb3-phy",
1051 .data
= &msm8996_usb3phy_cfg
,
1055 MODULE_DEVICE_TABLE(of
, qcom_qmp_phy_of_match_table
);
1057 static int qcom_qmp_phy_probe(struct platform_device
*pdev
)
1059 struct qcom_qmp
*qmp
;
1060 struct device
*dev
= &pdev
->dev
;
1061 struct resource
*res
;
1062 struct device_node
*child
;
1063 struct phy_provider
*phy_provider
;
1068 qmp
= devm_kzalloc(dev
, sizeof(*qmp
), GFP_KERNEL
);
1073 dev_set_drvdata(dev
, qmp
);
1075 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
1076 base
= devm_ioremap_resource(dev
, res
);
1078 return PTR_ERR(base
);
1080 /* per PHY serdes; usually located at base address */
1083 mutex_init(&qmp
->phy_mutex
);
1085 /* Get the specific init parameters of QMP phy */
1086 qmp
->cfg
= of_device_get_match_data(dev
);
1088 ret
= qcom_qmp_phy_clk_init(dev
);
1092 ret
= qcom_qmp_phy_reset_init(dev
);
1096 ret
= qcom_qmp_phy_vreg_init(dev
);
1098 dev_err(dev
, "failed to get regulator supplies\n");
1102 num
= of_get_available_child_count(dev
->of_node
);
1103 /* do we have a rogue child node ? */
1104 if (num
> qmp
->cfg
->nlanes
)
1107 qmp
->phys
= devm_kcalloc(dev
, num
, sizeof(*qmp
->phys
), GFP_KERNEL
);
1112 for_each_available_child_of_node(dev
->of_node
, child
) {
1113 /* Create per-lane phy */
1114 ret
= qcom_qmp_phy_create(dev
, child
, id
);
1116 dev_err(dev
, "failed to create lane%d phy, %d\n",
1122 * Register the pipe clock provided by phy.
1123 * See function description to see details of this pipe clock.
1125 ret
= phy_pipe_clk_register(qmp
, id
);
1128 "failed to register pipe clock source\n");
1134 phy_provider
= devm_of_phy_provider_register(dev
, of_phy_simple_xlate
);
1135 if (!IS_ERR(phy_provider
))
1136 dev_info(dev
, "Registered Qcom-QMP phy\n");
1138 return PTR_ERR_OR_ZERO(phy_provider
);
1141 static struct platform_driver qcom_qmp_phy_driver
= {
1142 .probe
= qcom_qmp_phy_probe
,
1144 .name
= "qcom-qmp-phy",
1145 .of_match_table
= qcom_qmp_phy_of_match_table
,
1149 module_platform_driver(qcom_qmp_phy_driver
);
1151 MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
1152 MODULE_DESCRIPTION("Qualcomm QMP PHY driver");
1153 MODULE_LICENSE("GPL v2");