1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2023, Linaro Limited
4  */
5 
6 #include <linux/clk.h>
7 #include <linux/ethtool.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/phy/phy.h>
11 #include <linux/platform_device.h>
12 #include <linux/regmap.h>
13 
14 #define QSERDES_QMP_PLL					0x0
15 #define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0		(QSERDES_QMP_PLL + 0x1ac)
16 #define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0		(QSERDES_QMP_PLL + 0x1b0)
17 #define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL		(QSERDES_QMP_PLL + 0x1bc)
18 #define QSERDES_COM_CORE_CLK_EN				(QSERDES_QMP_PLL + 0x174)
19 #define QSERDES_COM_CORECLK_DIV_MODE0			(QSERDES_QMP_PLL + 0x168)
20 #define QSERDES_COM_CP_CTRL_MODE0			(QSERDES_QMP_PLL + 0x74)
21 #define QSERDES_COM_DEC_START_MODE0			(QSERDES_QMP_PLL + 0xbc)
22 #define QSERDES_COM_DIV_FRAC_START1_MODE0		(QSERDES_QMP_PLL + 0xcc)
23 #define QSERDES_COM_DIV_FRAC_START2_MODE0		(QSERDES_QMP_PLL + 0xd0)
24 #define QSERDES_COM_DIV_FRAC_START3_MODE0		(QSERDES_QMP_PLL + 0xd4)
25 #define QSERDES_COM_HSCLK_HS_SWITCH_SEL			(QSERDES_QMP_PLL + 0x15c)
26 #define QSERDES_COM_HSCLK_SEL				(QSERDES_QMP_PLL + 0x158)
27 #define QSERDES_COM_LOCK_CMP1_MODE0			(QSERDES_QMP_PLL + 0xac)
28 #define QSERDES_COM_LOCK_CMP2_MODE0			(QSERDES_QMP_PLL + 0xb0)
29 #define QSERDES_COM_PLL_CCTRL_MODE0			(QSERDES_QMP_PLL + 0x84)
30 #define QSERDES_COM_PLL_IVCO				(QSERDES_QMP_PLL + 0x58)
31 #define QSERDES_COM_PLL_RCTRL_MODE0			(QSERDES_QMP_PLL + 0x7c)
32 #define QSERDES_COM_SYSCLK_EN_SEL			(QSERDES_QMP_PLL + 0x94)
33 #define QSERDES_COM_VCO_TUNE1_MODE0			(QSERDES_QMP_PLL + 0x110)
34 #define QSERDES_COM_VCO_TUNE2_MODE0			(QSERDES_QMP_PLL + 0x114)
35 #define QSERDES_COM_VCO_TUNE_INITVAL2			(QSERDES_QMP_PLL + 0x124)
36 #define QSERDES_COM_C_READY_STATUS			(QSERDES_QMP_PLL + 0x178)
37 #define QSERDES_COM_CMN_STATUS				(QSERDES_QMP_PLL + 0x140)
38 
39 #define QSERDES_RX					0x600
40 #define QSERDES_RX_UCDR_FO_GAIN				(QSERDES_RX + 0x8)
41 #define QSERDES_RX_UCDR_SO_GAIN				(QSERDES_RX + 0x14)
42 #define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN		(QSERDES_RX + 0x30)
43 #define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE	(QSERDES_RX + 0x34)
44 #define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW		(QSERDES_RX + 0x3c)
45 #define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH		(QSERDES_RX + 0x40)
46 #define QSERDES_RX_UCDR_PI_CONTROLS			(QSERDES_RX + 0x44)
47 #define QSERDES_RX_UCDR_PI_CTRL2			(QSERDES_RX + 0x48)
48 #define QSERDES_RX_RX_TERM_BW				(QSERDES_RX + 0x80)
49 #define QSERDES_RX_VGA_CAL_CNTRL2			(QSERDES_RX + 0xd8)
50 #define QSERDES_RX_GM_CAL				(QSERDES_RX + 0xdc)
51 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1		(QSERDES_RX + 0xe8)
52 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2		(QSERDES_RX + 0xec)
53 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3		(QSERDES_RX + 0xf0)
54 #define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4		(QSERDES_RX + 0xf4)
55 #define QSERDES_RX_RX_IDAC_TSETTLE_LOW			(QSERDES_RX + 0xf8)
56 #define QSERDES_RX_RX_IDAC_TSETTLE_HIGH			(QSERDES_RX + 0xfc)
57 #define QSERDES_RX_RX_IDAC_MEASURE_TIME			(QSERDES_RX + 0x100)
58 #define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1		(QSERDES_RX + 0x110)
59 #define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2		(QSERDES_RX + 0x114)
60 #define QSERDES_RX_SIGDET_CNTRL				(QSERDES_RX + 0x11c)
61 #define QSERDES_RX_SIGDET_DEGLITCH_CNTRL		(QSERDES_RX + 0x124)
62 #define QSERDES_RX_RX_BAND				(QSERDES_RX + 0x128)
63 #define QSERDES_RX_RX_MODE_00_LOW			(QSERDES_RX + 0x15c)
64 #define QSERDES_RX_RX_MODE_00_HIGH			(QSERDES_RX + 0x160)
65 #define QSERDES_RX_RX_MODE_00_HIGH2			(QSERDES_RX + 0x164)
66 #define QSERDES_RX_RX_MODE_00_HIGH3			(QSERDES_RX + 0x168)
67 #define QSERDES_RX_RX_MODE_00_HIGH4			(QSERDES_RX + 0x16c)
68 #define QSERDES_RX_RX_MODE_01_LOW			(QSERDES_RX + 0x170)
69 #define QSERDES_RX_RX_MODE_01_HIGH			(QSERDES_RX + 0x174)
70 #define QSERDES_RX_RX_MODE_01_HIGH2			(QSERDES_RX + 0x178)
71 #define QSERDES_RX_RX_MODE_01_HIGH3			(QSERDES_RX + 0x17c)
72 #define QSERDES_RX_RX_MODE_01_HIGH4			(QSERDES_RX + 0x180)
73 #define QSERDES_RX_RX_MODE_10_LOW			(QSERDES_RX + 0x184)
74 #define QSERDES_RX_RX_MODE_10_HIGH			(QSERDES_RX + 0x188)
75 #define QSERDES_RX_RX_MODE_10_HIGH2			(QSERDES_RX + 0x18c)
76 #define QSERDES_RX_RX_MODE_10_HIGH3			(QSERDES_RX + 0x190)
77 #define QSERDES_RX_RX_MODE_10_HIGH4			(QSERDES_RX + 0x194)
78 #define QSERDES_RX_DCC_CTRL1				(QSERDES_RX + 0x1a8)
79 
80 #define QSERDES_TX					0x400
81 #define QSERDES_TX_TX_BAND				(QSERDES_TX + 0x24)
82 #define QSERDES_TX_SLEW_CNTL				(QSERDES_TX + 0x28)
83 #define QSERDES_TX_RES_CODE_LANE_OFFSET_TX		(QSERDES_TX + 0x3c)
84 #define QSERDES_TX_RES_CODE_LANE_OFFSET_RX		(QSERDES_TX + 0x40)
85 #define QSERDES_TX_LANE_MODE_1				(QSERDES_TX + 0x84)
86 #define QSERDES_TX_LANE_MODE_3				(QSERDES_TX + 0x8c)
87 #define QSERDES_TX_RCV_DETECT_LVL_2			(QSERDES_TX + 0xa4)
88 #define QSERDES_TX_TRAN_DRVR_EMP_EN			(QSERDES_TX + 0xc0)
89 
90 #define QSERDES_PCS					0xC00
91 #define QSERDES_PCS_PHY_START				(QSERDES_PCS + 0x0)
92 #define QSERDES_PCS_POWER_DOWN_CONTROL			(QSERDES_PCS + 0x4)
93 #define QSERDES_PCS_SW_RESET				(QSERDES_PCS + 0x8)
94 #define QSERDES_PCS_LINE_RESET_TIME			(QSERDES_PCS + 0xc)
95 #define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL		(QSERDES_PCS + 0x20)
96 #define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL		(QSERDES_PCS + 0x28)
97 #define QSERDES_PCS_TX_MID_TERM_CTRL1			(QSERDES_PCS + 0xd8)
98 #define QSERDES_PCS_TX_MID_TERM_CTRL2			(QSERDES_PCS + 0xdc)
99 #define QSERDES_PCS_SGMII_MISC_CTRL8			(QSERDES_PCS + 0x118)
100 #define QSERDES_PCS_PCS_READY_STATUS			(QSERDES_PCS + 0x94)
101 
102 #define QSERDES_COM_C_READY				BIT(0)
103 #define QSERDES_PCS_READY				BIT(0)
104 #define QSERDES_PCS_SGMIIPHY_READY			BIT(7)
105 #define QSERDES_COM_C_PLL_LOCKED			BIT(1)
106 
107 struct qcom_dwmac_sgmii_phy_data {
108 	struct regmap *regmap;
109 	struct clk *refclk;
110 	int speed;
111 };
112 
113 static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
114 {
115 	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
116 	regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
117 
118 	regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
119 	regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
120 	regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
121 	regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
122 	regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
123 	regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
124 	regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
125 	regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82);
126 	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
127 	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
128 	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
129 	regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24);
130 
131 	regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
132 	regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
133 	regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04);
134 	regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
135 	regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A);
136 	regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
137 	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
138 	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
139 	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
140 
141 	regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05);
142 	regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
143 	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
144 	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
145 	regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
146 	regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
147 	regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
148 	regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
149 
150 	regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
151 	regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
152 	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
153 	regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
154 	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
155 	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
156 	regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
157 	regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
158 	regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04);
159 	regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
160 	regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
161 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
162 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
163 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
164 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
165 	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
166 	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
167 	regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
168 	regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
169 	regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
170 	regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
171 	regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
172 	regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05);
173 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0);
174 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
175 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
176 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09);
177 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1);
178 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
179 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
180 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
181 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
182 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
183 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
184 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
185 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
186 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
187 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
188 	regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
189 
190 	regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
191 	regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
192 	regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
193 	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
194 	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
195 	regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C);
196 	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
197 
198 	regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
199 }
200 
201 static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
202 {
203 	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
204 	regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
205 
206 	regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
207 	regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
208 	regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
209 	regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
210 	regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
211 	regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A);
212 	regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41);
213 	regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A);
214 	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
215 	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20);
216 	regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01);
217 	regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1);
218 
219 	regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
220 	regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
221 	regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03);
222 	regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
223 	regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05);
224 	regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
225 	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
226 	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
227 	regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
228 
229 	regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04);
230 	regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
231 	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
232 	regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
233 	regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
234 	regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
235 	regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
236 	regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
237 
238 	regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
239 	regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
240 	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
241 	regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
242 	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
243 	regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
244 	regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
245 	regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
246 	regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00);
247 	regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
248 	regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
249 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
250 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
251 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
252 	regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
253 	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
254 	regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
255 	regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
256 	regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
257 	regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
258 	regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
259 	regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
260 	regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18);
261 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18);
262 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
263 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
264 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C);
265 	regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8);
266 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
267 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
268 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
269 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
270 	regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
271 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
272 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
273 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
274 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
275 	regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
276 	regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
277 
278 	regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
279 	regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
280 	regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
281 	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
282 	regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
283 	regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C);
284 	regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
285 
286 	regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
287 }
288 
289 static inline int
290 qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,
291 				 unsigned int bit)
292 {
293 	unsigned int val;
294 
295 	return regmap_read_poll_timeout(regmap, reg, val,
296 					val & bit, 1500, 750000);
297 }
298 
299 static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
300 {
301 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
302 	struct device *dev = phy->dev.parent;
303 
304 	switch (data->speed) {
305 	case SPEED_10:
306 	case SPEED_100:
307 	case SPEED_1000:
308 		qcom_dwmac_sgmii_phy_init_1g(data->regmap);
309 		break;
310 	case SPEED_2500:
311 		qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
312 		break;
313 	}
314 
315 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
316 					     QSERDES_COM_C_READY_STATUS,
317 					     QSERDES_COM_C_READY)) {
318 		dev_err(dev, "QSERDES_COM_C_READY_STATUS timed-out");
319 		return -ETIMEDOUT;
320 	}
321 
322 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
323 					     QSERDES_PCS_PCS_READY_STATUS,
324 					     QSERDES_PCS_READY)) {
325 		dev_err(dev, "PCS_READY timed-out");
326 		return -ETIMEDOUT;
327 	}
328 
329 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
330 					     QSERDES_PCS_PCS_READY_STATUS,
331 					     QSERDES_PCS_SGMIIPHY_READY)) {
332 		dev_err(dev, "SGMIIPHY_READY timed-out");
333 		return -ETIMEDOUT;
334 	}
335 
336 	if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
337 					     QSERDES_COM_CMN_STATUS,
338 					     QSERDES_COM_C_PLL_LOCKED)) {
339 		dev_err(dev, "PLL Lock Status timed-out");
340 		return -ETIMEDOUT;
341 	}
342 
343 	return 0;
344 }
345 
346 static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
347 {
348 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
349 
350 	return clk_prepare_enable(data->refclk);
351 }
352 
353 static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
354 {
355 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
356 
357 	regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
358 	regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01);
359 	udelay(100);
360 	regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00);
361 	regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01);
362 
363 	clk_disable_unprepare(data->refclk);
364 
365 	return 0;
366 }
367 
368 static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
369 {
370 	struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
371 
372 	if (speed != data->speed)
373 		data->speed = speed;
374 
375 	return qcom_dwmac_sgmii_phy_calibrate(phy);
376 }
377 
378 static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
379 	.power_on	= qcom_dwmac_sgmii_phy_power_on,
380 	.power_off	= qcom_dwmac_sgmii_phy_power_off,
381 	.set_speed	= qcom_dwmac_sgmii_phy_set_speed,
382 	.calibrate	= qcom_dwmac_sgmii_phy_calibrate,
383 	.owner		= THIS_MODULE,
384 };
385 
386 static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
387 	.reg_bits		= 32,
388 	.val_bits		= 32,
389 	.reg_stride		= 4,
390 	.use_relaxed_mmio	= true,
391 	.disable_locking	= true,
392 };
393 
394 static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
395 {
396 	struct qcom_dwmac_sgmii_phy_data *data;
397 	struct device *dev = &pdev->dev;
398 	struct phy_provider *provider;
399 	void __iomem *base;
400 	struct phy *phy;
401 
402 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
403 	if (!data)
404 		return -ENOMEM;
405 
406 	data->speed = SPEED_10;
407 
408 	base = devm_platform_ioremap_resource(pdev, 0);
409 	if (IS_ERR(base))
410 		return PTR_ERR(base);
411 
412 	data->regmap = devm_regmap_init_mmio(dev, base,
413 					     &qcom_dwmac_sgmii_phy_regmap_cfg);
414 	if (IS_ERR(data->regmap))
415 		return PTR_ERR(data->regmap);
416 
417 	phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
418 	if (IS_ERR(phy))
419 		return PTR_ERR(phy);
420 
421 	data->refclk = devm_clk_get(dev, "sgmi_ref");
422 	if (IS_ERR(data->refclk))
423 		return PTR_ERR(data->refclk);
424 
425 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
426 	if (IS_ERR(provider))
427 		return PTR_ERR(provider);
428 
429 	phy_set_drvdata(phy, data);
430 
431 	return 0;
432 }
433 
434 static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
435 	{ .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
436 	{ },
437 };
438 MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
439 
440 static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
441 	.probe	= qcom_dwmac_sgmii_phy_probe,
442 	.driver = {
443 		.name	= "qcom-dwmac-sgmii-phy",
444 		.of_match_table	= qcom_dwmac_sgmii_phy_of_match,
445 	}
446 };
447 
448 module_platform_driver(qcom_dwmac_sgmii_phy_driver);
449 
450 MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
451 MODULE_LICENSE("GPL");
452