blob: e6007f6c9427b4a08b05f24d5d9498d3cf1d2f58 [file] [log] [blame]
developer089e8852022-09-28 14:43:46 +08001/* SPDX-License-Identifier: GPL-2.0
2 *
3 * Copyright (c) 2022 MediaTek Inc.
4 * Author: Henry Yen <henry.yen@mediatek.com>
5 */
6
7#include <linux/mfd/syscon.h>
8#include <linux/of.h>
9#include <linux/regmap.h>
10#include "mtk_eth_soc.h"
11
developer4e8a3fd2023-04-10 18:05:44 +080012static struct mtk_usxgmii_pcs *pcs_to_mtk_usxgmii_pcs(struct phylink_pcs *pcs)
developer089e8852022-09-28 14:43:46 +080013{
developer4e8a3fd2023-04-10 18:05:44 +080014 return container_of(pcs, struct mtk_usxgmii_pcs, pcs);
developer089e8852022-09-28 14:43:46 +080015}
16
developer4e8a3fd2023-04-10 18:05:44 +080017int mtk_usxgmii_xfi_pextp_init(struct mtk_usxgmii *ss, struct device_node *r)
developer089e8852022-09-28 14:43:46 +080018{
19 struct device_node *np;
20 int i;
21
22 for (i = 0; i < MTK_MAX_DEVS; i++) {
23 np = of_parse_phandle(r, "mediatek,xfi_pextp", i);
24 if (!np)
25 break;
26
developer4e8a3fd2023-04-10 18:05:44 +080027 ss->pcs[i].regmap_pextp = syscon_node_to_regmap(np);
28 if (IS_ERR(ss->pcs[i].regmap_pextp))
29 return PTR_ERR(ss->pcs[i].regmap_pextp);
30
31 of_node_put(np);
developer089e8852022-09-28 14:43:46 +080032 }
33
34 return 0;
35}
36
developer4e8a3fd2023-04-10 18:05:44 +080037int mtk_usxgmii_xfi_pll_init(struct mtk_usxgmii *ss, struct device_node *r)
developer089e8852022-09-28 14:43:46 +080038{
39 struct device_node *np;
developer4e8a3fd2023-04-10 18:05:44 +080040 int i;
developer089e8852022-09-28 14:43:46 +080041
42 np = of_parse_phandle(r, "mediatek,xfi_pll", 0);
43 if (!np)
44 return -1;
45
developer4e8a3fd2023-04-10 18:05:44 +080046 for (i = 0; i < MTK_MAX_DEVS; i++) {
47 ss->pll = syscon_node_to_regmap(np);
48 if (IS_ERR(ss->pll))
49 return PTR_ERR(ss->pll);
50 }
51
52 of_node_put(np);
developer089e8852022-09-28 14:43:46 +080053
54 return 0;
55}
56
57int mtk_toprgu_init(struct mtk_eth *eth, struct device_node *r)
58{
59 struct device_node *np;
60
61 np = of_parse_phandle(r, "mediatek,toprgu", 0);
62 if (!np)
63 return -1;
64
65 eth->toprgu = syscon_node_to_regmap(np);
66 if (IS_ERR(eth->toprgu))
67 return PTR_ERR(eth->toprgu);
68
69 return 0;
70}
71
developer4e8a3fd2023-04-10 18:05:44 +080072static int mtk_usxgmii_xfi_pll_enable(struct mtk_usxgmii *ss)
developer089e8852022-09-28 14:43:46 +080073{
74 u32 val = 0;
75
developer4e8a3fd2023-04-10 18:05:44 +080076 if (!ss->pll)
developer089e8852022-09-28 14:43:46 +080077 return -EINVAL;
78
79 /* Add software workaround for USXGMII PLL TCL issue */
developer4e8a3fd2023-04-10 18:05:44 +080080 regmap_write(ss->pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA);
developer089e8852022-09-28 14:43:46 +080081
developer4e8a3fd2023-04-10 18:05:44 +080082 regmap_read(ss->pll, XFI_PLL_DIG_GLB8, &val);
developer089e8852022-09-28 14:43:46 +080083 val |= RG_XFI_PLL_EN;
developer4e8a3fd2023-04-10 18:05:44 +080084 regmap_write(ss->pll, XFI_PLL_DIG_GLB8, val);
developer089e8852022-09-28 14:43:46 +080085
86 return 0;
87}
88
89int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id)
90{
91 u32 xgmii_id = mac_id;
92
93 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
94 switch (mac_id) {
95 case MTK_GMAC1_ID:
96 case MTK_GMAC2_ID:
97 xgmii_id = 1;
98 break;
99 case MTK_GMAC3_ID:
100 xgmii_id = 0;
101 break;
102 default:
103 pr_info("[%s] Warning: get illegal mac_id=%d !=!!!\n",
104 __func__, mac_id);
105 }
106 }
107
108 return xgmii_id;
109}
110
developer4e8a3fd2023-04-10 18:05:44 +0800111int mtk_xgmii2mac_id(struct mtk_eth *eth, int xgmii_id)
developer089e8852022-09-28 14:43:46 +0800112{
developer4e8a3fd2023-04-10 18:05:44 +0800113 u32 mac_id = xgmii_id;
developer089e8852022-09-28 14:43:46 +0800114
developer4e8a3fd2023-04-10 18:05:44 +0800115 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
116 switch (xgmii_id) {
117 case 0:
118 mac_id = 2;
119 break;
120 case 1:
121 mac_id = 1;
122 break;
123 default:
124 pr_info("[%s] Warning: get illegal xgmii_id=%d !=!!!\n",
125 __func__, xgmii_id);
126 }
127 }
128
129 return mac_id;
130}
131
developer95169b62023-05-12 17:58:58 +0800132void mtk_usxgmii_setup_phya_usxgmii(struct mtk_usxgmii_pcs *mpcs)
developer4e8a3fd2023-04-10 18:05:44 +0800133{
developer95169b62023-05-12 17:58:58 +0800134 if (!mpcs->regmap_pextp)
135 return;
developer089e8852022-09-28 14:43:46 +0800136
developer95169b62023-05-12 17:58:58 +0800137 /* Setup operation mode */
developer4e8a3fd2023-04-10 18:05:44 +0800138 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
139 0x00C9071C);
140 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
141 0xAA8585AA);
142 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
143 0x0C020707);
144 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
145 0x0E050F0F);
146 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
147 0x00140032);
148 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
149 0x00C014AA);
150 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
151 0x3777C12B);
152 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
153 0x005F9CFF);
154 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
155 0x9D9DFAFA);
156 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
157 0x27273F3F);
158 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
159 0xA7883C68);
160 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
161 0x11661166);
162 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
163 0x0E000AAF);
164 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
165 0x08080D0D);
166 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
167 0x02030909);
168 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
169 0x0C0C0000);
170 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
171 0x04040000);
172 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
173 0x0F0F0C06);
174 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
175 0x506E8C8C);
176 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
177 0x18190000);
178 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
179 0x01423342);
developer95169b62023-05-12 17:58:58 +0800180 /* Force SGDT_OUT off and select PCS */
developer4e8a3fd2023-04-10 18:05:44 +0800181 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
182 0x80201F20);
developer95169b62023-05-12 17:58:58 +0800183 /* Force GLB_CKDET_OUT */
developer4e8a3fd2023-04-10 18:05:44 +0800184 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
185 0x00050C00);
developer95169b62023-05-12 17:58:58 +0800186 /* Force AEQ on */
developer4e8a3fd2023-04-10 18:05:44 +0800187 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
188 0x02002800);
developer089e8852022-09-28 14:43:46 +0800189 ndelay(1020);
developer95169b62023-05-12 17:58:58 +0800190 /* Setup DA default value */
developer4e8a3fd2023-04-10 18:05:44 +0800191 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
192 0x00000020);
193 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
194 0x00008A01);
195 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
196 0x0000A884);
197 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
198 0x00083002);
199 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
200 0x00022220);
201 regmap_update_bits(mpcs->regmap_pextp, 0x5064, GENMASK(31, 0),
202 0x0F020A01);
203 regmap_update_bits(mpcs->regmap_pextp, 0x50B4, GENMASK(31, 0),
204 0x06100600);
205 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
206 0x40704000);
207 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
208 0xA8000000);
209 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
210 0x000000AA);
211 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
212 0x00000F00);
213 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
214 0x00040000);
215 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
216 0x00000001);
developer95169b62023-05-12 17:58:58 +0800217 /* Release reset */
developer4e8a3fd2023-04-10 18:05:44 +0800218 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
219 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800220 udelay(150);
developer95169b62023-05-12 17:58:58 +0800221 /* Switch to P0 */
developer4e8a3fd2023-04-10 18:05:44 +0800222 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
223 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800224 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800225 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
226 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800227 udelay(15);
developer95169b62023-05-12 17:58:58 +0800228 /* Switch to Gen3 */
developer4e8a3fd2023-04-10 18:05:44 +0800229 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
230 0x0202C111);
developer089e8852022-09-28 14:43:46 +0800231 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800232 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
233 0x0202C101);
developer089e8852022-09-28 14:43:46 +0800234 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800235 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
236 0x00000030);
237 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
238 0x80201F00);
239 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
240 0x30000000);
developer089e8852022-09-28 14:43:46 +0800241 udelay(400);
242}
243
developer95169b62023-05-12 17:58:58 +0800244void mtk_usxgmii_setup_phya_5gbaser(struct mtk_usxgmii_pcs *mpcs)
developer089e8852022-09-28 14:43:46 +0800245{
developer95169b62023-05-12 17:58:58 +0800246 if (!mpcs->regmap_pextp)
247 return;
developercfa104b2023-01-11 17:40:41 +0800248
developer95169b62023-05-12 17:58:58 +0800249 /* Setup operation mode */
developer4e8a3fd2023-04-10 18:05:44 +0800250 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800251 0x00D9071C);
developer4e8a3fd2023-04-10 18:05:44 +0800252 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800253 0xAAA5A5AA);
developer4e8a3fd2023-04-10 18:05:44 +0800254 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800255 0x0C020707);
developer4e8a3fd2023-04-10 18:05:44 +0800256 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800257 0x0E050F0F);
developer4e8a3fd2023-04-10 18:05:44 +0800258 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800259 0x00140032);
developer4e8a3fd2023-04-10 18:05:44 +0800260 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800261 0x00C018AA);
developer4e8a3fd2023-04-10 18:05:44 +0800262 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800263 0x3777812B);
developer4e8a3fd2023-04-10 18:05:44 +0800264 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800265 0x005C9CFF);
developer4e8a3fd2023-04-10 18:05:44 +0800266 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800267 0x9DFAFAFA);
developer4e8a3fd2023-04-10 18:05:44 +0800268 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800269 0x273F3F3F);
developer4e8a3fd2023-04-10 18:05:44 +0800270 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800271 0xA8883868);
developer4e8a3fd2023-04-10 18:05:44 +0800272 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800273 0x14661466);
developer4e8a3fd2023-04-10 18:05:44 +0800274 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800275 0x0E001ABF);
developer4e8a3fd2023-04-10 18:05:44 +0800276 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800277 0x080B0D0D);
developer4e8a3fd2023-04-10 18:05:44 +0800278 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800279 0x02050909);
developer4e8a3fd2023-04-10 18:05:44 +0800280 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800281 0x0C000000);
developer4e8a3fd2023-04-10 18:05:44 +0800282 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800283 0x04000000);
developer4e8a3fd2023-04-10 18:05:44 +0800284 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800285 0x0F0F0C06);
developer4e8a3fd2023-04-10 18:05:44 +0800286 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800287 0x50808C8C);
developer4e8a3fd2023-04-10 18:05:44 +0800288 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800289 0x18000000);
developer4e8a3fd2023-04-10 18:05:44 +0800290 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800291 0x00A132A1);
developer95169b62023-05-12 17:58:58 +0800292 /* Force SGDT_OUT off and select PCS */
developer4e8a3fd2023-04-10 18:05:44 +0800293 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800294 0x80201F20);
developer95169b62023-05-12 17:58:58 +0800295 /* Force GLB_CKDET_OUT */
developer4e8a3fd2023-04-10 18:05:44 +0800296 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800297 0x00050C00);
developer95169b62023-05-12 17:58:58 +0800298 /* Force AEQ on */
developer4e8a3fd2023-04-10 18:05:44 +0800299 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800300 0x02002800);
301 ndelay(1020);
developer95169b62023-05-12 17:58:58 +0800302 /* Setup DA default value */
developer4e8a3fd2023-04-10 18:05:44 +0800303 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800304 0x00000020);
developer4e8a3fd2023-04-10 18:05:44 +0800305 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800306 0x00008A01);
developer4e8a3fd2023-04-10 18:05:44 +0800307 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800308 0x0000A884);
developer4e8a3fd2023-04-10 18:05:44 +0800309 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800310 0x00083002);
developer4e8a3fd2023-04-10 18:05:44 +0800311 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800312 0x00022220);
developer4e8a3fd2023-04-10 18:05:44 +0800313 regmap_update_bits(mpcs->regmap_pextp, 0x5064, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800314 0x0F020A01);
developer4e8a3fd2023-04-10 18:05:44 +0800315 regmap_update_bits(mpcs->regmap_pextp, 0x50B4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800316 0x06100600);
developer4e8a3fd2023-04-10 18:05:44 +0800317 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800318 0x40704000);
developer4e8a3fd2023-04-10 18:05:44 +0800319 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800320 0xA8000000);
developer4e8a3fd2023-04-10 18:05:44 +0800321 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800322 0x000000AA);
developer4e8a3fd2023-04-10 18:05:44 +0800323 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800324 0x00000F00);
developer4e8a3fd2023-04-10 18:05:44 +0800325 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800326 0x00040000);
developer4e8a3fd2023-04-10 18:05:44 +0800327 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800328 0x00000003);
developer95169b62023-05-12 17:58:58 +0800329 /* Release reset */
developer4e8a3fd2023-04-10 18:05:44 +0800330 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800331 0x0200E800);
332 udelay(150);
developer95169b62023-05-12 17:58:58 +0800333 /* Switch to P0 */
developer4e8a3fd2023-04-10 18:05:44 +0800334 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800335 0x0200C111);
336 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800337 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800338 0x0200C101);
339 udelay(15);
developer95169b62023-05-12 17:58:58 +0800340 /* Switch to Gen3 */
developer4e8a3fd2023-04-10 18:05:44 +0800341 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800342 0x0202C111);
343 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800344 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800345 0x0202C101);
346 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800347 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800348 0x00000030);
developer4e8a3fd2023-04-10 18:05:44 +0800349 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800350 0x80201F00);
developer4e8a3fd2023-04-10 18:05:44 +0800351 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800352 0x30000000);
353 udelay(400);
354}
355
developer95169b62023-05-12 17:58:58 +0800356void mtk_usxgmii_setup_phya_10gbaser(struct mtk_usxgmii_pcs *mpcs)
developercfa104b2023-01-11 17:40:41 +0800357{
developer95169b62023-05-12 17:58:58 +0800358 if (!mpcs->regmap_pextp)
359 return;
developer089e8852022-09-28 14:43:46 +0800360
developer95169b62023-05-12 17:58:58 +0800361 /* Setup operation mode */
developer4e8a3fd2023-04-10 18:05:44 +0800362 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800363 0x00C9071C);
developer4e8a3fd2023-04-10 18:05:44 +0800364 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800365 0xAA8585AA);
developer4e8a3fd2023-04-10 18:05:44 +0800366 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800367 0x0C020707);
developer4e8a3fd2023-04-10 18:05:44 +0800368 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800369 0x0E050F0F);
developer4e8a3fd2023-04-10 18:05:44 +0800370 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800371 0x00140032);
developer4e8a3fd2023-04-10 18:05:44 +0800372 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800373 0x00C014AA);
developer4e8a3fd2023-04-10 18:05:44 +0800374 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800375 0x3777C12B);
developer4e8a3fd2023-04-10 18:05:44 +0800376 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800377 0x005F9CFF);
developer4e8a3fd2023-04-10 18:05:44 +0800378 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800379 0x9D9DFAFA);
developer4e8a3fd2023-04-10 18:05:44 +0800380 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800381 0x27273F3F);
developer4e8a3fd2023-04-10 18:05:44 +0800382 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800383 0xA7883C68);
developer4e8a3fd2023-04-10 18:05:44 +0800384 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800385 0x11661166);
developer4e8a3fd2023-04-10 18:05:44 +0800386 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800387 0x0E000AAF);
developer4e8a3fd2023-04-10 18:05:44 +0800388 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800389 0x08080D0D);
developer4e8a3fd2023-04-10 18:05:44 +0800390 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800391 0x02030909);
developer4e8a3fd2023-04-10 18:05:44 +0800392 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800393 0x0C0C0000);
developer4e8a3fd2023-04-10 18:05:44 +0800394 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800395 0x04040000);
developer4e8a3fd2023-04-10 18:05:44 +0800396 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800397 0x0F0F0C06);
developer4e8a3fd2023-04-10 18:05:44 +0800398 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800399 0x506E8C8C);
developer4e8a3fd2023-04-10 18:05:44 +0800400 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800401 0x18190000);
developer4e8a3fd2023-04-10 18:05:44 +0800402 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800403 0x01423342);
developer95169b62023-05-12 17:58:58 +0800404 /* Force SGDT_OUT off and select PCS */
developer4e8a3fd2023-04-10 18:05:44 +0800405 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800406 0x80201F20);
developer95169b62023-05-12 17:58:58 +0800407 /* Force GLB_CKDET_OUT */
developer4e8a3fd2023-04-10 18:05:44 +0800408 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800409 0x00050C00);
developer95169b62023-05-12 17:58:58 +0800410 /* Force AEQ on */
developer4e8a3fd2023-04-10 18:05:44 +0800411 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800412 0x02002800);
developer089e8852022-09-28 14:43:46 +0800413 ndelay(1020);
developer95169b62023-05-12 17:58:58 +0800414 /* Setup DA default value */
developer4e8a3fd2023-04-10 18:05:44 +0800415 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800416 0x00000020);
developer4e8a3fd2023-04-10 18:05:44 +0800417 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800418 0x00008A01);
developer4e8a3fd2023-04-10 18:05:44 +0800419 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800420 0x0000A884);
developer4e8a3fd2023-04-10 18:05:44 +0800421 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800422 0x00083002);
developer4e8a3fd2023-04-10 18:05:44 +0800423 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800424 0x00022220);
developer4e8a3fd2023-04-10 18:05:44 +0800425 regmap_update_bits(mpcs->regmap_pextp, 0x5064, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800426 0x0F020A01);
developer4e8a3fd2023-04-10 18:05:44 +0800427 regmap_update_bits(mpcs->regmap_pextp, 0x50B4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800428 0x06100600);
developer4e8a3fd2023-04-10 18:05:44 +0800429 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
developera500d942023-05-19 13:47:40 +0800430 0x47684100);
developer4e8a3fd2023-04-10 18:05:44 +0800431 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800432 0x00000000);
developer4e8a3fd2023-04-10 18:05:44 +0800433 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800434 0x00000000);
developer4e8a3fd2023-04-10 18:05:44 +0800435 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800436 0x00000F00);
developera500d942023-05-19 13:47:40 +0800437 if (mpcs->id == 0)
438 regmap_update_bits(mpcs->regmap_pextp, 0xA008, GENMASK(31, 0),
439 0x0007B400);
developer4e8a3fd2023-04-10 18:05:44 +0800440 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800441 0x00040000);
developer4e8a3fd2023-04-10 18:05:44 +0800442 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800443 0x00000001);
developer95169b62023-05-12 17:58:58 +0800444 /* Release reset */
developer4e8a3fd2023-04-10 18:05:44 +0800445 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800446 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800447 udelay(150);
developer95169b62023-05-12 17:58:58 +0800448 /* Switch to P0 */
developer4e8a3fd2023-04-10 18:05:44 +0800449 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800450 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800451 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800452 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800453 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800454 udelay(15);
developer95169b62023-05-12 17:58:58 +0800455 /* Switch to Gen3 */
developer4e8a3fd2023-04-10 18:05:44 +0800456 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800457 0x0202C111);
developer089e8852022-09-28 14:43:46 +0800458 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800459 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800460 0x0202C101);
developer089e8852022-09-28 14:43:46 +0800461 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800462 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800463 0x00000030);
developer4e8a3fd2023-04-10 18:05:44 +0800464 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800465 0x80201F00);
developer4e8a3fd2023-04-10 18:05:44 +0800466 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800467 0x30000000);
developer089e8852022-09-28 14:43:46 +0800468 udelay(400);
469}
470
developer4e8a3fd2023-04-10 18:05:44 +0800471void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
developer089e8852022-09-28 14:43:46 +0800472{
developer6aa00162023-03-20 11:56:51 +0800473 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800474
developer8b6f2402022-11-28 13:42:34 +0800475 if (id >= MTK_MAX_DEVS || !eth->toprgu)
developer089e8852022-09-28 14:43:46 +0800476 return;
477
developer4e8a3fd2023-04-10 18:05:44 +0800478 switch (id) {
479 case 0:
developer6aa00162023-03-20 11:56:51 +0800480 /* Enable software reset */
481 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800482 val |= SWSYSRST_XFI_PEXPT0_GRST |
483 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800484 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
485
486 /* Assert USXGMII reset */
487 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
488 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800489 SWSYSRST_XFI_PEXPT0_GRST |
490 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800491 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
492
493 udelay(100);
494
495 /* De-assert USXGMII reset */
496 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
497 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800498 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
499 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800500 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
501
502 /* Disable software reset */
503 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800504 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
505 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800506 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800507 break;
developer4e8a3fd2023-04-10 18:05:44 +0800508 case 1:
developer6aa00162023-03-20 11:56:51 +0800509 /* Enable software reset */
510 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800511 val |= SWSYSRST_XFI_PEXPT1_GRST |
512 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800513 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
514
515 /* Assert USXGMII reset */
516 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
517 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800518 SWSYSRST_XFI_PEXPT1_GRST |
519 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800520 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
521
522 udelay(100);
523
524 /* De-assert USXGMII reset */
525 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
526 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800527 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
528 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800529 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
530
531 /* Disable software reset */
532 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800533 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
534 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800535 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800536 break;
537 }
538
developer993b3852022-12-08 15:58:20 +0800539 mdelay(10);
developer089e8852022-09-28 14:43:46 +0800540}
541
developer8900c0a2023-05-09 10:37:33 +0800542static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
543 phy_interface_t interface,
544 const unsigned long *advertising,
545 bool permit_pause_to_mac)
546{
547 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
548 struct mtk_eth *eth = mpcs->eth;
developer95169b62023-05-12 17:58:58 +0800549 unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
550 bool mode_changed = false;
developer8900c0a2023-05-09 10:37:33 +0800551
developer95169b62023-05-12 17:58:58 +0800552 if (interface == PHY_INTERFACE_MODE_USXGMII) {
553 an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) |
554 USXGMII_AN_ENABLE;
555 link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
556 FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
557 FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
558 xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
559 FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
560 } else if (interface == PHY_INTERFACE_MODE_10GKR) {
561 an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF);
562 link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
563 FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
564 FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
565 xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
566 FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
567 adapt_mode = USXGMII_RATE_UPDATE_MODE;
568 } else if (interface == PHY_INTERFACE_MODE_5GBASER) {
569 an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF);
570 link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) |
571 FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) |
572 FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D);
573 xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_5G) |
574 FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_5G);
575 adapt_mode = USXGMII_RATE_UPDATE_MODE;
576 } else
577 return -EINVAL;
578
579 adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1);
580
581 if (mpcs->interface != interface) {
582 mpcs->interface = interface;
583 mode_changed = true;
584 }
developer8900c0a2023-05-09 10:37:33 +0800585
586 mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
587 mtk_usxgmii_reset(eth, mpcs->id);
588
developer95169b62023-05-12 17:58:58 +0800589 /* Setup USXGMII AN ctrl */
590 regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL0,
591 USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE,
592 an_ctrl);
593
594 regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL2,
595 USXGMII_LINK_TIMER_IDLE_DETECT |
596 USXGMII_LINK_TIMER_COMP_ACK_DETECT |
597 USXGMII_LINK_TIMER_AN_RESTART,
598 link_timer);
599
600 /* Gated MAC CK */
601 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
602 USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED);
603
604 /* Enable interface force mode */
605 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
606 USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN);
607
608 /* Setup USXGMII adapt mode */
609 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
610 USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE,
611 adapt_mode);
612
613 /* Setup USXGMII speed */
614 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
615 USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE,
616 xfi_mode);
617
618 udelay(1);
619
620 /* Un-gated MAC CK */
621 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
622 USXGMII_MAC_CK_GATED, 0);
623
624 udelay(1);
625
626 /* Disable interface force mode for the AN mode */
627 if (an_ctrl & USXGMII_AN_ENABLE)
628 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
629 USXGMII_IF_FORCE_EN, 0);
630
developer8900c0a2023-05-09 10:37:33 +0800631 /* Setup USXGMIISYS with the determined property */
632 if (interface == PHY_INTERFACE_MODE_USXGMII)
developer95169b62023-05-12 17:58:58 +0800633 mtk_usxgmii_setup_phya_usxgmii(mpcs);
developer8900c0a2023-05-09 10:37:33 +0800634 else if (interface == PHY_INTERFACE_MODE_10GKR)
developer95169b62023-05-12 17:58:58 +0800635 mtk_usxgmii_setup_phya_10gbaser(mpcs);
developer8900c0a2023-05-09 10:37:33 +0800636 else if (interface == PHY_INTERFACE_MODE_5GBASER)
developer95169b62023-05-12 17:58:58 +0800637 mtk_usxgmii_setup_phya_5gbaser(mpcs);
developer8900c0a2023-05-09 10:37:33 +0800638
developer95169b62023-05-12 17:58:58 +0800639 return mode_changed;
developer8900c0a2023-05-09 10:37:33 +0800640}
641
developer4e8a3fd2023-04-10 18:05:44 +0800642static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
643 struct phylink_link_state *state)
developer089e8852022-09-28 14:43:46 +0800644{
developer4e8a3fd2023-04-10 18:05:44 +0800645 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
646 struct mtk_eth *eth = mpcs->eth;
647 struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)];
648 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800649
developer4e8a3fd2023-04-10 18:05:44 +0800650 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
651 if (FIELD_GET(USXGMII_AN_ENABLE, val)) {
652 /* Refresh LPA by inverting LPA_LATCH */
653 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
654 regmap_update_bits(mpcs->regmap, RG_PCS_AN_STS0,
655 USXGMII_LPA_LATCH,
656 !(val & USXGMII_LPA_LATCH));
developer089e8852022-09-28 14:43:46 +0800657
developer4e8a3fd2023-04-10 18:05:44 +0800658 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
developer089e8852022-09-28 14:43:46 +0800659
developer4e8a3fd2023-04-10 18:05:44 +0800660 state->interface = mpcs->interface;
661 state->link = FIELD_GET(USXGMII_LPA_LINK, val);
662 state->duplex = FIELD_GET(USXGMII_LPA_DUPLEX, val);
663
664 switch (FIELD_GET(USXGMII_LPA_SPEED_MASK, val)) {
665 case USXGMII_LPA_SPEED_10:
666 state->speed = SPEED_10;
667 break;
668 case USXGMII_LPA_SPEED_100:
669 state->speed = SPEED_100;
670 break;
671 case USXGMII_LPA_SPEED_1000:
672 state->speed = SPEED_1000;
673 break;
674 case USXGMII_LPA_SPEED_2500:
675 state->speed = SPEED_2500;
676 break;
677 case USXGMII_LPA_SPEED_5000:
678 state->speed = SPEED_5000;
679 break;
680 case USXGMII_LPA_SPEED_10000:
681 state->speed = SPEED_10000;
682 break;
683 }
684 } else {
685 val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
686
687 if (mac->id == MTK_GMAC2_ID)
688 val = val >> 16;
689
690 switch (FIELD_GET(MTK_USXGMII_PCS_MODE, val)) {
691 case 0:
692 state->speed = SPEED_10000;
693 break;
694 case 1:
695 state->speed = SPEED_5000;
696 break;
697 case 2:
698 state->speed = SPEED_2500;
699 break;
700 case 3:
701 state->speed = SPEED_1000;
702 break;
703 }
704
705 state->interface = mpcs->interface;
706 state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, val);
707 state->duplex = DUPLEX_FULL;
708 }
developer4e8a3fd2023-04-10 18:05:44 +0800709
developer8900c0a2023-05-09 10:37:33 +0800710 if (state->link == 0)
711 mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
712 state->interface, NULL, false);
developer4e8a3fd2023-04-10 18:05:44 +0800713}
714
715void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
716{
717 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
718 unsigned int val = 0;
719
720 if (!mpcs->regmap)
721 return;
developer089e8852022-09-28 14:43:46 +0800722
developer4e8a3fd2023-04-10 18:05:44 +0800723 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
724 val |= USXGMII_AN_RESTART;
725 regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
726}
727
developeraeaea7b2023-05-18 18:20:10 +0800728static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
729 phy_interface_t interface,
730 int speed, int duplex)
731{
732 /* Reconfiguring USXGMII to ensure the quality of the RX signal
733 * after the line side link up.
734 */
735 mtk_usxgmii_pcs_config(pcs, mode,
736 interface, NULL, false);
737}
738
developer4e8a3fd2023-04-10 18:05:44 +0800739static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
740 .pcs_config = mtk_usxgmii_pcs_config,
741 .pcs_get_state = mtk_usxgmii_pcs_get_state,
742 .pcs_an_restart = mtk_usxgmii_pcs_restart_an,
developeraeaea7b2023-05-18 18:20:10 +0800743 .pcs_link_up = mtk_usxgmii_pcs_link_up,
developer4e8a3fd2023-04-10 18:05:44 +0800744};
745
746int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r)
747{
748 struct mtk_usxgmii *ss = eth->usxgmii;
749 struct device_node *np;
750 int ret, i;
751
752 for (i = 0; i < MTK_MAX_DEVS; i++) {
753 np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
754 if (!np)
755 break;
756
757 ss->pcs[i].id = i;
758 ss->pcs[i].eth = eth;
759
760 ss->pcs[i].regmap = syscon_node_to_regmap(np);
761 if (IS_ERR(ss->pcs[i].regmap))
762 return PTR_ERR(ss->pcs[i].regmap);
763
764 ss->pcs[i].pcs.ops = &mtk_usxgmii_pcs_ops;
765 ss->pcs[i].pcs.poll = true;
766 ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
767
768 of_node_put(np);
769 }
770
771 ret = mtk_usxgmii_xfi_pextp_init(ss, r);
772 if (ret)
773 return ret;
774
775 ret = mtk_usxgmii_xfi_pll_init(ss, r);
776 if (ret)
777 return ret;
developer089e8852022-09-28 14:43:46 +0800778
779 return 0;
780}
developer31d10662023-02-09 16:56:34 +0800781
developer4e8a3fd2023-04-10 18:05:44 +0800782struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id)
783{
784 if (!ss->pcs[id].regmap)
785 return NULL;
786
787 return &ss->pcs[id].pcs;
788}
789
developer31d10662023-02-09 16:56:34 +0800790int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range)
791{
792 unsigned int cur = offset;
793 unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0;
794
795 pr_info("\n============ %s ============ pmap:%x\n", name, pmap);
796 while (cur < offset + range) {
797 regmap_read(pmap, cur, &val1);
798 regmap_read(pmap, cur + 0x4, &val2);
799 regmap_read(pmap, cur + 0x8, &val3);
800 regmap_read(pmap, cur + 0xc, &val4);
801 pr_info("0x%x: %08x %08x %08x %08x\n", cur,
802 val1, val2, val3, val4);
803 cur += 0x10;
804 }
805 return 0;
806}
807