1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <asm/mach-rtl838x/mach-rtl83xx.h>
6 extern struct mutex smi_lock
;
7 extern struct rtl83xx_soc_info soc_info
;
9 void rtl930x_print_matrix(void)
12 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
14 for (i
= 0; i
< 29; i
++) {
16 pr_debug("> %08x\n", sw_r32(rtl_table_data(r
, 0)));
21 inline void rtl930x_exec_tbl0_cmd(u32 cmd
)
23 sw_w32(cmd
, RTL930X_TBL_ACCESS_CTRL_0
);
24 do { } while (sw_r32(RTL930X_TBL_ACCESS_CTRL_0
) & (1 << 17));
27 inline void rtl930x_exec_tbl1_cmd(u32 cmd
)
29 sw_w32(cmd
, RTL930X_TBL_ACCESS_CTRL_1
);
30 do { } while (sw_r32(RTL930X_TBL_ACCESS_CTRL_1
) & (1 << 17));
33 inline int rtl930x_tbl_access_data_0(int i
)
35 return RTL930X_TBL_ACCESS_DATA_0(i
);
38 static inline int rtl930x_l2_port_new_salrn(int p
)
40 return RTL930X_L2_PORT_SALRN(p
);
43 static inline int rtl930x_l2_port_new_sa_fwd(int p
)
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
);
49 inline static int rtl930x_trk_mbr_ctr(int group
)
51 return RTL930X_TRK_MBR_CTRL
+ (group
<< 2);
54 static void rtl930x_vlan_tables_read(u32 vlan
, struct rtl838x_vlan_info
*info
)
57 // Read VLAN table (1) via register 0
58 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 1);
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
);
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);
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));
78 info
->untagged_ports
= v
>> 3;
81 static void rtl930x_vlan_set_tagged(u32 vlan
, struct rtl838x_vlan_info
*info
)
84 // Access VLAN table (1) via register 0
85 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 1);
87 v
= info
->tagged_ports
<< 3;
88 v
|= ((u32
)info
->fid
) >> 3;
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;
95 sw_w32(v
, rtl_table_data(r
, 0));
96 sw_w32(w
, rtl_table_data(r
, 1));
98 rtl_table_write(r
, vlan
);
102 void rtl930x_vlan_profile_dump(int profile
)
106 if (profile
< 0 || profile
> 7)
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;
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]);
126 static void rtl930x_vlan_set_untagged(u32 vlan
, u64 portmask
)
128 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_2
, 0);
130 sw_w32(portmask
<< 3, rtl_table_data(r
, 0));
131 rtl_table_write(r
, vlan
);
132 rtl_table_release(r
);
135 /* Sets the L2 forwarding to be based on either the inner VLAN tag or the outer
137 static void rtl930x_vlan_fwd_on_inner(int port
, bool is_set
)
139 // Always set all tag modes to fwd based on either inner or outer tag
141 sw_w32_mask(0, 0xf, RTL930X_VLAN_PORT_FWD
+ (port
<< 2));
143 sw_w32_mask(0xf, 0, RTL930X_VLAN_PORT_FWD
+ (port
<< 2));
146 static void rtl930x_vlan_profile_setup(int profile
)
150 pr_info("In %s\n", __func__
);
151 p
[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile
));
152 p
[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(profile
) + 4);
154 // Enable routing of Ipv4/6 Unicast and IPv4/6 Multicast traffic
155 p
[0] |= BIT(17) | BIT(16) | BIT(13) | BIT(12);
156 p
[2] = 0x0fffffff; // L2 unknwon MC flooding portmask: all but the CPU-port
157 p
[3] = 0x0fffffff; // IPv4 unknwon MC flooding portmask
158 p
[4] = 0x0fffffff; // IPv6 unknwon MC flooding portmask
160 sw_w32(p
[0], RTL930X_VLAN_PROFILE_SET(profile
));
161 sw_w32(p
[1], RTL930X_VLAN_PROFILE_SET(profile
) + 4);
162 sw_w32(p
[2], RTL930X_VLAN_PROFILE_SET(profile
) + 8);
163 sw_w32(p
[3], RTL930X_VLAN_PROFILE_SET(profile
) + 12);
164 sw_w32(p
[4], RTL930X_VLAN_PROFILE_SET(profile
) + 16);
165 pr_info("Leaving %s\n", __func__
);
168 static void rtl930x_stp_get(struct rtl838x_switch_priv
*priv
, u16 msti
, u32 port_state
[])
171 u32 cmd
= 1 << 17 /* Execute cmd */
173 | 4 << 12 /* Table type 0b10 */
175 priv
->r
->exec_tbl0_cmd(cmd
);
177 for (i
= 0; i
< 2; i
++)
178 port_state
[i
] = sw_r32(RTL930X_TBL_ACCESS_DATA_0(i
));
179 pr_debug("MSTI: %d STATE: %08x, %08x\n", msti
, port_state
[0], port_state
[1]);
182 static void rtl930x_stp_set(struct rtl838x_switch_priv
*priv
, u16 msti
, u32 port_state
[])
185 u32 cmd
= 1 << 17 /* Execute cmd */
186 | 1 << 16 /* Write */
187 | 4 << 12 /* Table type 4 */
190 for (i
= 0; i
< 2; i
++)
191 sw_w32(port_state
[i
], RTL930X_TBL_ACCESS_DATA_0(i
));
192 priv
->r
->exec_tbl0_cmd(cmd
);
195 static inline int rtl930x_mac_force_mode_ctrl(int p
)
197 return RTL930X_MAC_FORCE_MODE_CTRL
+ (p
<< 2);
200 static inline int rtl930x_mac_port_ctrl(int p
)
202 return RTL930X_MAC_L2_PORT_CTRL(p
);
205 static inline int rtl930x_mac_link_spd_sts(int p
)
207 return RTL930X_MAC_LINK_SPD_STS(p
);
210 static u64
rtl930x_l2_hash_seed(u64 mac
, u32 vid
)
221 * Calculate both the block 0 and the block 1 hash by applyingthe same hash
222 * algorithm as the one used currently by the ASIC to the seed, and return
223 * both hashes in the lower and higher word of the return value since only 12 bit of
224 * the hash are significant
226 static u32
rtl930x_l2_hash_key(struct rtl838x_switch_priv
*priv
, u64 seed
)
228 u32 k0
, k1
, h1
, h2
, h
;
230 k0
= (u32
) (((seed
>> 55) & 0x1f) ^ ((seed
>> 44) & 0x7ff)
231 ^ ((seed
>> 33) & 0x7ff) ^ ((seed
>> 22) & 0x7ff)
232 ^ ((seed
>> 11) & 0x7ff) ^ (seed
& 0x7ff));
234 h1
= (seed
>> 11) & 0x7ff;
235 h1
= ((h1
& 0x1f) << 6) | ((h1
>> 5) & 0x3f);
237 h2
= (seed
>> 33) & 0x7ff;
238 h2
= ((h2
& 0x3f) << 5)| ((h2
>> 6) & 0x3f);
240 k1
= (u32
) (((seed
<< 55) & 0x1f) ^ ((seed
>> 44) & 0x7ff) ^ h2
241 ^ ((seed
>> 22) & 0x7ff) ^ h1
244 // Algorithm choice for block 0
245 if (sw_r32(RTL930X_L2_CTRL
) & BIT(0))
250 /* Algorithm choice for block 1
251 * Since k0 and k1 are < 2048, adding 2048 will offset the hash into the second
253 * 2048 is in fact the hash-table size 16384 divided by 4 hashes per bucket
254 * divided by 2 to divide the hash space in 2
256 if (sw_r32(RTL930X_L2_CTRL
) & BIT(1))
257 h
|= (k1
+ 2048) << 16;
259 h
|= (k0
+ 2048) << 16;
265 * Fills an L2 entry structure from the SoC registers
267 static void rtl930x_fill_l2_entry(u32 r
[], struct rtl838x_l2_entry
*e
)
269 pr_debug("In %s valid?\n", __func__
);
270 e
->valid
= !!(r
[2] & BIT(31));
274 pr_debug("In %s is valid\n", __func__
);
276 e
->is_ipv6_mc
= false;
278 // TODO: Is there not a function to copy directly MAC memory?
279 e
->mac
[0] = (r
[0] >> 24);
280 e
->mac
[1] = (r
[0] >> 16);
281 e
->mac
[2] = (r
[0] >> 8);
283 e
->mac
[4] = (r
[1] >> 24);
284 e
->mac
[5] = (r
[1] >> 16);
286 e
->next_hop
= !!(r
[2] & BIT(12));
287 e
->rvid
= r
[1] & 0xfff;
289 /* Is it a unicast entry? check multicast bit */
290 if (!(e
->mac
[0] & 1)) {
291 e
->type
= L2_UNICAST
;
292 e
->is_static
= !!(r
[2] & BIT(14));
293 e
->port
= (r
[2] >> 20) & 0x3ff;
294 // Check for trunk port
295 if (r
[2] & BIT(30)) {
297 e
->stack_dev
= (e
->port
>> 9) & 1;
298 e
->trunk
= e
->port
& 0x3f;
301 e
->stack_dev
= (e
->port
>> 6) & 0xf;
302 e
->port
= e
->port
& 0x3f;
305 e
->block_da
= !!(r
[2] & BIT(15));
306 e
->block_sa
= !!(r
[2] & BIT(16));
307 e
->suspended
= !!(r
[2] & BIT(13));
308 e
->age
= (r
[2] >> 17) & 3;
310 // the UC_VID field in hardware is used for the VID or for the route id
312 e
->nh_route_id
= r
[2] & 0xfff;
315 e
->vid
= r
[2] & 0xfff;
320 e
->type
= L2_MULTICAST
;
321 e
->mc_portmask_index
= (r
[2] >> 16) & 0x3ff;
326 * Fills the 3 SoC table registers r[] with the information of in the rtl838x_l2_entry
328 static void rtl930x_fill_l2_row(u32 r
[], struct rtl838x_l2_entry
*e
)
333 r
[0] = r
[1] = r
[2] = 0;
337 r
[2] = BIT(31); // Set valid bit
339 r
[0] = ((u32
)e
->mac
[0]) << 24 | ((u32
)e
->mac
[1]) << 16
340 | ((u32
)e
->mac
[2]) << 8 | ((u32
)e
->mac
[3]);
341 r
[1] = ((u32
)e
->mac
[4]) << 24 | ((u32
)e
->mac
[5]) << 16;
343 r
[2] |= e
->next_hop
? BIT(12) : 0;
345 if (e
->type
== L2_UNICAST
) {
346 r
[2] |= e
->is_static
? BIT(14) : 0;
347 r
[1] |= e
->rvid
& 0xfff;
348 r
[2] |= (e
->port
& 0x3ff) << 20;
351 port
= e
->stack_dev
<< 9 | (e
->port
& 0x3f);
353 port
= (e
->stack_dev
& 0xf) << 6;
354 port
|= e
->port
& 0x3f;
357 r
[2] |= e
->block_da
? BIT(15) : 0;
358 r
[2] |= e
->block_sa
? BIT(17) : 0;
359 r
[2] |= e
->suspended
? BIT(13) : 0;
360 r
[2] |= (e
->age
& 0x3) << 17;
361 // the UC_VID field in hardware is used for the VID or for the route id
363 r
[2] |= e
->nh_route_id
& 0xfff;
365 r
[2] |= e
->vid
& 0xfff;
366 } else { // L2_MULTICAST
367 r
[2] |= (e
->mc_portmask_index
& 0x3ff) << 16;
368 r
[2] |= e
->mc_mac_index
& 0x7ff;
373 * Read an L2 UC or MC entry out of a hash bucket of the L2 forwarding table
374 * hash is the id of the bucket and pos is the position of the entry in that bucket
375 * The data read from the SoC is filled into rtl838x_l2_entry
377 static u64
rtl930x_read_l2_entry_using_hash(u32 hash
, u32 pos
, struct rtl838x_l2_entry
*e
)
380 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 0);
386 pr_debug("%s: hash %08x, pos: %d\n", __func__
, hash
, pos
);
388 /* On the RTL93xx, 2 different hash algorithms are used making it a total of
389 * 8 buckets that need to be searched, 4 for each hash-half
390 * Use second hash space when bucket is between 4 and 8 */
398 idx
= (0 << 14) | (hash
<< 2) | pos
; // Search SRAM, with hash and at pos in bucket
399 pr_debug("%s: NOW hash %08x, pos: %d\n", __func__
, hash
, pos
);
401 rtl_table_read(q
, idx
);
402 for (i
= 0; i
< 3; i
++)
403 r
[i
] = sw_r32(rtl_table_data(q
, i
));
405 rtl_table_release(q
);
407 rtl930x_fill_l2_entry(r
, e
);
409 pr_debug("%s: valid: %d, nh: %d\n", __func__
, e
->valid
, e
->next_hop
);
413 mac
= ((u64
)e
->mac
[0]) << 40 | ((u64
)e
->mac
[1]) << 32 | ((u64
)e
->mac
[2]) << 24
414 | ((u64
)e
->mac
[3]) << 16 | ((u64
)e
->mac
[4]) << 8 | ((u64
)e
->mac
[5]);
416 seed
= rtl930x_l2_hash_seed(mac
, e
->rvid
);
417 pr_debug("%s: mac %016llx, seed %016llx\n", __func__
, mac
, seed
);
418 // return vid with concatenated mac as unique id
422 static void rtl930x_write_l2_entry_using_hash(u32 hash
, u32 pos
, struct rtl838x_l2_entry
*e
)
425 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 0);
426 u32 idx
= (0 << 14) | (hash
<< 2) | pos
; // Access SRAM, with hash and at pos in bucket
429 pr_info("%s: hash %d, pos %d\n", __func__
, hash
, pos
);
430 pr_info("%s: index %d -> mac %02x:%02x:%02x:%02x:%02x:%02x\n", __func__
, idx
,
431 e
->mac
[0], e
->mac
[1], e
->mac
[2], e
->mac
[3],e
->mac
[4],e
->mac
[5]);
433 rtl930x_fill_l2_row(r
, e
);
435 for (i
= 0; i
< 3; i
++)
436 sw_w32(r
[i
], rtl_table_data(q
, i
));
438 rtl_table_write(q
, idx
);
439 rtl_table_release(q
);
442 static u64
rtl930x_read_cam(int idx
, struct rtl838x_l2_entry
*e
)
445 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 1);
448 rtl_table_read(q
, idx
);
449 for (i
= 0; i
< 3; i
++)
450 r
[i
] = sw_r32(rtl_table_data(q
, i
));
452 rtl_table_release(q
);
454 rtl930x_fill_l2_entry(r
, e
);
458 // return mac with concatenated vid as unique id
459 return ((u64
)r
[0] << 28) | ((r
[1] & 0xffff0000) >> 4) | e
->vid
;
462 static void rtl930x_write_cam(int idx
, struct rtl838x_l2_entry
*e
)
465 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 1); // Access L2 Table 1
468 rtl930x_fill_l2_row(r
, e
);
470 for (i
= 0; i
< 3; i
++)
471 sw_w32(r
[i
], rtl_table_data(q
, i
));
473 rtl_table_write(q
, idx
);
474 rtl_table_release(q
);
477 static void dump_l2_entry(struct rtl838x_l2_entry
*e
)
479 pr_info("MAC: %02x:%02x:%02x:%02x:%02x:%02x vid: %d, rvid: %d, port: %d, valid: %d\n",
480 e
->mac
[0], e
->mac
[1], e
->mac
[2], e
->mac
[3], e
->mac
[4], e
->mac
[5],
481 e
->vid
, e
->rvid
, e
->port
, e
->valid
);
482 pr_info("Type: %d, is_static: %d, is_ip_mc: %d, is_ipv6_mc: %d, block_da: %d\n",
483 e
->type
, e
->is_static
, e
->is_ip_mc
, e
->is_ipv6_mc
, e
->block_da
);
484 pr_info(" block_sa: %d, suspended: %d, next_hop: %d, age: %d, is_trunk: %d, trunk: %d\n",
485 e
->block_sa
, e
->suspended
, e
->next_hop
, e
->age
, e
->is_trunk
, e
->trunk
);
486 if (e
->is_ip_mc
|| e
->is_ipv6_mc
)
487 pr_info(" mc_portmask_index: %d, mc_gip: %d, mc_sip: %d\n",
488 e
->mc_portmask_index
, e
->mc_gip
, e
->mc_sip
);
489 pr_info(" stac_dev: %d, nh_route_id: %d, port: %d, dev_id\n",
490 e
->stack_dev
, e
->nh_route_id
, e
->port
);
494 * Add an L2 nexthop entry for the L3 routing system in the SoC
495 * Use VID and MAC in rtl838x_l2_entry to identify either a free slot in the L2 hash table
496 * or mark an existing entry as a nexthop by setting it's nexthop bit
497 * Called from the L3 layer
498 * The index in the L2 hash table is filled into nh->l2_id;
500 static int rtl930x_l2_nexthop_add(struct rtl838x_switch_priv
*priv
, struct rtl838x_nexthop
*nh
)
502 struct rtl838x_l2_entry e
;
503 u64 seed
= rtl930x_l2_hash_seed(nh
->mac
, nh
->vid
);
504 u32 key
= rtl930x_l2_hash_key(priv
, seed
);
508 pr_info("%s searching for %08llx vid %d with key %d, seed: %016llx\n",
509 __func__
, nh
->mac
, nh
->vid
, key
, seed
);
512 e
.rvid
= nh
->fid
; // Verify its the forwarding ID!!! l2_entry.un.unicast.fid
513 u64_to_ether_addr(nh
->mac
, &e
.mac
[0]);
514 e
.port
= RTL930X_PORT_IGNORE
;
516 // Loop over all entries in the hash-bucket and over the second block on 93xx SoCs
517 for (i
= 0; i
< priv
->l2_bucket_size
; i
++) {
518 entry
= rtl930x_read_l2_entry_using_hash(key
, i
, &e
);
519 pr_info("%s i: %d, entry %016llx, seed %016llx\n", __func__
, i
, entry
, seed
);
520 if (e
.valid
&& e
.next_hop
)
522 if (!e
.valid
|| ((entry
& 0x0fffffffffffffffULL
) == seed
)) {
523 idx
= i
> 3 ? ((key
>> 14) & 0xffff) | i
>> 1
524 : ((key
<< 2) | i
) & 0xffff;
529 pr_info("%s: found idx %d and i %d\n", __func__
, idx
, i
);
532 pr_err("%s: No more L2 forwarding entries available\n", __func__
);
536 // Found an existing or empty entry, make it a nexthop entry
537 pr_info("%s BEFORE -> key %d, pos: %d, index: %d\n", __func__
, key
, i
, idx
);
541 // Found an existing (e->valid is true) or empty entry, make it a nexthop entry
546 nh
->dev_id
= e
.stack_dev
;
552 e
.port
= RTL930X_PORT_IGNORE
;
553 u64_to_ether_addr(nh
->mac
, &e
.mac
[0]);
556 // For nexthop entries, the vid field in the table is used to denote the dest mac_id
557 e
.nh_route_id
= nh
->mac_id
;
558 pr_info("%s AFTER\n", __func__
);
561 rtl930x_write_l2_entry_using_hash(idx
>> 2, idx
& 0x3, &e
);
563 // _dal_longan_l2_nexthop_add
567 static u64
rtl930x_read_mcast_pmask(int idx
)
570 // Read MC_PORTMASK (2) via register RTL9300_TBL_L2
571 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 2);
573 rtl_table_read(q
, idx
);
574 portmask
= sw_r32(rtl_table_data(q
, 0));
576 rtl_table_release(q
);
578 pr_debug("%s: Index idx %d has portmask %08x\n", __func__
, idx
, portmask
);
582 static void rtl930x_write_mcast_pmask(int idx
, u64 portmask
)
586 // Access MC_PORTMASK (2) via register RTL9300_TBL_L2
587 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 2);
589 pr_debug("%s: Index idx %d has portmask %08x\n", __func__
, idx
, pm
);
591 sw_w32(pm
, rtl_table_data(q
, 0));
592 rtl_table_write(q
, idx
);
593 rtl_table_release(q
);
596 u64
rtl930x_traffic_get(int source
)
599 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
601 rtl_table_read(r
, source
);
602 v
= sw_r32(rtl_table_data(r
, 0));
603 rtl_table_release(r
);
608 * Enable traffic between a source port and a destination port matrix
610 void rtl930x_traffic_set(int source
, u64 dest_matrix
)
612 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
614 sw_w32((dest_matrix
<< 3), rtl_table_data(r
, 0));
615 rtl_table_write(r
, source
);
616 rtl_table_release(r
);
619 void rtl930x_traffic_enable(int source
, int dest
)
621 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
622 rtl_table_read(r
, source
);
623 sw_w32_mask(0, BIT(dest
+ 3), rtl_table_data(r
, 0));
624 rtl_table_write(r
, source
);
625 rtl_table_release(r
);
628 void rtl930x_traffic_disable(int source
, int dest
)
630 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
631 rtl_table_read(r
, source
);
632 sw_w32_mask(BIT(dest
+ 3), 0, rtl_table_data(r
, 0));
633 rtl_table_write(r
, source
);
634 rtl_table_release(r
);
637 void rtl9300_dump_debug(void)
640 u16 r
= RTL930X_STAT_PRVTE_DROP_COUNTER0
;
642 for (i
= 0; i
< 10; i
++) {
643 pr_info("# %d %08x %08x %08x %08x %08x %08x %08x %08x\n", i
* 8,
644 sw_r32(r
), sw_r32(r
+ 4), sw_r32(r
+ 8), sw_r32(r
+ 12),
645 sw_r32(r
+ 16), sw_r32(r
+ 20), sw_r32(r
+ 24), sw_r32(r
+ 28));
648 pr_info("# %08x %08x %08x %08x %08x\n",
649 sw_r32(r
), sw_r32(r
+ 4), sw_r32(r
+ 8), sw_r32(r
+ 12), sw_r32(r
+ 16));
650 rtl930x_print_matrix();
651 pr_info("RTL930X_L2_PORT_SABLK_CTRL: %08x, RTL930X_L2_PORT_DABLK_CTRL %08x\n",
652 sw_r32(RTL930X_L2_PORT_SABLK_CTRL
), sw_r32(RTL930X_L2_PORT_DABLK_CTRL
)
657 irqreturn_t
rtl930x_switch_irq(int irq
, void *dev_id
)
659 struct dsa_switch
*ds
= dev_id
;
660 u32 status
= sw_r32(RTL930X_ISR_GLB
);
661 u32 ports
= sw_r32(RTL930X_ISR_PORT_LINK_STS_CHG
);
666 sw_w32(ports
, RTL930X_ISR_PORT_LINK_STS_CHG
);
667 pr_info("RTL9300 Link change: status: %x, ports %x\n", status
, ports
);
669 rtl9300_dump_debug();
671 for (i
= 0; i
< 28; i
++) {
672 if (ports
& BIT(i
)) {
673 /* Read the register twice because of issues with latency at least
674 * with the external RTL8226 PHY on the XGS1210 */
675 link
= sw_r32(RTL930X_MAC_LINK_STS
);
676 link
= sw_r32(RTL930X_MAC_LINK_STS
);
678 dsa_port_phylink_mac_change(ds
, i
, true);
680 dsa_port_phylink_mac_change(ds
, i
, false);
687 int rtl9300_sds_power(int mac
, int val
)
692 // TODO: these numbers are hard-coded for the Zyxel XGS1210 12 Switch
693 pr_info("SerDes: %s %d\n", __func__
, mac
);
697 mode
= 0x12; // HISGMII
701 mode
= 0x12; // HISGMII
705 mode
= 0x1b; // 10GR/1000BX auto
709 mode
= 0x1b; // 10GR/1000BX auto
717 rtl9300_sds_rst(sds_num
, mode
);
722 int rtl930x_write_phy(u32 port
, u32 page
, u32 reg
, u32 val
)
727 pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__
, port
, page
, reg
, val
);
729 if (port
> 63 || page
> 4095 || reg
> 31)
733 mutex_lock(&smi_lock
);
735 sw_w32(BIT(port
), RTL930X_SMI_ACCESS_PHY_CTRL_0
);
736 sw_w32_mask(0xffff << 16, val
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
737 v
= reg
<< 20 | page
<< 3 | 0x1f << 15 | BIT(2) | BIT(0);
738 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
741 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
747 mutex_unlock(&smi_lock
);
752 int rtl930x_read_phy(u32 port
, u32 page
, u32 reg
, u32
*val
)
757 if (port
> 63 || page
> 4095 || reg
> 31)
760 mutex_lock(&smi_lock
);
762 sw_w32_mask(0xffff << 16, port
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
763 v
= reg
<< 20 | page
<< 3 | 0x1f << 15 | 1;
764 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
767 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
771 pr_debug("Error reading phy %d, register %d\n", port
, reg
);
774 *val
= (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2
) & 0xffff);
776 pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__
, port
, page
, reg
, *val
);
778 mutex_unlock(&smi_lock
);
784 * Write to an mmd register of the PHY
786 int rtl930x_write_mmd_phy(u32 port
, u32 devnum
, u32 regnum
, u32 val
)
791 mutex_lock(&smi_lock
);
794 sw_w32(BIT(port
), RTL930X_SMI_ACCESS_PHY_CTRL_0
);
797 sw_w32_mask(0xffff << 16, val
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
799 // Set MMD device number and register to write to
800 sw_w32(devnum
<< 16 | (regnum
& 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3
);
802 v
= BIT(2) | BIT(1) | BIT(0); // WRITE | MMD-access | EXEC
803 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
806 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
807 } while (v
& BIT(0));
809 pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__
, port
, regnum
, val
, err
);
810 mutex_unlock(&smi_lock
);
815 * Read an mmd register of the PHY
817 int rtl930x_read_mmd_phy(u32 port
, u32 devnum
, u32 regnum
, u32
*val
)
822 mutex_lock(&smi_lock
);
825 sw_w32_mask(0xffff << 16, port
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
827 // Set MMD device number and register to write to
828 sw_w32(devnum
<< 16 | (regnum
& 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3
);
830 v
= BIT(1) | BIT(0); // MMD-access | EXEC
831 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
834 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
835 } while (v
& BIT(0));
836 // There is no error-checking via BIT 25 of v, as it does not seem to be set correctly
837 *val
= (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2
) & 0xffff);
838 pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__
, port
, regnum
, *val
, err
);
840 mutex_unlock(&smi_lock
);
846 * Calculate both the block 0 and the block 1 hash, and return in
847 * lower and higher word of the return value since only 12 bit of
848 * the hash are significant
850 u32
rtl930x_hash(struct rtl838x_switch_priv
*priv
, u64 seed
)
852 u32 k0
, k1
, h1
, h2
, h
;
854 k0
= (u32
) (((seed
>> 55) & 0x1f) ^ ((seed
>> 44) & 0x7ff)
855 ^ ((seed
>> 33) & 0x7ff) ^ ((seed
>> 22) & 0x7ff)
856 ^ ((seed
>> 11) & 0x7ff) ^ (seed
& 0x7ff));
858 h1
= (seed
>> 11) & 0x7ff;
859 h1
= ((h1
& 0x1f) << 6) | ((h1
>> 5) & 0x3f);
861 h2
= (seed
>> 33) & 0x7ff;
862 h2
= ((h2
& 0x3f) << 5)| ((h2
>> 6) & 0x3f);
864 k1
= (u32
) (((seed
<< 55) & 0x1f) ^ ((seed
>> 44) & 0x7ff) ^ h2
865 ^ ((seed
>> 22) & 0x7ff) ^ h1
868 // Algorithm choice for block 0
869 if (sw_r32(RTL930X_L2_CTRL
) & BIT(0))
874 /* Algorithm choice for block 1
875 * Since k0 and k1 are < 2048, adding 2048 will offset the hash into the second
877 * 2048 is in fact the hash-table size 16384 divided by 4 hashes per bucket
878 * divided by 2 to divide the hash space in 2
880 if (sw_r32(RTL930X_L2_CTRL
) & BIT(1))
881 h
|= (k1
+ 2048) << 16;
883 h
|= (k0
+ 2048) << 16;
889 * Enables or disables the EEE/EEEP capability of a port
891 void rtl930x_port_eee_set(struct rtl838x_switch_priv
*priv
, int port
, bool enable
)
895 // This works only for Ethernet ports, and on the RTL930X, ports from 26 are SFP
899 pr_debug("In %s: setting port %d to %d\n", __func__
, port
, enable
);
900 v
= enable
? 0x3f : 0x0;
902 // Set EEE/EEEP state for 100, 500, 1000MBit and 2.5, 5 and 10GBit
903 sw_w32_mask(0, v
<< 10, rtl930x_mac_force_mode_ctrl(port
));
905 // Set TX/RX EEE state
906 v
= enable
? 0x3 : 0x0;
907 sw_w32(v
, RTL930X_EEE_CTRL(port
));
909 priv
->ports
[port
].eee_enabled
= enable
;
913 * Get EEE own capabilities and negotiation result
915 int rtl930x_eee_port_ability(struct rtl838x_switch_priv
*priv
, struct ethtool_eee
*e
, int port
)
922 pr_info("In %s, port %d\n", __func__
, port
);
923 link
= sw_r32(RTL930X_MAC_LINK_STS
);
924 link
= sw_r32(RTL930X_MAC_LINK_STS
);
925 if (!(link
& BIT(port
)))
928 pr_info("Setting advertised\n");
929 if (sw_r32(rtl930x_mac_force_mode_ctrl(port
)) & BIT(10))
930 e
->advertised
|= ADVERTISED_100baseT_Full
;
932 if (sw_r32(rtl930x_mac_force_mode_ctrl(port
)) & BIT(12))
933 e
->advertised
|= ADVERTISED_1000baseT_Full
;
935 if (priv
->ports
[port
].is2G5
&& sw_r32(rtl930x_mac_force_mode_ctrl(port
)) & BIT(13)) {
936 pr_info("ADVERTISING 2.5G EEE\n");
937 e
->advertised
|= ADVERTISED_2500baseX_Full
;
940 if (priv
->ports
[port
].is10G
&& sw_r32(rtl930x_mac_force_mode_ctrl(port
)) & BIT(15))
941 e
->advertised
|= ADVERTISED_10000baseT_Full
;
943 a
= sw_r32(RTL930X_MAC_EEE_ABLTY
);
944 a
= sw_r32(RTL930X_MAC_EEE_ABLTY
);
945 pr_info("Link partner: %08x\n", a
);
947 e
->lp_advertised
= ADVERTISED_100baseT_Full
;
948 e
->lp_advertised
|= ADVERTISED_1000baseT_Full
;
949 if (priv
->ports
[port
].is2G5
)
950 e
->lp_advertised
|= ADVERTISED_2500baseX_Full
;
951 if (priv
->ports
[port
].is10G
)
952 e
->lp_advertised
|= ADVERTISED_10000baseT_Full
;
955 // Read 2x to clear latched state
956 a
= sw_r32(RTL930X_EEEP_PORT_CTRL(port
));
957 a
= sw_r32(RTL930X_EEEP_PORT_CTRL(port
));
958 pr_info("%s RTL930X_EEEP_PORT_CTRL: %08x\n", __func__
, a
);
963 static void rtl930x_init_eee(struct rtl838x_switch_priv
*priv
, bool enable
)
967 pr_info("Setting up EEE, state: %d\n", enable
);
969 // Setup EEE on all ports
970 for (i
= 0; i
< priv
->cpu_port
; i
++) {
971 if (priv
->ports
[i
].phy
)
972 rtl930x_port_eee_set(priv
, i
, enable
);
975 priv
->eee_enabled
= enable
;
978 const struct rtl838x_reg rtl930x_reg
= {
979 .mask_port_reg_be
= rtl838x_mask_port_reg
,
980 .set_port_reg_be
= rtl838x_set_port_reg
,
981 .get_port_reg_be
= rtl838x_get_port_reg
,
982 .mask_port_reg_le
= rtl838x_mask_port_reg
,
983 .set_port_reg_le
= rtl838x_set_port_reg
,
984 .get_port_reg_le
= rtl838x_get_port_reg
,
985 .stat_port_rst
= RTL930X_STAT_PORT_RST
,
986 .stat_rst
= RTL930X_STAT_RST
,
987 .stat_port_std_mib
= RTL930X_STAT_PORT_MIB_CNTR
,
988 .traffic_enable
= rtl930x_traffic_enable
,
989 .traffic_disable
= rtl930x_traffic_disable
,
990 .traffic_get
= rtl930x_traffic_get
,
991 .traffic_set
= rtl930x_traffic_set
,
992 .l2_ctrl_0
= RTL930X_L2_CTRL
,
993 .l2_ctrl_1
= RTL930X_L2_AGE_CTRL
,
994 .l2_port_aging_out
= RTL930X_L2_PORT_AGE_CTRL
,
995 .smi_poll_ctrl
= RTL930X_SMI_POLL_CTRL
, // TODO: Difference to RTL9300_SMI_PRVTE_POLLING_CTRL
996 .l2_tbl_flush_ctrl
= RTL930X_L2_TBL_FLUSH_CTRL
,
997 .exec_tbl0_cmd
= rtl930x_exec_tbl0_cmd
,
998 .exec_tbl1_cmd
= rtl930x_exec_tbl1_cmd
,
999 .tbl_access_data_0
= rtl930x_tbl_access_data_0
,
1000 .isr_glb_src
= RTL930X_ISR_GLB
,
1001 .isr_port_link_sts_chg
= RTL930X_ISR_PORT_LINK_STS_CHG
,
1002 .imr_port_link_sts_chg
= RTL930X_IMR_PORT_LINK_STS_CHG
,
1003 .imr_glb
= RTL930X_IMR_GLB
,
1004 .vlan_tables_read
= rtl930x_vlan_tables_read
,
1005 .vlan_set_tagged
= rtl930x_vlan_set_tagged
,
1006 .vlan_set_untagged
= rtl930x_vlan_set_untagged
,
1007 .vlan_profile_dump
= rtl930x_vlan_profile_dump
,
1008 .vlan_profile_setup
= rtl930x_vlan_profile_setup
,
1009 .vlan_fwd_on_inner
= rtl930x_vlan_fwd_on_inner
,
1010 .stp_get
= rtl930x_stp_get
,
1011 .stp_set
= rtl930x_stp_set
,
1012 .mac_force_mode_ctrl
= rtl930x_mac_force_mode_ctrl
,
1013 .mac_port_ctrl
= rtl930x_mac_port_ctrl
,
1014 .l2_port_new_salrn
= rtl930x_l2_port_new_salrn
,
1015 .l2_port_new_sa_fwd
= rtl930x_l2_port_new_sa_fwd
,
1016 .mir_ctrl
= RTL930X_MIR_CTRL
,
1017 .mir_dpm
= RTL930X_MIR_DPM_CTRL
,
1018 .mir_spm
= RTL930X_MIR_SPM_CTRL
,
1019 .mac_link_sts
= RTL930X_MAC_LINK_STS
,
1020 .mac_link_dup_sts
= RTL930X_MAC_LINK_DUP_STS
,
1021 .mac_link_spd_sts
= rtl930x_mac_link_spd_sts
,
1022 .mac_rx_pause_sts
= RTL930X_MAC_RX_PAUSE_STS
,
1023 .mac_tx_pause_sts
= RTL930X_MAC_TX_PAUSE_STS
,
1024 .read_l2_entry_using_hash
= rtl930x_read_l2_entry_using_hash
,
1025 .write_l2_entry_using_hash
= rtl930x_write_l2_entry_using_hash
,
1026 .read_cam
= rtl930x_read_cam
,
1027 .write_cam
= rtl930x_write_cam
,
1028 .vlan_port_egr_filter
= RTL930X_VLAN_PORT_EGR_FLTR
,
1029 .vlan_port_igr_filter
= RTL930X_VLAN_PORT_IGR_FLTR(0),
1030 .vlan_port_pb
= RTL930X_VLAN_PORT_PB_VLAN
,
1031 .vlan_port_tag_sts_ctrl
= RTL930X_VLAN_PORT_TAG_STS_CTRL
,
1032 .trk_mbr_ctr
= rtl930x_trk_mbr_ctr
,
1033 .rma_bpdu_fld_pmask
= RTL930X_RMA_BPDU_FLD_PMSK
,
1034 .init_eee
= rtl930x_init_eee
,
1035 .port_eee_set
= rtl930x_port_eee_set
,
1036 .eee_port_ability
= rtl930x_eee_port_ability
,
1037 .read_mcast_pmask
= rtl930x_read_mcast_pmask
,
1038 .write_mcast_pmask
= rtl930x_write_mcast_pmask
,