blob: cc4b1d5572a1a42e03254c01a20d3e397bfd7868 [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
developer30e13e72022-11-03 10:21:24 +0800165 spin_unlock(&eth->syscfg0_lock);
166
167 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
168 mtk_eth_path_name(path), __func__, updated);
169
170 return 0;
171}
172
developer089e8852022-09-28 14:43:46 +0800173static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800174{
175 unsigned int val = 0;
176 bool updated = true;
177
developerd82e8372022-02-09 15:00:09 +0800178 spin_lock(&eth->syscfg0_lock);
179
developerfd40db22021-04-29 10:08:25 +0800180 switch (path) {
181 case MTK_ETH_PATH_GMAC1_SGMII:
182 val = SYSCFG0_SGMII_GMAC1;
183 break;
184 case MTK_ETH_PATH_GMAC2_SGMII:
185 val = SYSCFG0_SGMII_GMAC2;
186 break;
187 case MTK_ETH_PATH_GMAC1_RGMII:
188 case MTK_ETH_PATH_GMAC2_RGMII:
189 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
190 val &= SYSCFG0_SGMII_MASK;
191
developer8b6f2402022-11-28 13:42:34 +0800192 if ((path == MTK_ETH_PATH_GMAC1_RGMII &&
193 val == SYSCFG0_SGMII_GMAC1) ||
194 (path == MTK_ETH_PATH_GMAC2_RGMII &&
195 val == SYSCFG0_SGMII_GMAC2))
developerfd40db22021-04-29 10:08:25 +0800196 val = 0;
197 else
198 updated = false;
199 break;
200 default:
201 updated = false;
202 break;
203 };
204
205 if (updated)
206 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
207 SYSCFG0_SGMII_MASK, val);
208
developerd82e8372022-02-09 15:00:09 +0800209 spin_unlock(&eth->syscfg0_lock);
210
developerfd40db22021-04-29 10:08:25 +0800211 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
212 mtk_eth_path_name(path), __func__, updated);
213
214 return 0;
215}
216
developer089e8852022-09-28 14:43:46 +0800217static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800218{
219 unsigned int val = 0;
220 bool updated = true;
developer30e13e72022-11-03 10:21:24 +0800221 int mac_id = 0;
developer089e8852022-09-28 14:43:46 +0800222
223 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
224 mtk_eth_path_name(path), __func__, updated);
225
226 /* Disable SYSCFG1 SGMII */
227 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
228
229 switch (path) {
230 case MTK_ETH_PATH_GMAC1_USXGMII:
231 val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2;
232 mac_id = MTK_GMAC1_ID;
233 break;
234 case MTK_ETH_PATH_GMAC2_USXGMII:
235 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
236 mac_id = MTK_GMAC2_ID;
237 break;
238 case MTK_ETH_PATH_GMAC3_USXGMII:
239 val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2;
240 mac_id = MTK_GMAC3_ID;
241 break;
242 default:
243 updated = false;
244 };
245
246 if (updated) {
247 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
248 SYSCFG0_SGMII_MASK, val);
249
250 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
251 mac_id == MTK_GMAC2_ID) {
developer30e13e72022-11-03 10:21:24 +0800252 regmap_update_bits(eth->infra,
253 TOP_MISC_NETSYS_PCS_MUX,
254 NETSYS_PCS_MUX_MASK,
255 MUX_G2_USXGMII_SEL);
developer089e8852022-09-28 14:43:46 +0800256 }
257 }
258
developer089e8852022-09-28 14:43:46 +0800259 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
260 mtk_eth_path_name(path), __func__, updated);
261
262
263 return 0;
264}
265
266static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
267{
268 unsigned int val = 0;
269 bool updated = true;
developerfd40db22021-04-29 10:08:25 +0800270
developerd82e8372022-02-09 15:00:09 +0800271 spin_lock(&eth->syscfg0_lock);
272
developerfd40db22021-04-29 10:08:25 +0800273 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
274
275 switch (path) {
276 case MTK_ETH_PATH_GMAC1_SGMII:
277 val |= SYSCFG0_SGMII_GMAC1_V2;
278 break;
279 case MTK_ETH_PATH_GMAC2_GEPHY:
280 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
281 break;
282 case MTK_ETH_PATH_GMAC2_SGMII:
283 val |= SYSCFG0_SGMII_GMAC2_V2;
284 break;
developer089e8852022-09-28 14:43:46 +0800285 case MTK_ETH_PATH_GMAC3_SGMII:
286 val |= SYSCFG0_SGMII_GMAC3_V2;
287 break;
developerfd40db22021-04-29 10:08:25 +0800288 default:
289 updated = false;
290 };
291
292 if (updated)
293 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
294 SYSCFG0_SGMII_MASK, val);
295
developerd82e8372022-02-09 15:00:09 +0800296 spin_unlock(&eth->syscfg0_lock);
297
developerfd40db22021-04-29 10:08:25 +0800298 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
299 mtk_eth_path_name(path), __func__, updated);
300
301 return 0;
302}
303
304static const struct mtk_eth_muxc mtk_eth_muxc[] = {
305 {
306 .name = "mux_gdm1_to_gmac1_esw",
307 .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
308 .set_path = set_mux_gdm1_to_gmac1_esw,
309 }, {
310 .name = "mux_gmac2_gmac0_to_gephy",
311 .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
312 .set_path = set_mux_gmac2_gmac0_to_gephy,
313 }, {
314 .name = "mux_u3_gmac2_to_qphy",
315 .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
316 .set_path = set_mux_u3_gmac2_to_qphy,
317 }, {
developer30e13e72022-11-03 10:21:24 +0800318 .name = "mux_gmac2_to_xgmii",
319 .cap_bit = MTK_ETH_MUX_GMAC2_TO_XGMII,
320 .set_path = set_mux_gmac2_to_xgmii,
321 }, {
developerfd40db22021-04-29 10:08:25 +0800322 .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
323 .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
324 .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
325 }, {
326 .name = "mux_gmac12_to_gephy_sgmii",
327 .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
developer089e8852022-09-28 14:43:46 +0800328 .set_path = set_mux_gmac123_to_gephy_sgmii,
329 }, {
330 .name = "mux_gmac123_to_gephy_sgmii",
331 .cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII,
332 .set_path = set_mux_gmac123_to_gephy_sgmii,
333 }, {
334 .name = "mux_gmac123_to_usxgmii",
335 .cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII,
336 .set_path = set_mux_gmac123_to_usxgmii,
developerfd40db22021-04-29 10:08:25 +0800337 },
338};
339
developer089e8852022-09-28 14:43:46 +0800340static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
developerfd40db22021-04-29 10:08:25 +0800341{
342 int i, err = 0;
343
344 if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
345 dev_err(eth->dev, "path %s isn't support on the SoC\n",
346 mtk_eth_path_name(path));
347 return -EINVAL;
348 }
349
350 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
351 return 0;
352
353 /* Setup MUX in path fabric */
354 for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
355 if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
356 err = mtk_eth_muxc[i].set_path(eth, path);
357 if (err)
358 goto out;
359 } else {
360 dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
361 mtk_eth_muxc[i].name);
362 }
363 }
364
365out:
366 return err;
367}
368
developer089e8852022-09-28 14:43:46 +0800369int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id)
370{
371 int err;
372 u64 path;
373
374 path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII :
375 (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_USXGMII :
376 MTK_ETH_PATH_GMAC3_USXGMII;
377
378 dev_err(eth->dev, "%s path %s in\n", __func__,
379 mtk_eth_path_name(path));
380
381 /* Setup proper MUXes along the path */
382 err = mtk_eth_mux_setup(eth, path);
383 if (err)
384 return err;
385
386 return 0;
387}
388
developerfd40db22021-04-29 10:08:25 +0800389int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
390{
developer089e8852022-09-28 14:43:46 +0800391 int err;
392 u64 path;
developerfd40db22021-04-29 10:08:25 +0800393
developer089e8852022-09-28 14:43:46 +0800394 path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII :
395 (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII :
396 MTK_ETH_PATH_GMAC3_SGMII;
developerfd40db22021-04-29 10:08:25 +0800397
398 /* Setup proper MUXes along the path */
399 err = mtk_eth_mux_setup(eth, path);
400 if (err)
401 return err;
402
403 return 0;
404}
405
developer30e13e72022-11-03 10:21:24 +0800406int mtk_gmac_xgmii_path_setup(struct mtk_eth *eth, int mac_id)
407{
408 int err;
developer543e7922022-12-01 11:24:47 +0800409 u64 path = 0;
developer30e13e72022-11-03 10:21:24 +0800410
411 if (mac_id == 1)
412 path = MTK_ETH_PATH_GMAC2_XGMII;
413
414 if (!path)
415 return -EINVAL;
416
417 /* Setup proper MUXes along the path */
418 err = mtk_eth_mux_setup(eth, path);
419 if (err)
420 return err;
421
422 return 0;
423}
424
developerfd40db22021-04-29 10:08:25 +0800425int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
426{
developer089e8852022-09-28 14:43:46 +0800427 int err;
428 u64 path = 0;
developerfd40db22021-04-29 10:08:25 +0800429
430 if (mac_id == 1)
431 path = MTK_ETH_PATH_GMAC2_GEPHY;
432
433 if (!path)
434 return -EINVAL;
435
436 /* Setup proper MUXes along the path */
437 err = mtk_eth_mux_setup(eth, path);
438 if (err)
439 return err;
440
441 return 0;
442}
443
444int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
445{
developer089e8852022-09-28 14:43:46 +0800446 int err;
447 u64 path;
developerfd40db22021-04-29 10:08:25 +0800448
449 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
450 MTK_ETH_PATH_GMAC2_RGMII;
451
452 /* Setup proper MUXes along the path */
453 err = mtk_eth_mux_setup(eth, path);
454 if (err)
455 return err;
456
457 return 0;
458}
459