blob: c42b28a6ca8e327aced0e2241b45b1b6ef55dad0 [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001// SPDX-License-Identifier: GPL-2.0
2// Copyright (c) 2018-2019 MediaTek Inc.
3
4/* A library for MediaTek SGMII circuit
5 *
6 * Author: Sean Wang <sean.wang@mediatek.com>
7 *
8 */
9
10#include <linux/mfd/syscon.h>
11#include <linux/of.h>
developer38afb1a2023-04-17 09:57:27 +080012#include <linux/phylink.h>
developerfd40db22021-04-29 10:08:25 +080013#include <linux/regmap.h>
14
15#include "mtk_eth_soc.h"
16
developer4e8a3fd2023-04-10 18:05:44 +080017static struct mtk_sgmii_pcs *pcs_to_mtk_sgmii_pcs(struct phylink_pcs *pcs)
18{
19 return container_of(pcs, struct mtk_sgmii_pcs, pcs);
20}
21
22static int mtk_sgmii_xfi_pextp_init(struct mtk_sgmii *ss, struct device_node *r)
developerfd40db22021-04-29 10:08:25 +080023{
24 struct device_node *np;
25 int i;
26
developerfd40db22021-04-29 10:08:25 +080027 for (i = 0; i < MTK_MAX_DEVS; i++) {
developer4e8a3fd2023-04-10 18:05:44 +080028 np = of_parse_phandle(r, "mediatek,xfi_pextp", i);
developerfd40db22021-04-29 10:08:25 +080029 if (!np)
30 break;
31
developer4e8a3fd2023-04-10 18:05:44 +080032 ss->pcs[i].regmap_pextp = syscon_node_to_regmap(np);
33 if (IS_ERR(ss->pcs[i].regmap_pextp))
34 return PTR_ERR(ss->pcs[i].regmap_pextp);
developerf8ac94a2021-07-29 16:40:01 +080035
developer4e8a3fd2023-04-10 18:05:44 +080036 of_node_put(np);
developerfd40db22021-04-29 10:08:25 +080037 }
38
39 return 0;
40}
41
developer4e8a3fd2023-04-10 18:05:44 +080042static int mtk_sgmii_xfi_pll_init(struct mtk_sgmii *ss, struct device_node *r)
43{
44 struct device_node *np;
45
46 np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
47 if (!np)
48 return -1;
49
50 ss->pll = syscon_node_to_regmap(np);
51 if (IS_ERR(ss->pll))
52 return PTR_ERR(ss->pll);
53
54 of_node_put(np);
55
56 return 0;
57}
58
59static int mtk_sgmii_xfi_pll_enable(struct mtk_sgmii *ss)
developer024387a2022-12-07 22:18:27 +080060{
developer024387a2022-12-07 22:18:27 +080061 u32 val = 0;
62
developer4e8a3fd2023-04-10 18:05:44 +080063 if (!ss->pll)
64 return -EINVAL;
65
66 /* Add software workaround for USXGMII PLL TCL issue */
67 regmap_write(ss->pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA);
68
69 regmap_read(ss->pll, XFI_PLL_DIG_GLB8, &val);
70 val |= RG_XFI_PLL_EN;
71 regmap_write(ss->pll, XFI_PLL_DIG_GLB8, val);
72
73 return 0;
74}
75
76void mtk_sgmii_reset(struct mtk_eth *eth, int id)
77{
78 u32 val = 0;
79
80 if (!eth->toprgu)
developer024387a2022-12-07 22:18:27 +080081 return;
82
developer4e8a3fd2023-04-10 18:05:44 +080083 switch (id) {
84 case 0:
developer024387a2022-12-07 22:18:27 +080085 /* Enable software reset */
86 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +080087 val |= SWSYSRST_XFI_PEXPT0_GRST |
88 SWSYSRST_SGMII0_GRST;
developer024387a2022-12-07 22:18:27 +080089 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
90
91 /* Assert SGMII reset */
92 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
93 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +080094 SWSYSRST_XFI_PEXPT0_GRST |
95 SWSYSRST_SGMII0_GRST;
developer024387a2022-12-07 22:18:27 +080096 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
97
98 udelay(100);
99
100 /* De-assert SGMII reset */
101 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
102 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800103 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
104 SWSYSRST_SGMII0_GRST);
developer024387a2022-12-07 22:18:27 +0800105 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
106
107 /* Disable software reset */
108 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800109 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
110 SWSYSRST_SGMII0_GRST);
developer024387a2022-12-07 22:18:27 +0800111 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
112 break;
developer4e8a3fd2023-04-10 18:05:44 +0800113 case 1:
114 /* Enable software reset */
developer024387a2022-12-07 22:18:27 +0800115 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800116 val |= SWSYSRST_XFI_PEXPT1_GRST |
117 SWSYSRST_SGMII1_GRST;
developer024387a2022-12-07 22:18:27 +0800118 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
119
120 /* Assert SGMII reset */
121 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
122 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800123 SWSYSRST_XFI_PEXPT1_GRST |
124 SWSYSRST_SGMII1_GRST;
developer024387a2022-12-07 22:18:27 +0800125 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
126
127 udelay(100);
128
129 /* De-assert SGMII reset */
130 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
131 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800132 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
133 SWSYSRST_SGMII1_GRST);
developer024387a2022-12-07 22:18:27 +0800134 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
135
136 /* Disable software reset */
137 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800138 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
139 SWSYSRST_SGMII1_GRST);
developer024387a2022-12-07 22:18:27 +0800140 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
141 break;
142 }
143
144 mdelay(1);
145}
146
developer1251a932023-05-08 22:22:51 +0800147int mtk_sgmii_need_powerdown(struct mtk_sgmii_pcs *mpcs)
148{
149 u32 val;
150
151 /* need to power down sgmii if link down */
152 regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
153 if (!(val & SGMII_LINK_STATYS))
154 return true;
155
156 return false;
157}
158
developer4e8a3fd2023-04-10 18:05:44 +0800159void mtk_sgmii_setup_phya_gen1(struct mtk_sgmii_pcs *mpcs)
developerfd40db22021-04-29 10:08:25 +0800160{
developer4e8a3fd2023-04-10 18:05:44 +0800161 if (!mpcs->regmap_pextp)
developer089e8852022-09-28 14:43:46 +0800162 return;
163
developer4e8a3fd2023-04-10 18:05:44 +0800164 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
165 0x00D9071C);
166 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
167 0xAA8585AA);
168 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
169 0x0C020207);
170 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
171 0x0E05050F);
172 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
173 0x00200032);
174 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
175 0x00C014BA);
176 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
177 0x3777C12B);
178 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
179 0x005F9CFF);
180 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
181 0x9D9DFAFA);
182 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
183 0x27273F3F);
184 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
185 0xA7883C68);
186 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
187 0x11661166);
188 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
189 0x0E000EAF);
190 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
191 0x08080E0D);
192 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
193 0x02030B09);
194 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
195 0x0C0C0000);
196 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
197 0x04040000);
198 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
199 0x0F0F0606);
200 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
201 0x506E8C8C);
202 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
203 0x18190000);
204 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
205 0x00FA32FA);
206 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
207 0x80201F21);
208 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
209 0x00050C00);
210 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
211 0x02002800);
developer089e8852022-09-28 14:43:46 +0800212 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800213 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
214 0x00000020);
215 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
216 0x00008A01);
217 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
218 0x0000A884);
219 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
220 0x00083002);
221 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
222 0x00011110);
223 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
224 0x40704000);
225 regmap_update_bits(mpcs->regmap_pextp, 0x3064, GENMASK(31, 0),
226 0x0000C000);
227 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
228 0xA8000000);
229 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
230 0x000000AA);
231 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
232 0x20200F00);
233 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
234 0x00050000);
235 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
236 0x00000007);
237 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
238 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800239 udelay(150);
developer4e8a3fd2023-04-10 18:05:44 +0800240 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
241 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800242 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800243 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
244 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800245 udelay(15);
developer4e8a3fd2023-04-10 18:05:44 +0800246 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
247 0x0201C111);
developer089e8852022-09-28 14:43:46 +0800248 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800249 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
250 0x0201C101);
developer089e8852022-09-28 14:43:46 +0800251 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800252 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
253 0x00000030);
254 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
255 0x80201F01);
256 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
257 0x30000000);
developer089e8852022-09-28 14:43:46 +0800258 udelay(400);
259}
260
developer4e8a3fd2023-04-10 18:05:44 +0800261void mtk_sgmii_setup_phya_gen2(struct mtk_sgmii_pcs *mpcs)
developer089e8852022-09-28 14:43:46 +0800262{
developer4e8a3fd2023-04-10 18:05:44 +0800263 if (!mpcs->regmap_pextp)
developer089e8852022-09-28 14:43:46 +0800264 return;
265
developer4e8a3fd2023-04-10 18:05:44 +0800266 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
267 0x00D9071C);
268 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
269 0xAA8585AA);
270 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
271 0x0C020707);
272 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
273 0x0E050F0F);
274 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
275 0x00140032);
276 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
277 0x00C014AA);
278 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
279 0x3777C12B);
280 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
281 0x005F9CFF);
282 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
283 0x9D9DFAFA);
284 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
285 0x27273F3F);
286 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
287 0xA7883C68);
288 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
289 0x11661166);
290 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
291 0x0E000AAF);
292 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
293 0x08080D0D);
294 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
295 0x02030909);
296 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
297 0x0C0C0000);
298 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
299 0x04040000);
300 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
301 0x0F0F0C06);
302 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
303 0x506E8C8C);
304 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
305 0x18190000);
306 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
307 0x009C329C);
308 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
309 0x80201F21);
310 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
311 0x00050C00);
312 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
313 0x02002800);
developer089e8852022-09-28 14:43:46 +0800314 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800315 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
316 0x00000020);
317 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
318 0x00008A01);
319 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
320 0x0000A884);
321 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
322 0x00083002);
323 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
324 0x00011110);
325 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
326 0x40704000);
327 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
328 0xA8000000);
329 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
330 0x000000AA);
331 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
332 0x22000F00);
333 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
334 0x00050000);
335 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
336 0x00000005);
337 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
338 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800339 udelay(150);
developer4e8a3fd2023-04-10 18:05:44 +0800340 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
341 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800342 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800343 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
344 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800345 udelay(15);
developer4e8a3fd2023-04-10 18:05:44 +0800346 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
347 0x0201C111);
developer089e8852022-09-28 14:43:46 +0800348 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800349 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
350 0x0201C101);
developer089e8852022-09-28 14:43:46 +0800351 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800352 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
353 0x00000030);
354 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
355 0x80201F01);
356 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
357 0x30000000);
developer089e8852022-09-28 14:43:46 +0800358 udelay(400);
359}
360
developer38afb1a2023-04-17 09:57:27 +0800361static void mtk_sgmii_pcs_get_state(struct phylink_pcs *pcs,
362 struct phylink_link_state *state)
developer089e8852022-09-28 14:43:46 +0800363{
developer38afb1a2023-04-17 09:57:27 +0800364 struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
365 unsigned int bm, adv, rgc3, sgm_mode;
developerfd40db22021-04-29 10:08:25 +0800366
developer38afb1a2023-04-17 09:57:27 +0800367 state->interface = mpcs->interface;
developer2fbee452022-08-12 13:58:20 +0800368
developer38afb1a2023-04-17 09:57:27 +0800369 regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &bm);
370 if (bm & SGMII_AN_ENABLE) {
371 regmap_read(mpcs->regmap, SGMSYS_PCS_ADVERTISE, &adv);
developerfd40db22021-04-29 10:08:25 +0800372
developer38afb1a2023-04-17 09:57:27 +0800373 phylink_mii_c22_pcs_decode_state(state,
374 FIELD_GET(SGMII_BMSR, bm),
375 FIELD_GET(SGMII_LPA, adv));
376 } else {
377 state->link = !!(bm & SGMII_LINK_STATYS);
developerf8ac94a2021-07-29 16:40:01 +0800378
developer38afb1a2023-04-17 09:57:27 +0800379 regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &sgm_mode);
developer089e8852022-09-28 14:43:46 +0800380
developer38afb1a2023-04-17 09:57:27 +0800381 switch (sgm_mode & SGMII_SPEED_MASK) {
382 case SGMII_SPEED_10:
383 state->speed = SPEED_10;
384 break;
385 case SGMII_SPEED_100:
386 state->speed = SPEED_100;
387 break;
388 case SGMII_SPEED_1000:
389 regmap_read(mpcs->regmap, mpcs->ana_rgc3, &rgc3);
390 rgc3 = FIELD_GET(RG_PHY_SPEED_3_125G, rgc3);
391 state->speed = rgc3 ? SPEED_2500 : SPEED_1000;
392 break;
393 }
developerfd40db22021-04-29 10:08:25 +0800394
developer38afb1a2023-04-17 09:57:27 +0800395 if (sgm_mode & SGMII_DUPLEX_HALF)
396 state->duplex = DUPLEX_HALF;
397 else
398 state->duplex = DUPLEX_FULL;
399 }
developerfd40db22021-04-29 10:08:25 +0800400}
401
developer38afb1a2023-04-17 09:57:27 +0800402static int mtk_sgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
403 phy_interface_t interface,
404 const unsigned long *advertising,
405 bool permit_pause_to_mac)
developerfd40db22021-04-29 10:08:25 +0800406{
developer38afb1a2023-04-17 09:57:27 +0800407 struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
developer4e8a3fd2023-04-10 18:05:44 +0800408 struct mtk_eth *eth = mpcs->eth;
developer38afb1a2023-04-17 09:57:27 +0800409 unsigned int rgc3, sgm_mode = 0, bmcr = 0, speed = 0;
410 bool mode_changed = false, changed;
411 int advertise, link_timer;
developerfd40db22021-04-29 10:08:25 +0800412
developer38afb1a2023-04-17 09:57:27 +0800413 advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
414 advertising);
415 if (advertise < 0)
416 return advertise;
developerfd40db22021-04-29 10:08:25 +0800417
developer38afb1a2023-04-17 09:57:27 +0800418 /* Clearing IF_MODE_BIT0 switches the PCS to BASE-X mode, and
419 * we assume that fixes it's speed at bitrate = line rate (in
420 * other words, 1000Mbps or 2500Mbps).
421 */
422 if (interface == PHY_INTERFACE_MODE_SGMII) {
423 bmcr = SGMII_AN_ENABLE;
424 sgm_mode = SGMII_IF_MODE_SGMII |
425 SGMII_REMOTE_FAULT_DIS |
426 SGMII_SPEED_DUPLEX_AN;
427 } else {
428 /* 1000base-X or HSGMII without autoneg */
429 speed = SGMII_SPEED_1000;
430 if (interface == PHY_INTERFACE_MODE_2500BASEX)
431 sgm_mode = SGMII_IF_MODE_SGMII;
432 }
developer2fbee452022-08-12 13:58:20 +0800433
developer1251a932023-05-08 22:22:51 +0800434 if (mpcs->interface != interface ||
435 mtk_sgmii_need_powerdown(mpcs)) {
developer38afb1a2023-04-17 09:57:27 +0800436 link_timer = phylink_get_link_timer_ns(interface);
437 if (link_timer < 0)
438 return link_timer;
developer2b76a9d2022-09-20 14:59:45 +0800439
developercd762f82023-05-03 09:03:39 +0800440 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
441 mtk_sgmii_xfi_pll_enable(eth->sgmii);
442 mtk_sgmii_reset(eth, mpcs->id);
443 }
444
developer38afb1a2023-04-17 09:57:27 +0800445 /* PHYA power down */
446 regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL,
447 SGMII_PHYA_PWD, SGMII_PHYA_PWD);
developerfd40db22021-04-29 10:08:25 +0800448
developer38afb1a2023-04-17 09:57:27 +0800449 /* Reset SGMII PCS state */
450 regmap_update_bits(mpcs->regmap, SGMII_RESERVED_0,
451 SGMII_SW_RESET, SGMII_SW_RESET);
developerfd40db22021-04-29 10:08:25 +0800452
developercd762f82023-05-03 09:03:39 +0800453 /* Configure the interface polarity */
454 if (MTK_HAS_FLAGS(mpcs->flags, MTK_SGMII_PN_SWAP))
455 regmap_update_bits(mpcs->regmap, SGMSYS_QPHY_WRAP_CTRL,
456 SGMII_PN_SWAP_MASK,
457 SGMII_PN_SWAP_TX_RX);
458
developer38afb1a2023-04-17 09:57:27 +0800459 if (interface == PHY_INTERFACE_MODE_2500BASEX)
460 rgc3 = RG_PHY_SPEED_3_125G;
461 else
462 rgc3 = 0;
developerfd40db22021-04-29 10:08:25 +0800463
developer38afb1a2023-04-17 09:57:27 +0800464 /* Configure the underlying interface speed */
465 regmap_update_bits(mpcs->regmap, mpcs->ana_rgc3,
466 RG_PHY_SPEED_3_125G, rgc3);
developer3d014da2022-05-11 16:29:59 +0800467
developer38afb1a2023-04-17 09:57:27 +0800468 /* Setup the link timer */
469 regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
470 link_timer / 2 / 8);
developer089e8852022-09-28 14:43:46 +0800471
developer38afb1a2023-04-17 09:57:27 +0800472 mpcs->interface = interface;
473 mode_changed = true;
474 }
developerfd40db22021-04-29 10:08:25 +0800475
developer38afb1a2023-04-17 09:57:27 +0800476 /* Update the advertisement, noting whether it has changed */
477 regmap_update_bits_check(mpcs->regmap, SGMSYS_PCS_ADVERTISE,
478 SGMII_ADVERTISE, advertise, &changed);
developerfd40db22021-04-29 10:08:25 +0800479
developer38afb1a2023-04-17 09:57:27 +0800480 /* Update the sgmsys mode register */
481 regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
482 SGMII_REMOTE_FAULT_DIS | SGMII_DUPLEX_HALF |
483 SGMII_SPEED_MASK | SGMII_SPEED_DUPLEX_AN |
484 SGMII_IF_MODE_SGMII, sgm_mode | speed);
developer4e8a3fd2023-04-10 18:05:44 +0800485
developer38afb1a2023-04-17 09:57:27 +0800486 /* Update the BMCR */
487 regmap_update_bits(mpcs->regmap, SGMSYS_PCS_CONTROL_1,
488 SGMII_AN_ENABLE, bmcr);
developer4e8a3fd2023-04-10 18:05:44 +0800489
developer38afb1a2023-04-17 09:57:27 +0800490 /* Release PHYA power down state */
491 usleep_range(50, 100);
492 regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, 0);
developer4e8a3fd2023-04-10 18:05:44 +0800493
developercd762f82023-05-03 09:03:39 +0800494 if (mode_changed) {
495 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
496 if (interface == PHY_INTERFACE_MODE_2500BASEX)
497 mtk_sgmii_setup_phya_gen2(mpcs);
498 else
499 mtk_sgmii_setup_phya_gen1(mpcs);
500 }
developer4e8a3fd2023-04-10 18:05:44 +0800501 }
developer4e8a3fd2023-04-10 18:05:44 +0800502
developer38afb1a2023-04-17 09:57:27 +0800503 return changed || mode_changed;
developer4e8a3fd2023-04-10 18:05:44 +0800504}
505
506void mtk_sgmii_pcs_restart_an(struct phylink_pcs *pcs)
507{
508 struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
509 unsigned int val = 0;
510
511 if (!mpcs->regmap)
developerfd40db22021-04-29 10:08:25 +0800512 return;
513
developer4e8a3fd2023-04-10 18:05:44 +0800514 regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
developerfd40db22021-04-29 10:08:25 +0800515 val |= SGMII_AN_RESTART;
developer4e8a3fd2023-04-10 18:05:44 +0800516 regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
517}
518
519static void mtk_sgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
520 phy_interface_t interface,
521 int speed, int duplex)
522{
523 struct mtk_sgmii_pcs *mpcs = pcs_to_mtk_sgmii_pcs(pcs);
developer38afb1a2023-04-17 09:57:27 +0800524 unsigned int sgm_mode, val;
developer4e8a3fd2023-04-10 18:05:44 +0800525
developer38afb1a2023-04-17 09:57:27 +0800526 /* If autoneg is enabled, the force speed and duplex
527 * are not useful, so don't go any further.
528 */
529 regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
530 if (val & SGMII_AN_ENABLE)
developer4e8a3fd2023-04-10 18:05:44 +0800531 return;
532
developer38afb1a2023-04-17 09:57:27 +0800533 /* SGMII force speed and duplex setting */
534 if (speed == SPEED_10)
535 sgm_mode = SGMII_SPEED_10;
536 else if (speed == SPEED_100)
537 sgm_mode = SGMII_SPEED_100;
538 else
539 sgm_mode = SGMII_SPEED_1000;
540
developer4e8a3fd2023-04-10 18:05:44 +0800541 if (duplex != DUPLEX_FULL)
developer38afb1a2023-04-17 09:57:27 +0800542 sgm_mode |= SGMII_DUPLEX_HALF;
developer4e8a3fd2023-04-10 18:05:44 +0800543
developer38afb1a2023-04-17 09:57:27 +0800544 regmap_update_bits(mpcs->regmap, SGMSYS_SGMII_MODE,
545 SGMII_DUPLEX_HALF | SGMII_SPEED_MASK,
546 sgm_mode);
developer4e8a3fd2023-04-10 18:05:44 +0800547}
548
549static const struct phylink_pcs_ops mtk_sgmii_pcs_ops = {
550 .pcs_config = mtk_sgmii_pcs_config,
551 .pcs_get_state = mtk_sgmii_pcs_get_state,
552 .pcs_an_restart = mtk_sgmii_pcs_restart_an,
553 .pcs_link_up = mtk_sgmii_pcs_link_up,
554};
555
556int mtk_sgmii_init(struct mtk_eth *eth, struct device_node *r, u32 ana_rgc3)
557{
558 struct mtk_sgmii *ss = eth->sgmii;
559 struct device_node *np;
560 int ret, i;
561
562 for (i = 0; i < MTK_MAX_DEVS; i++) {
563 np = of_parse_phandle(r, "mediatek,sgmiisys", i);
564 if (!np)
565 break;
566
567 ss->pcs[i].id = i;
568 ss->pcs[i].eth = eth;
569 ss->pcs[i].ana_rgc3 = ana_rgc3;
570
571 ss->pcs[i].regmap = syscon_node_to_regmap(np);
572 if (IS_ERR(ss->pcs[i].regmap))
573 return PTR_ERR(ss->pcs[i].regmap);
574
575 ss->pcs[i].flags &= ~(MTK_SGMII_PN_SWAP);
576 if (of_property_read_bool(np, "pn_swap"))
577 ss->pcs[i].flags |= MTK_SGMII_PN_SWAP;
578
579 ss->pcs[i].pcs.ops = &mtk_sgmii_pcs_ops;
580 ss->pcs[i].pcs.poll = true;
581 ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
582
583 of_node_put(np);
584 }
585
586 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
587 ret = mtk_sgmii_xfi_pextp_init(ss, r);
588 if (ret)
589 return ret;
590
591 ret = mtk_sgmii_xfi_pll_init(ss, r);
592 if (ret)
593 return ret;
594 }
595
596 return 0;
597}
598
599struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id)
600{
601 if (!ss->pcs[id].regmap)
602 return NULL;
603
604 return &ss->pcs[id].pcs;
developerfd40db22021-04-29 10:08:25 +0800605}