a6e5cb763fd3d8df1395bffe856aa81ca123af66
[openwrt/staging/jow.git] / target / linux / realtek / files-5.4 / drivers / net / dsa / rtl83xx / rtl930x.c
1 // SPDX-License-Identifier: GPL-2.0-only
2
3 #include <asm/mach-rtl838x/mach-rtl83xx.h>
4 #include "rtl83xx.h"
5
6 extern struct mutex smi_lock;
7 extern struct rtl83xx_soc_info soc_info;
8
9 void rtl930x_print_matrix(void)
10 {
11 int i;
12 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6);
13
14 for (i = 0; i < 29; i++) {
15 rtl_table_read(r, i);
16 pr_debug("> %08x\n", sw_r32(rtl_table_data(r, 0)));
17 }
18 rtl_table_release(r);
19 }
20
21 inline void rtl930x_exec_tbl0_cmd(u32 cmd)
22 {
23 sw_w32(cmd, RTL930X_TBL_ACCESS_CTRL_0);
24 do { } while (sw_r32(RTL930X_TBL_ACCESS_CTRL_0) & (1 << 17));
25 }
26
27 inline void rtl930x_exec_tbl1_cmd(u32 cmd)
28 {
29 sw_w32(cmd, RTL930X_TBL_ACCESS_CTRL_1);
30 do { } while (sw_r32(RTL930X_TBL_ACCESS_CTRL_1) & (1 << 17));
31 }
32
33 inline int rtl930x_tbl_access_data_0(int i)
34 {
35 return RTL930X_TBL_ACCESS_DATA_0(i);
36 }
37
38 static inline int rtl930x_l2_port_new_salrn(int p)
39 {
40 return RTL930X_L2_PORT_SALRN(p);
41 }
42
43 static inline int rtl930x_l2_port_new_sa_fwd(int p)
44 {
45 // TODO: The definition of the fields changed, because of the master-cpu in a stack
46 return RTL930X_L2_PORT_NEW_SA_FWD(p);
47 }
48
49 inline static int rtl930x_trk_mbr_ctr(int group)
50 {
51 return RTL930X_TRK_MBR_CTRL + (group << 2);
52 }
53
54 static void rtl930x_vlan_tables_read(u32 vlan, struct rtl838x_vlan_info *info)
55 {
56 u32 v, w;
57 // Read VLAN table (1) via register 0
58 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 1);
59
60 rtl_table_read(r, vlan);
61 v = sw_r32(rtl_table_data(r, 0));
62 w = sw_r32(rtl_table_data(r, 1));
63 pr_debug("VLAN_READ %d: %08x %08x\n", vlan, v, w);
64 rtl_table_release(r);
65
66 info->tagged_ports = v >> 3;
67 info->profile_id = (w >> 24) & 7;
68 info->hash_mc_fid = !!(w & BIT(27));
69 info->hash_uc_fid = !!(w & BIT(28));
70 info->fid = ((v & 0x7) << 3) | ((w >> 29) & 0x7);
71
72 // Read UNTAG table via table register 2
73 r = rtl_table_get(RTL9300_TBL_2, 0);
74 rtl_table_read(r, vlan);
75 v = sw_r32(rtl_table_data(r, 0));
76 rtl_table_release(r);
77
78 info->untagged_ports = v >> 3;
79 }
80
81 static void rtl930x_vlan_set_tagged(u32 vlan, struct rtl838x_vlan_info *info)
82 {
83 u32 v, w;
84 // Access VLAN table (1) via register 0
85 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 1);
86
87 v = info->tagged_ports << 3;
88 v |= ((u32)info->fid) >> 3;
89
90 w = ((u32)info->fid) << 29;
91 w |= info->hash_mc_fid ? BIT(27) : 0;
92 w |= info->hash_uc_fid ? BIT(28) : 0;
93 w |= info->profile_id << 24;
94
95 sw_w32(v, rtl_table_data(r, 0));
96 sw_w32(w, rtl_table_data(r, 1));
97
98 rtl_table_write(r, vlan);
99 rtl_table_release(r);
100 }
101
102 void rtl930x_vlan_profile_dump(int profile)
103 {
104 u32 p[5];
105
106 if (profile < 0 || profile > 7)
107 return;
108
109 p[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile));
110 p[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 4);
111 p[2] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 8) & 0x1FFFFFFF;
112 p[3] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 12) & 0x1FFFFFFF;
113 p[4] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 16) & 0x1FFFFFFF;
114
115 pr_info("VLAN %d: L2 learn: %d; Unknown MC PMasks: L2 %0x, IPv4 %0x, IPv6: %0x",
116 profile, p[0] & (3 << 21), p[2], p[3], p[4]);
117 pr_info(" Routing enabled: IPv4 UC %c, IPv6 UC %c, IPv4 MC %c, IPv6 MC %c\n",
118 p[0] & BIT(17) ? 'y' : 'n', p[0] & BIT(16) ? 'y' : 'n',
119 p[0] & BIT(13) ? 'y' : 'n', p[0] & BIT(12) ? 'y' : 'n');
120 pr_info(" Bridge enabled: IPv4 MC %c, IPv6 MC %c,\n",
121 p[0] & BIT(15) ? 'y' : 'n', p[0] & BIT(14) ? 'y' : 'n');
122 pr_info("VLAN profile %d: raw %08x %08x %08x %08x %08x\n",
123 profile, p[0], p[1], p[2], p[3], p[4]);
124 }
125
126 static void rtl930x_vlan_set_untagged(u32 vlan, u64 portmask)
127 {
128 struct table_reg *r = rtl_table_get(RTL9300_TBL_2, 0);
129
130 sw_w32(portmask << 3, rtl_table_data(r, 0));
131 rtl_table_write(r, vlan);
132 rtl_table_release(r);
133 }
134
135 static void rtl930x_vlan_profile_setup(int profile)
136 {
137 u32 p[5];
138
139 pr_info("In %s\n", __func__);
140 p[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile));
141 p[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile) + 4);
142
143 // Enable routing of Ipv4/6 Unicast and IPv4/6 Multicast traffic
144 p[0] |= BIT(17) | BIT(16) | BIT(13) | BIT(12);
145 p[2] = 0x0fffffff; // L2 unknwon MC flooding portmask: all but the CPU-port
146 p[3] = 0x0fffffff; // IPv4 unknwon MC flooding portmask
147 p[4] = 0x0fffffff; // IPv6 unknwon MC flooding portmask
148
149 sw_w32(p[0], RTL930X_VLAN_PROFILE_SET(profile));
150 sw_w32(p[1], RTL930X_VLAN_PROFILE_SET(profile) + 4);
151 sw_w32(p[2], RTL930X_VLAN_PROFILE_SET(profile) + 8);
152 sw_w32(p[3], RTL930X_VLAN_PROFILE_SET(profile) + 12);
153 sw_w32(p[4], RTL930X_VLAN_PROFILE_SET(profile) + 16);
154 pr_info("Leaving %s\n", __func__);
155 }
156
157 static void rtl930x_stp_get(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
158 {
159 int i;
160 u32 cmd = 1 << 17 /* Execute cmd */
161 | 0 << 16 /* Read */
162 | 4 << 12 /* Table type 0b10 */
163 | (msti & 0xfff);
164 priv->r->exec_tbl0_cmd(cmd);
165
166 for (i = 0; i < 2; i++)
167 port_state[i] = sw_r32(RTL930X_TBL_ACCESS_DATA_0(i));
168 pr_debug("MSTI: %d STATE: %08x, %08x\n", msti, port_state[0], port_state[1]);
169 }
170
171 static void rtl930x_stp_set(struct rtl838x_switch_priv *priv, u16 msti, u32 port_state[])
172 {
173 int i;
174 u32 cmd = 1 << 17 /* Execute cmd */
175 | 1 << 16 /* Write */
176 | 4 << 12 /* Table type 4 */
177 | (msti & 0xfff);
178
179 for (i = 0; i < 2; i++)
180 sw_w32(port_state[i], RTL930X_TBL_ACCESS_DATA_0(i));
181 priv->r->exec_tbl0_cmd(cmd);
182 }
183
184 static inline int rtl930x_mac_force_mode_ctrl(int p)
185 {
186 return RTL930X_MAC_FORCE_MODE_CTRL + (p << 2);
187 }
188
189 static inline int rtl930x_mac_port_ctrl(int p)
190 {
191 return RTL930X_MAC_L2_PORT_CTRL(p);
192 }
193
194 static inline int rtl930x_mac_link_spd_sts(int p)
195 {
196 return RTL930X_MAC_LINK_SPD_STS(p);
197 }
198
199 static void rtl930x_fill_l2_entry(u32 r[], struct rtl838x_l2_entry *e)
200 {
201 e->valid = !!(r[2] & BIT(31));
202 if (!e->valid)
203 return;
204
205 // TODO: Is there not a function to copy directly MAC memory?
206 e->mac[0] = (r[0] >> 24);
207 e->mac[1] = (r[0] >> 16);
208 e->mac[2] = (r[0] >> 8);
209 e->mac[3] = r[0];
210 e->mac[4] = (r[1] >> 24);
211 e->mac[5] = (r[1] >> 16);
212
213 /* Is it a unicast entry? check multicast bit */
214 if (!(e->mac[0] & 1)) {
215 e->type = L2_UNICAST;
216 e->is_static = !!(r[2] & BIT(14));
217 e->vid = r[2] & 0xfff;
218 e->rvid = r[1] & 0xfff;
219 e->port = (r[2] >> 20) & 0x3ff;
220 // Check for trunk port
221 if (r[2] & BIT(30)) {
222 e->stackDev = (e->port >> 9) & 1;
223 e->trunk = e->port & 0x3f;
224 } else {
225 e->stackDev = (e->port >> 6) & 0xf;
226 e->port = e->port & 0x3f;
227 }
228
229 e->block_da = !!(r[2] & BIT(15));
230 e->block_sa = !!(r[2] & BIT(16));
231 e->suspended = !!(r[2] & BIT(13));
232 e->next_hop = !!(r[2] & BIT(12));
233 e->age = (r[2] >> 17) & 3;
234 e->valid = true;
235
236 } else {
237 e->valid = true;
238 e->type = L2_MULTICAST;
239 e->mc_portmask_index = (r[2]>>6) & 0xfff;
240 }
241 }
242
243 static u64 rtl930x_read_l2_entry_using_hash(u32 hash, u32 position, struct rtl838x_l2_entry *e)
244 {
245 u64 entry;
246 u32 r[3];
247 struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 0);
248 u32 idx = (0 << 14) | (hash << 2) | position;
249 int i;
250
251 rtl_table_read(q, idx);
252 for (i= 0; i < 3; i++)
253 r[i] = sw_r32(rtl_table_data(q, i));
254
255 rtl_table_release(q);
256
257 rtl930x_fill_l2_entry(r, e);
258 if (!e->valid)
259 return 0;
260
261 entry = ((u64)r[0] << 32) | (r[1] & 0xffff0000) | e->vid;
262 return entry;
263 }
264
265 static u64 rtl930x_read_cam(int idx, struct rtl838x_l2_entry *e)
266 {
267 u64 entry;
268 u32 r[3];
269 struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 1);
270 int i;
271
272 rtl_table_read(q, idx);
273 for (i= 0; i < 3; i++)
274 r[i] = sw_r32(rtl_table_data(q, i));
275
276 rtl_table_release(q);
277
278 rtl930x_fill_l2_entry(r, e);
279 if (!e->valid)
280 return 0;
281
282 entry = ((u64)r[0] << 32) | (r[1] & 0xffff0000) | e->vid;
283
284 return entry;
285 }
286
287 static u64 rtl930x_read_mcast_pmask(int idx)
288 {
289 u32 portmask;
290 // Read MC_PORTMASK (2) via register RTL9300_TBL_L2
291 struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 2);
292
293 rtl_table_read(q, idx);
294 portmask = sw_r32(rtl_table_data(q, 0));
295 portmask >>= 3;
296 rtl_table_release(q);
297
298 pr_debug("%s: Index idx %d has portmask %08x\n", __func__, idx, portmask);
299 return portmask;
300 }
301
302 static void rtl930x_write_mcast_pmask(int idx, u64 portmask)
303 {
304 u32 pm = portmask;
305
306 // Access MC_PORTMASK (2) via register RTL9300_TBL_L2
307 struct table_reg *q = rtl_table_get(RTL9300_TBL_L2, 2);
308
309 pr_debug("%s: Index idx %d has portmask %08x\n", __func__, idx, pm);
310 pm <<= 3;
311 sw_w32(pm, rtl_table_data(q, 0));
312 rtl_table_write(q, idx);
313 rtl_table_release(q);
314 }
315
316 u64 rtl930x_traffic_get(int source)
317 {
318 u32 v;
319 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6);
320
321 rtl_table_read(r, source);
322 v = sw_r32(rtl_table_data(r, 0));
323 rtl_table_release(r);
324 return v >> 3;
325 }
326
327 /*
328 * Enable traffic between a source port and a destination port matrix
329 */
330 void rtl930x_traffic_set(int source, u64 dest_matrix)
331 {
332 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6);
333
334 sw_w32((dest_matrix << 3), rtl_table_data(r, 0));
335 rtl_table_write(r, source);
336 rtl_table_release(r);
337 }
338
339 void rtl930x_traffic_enable(int source, int dest)
340 {
341 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6);
342 rtl_table_read(r, source);
343 sw_w32_mask(0, BIT(dest + 3), rtl_table_data(r, 0));
344 rtl_table_write(r, source);
345 rtl_table_release(r);
346 }
347
348 void rtl930x_traffic_disable(int source, int dest)
349 {
350 struct table_reg *r = rtl_table_get(RTL9300_TBL_0, 6);
351 rtl_table_read(r, source);
352 sw_w32_mask(BIT(dest + 3), 0, rtl_table_data(r, 0));
353 rtl_table_write(r, source);
354 rtl_table_release(r);
355 }
356
357 void rtl9300_dump_debug(void)
358 {
359 int i;
360 u16 r = RTL930X_STAT_PRVTE_DROP_COUNTER0;
361
362 for (i = 0; i < 10; i ++) {
363 pr_info("# %d %08x %08x %08x %08x %08x %08x %08x %08x\n", i * 8,
364 sw_r32(r), sw_r32(r + 4), sw_r32(r + 8), sw_r32(r + 12),
365 sw_r32(r + 16), sw_r32(r + 20), sw_r32(r + 24), sw_r32(r + 28));
366 r += 32;
367 }
368 pr_info("# %08x %08x %08x %08x %08x\n",
369 sw_r32(r), sw_r32(r + 4), sw_r32(r + 8), sw_r32(r + 12), sw_r32(r + 16));
370 rtl930x_print_matrix();
371 pr_info("RTL930X_L2_PORT_SABLK_CTRL: %08x, RTL930X_L2_PORT_DABLK_CTRL %08x\n",
372 sw_r32(RTL930X_L2_PORT_SABLK_CTRL), sw_r32(RTL930X_L2_PORT_DABLK_CTRL)
373
374 );
375 }
376
377 irqreturn_t rtl930x_switch_irq(int irq, void *dev_id)
378 {
379 struct dsa_switch *ds = dev_id;
380 u32 status = sw_r32(RTL930X_ISR_GLB);
381 u32 ports = sw_r32(RTL930X_ISR_PORT_LINK_STS_CHG);
382 u32 link;
383 int i;
384
385 /* Clear status */
386 sw_w32(ports, RTL930X_ISR_PORT_LINK_STS_CHG);
387 pr_info("RTL9300 Link change: status: %x, ports %x\n", status, ports);
388
389 rtl9300_dump_debug();
390
391 for (i = 0; i < 28; i++) {
392 if (ports & BIT(i)) {
393 /* Read the register twice because of issues with latency at least
394 * with the external RTL8226 PHY on the XGS1210 */
395 link = sw_r32(RTL930X_MAC_LINK_STS);
396 link = sw_r32(RTL930X_MAC_LINK_STS);
397 if (link & BIT(i))
398 dsa_port_phylink_mac_change(ds, i, true);
399 else
400 dsa_port_phylink_mac_change(ds, i, false);
401 }
402 }
403
404 return IRQ_HANDLED;
405 }
406
407 int rtl9300_sds_power(int mac, int val)
408 {
409 int sds_num;
410 u32 mode;
411
412 // TODO: these numbers are hard-coded for the Zyxel XGS1210 12 Switch
413 pr_info("SerDes: %s %d\n", __func__, mac);
414 switch (mac) {
415 case 24:
416 sds_num = 6;
417 mode = 0x12; // HISGMII
418 break;
419 case 25:
420 sds_num = 7;
421 mode = 0x12; // HISGMII
422 break;
423 case 26:
424 sds_num = 8;
425 mode = 0x1b; // 10GR/1000BX auto
426 break;
427 case 27:
428 sds_num = 9;
429 mode = 0x1b; // 10GR/1000BX auto
430 break;
431 default:
432 return -1;
433 }
434 if (!val)
435 mode = 0x1f; // OFF
436
437 rtl9300_sds_rst(sds_num, mode);
438
439 return 0;
440 }
441
442 int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val)
443 {
444 u32 v;
445 int err = 0;
446
447 pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, val);
448
449 if (port > 63 || page > 4095 || reg > 31)
450 return -ENOTSUPP;
451
452 val &= 0xffff;
453 mutex_lock(&smi_lock);
454
455 sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0);
456 sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
457 v = reg << 20 | page << 3 | 0x1f << 15 | BIT(2) | BIT(0);
458 sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
459
460 do {
461 v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
462 } while (v & 0x1);
463
464 if (v & 0x2)
465 err = -EIO;
466
467 mutex_unlock(&smi_lock);
468
469 return err;
470 }
471
472 int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
473 {
474 u32 v;
475 int err = 0;
476
477 // pr_info("In %s\n", __func__);
478 if (port > 63 || page > 4095 || reg > 31)
479 return -ENOTSUPP;
480
481 mutex_lock(&smi_lock);
482
483 sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
484 v = reg << 20 | page << 3 | 0x1f << 15 | 1;
485 sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
486
487 do {
488 v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
489 } while ( v & 0x1);
490
491 if (v & BIT(25)) {
492 pr_debug("Error reading phy %d, register %d\n", port, reg);
493 err = -EIO;
494 }
495 *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff);
496
497 pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, *val);
498
499 mutex_unlock(&smi_lock);
500
501 return err;
502 }
503
504 /*
505 * Write to an mmd register of the PHY
506 */
507 int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
508 {
509 int err = 0;
510 u32 v;
511
512 mutex_lock(&smi_lock);
513
514 // Set PHY to access
515 sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0);
516
517 // Set data to write
518 sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
519
520 // Set MMD device number and register to write to
521 sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3);
522
523 v = BIT(2)| BIT(1)| BIT(0); // WRITE | MMD-access | EXEC
524 sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
525
526 do {
527 v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
528 } while ( v & BIT(0));
529
530 pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err);
531 mutex_unlock(&smi_lock);
532 return err;
533 }
534
535 /*
536 * Read an mmd register of the PHY
537 */
538 int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
539 {
540 int err = 0;
541 u32 v;
542
543 mutex_lock(&smi_lock);
544
545 // Set PHY to access
546 sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
547
548 // Set MMD device number and register to write to
549 sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3);
550
551 v = BIT(1)| BIT(0); // MMD-access | EXEC
552 sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
553
554 do {
555 v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
556 } while ( v & 0x1);
557 // There is no error-checking via BIT 25 of v, as it does not seem to be set correctly
558 *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff);
559 pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err);
560
561 mutex_unlock(&smi_lock);
562
563 return err;
564 }
565
566
567 /*
568 * Calculate both the block 0 and the block 1 hash, and return in
569 * lower and higher word of the return value since only 12 bit of
570 * the hash are significant
571 */
572 u32 rtl930x_hash(struct rtl838x_switch_priv *priv, u64 seed)
573 {
574 u32 k0, k1, h1, h2, h;
575
576 k0 = (u32) (((seed >> 55) & 0x1f) ^ ((seed >> 44) & 0x7ff)
577 ^ ((seed >> 33) & 0x7ff) ^ ((seed >> 22) & 0x7ff)
578 ^ ((seed >> 11) & 0x7ff) ^ (seed & 0x7ff));
579
580 h1 = (seed >> 11) & 0x7ff;
581 h1 = ((h1 & 0x1f) << 6) | ((h1 >> 5) & 0x3f);
582
583 h2 = (seed >> 33) & 0x7ff;
584 h2 = ((h2 & 0x3f) << 5)| ((h2 >> 6) & 0x3f);
585
586 k1 = (u32) (((seed << 55) & 0x1f) ^ ((seed >> 44) & 0x7ff) ^ h2
587 ^ ((seed >> 22) & 0x7ff) ^ h1
588 ^ (seed & 0x7ff));
589
590 // Algorithm choice for block 0
591 if (sw_r32(RTL930X_L2_CTRL) & BIT(0))
592 h = k1;
593 else
594 h = k0;
595
596 /* Algorithm choice for block 1
597 * Since k0 and k1 are < 2048, adding 2048 will offset the hash into the second
598 * half of hash-space
599 * 2048 is in fact the hash-table size 16384 divided by 4 hashes per bucket
600 * divided by 2 to divide the hash space in 2
601 */
602 if (sw_r32(RTL930X_L2_CTRL) & BIT(1))
603 h |= (k1 + 2048) << 16;
604 else
605 h |= (k0 + 2048) << 16;
606
607 return h;
608 }
609 /*
610 * Enables or disables the EEE/EEEP capability of a port
611 */
612 void rtl930x_port_eee_set(struct rtl838x_switch_priv *priv, int port, bool enable)
613 {
614 u32 v;
615
616 // This works only for Ethernet ports, and on the RTL930X, ports from 26 are SFP
617 if (port >= 26)
618 return;
619
620 pr_debug("In %s: setting port %d to %d\n", __func__, port, enable);
621 v = enable ? 0x3f : 0x0;
622
623 // Set EEE/EEEP state for 100, 500, 1000MBit and 2.5, 5 and 10GBit
624 sw_w32_mask(0, v << 10, rtl930x_mac_force_mode_ctrl(port));
625
626 // Set TX/RX EEE state
627 v = enable ? 0x3 : 0x0;
628 sw_w32(v, RTL930X_EEE_CTRL(port));
629
630 priv->ports[port].eee_enabled = enable;
631 }
632
633 /*
634 * Get EEE own capabilities and negotiation result
635 */
636 int rtl930x_eee_port_ability(struct rtl838x_switch_priv *priv, struct ethtool_eee *e, int port)
637 {
638 u32 link, a;
639
640 if (port >= 26)
641 return -ENOTSUPP;
642
643 pr_info("In %s, port %d\n", __func__, port);
644 link = sw_r32(RTL930X_MAC_LINK_STS);
645 link = sw_r32(RTL930X_MAC_LINK_STS);
646 if (!(link & BIT(port)))
647 return 0;
648
649 pr_info("Setting advertised\n");
650 if (sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(10))
651 e->advertised |= ADVERTISED_100baseT_Full;
652
653 if (sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(12))
654 e->advertised |= ADVERTISED_1000baseT_Full;
655
656 if (priv->ports[port].is2G5 && sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(13)) {
657 pr_info("ADVERTISING 2.5G EEE\n");
658 e->advertised |= ADVERTISED_2500baseX_Full;
659 }
660
661 if (priv->ports[port].is10G && sw_r32(rtl930x_mac_force_mode_ctrl(port)) & BIT(15))
662 e->advertised |= ADVERTISED_10000baseT_Full;
663
664 a = sw_r32(RTL930X_MAC_EEE_ABLTY);
665 a = sw_r32(RTL930X_MAC_EEE_ABLTY);
666 pr_info("Link partner: %08x\n", a);
667 if (a & BIT(port)) {
668 e->lp_advertised = ADVERTISED_100baseT_Full;
669 e->lp_advertised |= ADVERTISED_1000baseT_Full;
670 if (priv->ports[port].is2G5)
671 e->lp_advertised |= ADVERTISED_2500baseX_Full;
672 if (priv->ports[port].is10G)
673 e->lp_advertised |= ADVERTISED_10000baseT_Full;
674 }
675
676 // Read 2x to clear latched state
677 a = sw_r32(RTL930X_EEEP_PORT_CTRL(port));
678 a = sw_r32(RTL930X_EEEP_PORT_CTRL(port));
679 pr_info("%s RTL930X_EEEP_PORT_CTRL: %08x\n", __func__, a);
680
681 return 0;
682 }
683
684 static void rtl930x_init_eee(struct rtl838x_switch_priv *priv, bool enable)
685 {
686 int i;
687
688 pr_info("Setting up EEE, state: %d\n", enable);
689
690 // Setup EEE on all ports
691 for (i = 0; i < priv->cpu_port; i++) {
692 if (priv->ports[i].phy)
693 rtl930x_port_eee_set(priv, i, enable);
694 }
695
696 priv->eee_enabled = enable;
697 }
698
699 const struct rtl838x_reg rtl930x_reg = {
700 .mask_port_reg_be = rtl838x_mask_port_reg,
701 .set_port_reg_be = rtl838x_set_port_reg,
702 .get_port_reg_be = rtl838x_get_port_reg,
703 .mask_port_reg_le = rtl838x_mask_port_reg,
704 .set_port_reg_le = rtl838x_set_port_reg,
705 .get_port_reg_le = rtl838x_get_port_reg,
706 .stat_port_rst = RTL930X_STAT_PORT_RST,
707 .stat_rst = RTL930X_STAT_RST,
708 .stat_port_std_mib = RTL930X_STAT_PORT_MIB_CNTR,
709 .traffic_enable = rtl930x_traffic_enable,
710 .traffic_disable = rtl930x_traffic_disable,
711 .traffic_get = rtl930x_traffic_get,
712 .traffic_set = rtl930x_traffic_set,
713 .l2_ctrl_0 = RTL930X_L2_CTRL,
714 .l2_ctrl_1 = RTL930X_L2_AGE_CTRL,
715 .l2_port_aging_out = RTL930X_L2_PORT_AGE_CTRL,
716 .smi_poll_ctrl = RTL930X_SMI_POLL_CTRL, // TODO: Difference to RTL9300_SMI_PRVTE_POLLING_CTRL
717 .l2_tbl_flush_ctrl = RTL930X_L2_TBL_FLUSH_CTRL,
718 .exec_tbl0_cmd = rtl930x_exec_tbl0_cmd,
719 .exec_tbl1_cmd = rtl930x_exec_tbl1_cmd,
720 .tbl_access_data_0 = rtl930x_tbl_access_data_0,
721 .isr_glb_src = RTL930X_ISR_GLB,
722 .isr_port_link_sts_chg = RTL930X_ISR_PORT_LINK_STS_CHG,
723 .imr_port_link_sts_chg = RTL930X_IMR_PORT_LINK_STS_CHG,
724 .imr_glb = RTL930X_IMR_GLB,
725 .vlan_tables_read = rtl930x_vlan_tables_read,
726 .vlan_set_tagged = rtl930x_vlan_set_tagged,
727 .vlan_set_untagged = rtl930x_vlan_set_untagged,
728 .vlan_profile_dump = rtl930x_vlan_profile_dump,
729 .vlan_profile_setup = rtl930x_vlan_profile_setup,
730 .stp_get = rtl930x_stp_get,
731 .stp_set = rtl930x_stp_set,
732 .mac_force_mode_ctrl = rtl930x_mac_force_mode_ctrl,
733 .mac_port_ctrl = rtl930x_mac_port_ctrl,
734 .l2_port_new_salrn = rtl930x_l2_port_new_salrn,
735 .l2_port_new_sa_fwd = rtl930x_l2_port_new_sa_fwd,
736 .mir_ctrl = RTL930X_MIR_CTRL,
737 .mir_dpm = RTL930X_MIR_DPM_CTRL,
738 .mir_spm = RTL930X_MIR_SPM_CTRL,
739 .mac_link_sts = RTL930X_MAC_LINK_STS,
740 .mac_link_dup_sts = RTL930X_MAC_LINK_DUP_STS,
741 .mac_link_spd_sts = rtl930x_mac_link_spd_sts,
742 .mac_rx_pause_sts = RTL930X_MAC_RX_PAUSE_STS,
743 .mac_tx_pause_sts = RTL930X_MAC_TX_PAUSE_STS,
744 .read_l2_entry_using_hash = rtl930x_read_l2_entry_using_hash,
745 .read_cam = rtl930x_read_cam,
746 .vlan_port_egr_filter = RTL930X_VLAN_PORT_EGR_FLTR,
747 .vlan_port_igr_filter = RTL930X_VLAN_PORT_IGR_FLTR(0),
748 .vlan_port_pb = RTL930X_VLAN_PORT_PB_VLAN,
749 .vlan_port_tag_sts_ctrl = RTL930X_VLAN_PORT_TAG_STS_CTRL,
750 .trk_mbr_ctr = rtl930x_trk_mbr_ctr,
751 .rma_bpdu_fld_pmask = RTL930X_RMA_BPDU_FLD_PMSK,
752 .init_eee = rtl930x_init_eee,
753 .port_eee_set = rtl930x_port_eee_set,
754 .eee_port_ability = rtl930x_eee_port_ability,
755 .read_mcast_pmask = rtl930x_read_mcast_pmask,
756 .write_mcast_pmask = rtl930x_write_mcast_pmask,
757 };