blob: 0cadc85e5a1bc424436c3658569cf7d4102e5d74 [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
developer21260d02023-09-04 11:29:04 +0800471int mtk_usxgmii_link_status(struct mtk_usxgmii_pcs *mpcs)
472{
473 unsigned int val;
474
475 /* Refresh USXGMII link status by toggling RG_PCS_RX_STATUS_UPDATE */
476 regmap_read(mpcs->regmap, RG_PCS_RX_STATUS0, &val);
477 val |= RG_PCS_RX_STATUS_UPDATE;
478 regmap_write(mpcs->regmap, RG_PCS_RX_STATUS0, val);
479
480 regmap_read(mpcs->regmap, RG_PCS_RX_STATUS0, &val);
481 val &= ~RG_PCS_RX_STATUS_UPDATE;
482 regmap_write(mpcs->regmap, RG_PCS_RX_STATUS0, val);
483
484 /* Read USXGMII link status */
485 regmap_read(mpcs->regmap, RG_PCS_RX_STATUS0, &val);
486
487 return FIELD_GET(RG_PCS_RX_LINK_STATUS, val);
488}
489
developer4e8a3fd2023-04-10 18:05:44 +0800490void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
developer089e8852022-09-28 14:43:46 +0800491{
developer6aa00162023-03-20 11:56:51 +0800492 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800493
developer8b6f2402022-11-28 13:42:34 +0800494 if (id >= MTK_MAX_DEVS || !eth->toprgu)
developer089e8852022-09-28 14:43:46 +0800495 return;
496
developer4e8a3fd2023-04-10 18:05:44 +0800497 switch (id) {
498 case 0:
developer6aa00162023-03-20 11:56:51 +0800499 /* Enable software reset */
500 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800501 val |= SWSYSRST_XFI_PEXPT0_GRST |
502 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800503 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
504
505 /* Assert USXGMII reset */
506 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
507 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800508 SWSYSRST_XFI_PEXPT0_GRST |
509 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800510 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
511
512 udelay(100);
513
514 /* De-assert USXGMII reset */
515 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
516 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800517 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
518 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800519 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
520
521 /* Disable software reset */
522 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800523 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
524 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800525 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800526 break;
developer4e8a3fd2023-04-10 18:05:44 +0800527 case 1:
developer6aa00162023-03-20 11:56:51 +0800528 /* Enable software reset */
529 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800530 val |= SWSYSRST_XFI_PEXPT1_GRST |
531 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800532 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
533
534 /* Assert USXGMII reset */
535 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
536 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800537 SWSYSRST_XFI_PEXPT1_GRST |
538 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800539 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
540
541 udelay(100);
542
543 /* De-assert USXGMII reset */
544 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
545 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800546 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
547 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800548 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
549
550 /* Disable software reset */
551 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800552 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
553 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800554 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800555 break;
556 }
557
developer993b3852022-12-08 15:58:20 +0800558 mdelay(10);
developer089e8852022-09-28 14:43:46 +0800559}
560
developer8900c0a2023-05-09 10:37:33 +0800561static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
562 phy_interface_t interface,
563 const unsigned long *advertising,
564 bool permit_pause_to_mac)
565{
566 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
567 struct mtk_eth *eth = mpcs->eth;
developer95169b62023-05-12 17:58:58 +0800568 unsigned int an_ctrl = 0, link_timer = 0, xfi_mode = 0, adapt_mode = 0;
569 bool mode_changed = false;
developer8900c0a2023-05-09 10:37:33 +0800570
developer95169b62023-05-12 17:58:58 +0800571 if (interface == PHY_INTERFACE_MODE_USXGMII) {
572 an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF) |
573 USXGMII_AN_ENABLE;
574 link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
575 FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
576 FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
577 xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
578 FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
579 } else if (interface == PHY_INTERFACE_MODE_10GKR) {
580 an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0x1FF);
581 link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x7B) |
582 FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x7B) |
583 FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x7B);
584 xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_10G) |
585 FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_10G);
586 adapt_mode = USXGMII_RATE_UPDATE_MODE;
587 } else if (interface == PHY_INTERFACE_MODE_5GBASER) {
588 an_ctrl = FIELD_PREP(USXGMII_AN_SYNC_CNT, 0xFF);
589 link_timer = FIELD_PREP(USXGMII_LINK_TIMER_IDLE_DETECT, 0x3D) |
590 FIELD_PREP(USXGMII_LINK_TIMER_COMP_ACK_DETECT, 0x3D) |
591 FIELD_PREP(USXGMII_LINK_TIMER_AN_RESTART, 0x3D);
592 xfi_mode = FIELD_PREP(USXGMII_XFI_RX_MODE, USXGMII_XFI_RX_MODE_5G) |
593 FIELD_PREP(USXGMII_XFI_TX_MODE, USXGMII_XFI_TX_MODE_5G);
594 adapt_mode = USXGMII_RATE_UPDATE_MODE;
595 } else
596 return -EINVAL;
597
598 adapt_mode |= FIELD_PREP(USXGMII_RATE_ADAPT_MODE, USXGMII_RATE_ADAPT_MODE_X1);
599
600 if (mpcs->interface != interface) {
601 mpcs->interface = interface;
developer21260d02023-09-04 11:29:04 +0800602 mpcs->mode = mode;
developer95169b62023-05-12 17:58:58 +0800603 mode_changed = true;
604 }
developer8900c0a2023-05-09 10:37:33 +0800605
606 mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
607 mtk_usxgmii_reset(eth, mpcs->id);
608
developer95169b62023-05-12 17:58:58 +0800609 /* Setup USXGMII AN ctrl */
610 regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL0,
611 USXGMII_AN_SYNC_CNT | USXGMII_AN_ENABLE,
612 an_ctrl);
613
614 regmap_update_bits(mpcs->regmap, RG_PCS_AN_CTRL2,
615 USXGMII_LINK_TIMER_IDLE_DETECT |
616 USXGMII_LINK_TIMER_COMP_ACK_DETECT |
617 USXGMII_LINK_TIMER_AN_RESTART,
618 link_timer);
619
620 /* Gated MAC CK */
621 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
622 USXGMII_MAC_CK_GATED, USXGMII_MAC_CK_GATED);
623
624 /* Enable interface force mode */
625 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
626 USXGMII_IF_FORCE_EN, USXGMII_IF_FORCE_EN);
627
628 /* Setup USXGMII adapt mode */
629 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
630 USXGMII_RATE_UPDATE_MODE | USXGMII_RATE_ADAPT_MODE,
631 adapt_mode);
632
633 /* Setup USXGMII speed */
634 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
635 USXGMII_XFI_RX_MODE | USXGMII_XFI_TX_MODE,
636 xfi_mode);
637
638 udelay(1);
639
640 /* Un-gated MAC CK */
641 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
642 USXGMII_MAC_CK_GATED, 0);
643
644 udelay(1);
645
646 /* Disable interface force mode for the AN mode */
647 if (an_ctrl & USXGMII_AN_ENABLE)
648 regmap_update_bits(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1,
649 USXGMII_IF_FORCE_EN, 0);
650
developer8900c0a2023-05-09 10:37:33 +0800651 /* Setup USXGMIISYS with the determined property */
652 if (interface == PHY_INTERFACE_MODE_USXGMII)
developer95169b62023-05-12 17:58:58 +0800653 mtk_usxgmii_setup_phya_usxgmii(mpcs);
developer8900c0a2023-05-09 10:37:33 +0800654 else if (interface == PHY_INTERFACE_MODE_10GKR)
developer95169b62023-05-12 17:58:58 +0800655 mtk_usxgmii_setup_phya_10gbaser(mpcs);
developer8900c0a2023-05-09 10:37:33 +0800656 else if (interface == PHY_INTERFACE_MODE_5GBASER)
developer95169b62023-05-12 17:58:58 +0800657 mtk_usxgmii_setup_phya_5gbaser(mpcs);
developer8900c0a2023-05-09 10:37:33 +0800658
developer95169b62023-05-12 17:58:58 +0800659 return mode_changed;
developer8900c0a2023-05-09 10:37:33 +0800660}
661
developer4e8a3fd2023-04-10 18:05:44 +0800662static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
663 struct phylink_link_state *state)
developer089e8852022-09-28 14:43:46 +0800664{
developer4e8a3fd2023-04-10 18:05:44 +0800665 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
666 struct mtk_eth *eth = mpcs->eth;
667 struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)];
668 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800669
developer4e8a3fd2023-04-10 18:05:44 +0800670 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
671 if (FIELD_GET(USXGMII_AN_ENABLE, val)) {
672 /* Refresh LPA by inverting LPA_LATCH */
673 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
674 regmap_update_bits(mpcs->regmap, RG_PCS_AN_STS0,
675 USXGMII_LPA_LATCH,
676 !(val & USXGMII_LPA_LATCH));
developer089e8852022-09-28 14:43:46 +0800677
developer4e8a3fd2023-04-10 18:05:44 +0800678 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
developer089e8852022-09-28 14:43:46 +0800679
developer4e8a3fd2023-04-10 18:05:44 +0800680 state->interface = mpcs->interface;
681 state->link = FIELD_GET(USXGMII_LPA_LINK, val);
682 state->duplex = FIELD_GET(USXGMII_LPA_DUPLEX, val);
683
684 switch (FIELD_GET(USXGMII_LPA_SPEED_MASK, val)) {
685 case USXGMII_LPA_SPEED_10:
686 state->speed = SPEED_10;
687 break;
688 case USXGMII_LPA_SPEED_100:
689 state->speed = SPEED_100;
690 break;
691 case USXGMII_LPA_SPEED_1000:
692 state->speed = SPEED_1000;
693 break;
694 case USXGMII_LPA_SPEED_2500:
695 state->speed = SPEED_2500;
696 break;
697 case USXGMII_LPA_SPEED_5000:
698 state->speed = SPEED_5000;
699 break;
700 case USXGMII_LPA_SPEED_10000:
701 state->speed = SPEED_10000;
702 break;
703 }
704 } else {
705 val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
706
707 if (mac->id == MTK_GMAC2_ID)
708 val = val >> 16;
709
710 switch (FIELD_GET(MTK_USXGMII_PCS_MODE, val)) {
711 case 0:
712 state->speed = SPEED_10000;
713 break;
714 case 1:
715 state->speed = SPEED_5000;
716 break;
717 case 2:
718 state->speed = SPEED_2500;
719 break;
720 case 3:
721 state->speed = SPEED_1000;
722 break;
723 }
724
725 state->interface = mpcs->interface;
726 state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, val);
727 state->duplex = DUPLEX_FULL;
728 }
developer4e8a3fd2023-04-10 18:05:44 +0800729
developer8900c0a2023-05-09 10:37:33 +0800730 if (state->link == 0)
731 mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
732 state->interface, NULL, false);
developer4e8a3fd2023-04-10 18:05:44 +0800733}
734
735void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
736{
737 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
738 unsigned int val = 0;
739
740 if (!mpcs->regmap)
741 return;
developer089e8852022-09-28 14:43:46 +0800742
developer4e8a3fd2023-04-10 18:05:44 +0800743 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
744 val |= USXGMII_AN_RESTART;
745 regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
746}
747
developer21260d02023-09-04 11:29:04 +0800748void mtk_usxgmii_link_poll(struct work_struct *work)
749{
750 struct delayed_work *dwork = to_delayed_work(work);
751 struct mtk_usxgmii_pcs *mpcs = container_of(dwork, struct mtk_usxgmii_pcs, link_poll);
752
753 if (!mtk_usxgmii_link_status(mpcs)) {
754 mtk_usxgmii_pcs_config(&mpcs->pcs, mpcs->mode,
755 mpcs->interface, NULL, false);
756
757 queue_delayed_work(system_power_efficient_wq, &mpcs->link_poll,
758 msecs_to_jiffies(1000));
759 }
760}
761
developeraeaea7b2023-05-18 18:20:10 +0800762static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
763 phy_interface_t interface,
764 int speed, int duplex)
765{
developer21260d02023-09-04 11:29:04 +0800766 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
767
developeraeaea7b2023-05-18 18:20:10 +0800768 /* Reconfiguring USXGMII to ensure the quality of the RX signal
769 * after the line side link up.
770 */
771 mtk_usxgmii_pcs_config(pcs, mode,
772 interface, NULL, false);
developer21260d02023-09-04 11:29:04 +0800773
774 queue_delayed_work(system_power_efficient_wq, &mpcs->link_poll,
775 msecs_to_jiffies(1000));
developeraeaea7b2023-05-18 18:20:10 +0800776}
777
developer4e8a3fd2023-04-10 18:05:44 +0800778static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
779 .pcs_config = mtk_usxgmii_pcs_config,
780 .pcs_get_state = mtk_usxgmii_pcs_get_state,
781 .pcs_an_restart = mtk_usxgmii_pcs_restart_an,
developeraeaea7b2023-05-18 18:20:10 +0800782 .pcs_link_up = mtk_usxgmii_pcs_link_up,
developer4e8a3fd2023-04-10 18:05:44 +0800783};
784
785int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r)
786{
787 struct mtk_usxgmii *ss = eth->usxgmii;
788 struct device_node *np;
789 int ret, i;
790
791 for (i = 0; i < MTK_MAX_DEVS; i++) {
792 np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
793 if (!np)
794 break;
795
796 ss->pcs[i].id = i;
797 ss->pcs[i].eth = eth;
798
799 ss->pcs[i].regmap = syscon_node_to_regmap(np);
800 if (IS_ERR(ss->pcs[i].regmap))
801 return PTR_ERR(ss->pcs[i].regmap);
802
803 ss->pcs[i].pcs.ops = &mtk_usxgmii_pcs_ops;
804 ss->pcs[i].pcs.poll = true;
805 ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
806
developer21260d02023-09-04 11:29:04 +0800807 INIT_DELAYED_WORK(&ss->pcs[i].link_poll, mtk_usxgmii_link_poll);
808
developer4e8a3fd2023-04-10 18:05:44 +0800809 of_node_put(np);
810 }
811
812 ret = mtk_usxgmii_xfi_pextp_init(ss, r);
813 if (ret)
814 return ret;
815
816 ret = mtk_usxgmii_xfi_pll_init(ss, r);
817 if (ret)
818 return ret;
developer089e8852022-09-28 14:43:46 +0800819
820 return 0;
821}
developer31d10662023-02-09 16:56:34 +0800822
developer4e8a3fd2023-04-10 18:05:44 +0800823struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id)
824{
825 if (!ss->pcs[id].regmap)
826 return NULL;
827
828 return &ss->pcs[id].pcs;
829}
830
developer31d10662023-02-09 16:56:34 +0800831int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range)
832{
833 unsigned int cur = offset;
834 unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0;
835
developerebf63e22023-06-15 17:45:36 +0800836 pr_info("\n============ %s ============ pmap:%lx\n",
837 name, (unsigned long)pmap);
developer31d10662023-02-09 16:56:34 +0800838 while (cur < offset + range) {
839 regmap_read(pmap, cur, &val1);
840 regmap_read(pmap, cur + 0x4, &val2);
841 regmap_read(pmap, cur + 0x8, &val3);
842 regmap_read(pmap, cur + 0xc, &val4);
843 pr_info("0x%x: %08x %08x %08x %08x\n", cur,
844 val1, val2, val3, val4);
845 cur += 0x10;
846 }
847 return 0;
848}
849