blob: 7da251703fb05191b25d8eab1bffe2faa6693398 [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001/* Copyright 2016 MediaTek Inc.
2 * Author: Carlos Huang <carlos.huang@mediatek.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#include "mii_mgr.h"
14
15void set_an_polling(u32 an_status)
16{
17 if (an_status == 1)
18 *(unsigned long *)(ESW_PHY_POLLING) |= (1 << 31);
19 else
20 *(unsigned long *)(ESW_PHY_POLLING) &= ~(1 << 31);
21}
22
23u32 __mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
24{
25 u32 status = 0;
26 u32 rc = 0;
27 unsigned long t_start = jiffies;
28 u32 data = 0;
29 struct END_DEVICE *ei_local = netdev_priv(dev_raether);
30 unsigned long flags;
31
32 spin_lock_irqsave(&ei_local->mdio_lock, flags);
33 /* We enable mdio gpio purpose register, and disable it when exit. */
34 enable_mdio(1);
35
36 /* make sure previous read operation is complete */
37 while (1) {
38 /* 0 : Read/write operation complete */
39 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
40 break;
41 } else if (time_after(jiffies, t_start + 5 * HZ)) {
42 enable_mdio(0);
43 rc = 0;
44 pr_err("\n MDIO Read operation is ongoing !!\n");
45 goto out;
46 }
47 }
48
49 data =
50 (0x01 << 16) | (0x02 << 18) | (phy_addr << 20) | (phy_register <<
51 25);
52 sys_reg_write(MDIO_PHY_CONTROL_0, data);
53 sys_reg_write(MDIO_PHY_CONTROL_0, (data | (1 << 31)));
54
55 /* make sure read operation is complete */
56 t_start = jiffies;
57 while (1) {
58 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
59 status = sys_reg_read(MDIO_PHY_CONTROL_0);
60 *read_data = (u32)(status & 0x0000FFFF);
61
62 enable_mdio(0);
63 rc = 1;
64 goto out;
65 } else if (time_after(jiffies, t_start + 5 * HZ)) {
66 enable_mdio(0);
67 rc = 0;
68 pr_err
69 ("\n MDIO Read operation Time Out!!\n");
70 goto out;
71 }
72 }
73out:
74 spin_unlock_irqrestore(&ei_local->mdio_lock, flags);
75 return rc;
76}
77
78u32 __mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
79{
80 unsigned long t_start = jiffies;
81 u32 data;
82 u32 rc = 0;
83 struct END_DEVICE *ei_local = netdev_priv(dev_raether);
84 unsigned long flags;
85
86 spin_lock_irqsave(&ei_local->mdio_lock, flags);
87 enable_mdio(1);
88
89 /* make sure previous write operation is complete */
90 while (1) {
91 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
92 break;
93 } else if (time_after(jiffies, t_start + 5 * HZ)) {
94 enable_mdio(0);
95 rc = 0;
96 pr_err("\n MDIO Write operation ongoing\n");
97 goto out;
98 }
99 }
100
101 data =
102 (0x01 << 16) | (1 << 18) | (phy_addr << 20) | (phy_register << 25) |
103 write_data;
104 sys_reg_write(MDIO_PHY_CONTROL_0, data);
105 sys_reg_write(MDIO_PHY_CONTROL_0, (data | (1 << 31))); /*start*/
106 /* pr_err("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0); */
107
108 t_start = jiffies;
109
110 /* make sure write operation is complete */
111 while (1) {
112 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
113 enable_mdio(0);
114 rc = 1;
115 goto out;
116 } else if (time_after(jiffies, t_start + 5 * HZ)) {
117 enable_mdio(0);
118 rc = 0;
119 pr_err("\n MDIO Write operation Time Out\n");
120 goto out;
121 }
122 }
123out:
124 spin_unlock_irqrestore(&ei_local->mdio_lock, flags);
125 return rc;
126}
127
128u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
129{
130 struct END_DEVICE *ei_local = netdev_priv(dev_raether);
131 u32 low_word;
132 u32 high_word;
133 u32 an_status = 0;
134
135 if ((ei_local->architecture &
136 (GE1_RGMII_FORCE_1000 | GE1_TRGMII_FORCE_2000 |
137 GE1_TRGMII_FORCE_2600)) && (phy_addr == 31)) {
138 an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1 << 31));
139 if (an_status)
140 set_an_polling(0);
141 if (__mii_mgr_write
142 (phy_addr, 0x1f, ((phy_register >> 6) & 0x3FF))) {
143 if (__mii_mgr_read
144 (phy_addr, (phy_register >> 2) & 0xF, &low_word)) {
145 if (__mii_mgr_read
146 (phy_addr, (0x1 << 4), &high_word)) {
147 *read_data =
148 (high_word << 16) | (low_word &
149 0xFFFF);
150 if (an_status)
151 set_an_polling(1);
152 return 1;
153 }
154 }
155 }
156 if (an_status)
157 set_an_polling(1);
158 } else {
159 if (__mii_mgr_read(phy_addr, phy_register, read_data))
160 return 1;
161 }
162 return 0;
163}
164EXPORT_SYMBOL(mii_mgr_read);
165
166u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
167{
168 struct END_DEVICE *ei_local = netdev_priv(dev_raether);
169 u32 an_status = 0;
170
171 if ((ei_local->architecture &
172 (GE1_RGMII_FORCE_1000 | GE1_TRGMII_FORCE_2000 |
173 GE1_TRGMII_FORCE_2600)) && (phy_addr == 31)) {
174 an_status = (*(unsigned long *)(ESW_PHY_POLLING) & (1 << 31));
175 if (an_status)
176 set_an_polling(0);
177 if (__mii_mgr_write
178 (phy_addr, 0x1f, (phy_register >> 6) & 0x3FF)) {
179 if (__mii_mgr_write
180 (phy_addr, ((phy_register >> 2) & 0xF),
181 write_data & 0xFFFF)) {
182 if (__mii_mgr_write
183 (phy_addr, (0x1 << 4), write_data >> 16)) {
184 if (an_status)
185 set_an_polling(1);
186 return 1;
187 }
188 }
189 }
190 if (an_status)
191 set_an_polling(1);
192 } else {
193 if (__mii_mgr_write(phy_addr, phy_register, write_data))
194 return 1;
195 }
196
197 return 0;
198}
199EXPORT_SYMBOL(mii_mgr_write);
200
201u32 mii_mgr_cl45_set_address(u32 port_num, u32 dev_addr, u32 reg_addr)
202{
203 u32 rc = 0;
204 unsigned long t_start = jiffies;
205 u32 data = 0;
206
207 enable_mdio(1);
208
209 while (1) {
210 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
211 break;
212 } else if (time_after(jiffies, t_start + 5 * HZ)) {
213 enable_mdio(0);
214 pr_err("\n MDIO Read operation is ongoing !!\n");
215 return rc;
216 }
217 }
218 data =
219 (dev_addr << 25) | (port_num << 20) | (0x00 << 18) | (0x00 << 16) |
220 reg_addr;
221 sys_reg_write(MDIO_PHY_CONTROL_0, data);
222 sys_reg_write(MDIO_PHY_CONTROL_0, (data | (1 << 31)));
223
224 t_start = jiffies;
225 while (1) {
226 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
227 enable_mdio(0);
228 return 1;
229 } else if (time_after(jiffies, t_start + 5 * HZ)) {
230 enable_mdio(0);
231 pr_err("\n MDIO Write operation Time Out\n");
232 return 0;
233 }
234 }
235}
236
237u32 mii_mgr_read_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 *read_data)
238{
239 u32 status = 0;
240 u32 rc = 0;
241 unsigned long t_start = jiffies;
242 u32 data = 0;
243 struct END_DEVICE *ei_local = netdev_priv(dev_raether);
244 unsigned long flags;
245
246 spin_lock_irqsave(&ei_local->mdio_lock, flags);
247 /* set address first */
248 mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr);
249 /* udelay(10); */
250
251 enable_mdio(1);
252
253 while (1) {
254 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
255 break;
256 } else if (time_after(jiffies, t_start + 5 * HZ)) {
257 enable_mdio(0);
258 rc = 0;
259 pr_err("\n MDIO Read operation is ongoing !!\n");
260 goto out;
261 }
262 }
263 data =
264 (dev_addr << 25) | (port_num << 20) | (0x03 << 18) | (0x00 << 16) |
265 reg_addr;
266 sys_reg_write(MDIO_PHY_CONTROL_0, data);
267 sys_reg_write(MDIO_PHY_CONTROL_0, (data | (1 << 31)));
268 t_start = jiffies;
269 while (1) {
270 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
271 *read_data =
272 (sys_reg_read(MDIO_PHY_CONTROL_0) & 0x0000FFFF);
273 enable_mdio(0);
274 rc = 1;
275 goto out;
276 } else if (time_after(jiffies, t_start + 5 * HZ)) {
277 enable_mdio(0);
278 rc = 0;
279 pr_err
280 ("\n MDIO Read operation Time Out!!\n");
281 goto out;
282 }
283 status = sys_reg_read(MDIO_PHY_CONTROL_0);
284 }
285out:
286 spin_unlock_irqrestore(&ei_local->mdio_lock, flags);
287 return rc;
288}
289
290u32 mii_mgr_write_cl45(u32 port_num, u32 dev_addr, u32 reg_addr, u32 write_data)
291{
292 u32 rc = 0;
293 unsigned long t_start = jiffies;
294 u32 data = 0;
295 struct END_DEVICE *ei_local = netdev_priv(dev_raether);
296 unsigned long flags;
297
298 spin_lock_irqsave(&ei_local->mdio_lock, flags);
299 /* set address first */
300 mii_mgr_cl45_set_address(port_num, dev_addr, reg_addr);
301 /* udelay(10); */
302
303 enable_mdio(1);
304 while (1) {
305 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
306 break;
307 } else if (time_after(jiffies, t_start + 5 * HZ)) {
308 enable_mdio(0);
309 rc = 0;
310 pr_err("\n MDIO Read operation is ongoing !!\n");
311 goto out;
312 }
313 }
314
315 data =
316 (dev_addr << 25) | (port_num << 20) | (0x01 << 18) | (0x00 << 16) |
317 write_data;
318 sys_reg_write(MDIO_PHY_CONTROL_0, data);
319 sys_reg_write(MDIO_PHY_CONTROL_0, (data | (1 << 31)));
320
321 t_start = jiffies;
322
323 while (1) {
324 if (!(sys_reg_read(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
325 enable_mdio(0);
326 rc = 1;
327 goto out;
328 } else if (time_after(jiffies, t_start + 5 * HZ)) {
329 enable_mdio(0);
330 rc = 0;
331 pr_err("\n MDIO Write operation Time Out\n");
332 goto out;
333 }
334 }
335out:
336 spin_unlock_irqrestore(&ei_local->mdio_lock, flags);
337 return rc;
338}