blob: fe06c2e7f5b0d61d76e086f4ace9a83bcae2bc89 [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
132int mtk_usxgmii_setup_phya_an_10000(struct mtk_usxgmii_pcs *mpcs)
133{
134 if (!mpcs->regmap || !mpcs->regmap_pextp)
135 return -EINVAL;
developer089e8852022-09-28 14:43:46 +0800136
developer4e8a3fd2023-04-10 18:05:44 +0800137 regmap_update_bits(mpcs->regmap, 0x810, GENMASK(31, 0),
138 0x000FFE6D);
139 regmap_update_bits(mpcs->regmap, 0x818, GENMASK(31, 0),
140 0x07B1EC7B);
141 regmap_update_bits(mpcs->regmap, 0x80C, GENMASK(31, 0),
142 0x30000000);
developer089e8852022-09-28 14:43:46 +0800143 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800144 regmap_update_bits(mpcs->regmap, 0x80C, GENMASK(31, 0),
145 0x10000000);
developer089e8852022-09-28 14:43:46 +0800146 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800147 regmap_update_bits(mpcs->regmap, 0x80C, GENMASK(31, 0),
148 0x00000000);
developer089e8852022-09-28 14:43:46 +0800149
developer4e8a3fd2023-04-10 18:05:44 +0800150 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
151 0x00C9071C);
152 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
153 0xAA8585AA);
154 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
155 0x0C020707);
156 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
157 0x0E050F0F);
158 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
159 0x00140032);
160 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
161 0x00C014AA);
162 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
163 0x3777C12B);
164 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
165 0x005F9CFF);
166 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
167 0x9D9DFAFA);
168 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
169 0x27273F3F);
170 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
171 0xA7883C68);
172 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
173 0x11661166);
174 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
175 0x0E000AAF);
176 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
177 0x08080D0D);
178 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
179 0x02030909);
180 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
181 0x0C0C0000);
182 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
183 0x04040000);
184 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
185 0x0F0F0C06);
186 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
187 0x506E8C8C);
188 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
189 0x18190000);
190 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
191 0x01423342);
192 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
193 0x80201F20);
194 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
195 0x00050C00);
196 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
197 0x02002800);
developer089e8852022-09-28 14:43:46 +0800198 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800199 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
200 0x00000020);
201 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
202 0x00008A01);
203 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
204 0x0000A884);
205 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
206 0x00083002);
207 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
208 0x00022220);
209 regmap_update_bits(mpcs->regmap_pextp, 0x5064, GENMASK(31, 0),
210 0x0F020A01);
211 regmap_update_bits(mpcs->regmap_pextp, 0x50B4, GENMASK(31, 0),
212 0x06100600);
213 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
214 0x40704000);
215 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
216 0xA8000000);
217 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
218 0x000000AA);
219 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
220 0x00000F00);
221 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
222 0x00040000);
223 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
224 0x00000001);
225 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
226 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800227 udelay(150);
developer4e8a3fd2023-04-10 18:05:44 +0800228 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
229 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800230 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800231 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
232 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800233 udelay(15);
developer4e8a3fd2023-04-10 18:05:44 +0800234 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
235 0x0202C111);
developer089e8852022-09-28 14:43:46 +0800236 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800237 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
238 0x0202C101);
developer089e8852022-09-28 14:43:46 +0800239 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800240 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
241 0x00000030);
242 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
243 0x80201F00);
244 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
245 0x30000000);
developer089e8852022-09-28 14:43:46 +0800246 udelay(400);
developer4e8a3fd2023-04-10 18:05:44 +0800247
248 return 0;
developer089e8852022-09-28 14:43:46 +0800249}
250
developer4e8a3fd2023-04-10 18:05:44 +0800251int mtk_usxgmii_setup_phya_force_5000(struct mtk_usxgmii_pcs *mpcs)
developer089e8852022-09-28 14:43:46 +0800252{
253 unsigned int val;
developer089e8852022-09-28 14:43:46 +0800254
developer4e8a3fd2023-04-10 18:05:44 +0800255 if (!mpcs->regmap || !mpcs->regmap_pextp)
256 return -EINVAL;
developer089e8852022-09-28 14:43:46 +0800257
developercfa104b2023-01-11 17:40:41 +0800258 /* Setup USXGMII speed */
259 val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_5G) |
260 FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_5G);
developer4e8a3fd2023-04-10 18:05:44 +0800261 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developercfa104b2023-01-11 17:40:41 +0800262
263 /* Disable USXGMII AN mode */
developer4e8a3fd2023-04-10 18:05:44 +0800264 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
265 val &= ~USXGMII_AN_ENABLE;
266 regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
developercfa104b2023-01-11 17:40:41 +0800267
268 /* Gated USXGMII */
developer4e8a3fd2023-04-10 18:05:44 +0800269 regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
developercfa104b2023-01-11 17:40:41 +0800270 val |= RG_MAC_CK_GATED;
developer4e8a3fd2023-04-10 18:05:44 +0800271 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developercfa104b2023-01-11 17:40:41 +0800272
273 ndelay(1020);
274
275 /* USXGMII force mode setting */
developer4e8a3fd2023-04-10 18:05:44 +0800276 regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
developercfa104b2023-01-11 17:40:41 +0800277 val |= RG_USXGMII_RATE_UPDATE_MODE;
278 val |= RG_IF_FORCE_EN;
279 val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
developer4e8a3fd2023-04-10 18:05:44 +0800280 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developercfa104b2023-01-11 17:40:41 +0800281
282 /* Un-gated USXGMII */
developer4e8a3fd2023-04-10 18:05:44 +0800283 regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
developercfa104b2023-01-11 17:40:41 +0800284 val &= ~RG_MAC_CK_GATED;
developer4e8a3fd2023-04-10 18:05:44 +0800285 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developer089e8852022-09-28 14:43:46 +0800286
developercfa104b2023-01-11 17:40:41 +0800287 ndelay(1020);
288
developer4e8a3fd2023-04-10 18:05:44 +0800289 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800290 0x00D9071C);
developer4e8a3fd2023-04-10 18:05:44 +0800291 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800292 0xAAA5A5AA);
developer4e8a3fd2023-04-10 18:05:44 +0800293 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800294 0x0C020707);
developer4e8a3fd2023-04-10 18:05:44 +0800295 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800296 0x0E050F0F);
developer4e8a3fd2023-04-10 18:05:44 +0800297 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800298 0x00140032);
developer4e8a3fd2023-04-10 18:05:44 +0800299 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800300 0x00C018AA);
developer4e8a3fd2023-04-10 18:05:44 +0800301 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800302 0x3777812B);
developer4e8a3fd2023-04-10 18:05:44 +0800303 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800304 0x005C9CFF);
developer4e8a3fd2023-04-10 18:05:44 +0800305 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800306 0x9DFAFAFA);
developer4e8a3fd2023-04-10 18:05:44 +0800307 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800308 0x273F3F3F);
developer4e8a3fd2023-04-10 18:05:44 +0800309 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800310 0xA8883868);
developer4e8a3fd2023-04-10 18:05:44 +0800311 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800312 0x14661466);
developer4e8a3fd2023-04-10 18:05:44 +0800313 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800314 0x0E001ABF);
developer4e8a3fd2023-04-10 18:05:44 +0800315 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800316 0x080B0D0D);
developer4e8a3fd2023-04-10 18:05:44 +0800317 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800318 0x02050909);
developer4e8a3fd2023-04-10 18:05:44 +0800319 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800320 0x0C000000);
developer4e8a3fd2023-04-10 18:05:44 +0800321 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800322 0x04000000);
developer4e8a3fd2023-04-10 18:05:44 +0800323 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800324 0x0F0F0C06);
developer4e8a3fd2023-04-10 18:05:44 +0800325 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800326 0x50808C8C);
developer4e8a3fd2023-04-10 18:05:44 +0800327 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800328 0x18000000);
developer4e8a3fd2023-04-10 18:05:44 +0800329 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800330 0x00A132A1);
developer4e8a3fd2023-04-10 18:05:44 +0800331 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800332 0x80201F20);
developer4e8a3fd2023-04-10 18:05:44 +0800333 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800334 0x00050C00);
developer4e8a3fd2023-04-10 18:05:44 +0800335 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800336 0x02002800);
337 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800338 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800339 0x00000020);
developer4e8a3fd2023-04-10 18:05:44 +0800340 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800341 0x00008A01);
developer4e8a3fd2023-04-10 18:05:44 +0800342 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800343 0x0000A884);
developer4e8a3fd2023-04-10 18:05:44 +0800344 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800345 0x00083002);
developer4e8a3fd2023-04-10 18:05:44 +0800346 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800347 0x00022220);
developer4e8a3fd2023-04-10 18:05:44 +0800348 regmap_update_bits(mpcs->regmap_pextp, 0x5064, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800349 0x0F020A01);
developer4e8a3fd2023-04-10 18:05:44 +0800350 regmap_update_bits(mpcs->regmap_pextp, 0x50B4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800351 0x06100600);
developer4e8a3fd2023-04-10 18:05:44 +0800352 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800353 0x40704000);
developer4e8a3fd2023-04-10 18:05:44 +0800354 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800355 0xA8000000);
developer4e8a3fd2023-04-10 18:05:44 +0800356 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800357 0x000000AA);
developer4e8a3fd2023-04-10 18:05:44 +0800358 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800359 0x00000F00);
developer4e8a3fd2023-04-10 18:05:44 +0800360 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800361 0x00040000);
developer4e8a3fd2023-04-10 18:05:44 +0800362 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800363 0x00000003);
developer4e8a3fd2023-04-10 18:05:44 +0800364 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800365 0x0200E800);
366 udelay(150);
developer4e8a3fd2023-04-10 18:05:44 +0800367 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800368 0x0200C111);
369 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800370 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800371 0x0200C101);
372 udelay(15);
developer4e8a3fd2023-04-10 18:05:44 +0800373 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800374 0x0202C111);
375 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800376 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800377 0x0202C101);
378 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800379 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800380 0x00000030);
developer4e8a3fd2023-04-10 18:05:44 +0800381 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800382 0x80201F00);
developer4e8a3fd2023-04-10 18:05:44 +0800383 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800384 0x30000000);
385 udelay(400);
developer4e8a3fd2023-04-10 18:05:44 +0800386
387 return 0;
developercfa104b2023-01-11 17:40:41 +0800388}
389
developer4e8a3fd2023-04-10 18:05:44 +0800390int mtk_usxgmii_setup_phya_force_10000(struct mtk_usxgmii_pcs *mpcs)
developercfa104b2023-01-11 17:40:41 +0800391{
392 unsigned int val;
developercfa104b2023-01-11 17:40:41 +0800393
developer4e8a3fd2023-04-10 18:05:44 +0800394 if (!mpcs->regmap || !mpcs->regmap_pextp)
395 return -EINVAL;
developercfa104b2023-01-11 17:40:41 +0800396
397 /* Setup USXGMII speed */
398 val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_10G) |
399 FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_10G);
developer4e8a3fd2023-04-10 18:05:44 +0800400 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developercfa104b2023-01-11 17:40:41 +0800401
developer089e8852022-09-28 14:43:46 +0800402 /* Disable USXGMII AN mode */
developer4e8a3fd2023-04-10 18:05:44 +0800403 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
404 val &= ~USXGMII_AN_ENABLE;
405 regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
developer089e8852022-09-28 14:43:46 +0800406
407 /* Gated USXGMII */
developer4e8a3fd2023-04-10 18:05:44 +0800408 regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
developer089e8852022-09-28 14:43:46 +0800409 val |= RG_MAC_CK_GATED;
developer4e8a3fd2023-04-10 18:05:44 +0800410 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developer089e8852022-09-28 14:43:46 +0800411
412 ndelay(1020);
413
414 /* USXGMII force mode setting */
developer4e8a3fd2023-04-10 18:05:44 +0800415 regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
developer089e8852022-09-28 14:43:46 +0800416 val |= RG_USXGMII_RATE_UPDATE_MODE;
417 val |= RG_IF_FORCE_EN;
418 val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1);
developer4e8a3fd2023-04-10 18:05:44 +0800419 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developer089e8852022-09-28 14:43:46 +0800420
421 /* Un-gated USXGMII */
developer4e8a3fd2023-04-10 18:05:44 +0800422 regmap_read(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, &val);
developer089e8852022-09-28 14:43:46 +0800423 val &= ~RG_MAC_CK_GATED;
developer4e8a3fd2023-04-10 18:05:44 +0800424 regmap_write(mpcs->regmap, RG_PHY_TOP_SPEED_CTRL1, val);
developer089e8852022-09-28 14:43:46 +0800425
426 ndelay(1020);
427
developer4e8a3fd2023-04-10 18:05:44 +0800428 regmap_update_bits(mpcs->regmap_pextp, 0x9024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800429 0x00C9071C);
developer4e8a3fd2023-04-10 18:05:44 +0800430 regmap_update_bits(mpcs->regmap_pextp, 0x2020, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800431 0xAA8585AA);
developer4e8a3fd2023-04-10 18:05:44 +0800432 regmap_update_bits(mpcs->regmap_pextp, 0x2030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800433 0x0C020707);
developer4e8a3fd2023-04-10 18:05:44 +0800434 regmap_update_bits(mpcs->regmap_pextp, 0x2034, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800435 0x0E050F0F);
developer4e8a3fd2023-04-10 18:05:44 +0800436 regmap_update_bits(mpcs->regmap_pextp, 0x2040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800437 0x00140032);
developer4e8a3fd2023-04-10 18:05:44 +0800438 regmap_update_bits(mpcs->regmap_pextp, 0x50F0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800439 0x00C014AA);
developer4e8a3fd2023-04-10 18:05:44 +0800440 regmap_update_bits(mpcs->regmap_pextp, 0x50E0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800441 0x3777C12B);
developer4e8a3fd2023-04-10 18:05:44 +0800442 regmap_update_bits(mpcs->regmap_pextp, 0x506C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800443 0x005F9CFF);
developer4e8a3fd2023-04-10 18:05:44 +0800444 regmap_update_bits(mpcs->regmap_pextp, 0x5070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800445 0x9D9DFAFA);
developer4e8a3fd2023-04-10 18:05:44 +0800446 regmap_update_bits(mpcs->regmap_pextp, 0x5074, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800447 0x27273F3F);
developer4e8a3fd2023-04-10 18:05:44 +0800448 regmap_update_bits(mpcs->regmap_pextp, 0x5078, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800449 0xA7883C68);
developer4e8a3fd2023-04-10 18:05:44 +0800450 regmap_update_bits(mpcs->regmap_pextp, 0x507C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800451 0x11661166);
developer4e8a3fd2023-04-10 18:05:44 +0800452 regmap_update_bits(mpcs->regmap_pextp, 0x5080, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800453 0x0E000AAF);
developer4e8a3fd2023-04-10 18:05:44 +0800454 regmap_update_bits(mpcs->regmap_pextp, 0x5084, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800455 0x08080D0D);
developer4e8a3fd2023-04-10 18:05:44 +0800456 regmap_update_bits(mpcs->regmap_pextp, 0x5088, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800457 0x02030909);
developer4e8a3fd2023-04-10 18:05:44 +0800458 regmap_update_bits(mpcs->regmap_pextp, 0x50E4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800459 0x0C0C0000);
developer4e8a3fd2023-04-10 18:05:44 +0800460 regmap_update_bits(mpcs->regmap_pextp, 0x50E8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800461 0x04040000);
developer4e8a3fd2023-04-10 18:05:44 +0800462 regmap_update_bits(mpcs->regmap_pextp, 0x50EC, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800463 0x0F0F0C06);
developer4e8a3fd2023-04-10 18:05:44 +0800464 regmap_update_bits(mpcs->regmap_pextp, 0x50A8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800465 0x506E8C8C);
developer4e8a3fd2023-04-10 18:05:44 +0800466 regmap_update_bits(mpcs->regmap_pextp, 0x6004, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800467 0x18190000);
developer4e8a3fd2023-04-10 18:05:44 +0800468 regmap_update_bits(mpcs->regmap_pextp, 0x00F8, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800469 0x01423342);
developer4e8a3fd2023-04-10 18:05:44 +0800470 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800471 0x80201F20);
developer4e8a3fd2023-04-10 18:05:44 +0800472 regmap_update_bits(mpcs->regmap_pextp, 0x0030, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800473 0x00050C00);
developer4e8a3fd2023-04-10 18:05:44 +0800474 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800475 0x02002800);
developer089e8852022-09-28 14:43:46 +0800476 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800477 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800478 0x00000020);
developer4e8a3fd2023-04-10 18:05:44 +0800479 regmap_update_bits(mpcs->regmap_pextp, 0x3028, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800480 0x00008A01);
developer4e8a3fd2023-04-10 18:05:44 +0800481 regmap_update_bits(mpcs->regmap_pextp, 0x302C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800482 0x0000A884);
developer4e8a3fd2023-04-10 18:05:44 +0800483 regmap_update_bits(mpcs->regmap_pextp, 0x3024, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800484 0x00083002);
developer4e8a3fd2023-04-10 18:05:44 +0800485 regmap_update_bits(mpcs->regmap_pextp, 0x3010, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800486 0x00022220);
developer4e8a3fd2023-04-10 18:05:44 +0800487 regmap_update_bits(mpcs->regmap_pextp, 0x5064, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800488 0x0F020A01);
developer4e8a3fd2023-04-10 18:05:44 +0800489 regmap_update_bits(mpcs->regmap_pextp, 0x50B4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800490 0x06100600);
developer4e8a3fd2023-04-10 18:05:44 +0800491 regmap_update_bits(mpcs->regmap_pextp, 0x3048, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800492 0x49664100);
developer4e8a3fd2023-04-10 18:05:44 +0800493 regmap_update_bits(mpcs->regmap_pextp, 0x3050, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800494 0x00000000);
developer4e8a3fd2023-04-10 18:05:44 +0800495 regmap_update_bits(mpcs->regmap_pextp, 0x3054, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800496 0x00000000);
developer4e8a3fd2023-04-10 18:05:44 +0800497 regmap_update_bits(mpcs->regmap_pextp, 0x306C, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800498 0x00000F00);
developer4e8a3fd2023-04-10 18:05:44 +0800499 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800500 0x00040000);
developer4e8a3fd2023-04-10 18:05:44 +0800501 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800502 0x00000001);
developer4e8a3fd2023-04-10 18:05:44 +0800503 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800504 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800505 udelay(150);
developer4e8a3fd2023-04-10 18:05:44 +0800506 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800507 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800508 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800509 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800510 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800511 udelay(15);
developer4e8a3fd2023-04-10 18:05:44 +0800512 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800513 0x0202C111);
developer089e8852022-09-28 14:43:46 +0800514 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800515 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800516 0x0202C101);
developer089e8852022-09-28 14:43:46 +0800517 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800518 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800519 0x00000030);
developer4e8a3fd2023-04-10 18:05:44 +0800520 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800521 0x80201F00);
developer4e8a3fd2023-04-10 18:05:44 +0800522 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800523 0x30000000);
developer089e8852022-09-28 14:43:46 +0800524 udelay(400);
developer4e8a3fd2023-04-10 18:05:44 +0800525
526 return 0;
developer089e8852022-09-28 14:43:46 +0800527}
528
developer4e8a3fd2023-04-10 18:05:44 +0800529void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
developer089e8852022-09-28 14:43:46 +0800530{
developer6aa00162023-03-20 11:56:51 +0800531 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800532
developer8b6f2402022-11-28 13:42:34 +0800533 if (id >= MTK_MAX_DEVS || !eth->toprgu)
developer089e8852022-09-28 14:43:46 +0800534 return;
535
developer4e8a3fd2023-04-10 18:05:44 +0800536 switch (id) {
537 case 0:
developer6aa00162023-03-20 11:56:51 +0800538 /* Enable software reset */
539 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800540 val |= SWSYSRST_XFI_PEXPT0_GRST |
541 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800542 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
543
544 /* Assert USXGMII reset */
545 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
546 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800547 SWSYSRST_XFI_PEXPT0_GRST |
548 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800549 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
550
551 udelay(100);
552
553 /* De-assert USXGMII reset */
554 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
555 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800556 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
557 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800558 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
559
560 /* Disable software reset */
561 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800562 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
563 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800564 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800565 break;
developer4e8a3fd2023-04-10 18:05:44 +0800566 case 1:
developer6aa00162023-03-20 11:56:51 +0800567 /* Enable software reset */
568 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800569 val |= SWSYSRST_XFI_PEXPT1_GRST |
570 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800571 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
572
573 /* Assert USXGMII reset */
574 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
575 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800576 SWSYSRST_XFI_PEXPT1_GRST |
577 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800578 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
579
580 udelay(100);
581
582 /* De-assert USXGMII reset */
583 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
584 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800585 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
586 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800587 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
588
589 /* Disable software reset */
590 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800591 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
592 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800593 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800594 break;
595 }
596
developer993b3852022-12-08 15:58:20 +0800597 mdelay(10);
developer089e8852022-09-28 14:43:46 +0800598}
599
developer8900c0a2023-05-09 10:37:33 +0800600static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
601 phy_interface_t interface,
602 const unsigned long *advertising,
603 bool permit_pause_to_mac)
604{
605 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
606 struct mtk_eth *eth = mpcs->eth;
607 int err = 0;
608
609 mpcs->interface = interface;
610
611 mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
612 mtk_usxgmii_reset(eth, mpcs->id);
613
614 /* Setup USXGMIISYS with the determined property */
615 if (interface == PHY_INTERFACE_MODE_USXGMII)
616 err = mtk_usxgmii_setup_phya_an_10000(mpcs);
617 else if (interface == PHY_INTERFACE_MODE_10GKR)
618 err = mtk_usxgmii_setup_phya_force_10000(mpcs);
619 else if (interface == PHY_INTERFACE_MODE_5GBASER)
620 err = mtk_usxgmii_setup_phya_force_5000(mpcs);
621
622 return err;
623}
624
developer4e8a3fd2023-04-10 18:05:44 +0800625static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
626 struct phylink_link_state *state)
developer089e8852022-09-28 14:43:46 +0800627{
developer4e8a3fd2023-04-10 18:05:44 +0800628 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
629 struct mtk_eth *eth = mpcs->eth;
630 struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)];
631 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800632
developer4e8a3fd2023-04-10 18:05:44 +0800633 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
634 if (FIELD_GET(USXGMII_AN_ENABLE, val)) {
635 /* Refresh LPA by inverting LPA_LATCH */
636 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
637 regmap_update_bits(mpcs->regmap, RG_PCS_AN_STS0,
638 USXGMII_LPA_LATCH,
639 !(val & USXGMII_LPA_LATCH));
developer089e8852022-09-28 14:43:46 +0800640
developer4e8a3fd2023-04-10 18:05:44 +0800641 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
developer089e8852022-09-28 14:43:46 +0800642
developer4e8a3fd2023-04-10 18:05:44 +0800643 state->interface = mpcs->interface;
644 state->link = FIELD_GET(USXGMII_LPA_LINK, val);
645 state->duplex = FIELD_GET(USXGMII_LPA_DUPLEX, val);
646
647 switch (FIELD_GET(USXGMII_LPA_SPEED_MASK, val)) {
648 case USXGMII_LPA_SPEED_10:
649 state->speed = SPEED_10;
650 break;
651 case USXGMII_LPA_SPEED_100:
652 state->speed = SPEED_100;
653 break;
654 case USXGMII_LPA_SPEED_1000:
655 state->speed = SPEED_1000;
656 break;
657 case USXGMII_LPA_SPEED_2500:
658 state->speed = SPEED_2500;
659 break;
660 case USXGMII_LPA_SPEED_5000:
661 state->speed = SPEED_5000;
662 break;
663 case USXGMII_LPA_SPEED_10000:
664 state->speed = SPEED_10000;
665 break;
666 }
667 } else {
668 val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
669
670 if (mac->id == MTK_GMAC2_ID)
671 val = val >> 16;
672
673 switch (FIELD_GET(MTK_USXGMII_PCS_MODE, val)) {
674 case 0:
675 state->speed = SPEED_10000;
676 break;
677 case 1:
678 state->speed = SPEED_5000;
679 break;
680 case 2:
681 state->speed = SPEED_2500;
682 break;
683 case 3:
684 state->speed = SPEED_1000;
685 break;
686 }
687
688 state->interface = mpcs->interface;
689 state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, val);
690 state->duplex = DUPLEX_FULL;
691 }
developer4e8a3fd2023-04-10 18:05:44 +0800692
developer8900c0a2023-05-09 10:37:33 +0800693 if (state->link == 0)
694 mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
695 state->interface, NULL, false);
developer4e8a3fd2023-04-10 18:05:44 +0800696}
697
698void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
699{
700 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
701 unsigned int val = 0;
702
703 if (!mpcs->regmap)
704 return;
developer089e8852022-09-28 14:43:46 +0800705
developer4e8a3fd2023-04-10 18:05:44 +0800706 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
707 val |= USXGMII_AN_RESTART;
708 regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
709}
710
developeraeaea7b2023-05-18 18:20:10 +0800711static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
712 phy_interface_t interface,
713 int speed, int duplex)
714{
715 /* Reconfiguring USXGMII to ensure the quality of the RX signal
716 * after the line side link up.
717 */
718 mtk_usxgmii_pcs_config(pcs, mode,
719 interface, NULL, false);
720}
721
developer4e8a3fd2023-04-10 18:05:44 +0800722static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
723 .pcs_config = mtk_usxgmii_pcs_config,
724 .pcs_get_state = mtk_usxgmii_pcs_get_state,
725 .pcs_an_restart = mtk_usxgmii_pcs_restart_an,
developeraeaea7b2023-05-18 18:20:10 +0800726 .pcs_link_up = mtk_usxgmii_pcs_link_up,
developer4e8a3fd2023-04-10 18:05:44 +0800727};
728
729int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r)
730{
731 struct mtk_usxgmii *ss = eth->usxgmii;
732 struct device_node *np;
733 int ret, i;
734
735 for (i = 0; i < MTK_MAX_DEVS; i++) {
736 np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
737 if (!np)
738 break;
739
740 ss->pcs[i].id = i;
741 ss->pcs[i].eth = eth;
742
743 ss->pcs[i].regmap = syscon_node_to_regmap(np);
744 if (IS_ERR(ss->pcs[i].regmap))
745 return PTR_ERR(ss->pcs[i].regmap);
746
747 ss->pcs[i].pcs.ops = &mtk_usxgmii_pcs_ops;
748 ss->pcs[i].pcs.poll = true;
749 ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
750
751 of_node_put(np);
752 }
753
754 ret = mtk_usxgmii_xfi_pextp_init(ss, r);
755 if (ret)
756 return ret;
757
758 ret = mtk_usxgmii_xfi_pll_init(ss, r);
759 if (ret)
760 return ret;
developer089e8852022-09-28 14:43:46 +0800761
762 return 0;
763}
developer31d10662023-02-09 16:56:34 +0800764
developer4e8a3fd2023-04-10 18:05:44 +0800765struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id)
766{
767 if (!ss->pcs[id].regmap)
768 return NULL;
769
770 return &ss->pcs[id].pcs;
771}
772
developer31d10662023-02-09 16:56:34 +0800773int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range)
774{
775 unsigned int cur = offset;
776 unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0;
777
778 pr_info("\n============ %s ============ pmap:%x\n", name, pmap);
779 while (cur < offset + range) {
780 regmap_read(pmap, cur, &val1);
781 regmap_read(pmap, cur + 0x4, &val2);
782 regmap_read(pmap, cur + 0x8, &val3);
783 regmap_read(pmap, cur + 0xc, &val4);
784 pr_info("0x%x: %08x %08x %08x %08x\n", cur,
785 val1, val2, val3, val4);
786 cur += 0x10;
787 }
788 return 0;
789}
790