blob: 1bc4912e3082d6962ef757ae8247634391c70c32 [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),
developera500d942023-05-19 13:47:40 +0800492 0x47684100);
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);
developera500d942023-05-19 13:47:40 +0800499 if (mpcs->id == 0)
500 regmap_update_bits(mpcs->regmap_pextp, 0xA008, GENMASK(31, 0),
501 0x0007B400);
developer4e8a3fd2023-04-10 18:05:44 +0800502 regmap_update_bits(mpcs->regmap_pextp, 0xA060, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800503 0x00040000);
developer4e8a3fd2023-04-10 18:05:44 +0800504 regmap_update_bits(mpcs->regmap_pextp, 0x90D0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800505 0x00000001);
developer4e8a3fd2023-04-10 18:05:44 +0800506 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800507 0x0200E800);
developer089e8852022-09-28 14:43:46 +0800508 udelay(150);
developer4e8a3fd2023-04-10 18:05:44 +0800509 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800510 0x0200C111);
developer089e8852022-09-28 14:43:46 +0800511 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800512 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800513 0x0200C101);
developer089e8852022-09-28 14:43:46 +0800514 udelay(15);
developer4e8a3fd2023-04-10 18:05:44 +0800515 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800516 0x0202C111);
developer089e8852022-09-28 14:43:46 +0800517 ndelay(1020);
developer4e8a3fd2023-04-10 18:05:44 +0800518 regmap_update_bits(mpcs->regmap_pextp, 0x0070, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800519 0x0202C101);
developer089e8852022-09-28 14:43:46 +0800520 udelay(100);
developer4e8a3fd2023-04-10 18:05:44 +0800521 regmap_update_bits(mpcs->regmap_pextp, 0x30B0, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800522 0x00000030);
developer4e8a3fd2023-04-10 18:05:44 +0800523 regmap_update_bits(mpcs->regmap_pextp, 0x00F4, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800524 0x80201F00);
developer4e8a3fd2023-04-10 18:05:44 +0800525 regmap_update_bits(mpcs->regmap_pextp, 0x3040, GENMASK(31, 0),
developercfa104b2023-01-11 17:40:41 +0800526 0x30000000);
developer089e8852022-09-28 14:43:46 +0800527 udelay(400);
developer4e8a3fd2023-04-10 18:05:44 +0800528
529 return 0;
developer089e8852022-09-28 14:43:46 +0800530}
531
developer4e8a3fd2023-04-10 18:05:44 +0800532void mtk_usxgmii_reset(struct mtk_eth *eth, int id)
developer089e8852022-09-28 14:43:46 +0800533{
developer6aa00162023-03-20 11:56:51 +0800534 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800535
developer8b6f2402022-11-28 13:42:34 +0800536 if (id >= MTK_MAX_DEVS || !eth->toprgu)
developer089e8852022-09-28 14:43:46 +0800537 return;
538
developer4e8a3fd2023-04-10 18:05:44 +0800539 switch (id) {
540 case 0:
developer6aa00162023-03-20 11:56:51 +0800541 /* Enable software reset */
542 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800543 val |= SWSYSRST_XFI_PEXPT0_GRST |
544 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800545 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
546
547 /* Assert USXGMII reset */
548 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
549 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800550 SWSYSRST_XFI_PEXPT0_GRST |
551 SWSYSRST_XFI0_GRST;
developer6aa00162023-03-20 11:56:51 +0800552 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
553
554 udelay(100);
555
556 /* De-assert USXGMII reset */
557 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
558 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800559 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
560 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800561 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
562
563 /* Disable software reset */
564 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800565 val &= ~(SWSYSRST_XFI_PEXPT0_GRST |
566 SWSYSRST_XFI0_GRST);
developer6aa00162023-03-20 11:56:51 +0800567 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800568 break;
developer4e8a3fd2023-04-10 18:05:44 +0800569 case 1:
developer6aa00162023-03-20 11:56:51 +0800570 /* Enable software reset */
571 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800572 val |= SWSYSRST_XFI_PEXPT1_GRST |
573 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800574 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
575
576 /* Assert USXGMII reset */
577 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
578 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) |
developer4e8a3fd2023-04-10 18:05:44 +0800579 SWSYSRST_XFI_PEXPT1_GRST |
580 SWSYSRST_XFI1_GRST;
developer6aa00162023-03-20 11:56:51 +0800581 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
582
583 udelay(100);
584
585 /* De-assert USXGMII reset */
586 regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val);
587 val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88);
developer4e8a3fd2023-04-10 18:05:44 +0800588 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
589 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800590 regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val);
591
592 /* Disable software reset */
593 regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val);
developer4e8a3fd2023-04-10 18:05:44 +0800594 val &= ~(SWSYSRST_XFI_PEXPT1_GRST |
595 SWSYSRST_XFI1_GRST);
developer6aa00162023-03-20 11:56:51 +0800596 regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val);
developer089e8852022-09-28 14:43:46 +0800597 break;
598 }
599
developer993b3852022-12-08 15:58:20 +0800600 mdelay(10);
developer089e8852022-09-28 14:43:46 +0800601}
602
developer8900c0a2023-05-09 10:37:33 +0800603static int mtk_usxgmii_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
604 phy_interface_t interface,
605 const unsigned long *advertising,
606 bool permit_pause_to_mac)
607{
608 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
609 struct mtk_eth *eth = mpcs->eth;
610 int err = 0;
611
612 mpcs->interface = interface;
613
614 mtk_usxgmii_xfi_pll_enable(eth->usxgmii);
615 mtk_usxgmii_reset(eth, mpcs->id);
616
617 /* Setup USXGMIISYS with the determined property */
618 if (interface == PHY_INTERFACE_MODE_USXGMII)
619 err = mtk_usxgmii_setup_phya_an_10000(mpcs);
620 else if (interface == PHY_INTERFACE_MODE_10GKR)
621 err = mtk_usxgmii_setup_phya_force_10000(mpcs);
622 else if (interface == PHY_INTERFACE_MODE_5GBASER)
623 err = mtk_usxgmii_setup_phya_force_5000(mpcs);
624
625 return err;
626}
627
developer4e8a3fd2023-04-10 18:05:44 +0800628static void mtk_usxgmii_pcs_get_state(struct phylink_pcs *pcs,
629 struct phylink_link_state *state)
developer089e8852022-09-28 14:43:46 +0800630{
developer4e8a3fd2023-04-10 18:05:44 +0800631 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
632 struct mtk_eth *eth = mpcs->eth;
633 struct mtk_mac *mac = eth->mac[mtk_xgmii2mac_id(eth, mpcs->id)];
634 u32 val = 0;
developer089e8852022-09-28 14:43:46 +0800635
developer4e8a3fd2023-04-10 18:05:44 +0800636 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
637 if (FIELD_GET(USXGMII_AN_ENABLE, val)) {
638 /* Refresh LPA by inverting LPA_LATCH */
639 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
640 regmap_update_bits(mpcs->regmap, RG_PCS_AN_STS0,
641 USXGMII_LPA_LATCH,
642 !(val & USXGMII_LPA_LATCH));
developer089e8852022-09-28 14:43:46 +0800643
developer4e8a3fd2023-04-10 18:05:44 +0800644 regmap_read(mpcs->regmap, RG_PCS_AN_STS0, &val);
developer089e8852022-09-28 14:43:46 +0800645
developer4e8a3fd2023-04-10 18:05:44 +0800646 state->interface = mpcs->interface;
647 state->link = FIELD_GET(USXGMII_LPA_LINK, val);
648 state->duplex = FIELD_GET(USXGMII_LPA_DUPLEX, val);
649
650 switch (FIELD_GET(USXGMII_LPA_SPEED_MASK, val)) {
651 case USXGMII_LPA_SPEED_10:
652 state->speed = SPEED_10;
653 break;
654 case USXGMII_LPA_SPEED_100:
655 state->speed = SPEED_100;
656 break;
657 case USXGMII_LPA_SPEED_1000:
658 state->speed = SPEED_1000;
659 break;
660 case USXGMII_LPA_SPEED_2500:
661 state->speed = SPEED_2500;
662 break;
663 case USXGMII_LPA_SPEED_5000:
664 state->speed = SPEED_5000;
665 break;
666 case USXGMII_LPA_SPEED_10000:
667 state->speed = SPEED_10000;
668 break;
669 }
670 } else {
671 val = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id));
672
673 if (mac->id == MTK_GMAC2_ID)
674 val = val >> 16;
675
676 switch (FIELD_GET(MTK_USXGMII_PCS_MODE, val)) {
677 case 0:
678 state->speed = SPEED_10000;
679 break;
680 case 1:
681 state->speed = SPEED_5000;
682 break;
683 case 2:
684 state->speed = SPEED_2500;
685 break;
686 case 3:
687 state->speed = SPEED_1000;
688 break;
689 }
690
691 state->interface = mpcs->interface;
692 state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, val);
693 state->duplex = DUPLEX_FULL;
694 }
developer4e8a3fd2023-04-10 18:05:44 +0800695
developer8900c0a2023-05-09 10:37:33 +0800696 if (state->link == 0)
697 mtk_usxgmii_pcs_config(pcs, MLO_AN_INBAND,
698 state->interface, NULL, false);
developer4e8a3fd2023-04-10 18:05:44 +0800699}
700
701void mtk_usxgmii_pcs_restart_an(struct phylink_pcs *pcs)
702{
703 struct mtk_usxgmii_pcs *mpcs = pcs_to_mtk_usxgmii_pcs(pcs);
704 unsigned int val = 0;
705
706 if (!mpcs->regmap)
707 return;
developer089e8852022-09-28 14:43:46 +0800708
developer4e8a3fd2023-04-10 18:05:44 +0800709 regmap_read(mpcs->regmap, RG_PCS_AN_CTRL0, &val);
710 val |= USXGMII_AN_RESTART;
711 regmap_write(mpcs->regmap, RG_PCS_AN_CTRL0, val);
712}
713
developeraeaea7b2023-05-18 18:20:10 +0800714static void mtk_usxgmii_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
715 phy_interface_t interface,
716 int speed, int duplex)
717{
718 /* Reconfiguring USXGMII to ensure the quality of the RX signal
719 * after the line side link up.
720 */
721 mtk_usxgmii_pcs_config(pcs, mode,
722 interface, NULL, false);
723}
724
developer4e8a3fd2023-04-10 18:05:44 +0800725static const struct phylink_pcs_ops mtk_usxgmii_pcs_ops = {
726 .pcs_config = mtk_usxgmii_pcs_config,
727 .pcs_get_state = mtk_usxgmii_pcs_get_state,
728 .pcs_an_restart = mtk_usxgmii_pcs_restart_an,
developeraeaea7b2023-05-18 18:20:10 +0800729 .pcs_link_up = mtk_usxgmii_pcs_link_up,
developer4e8a3fd2023-04-10 18:05:44 +0800730};
731
732int mtk_usxgmii_init(struct mtk_eth *eth, struct device_node *r)
733{
734 struct mtk_usxgmii *ss = eth->usxgmii;
735 struct device_node *np;
736 int ret, i;
737
738 for (i = 0; i < MTK_MAX_DEVS; i++) {
739 np = of_parse_phandle(r, "mediatek,usxgmiisys", i);
740 if (!np)
741 break;
742
743 ss->pcs[i].id = i;
744 ss->pcs[i].eth = eth;
745
746 ss->pcs[i].regmap = syscon_node_to_regmap(np);
747 if (IS_ERR(ss->pcs[i].regmap))
748 return PTR_ERR(ss->pcs[i].regmap);
749
750 ss->pcs[i].pcs.ops = &mtk_usxgmii_pcs_ops;
751 ss->pcs[i].pcs.poll = true;
752 ss->pcs[i].interface = PHY_INTERFACE_MODE_NA;
753
754 of_node_put(np);
755 }
756
757 ret = mtk_usxgmii_xfi_pextp_init(ss, r);
758 if (ret)
759 return ret;
760
761 ret = mtk_usxgmii_xfi_pll_init(ss, r);
762 if (ret)
763 return ret;
developer089e8852022-09-28 14:43:46 +0800764
765 return 0;
766}
developer31d10662023-02-09 16:56:34 +0800767
developer4e8a3fd2023-04-10 18:05:44 +0800768struct phylink_pcs *mtk_usxgmii_select_pcs(struct mtk_usxgmii *ss, int id)
769{
770 if (!ss->pcs[id].regmap)
771 return NULL;
772
773 return &ss->pcs[id].pcs;
774}
775
developer31d10662023-02-09 16:56:34 +0800776int mtk_dump_usxgmii(struct regmap *pmap, char *name, u32 offset, u32 range)
777{
778 unsigned int cur = offset;
779 unsigned int val1 = 0, val2 = 0, val3 = 0, val4 = 0;
780
781 pr_info("\n============ %s ============ pmap:%x\n", name, pmap);
782 while (cur < offset + range) {
783 regmap_read(pmap, cur, &val1);
784 regmap_read(pmap, cur + 0x4, &val2);
785 regmap_read(pmap, cur + 0x8, &val3);
786 regmap_read(pmap, cur + 0xc, &val4);
787 pr_info("0x%x: %08x %08x %08x %08x\n", cur,
788 val1, val2, val3, val4);
789 cur += 0x10;
790 }
791 return 0;
792}
793