blob: c9b1a43b48b5385013ed6b1bcbf2241a8476bce6 [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 configuring path from GMAC/GDM to target PHY
5 *
6 * Author: Sean Wang <sean.wang@mediatek.com>
7 *
8 */
9
10#include <linux/phy.h>
11#include <linux/regmap.h>
12
13#include "mtk_eth_soc.h"
14
15struct mtk_eth_muxc {
16 const char *name;
developer089e8852022-09-28 14:43:46 +080017 u64 cap_bit;
18 int (*set_path)(struct mtk_eth *eth, u64 path);
developerfd40db22021-04-29 10:08:25 +080019};
20
developer089e8852022-09-28 14:43:46 +080021static const char *mtk_eth_path_name(u64 path)
developerfd40db22021-04-29 10:08:25 +080022{
23 switch (path) {
24 case MTK_ETH_PATH_GMAC1_RGMII:
25 return "gmac1_rgmii";
26 case MTK_ETH_PATH_GMAC1_TRGMII:
27 return "gmac1_trgmii";
28 case MTK_ETH_PATH_GMAC1_SGMII:
29 return "gmac1_sgmii";
30 case MTK_ETH_PATH_GMAC2_RGMII:
31 return "gmac2_rgmii";
32 case MTK_ETH_PATH_GMAC2_SGMII:
33 return "gmac2_sgmii";
developer30e13e72022-11-03 10:21:24 +080034 case MTK_ETH_PATH_GMAC2_XGMII:
35 return "gmac2_xgmii";
developerfd40db22021-04-29 10:08:25 +080036 case MTK_ETH_PATH_GMAC2_GEPHY:
37 return "gmac2_gephy";
developer089e8852022-09-28 14:43:46 +080038 case MTK_ETH_PATH_GMAC3_SGMII:
39 return "gmac3_sgmii";
developerfd40db22021-04-29 10:08:25 +080040 case MTK_ETH_PATH_GDM1_ESW:
41 return "gdm1_esw";
developer089e8852022-09-28 14:43:46 +080042 case MTK_ETH_PATH_GMAC1_USXGMII:
43 return "gmac1_usxgmii";
44 case MTK_ETH_PATH_GMAC2_USXGMII:
45 return "gmac2_usxgmii";
46 case MTK_ETH_PATH_GMAC3_USXGMII:
47 return "gmac3_usxgmii";
developerfd40db22021-04-29 10:08:25 +080048 default:
49 return "unknown path";
50 }
51}
52
developer089e8852022-09-28 14:43:46 +080053static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +080054{
55 bool updated = true;
56 u32 val, mask, set;
57
58 switch (path) {
59 case MTK_ETH_PATH_GMAC1_SGMII:
60 mask = ~(u32)MTK_MUX_TO_ESW;
61 set = 0;
62 break;
63 case MTK_ETH_PATH_GDM1_ESW:
64 mask = ~(u32)MTK_MUX_TO_ESW;
65 set = MTK_MUX_TO_ESW;
66 break;
67 default:
68 updated = false;
69 break;
70 };
71
72 if (updated) {
73 val = mtk_r32(eth, MTK_MAC_MISC);
74 val = (val & mask) | set;
75 mtk_w32(eth, val, MTK_MAC_MISC);
76 }
77
78 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
79 mtk_eth_path_name(path), __func__, updated);
80
81 return 0;
82}
83
developer089e8852022-09-28 14:43:46 +080084static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +080085{
86 unsigned int val = 0;
87 bool updated = true;
88
89 switch (path) {
90 case MTK_ETH_PATH_GMAC2_GEPHY:
91 val = ~(u32)GEPHY_MAC_SEL;
92 break;
93 default:
94 updated = false;
95 break;
96 }
97
98 if (updated)
99 regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
100
101 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
102 mtk_eth_path_name(path), __func__, updated);
103
104 return 0;
105}
106
developer089e8852022-09-28 14:43:46 +0800107static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800108{
developer255bba22021-07-27 15:16:33 +0800109 unsigned int val = 0,mask=0,reg=0;
developerfd40db22021-04-29 10:08:25 +0800110 bool updated = true;
111
112 switch (path) {
113 case MTK_ETH_PATH_GMAC2_SGMII:
developer255bba22021-07-27 15:16:33 +0800114 if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
115 reg = USB_PHY_SWITCH_REG;
116 val = SGMII_QPHY_SEL;
117 mask = QPHY_SEL_MASK;
118 } else {
119 reg = INFRA_MISC2;
120 val = CO_QPHY_SEL;
121 mask = val;
122 }
developerfd40db22021-04-29 10:08:25 +0800123 break;
124 default:
125 updated = false;
126 break;
127 }
128
129 if (updated)
developer255bba22021-07-27 15:16:33 +0800130 regmap_update_bits(eth->infra, reg, mask, val);
developerfd40db22021-04-29 10:08:25 +0800131
132 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
133 mtk_eth_path_name(path), __func__, updated);
134
135 return 0;
136}
137
developer30e13e72022-11-03 10:21:24 +0800138static int set_mux_gmac2_to_xgmii(struct mtk_eth *eth, u64 path)
139{
140 unsigned int val = 0;
141 bool updated = true;
142 int mac_id = 0;
143
144 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
145 mtk_eth_path_name(path), __func__, updated);
146
147 spin_lock(&eth->syscfg0_lock);
148
149 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
150
151 switch (path) {
152 case MTK_ETH_PATH_GMAC2_XGMII:
153 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
154 mac_id = MTK_GMAC2_ID;
155 break;
156 default:
157 updated = false;
158 break;
159 };
160
161 if (updated)
162 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
163 SYSCFG0_SGMII_MASK, val);
164
165 /* Enable GDM/XGDM Path */
166 if (eth->mac[mac_id]->type == MTK_GDM_TYPE) {
167 val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac_id));
168 mtk_w32(eth, val & ~MTK_GDMA_XGDM_SEL,
169 MTK_GDMA_EG_CTRL(mac_id));
170 } else if (eth->mac[mac_id]->type == MTK_XGDM_TYPE) {
171 val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac_id));
172 mtk_w32(eth, val | MTK_GDMA_XGDM_SEL,
173 MTK_GDMA_EG_CTRL(mac_id));
174
175 val = mtk_r32(eth, MTK_XGMAC_STS(mac_id));
176 mtk_w32(eth, val | (MTK_XGMAC_FORCE_LINK << 16),
177 MTK_XGMAC_STS(mac_id));
178 }
179
180 spin_unlock(&eth->syscfg0_lock);
181
182 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
183 mtk_eth_path_name(path), __func__, updated);
184
185 return 0;
186}
187
developer089e8852022-09-28 14:43:46 +0800188static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800189{
190 unsigned int val = 0;
191 bool updated = true;
192
developerd82e8372022-02-09 15:00:09 +0800193 spin_lock(&eth->syscfg0_lock);
194
developerfd40db22021-04-29 10:08:25 +0800195 switch (path) {
196 case MTK_ETH_PATH_GMAC1_SGMII:
197 val = SYSCFG0_SGMII_GMAC1;
198 break;
199 case MTK_ETH_PATH_GMAC2_SGMII:
200 val = SYSCFG0_SGMII_GMAC2;
201 break;
202 case MTK_ETH_PATH_GMAC1_RGMII:
203 case MTK_ETH_PATH_GMAC2_RGMII:
204 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
205 val &= SYSCFG0_SGMII_MASK;
206
developer8b6f2402022-11-28 13:42:34 +0800207 if ((path == MTK_ETH_PATH_GMAC1_RGMII &&
208 val == SYSCFG0_SGMII_GMAC1) ||
209 (path == MTK_ETH_PATH_GMAC2_RGMII &&
210 val == SYSCFG0_SGMII_GMAC2))
developerfd40db22021-04-29 10:08:25 +0800211 val = 0;
212 else
213 updated = false;
214 break;
215 default:
216 updated = false;
217 break;
218 };
219
220 if (updated)
221 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
222 SYSCFG0_SGMII_MASK, val);
223
developerd82e8372022-02-09 15:00:09 +0800224 spin_unlock(&eth->syscfg0_lock);
225
developerfd40db22021-04-29 10:08:25 +0800226 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
227 mtk_eth_path_name(path), __func__, updated);
228
229 return 0;
230}
231
developer089e8852022-09-28 14:43:46 +0800232static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800233{
234 unsigned int val = 0;
235 bool updated = true;
developer30e13e72022-11-03 10:21:24 +0800236 int mac_id = 0;
developer089e8852022-09-28 14:43:46 +0800237
238 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
239 mtk_eth_path_name(path), __func__, updated);
240
241 /* Disable SYSCFG1 SGMII */
242 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
243
244 switch (path) {
245 case MTK_ETH_PATH_GMAC1_USXGMII:
246 val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2;
247 mac_id = MTK_GMAC1_ID;
248 break;
249 case MTK_ETH_PATH_GMAC2_USXGMII:
250 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
251 mac_id = MTK_GMAC2_ID;
252 break;
253 case MTK_ETH_PATH_GMAC3_USXGMII:
254 val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2;
255 mac_id = MTK_GMAC3_ID;
256 break;
257 default:
258 updated = false;
259 };
260
261 if (updated) {
262 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
263 SYSCFG0_SGMII_MASK, val);
264
265 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
266 mac_id == MTK_GMAC2_ID) {
developer30e13e72022-11-03 10:21:24 +0800267 regmap_update_bits(eth->infra,
268 TOP_MISC_NETSYS_PCS_MUX,
269 NETSYS_PCS_MUX_MASK,
270 MUX_G2_USXGMII_SEL);
developer089e8852022-09-28 14:43:46 +0800271 }
272 }
273
274 /* Enable XGDM Path */
275 val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac_id));
276 val |= MTK_GDMA_XGDM_SEL;
277 mtk_w32(eth, val, MTK_GDMA_EG_CTRL(mac_id));
278
279 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
280 mtk_eth_path_name(path), __func__, updated);
281
282
283 return 0;
284}
285
286static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
287{
288 unsigned int val = 0;
289 bool updated = true;
developerfd40db22021-04-29 10:08:25 +0800290
developerd82e8372022-02-09 15:00:09 +0800291 spin_lock(&eth->syscfg0_lock);
292
developerfd40db22021-04-29 10:08:25 +0800293 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
294
295 switch (path) {
296 case MTK_ETH_PATH_GMAC1_SGMII:
297 val |= SYSCFG0_SGMII_GMAC1_V2;
298 break;
299 case MTK_ETH_PATH_GMAC2_GEPHY:
300 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
301 break;
302 case MTK_ETH_PATH_GMAC2_SGMII:
303 val |= SYSCFG0_SGMII_GMAC2_V2;
304 break;
developer089e8852022-09-28 14:43:46 +0800305 case MTK_ETH_PATH_GMAC3_SGMII:
306 val |= SYSCFG0_SGMII_GMAC3_V2;
307 break;
developerfd40db22021-04-29 10:08:25 +0800308 default:
309 updated = false;
310 };
311
312 if (updated)
313 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
314 SYSCFG0_SGMII_MASK, val);
315
developerd82e8372022-02-09 15:00:09 +0800316 spin_unlock(&eth->syscfg0_lock);
317
developerfd40db22021-04-29 10:08:25 +0800318 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
319 mtk_eth_path_name(path), __func__, updated);
320
321 return 0;
322}
323
324static const struct mtk_eth_muxc mtk_eth_muxc[] = {
325 {
326 .name = "mux_gdm1_to_gmac1_esw",
327 .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
328 .set_path = set_mux_gdm1_to_gmac1_esw,
329 }, {
330 .name = "mux_gmac2_gmac0_to_gephy",
331 .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
332 .set_path = set_mux_gmac2_gmac0_to_gephy,
333 }, {
334 .name = "mux_u3_gmac2_to_qphy",
335 .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
336 .set_path = set_mux_u3_gmac2_to_qphy,
337 }, {
developer30e13e72022-11-03 10:21:24 +0800338 .name = "mux_gmac2_to_xgmii",
339 .cap_bit = MTK_ETH_MUX_GMAC2_TO_XGMII,
340 .set_path = set_mux_gmac2_to_xgmii,
341 }, {
developerfd40db22021-04-29 10:08:25 +0800342 .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
343 .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
344 .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
345 }, {
346 .name = "mux_gmac12_to_gephy_sgmii",
347 .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
developer089e8852022-09-28 14:43:46 +0800348 .set_path = set_mux_gmac123_to_gephy_sgmii,
349 }, {
350 .name = "mux_gmac123_to_gephy_sgmii",
351 .cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII,
352 .set_path = set_mux_gmac123_to_gephy_sgmii,
353 }, {
354 .name = "mux_gmac123_to_usxgmii",
355 .cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII,
356 .set_path = set_mux_gmac123_to_usxgmii,
developerfd40db22021-04-29 10:08:25 +0800357 },
358};
359
developer089e8852022-09-28 14:43:46 +0800360static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800361{
362 int i, err = 0;
363
364 if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
365 dev_err(eth->dev, "path %s isn't support on the SoC\n",
366 mtk_eth_path_name(path));
367 return -EINVAL;
368 }
369
370 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
371 return 0;
372
373 /* Setup MUX in path fabric */
374 for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
375 if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
376 err = mtk_eth_muxc[i].set_path(eth, path);
377 if (err)
378 goto out;
379 } else {
380 dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
381 mtk_eth_muxc[i].name);
382 }
383 }
384
385out:
386 return err;
387}
388
developer089e8852022-09-28 14:43:46 +0800389int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
390{
391 int err;
392 u64 path;
393
394 path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII :
395 (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_USXGMII :
396 MTK_ETH_PATH_GMAC3_USXGMII;
397
398 dev_err(eth->dev, "%s path %s in\n", __func__,
399 mtk_eth_path_name(path));
400
401 /* Setup proper MUXes along the path */
402 err = mtk_eth_mux_setup(eth, path);
403 if (err)
404 return err;
405
406 return 0;
407}
408
developerfd40db22021-04-29 10:08:25 +0800409int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
410{
developer089e8852022-09-28 14:43:46 +0800411 int err;
412 u64 path;
developerfd40db22021-04-29 10:08:25 +0800413
developer089e8852022-09-28 14:43:46 +0800414 path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII :
415 (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII :
416 MTK_ETH_PATH_GMAC3_SGMII;
developerfd40db22021-04-29 10:08:25 +0800417
418 /* Setup proper MUXes along the path */
419 err = mtk_eth_mux_setup(eth, path);
420 if (err)
421 return err;
422
423 return 0;
424}
425
developer30e13e72022-11-03 10:21:24 +0800426int mtk_gmac_xgmii_path_setup(struct mtk_eth *eth, int mac_id)
427{
428 int err;
429 u64 path;
430
431 if (mac_id == 1)
432 path = MTK_ETH_PATH_GMAC2_XGMII;
433
434 if (!path)
435 return -EINVAL;
436
437 /* Setup proper MUXes along the path */
438 err = mtk_eth_mux_setup(eth, path);
439 if (err)
440 return err;
441
442 return 0;
443}
444
developerfd40db22021-04-29 10:08:25 +0800445int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
446{
developer089e8852022-09-28 14:43:46 +0800447 int err;
448 u64 path = 0;
developerfd40db22021-04-29 10:08:25 +0800449
450 if (mac_id == 1)
451 path = MTK_ETH_PATH_GMAC2_GEPHY;
452
453 if (!path)
454 return -EINVAL;
455
456 /* Setup proper MUXes along the path */
457 err = mtk_eth_mux_setup(eth, path);
458 if (err)
459 return err;
460
461 return 0;
462}
463
464int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
465{
developer089e8852022-09-28 14:43:46 +0800466 int err;
467 u64 path;
developerfd40db22021-04-29 10:08:25 +0800468
469 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
470 MTK_ETH_PATH_GMAC2_RGMII;
471
472 /* Setup proper MUXes along the path */
473 err = mtk_eth_mux_setup(eth, path);
474 if (err)
475 return err;
476
477 return 0;
478}
479