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 (0) 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 index
)
106 if (index
< 0 || index
> 7)
109 profile
[0] = sw_r32(RTL930X_VLAN_PROFILE_SET(index
));
110 profile
[1] = sw_r32(RTL930X_VLAN_PROFILE_SET(index
) + 4);
111 profile
[2] = sw_r32(RTL930X_VLAN_PROFILE_SET(index
) + 8) & 0x1FFFFFFF;
112 profile
[3] = sw_r32(RTL930X_VLAN_PROFILE_SET(index
) + 12) & 0x1FFFFFFF;
113 profile
[4] = sw_r32(RTL930X_VLAN_PROFILE_SET(index
) + 16) & 0x1FFFFFFF;
115 pr_debug("VLAN %d: L2 learning: %d, L2 Unknown MultiCast Field %x, \
116 IPv4 Unknown MultiCast Field %x, IPv6 Unknown MultiCast Field: %x",
117 index
, profile
[0] & (3 << 21), profile
[2], profile
[3], profile
[4]);
120 static void rtl930x_vlan_set_untagged(u32 vlan
, u64 portmask
)
122 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_2
, 0);
124 sw_w32(portmask
<< 3, rtl_table_data(r
, 0));
125 rtl_table_write(r
, vlan
);
126 rtl_table_release(r
);
129 static void rtl930x_stp_get(struct rtl838x_switch_priv
*priv
, u16 msti
, u32 port_state
[])
132 u32 cmd
= 1 << 17 /* Execute cmd */
134 | 4 << 12 /* Table type 0b10 */
136 priv
->r
->exec_tbl0_cmd(cmd
);
138 for (i
= 0; i
< 2; i
++)
139 port_state
[i
] = sw_r32(RTL930X_TBL_ACCESS_DATA_0(i
));
140 pr_debug("MSTI: %d STATE: %08x, %08x\n", msti
, port_state
[0], port_state
[1]);
143 static void rtl930x_stp_set(struct rtl838x_switch_priv
*priv
, u16 msti
, u32 port_state
[])
146 u32 cmd
= 1 << 17 /* Execute cmd */
147 | 1 << 16 /* Write */
148 | 4 << 12 /* Table type 4 */
151 for (i
= 0; i
< 2; i
++)
152 sw_w32(port_state
[i
], RTL930X_TBL_ACCESS_DATA_0(i
));
153 priv
->r
->exec_tbl0_cmd(cmd
);
156 static inline int rtl930x_mac_force_mode_ctrl(int p
)
158 return RTL930X_MAC_FORCE_MODE_CTRL
+ (p
<< 2);
161 static inline int rtl930x_mac_port_ctrl(int p
)
163 return RTL930X_MAC_L2_PORT_CTRL(p
);
166 static inline int rtl930x_mac_link_spd_sts(int p
)
168 return RTL930X_MAC_LINK_SPD_STS(p
);
171 static void rtl930x_fill_l2_entry(u32 r
[], struct rtl838x_l2_entry
*e
)
173 e
->valid
= !!(r
[2] & BIT(31));
177 // TODO: Is there not a function to copy directly MAC memory?
178 e
->mac
[0] = (r
[0] >> 24);
179 e
->mac
[1] = (r
[0] >> 16);
180 e
->mac
[2] = (r
[0] >> 8);
182 e
->mac
[4] = (r
[1] >> 24);
183 e
->mac
[5] = (r
[1] >> 16);
185 /* Is it a unicast entry? check multicast bit */
186 if (!(e
->mac
[0] & 1)) {
187 e
->type
= L2_UNICAST
;
188 e
->is_static
= !!(r
[2] & BIT(14));
189 e
->vid
= r
[2] & 0xfff;
190 e
->rvid
= r
[1] & 0xfff;
191 e
->port
= (r
[2] >> 20) & 0x3ff;
192 // Check for trunk port
193 if (r
[2] & BIT(30)) {
194 e
->stackDev
= (e
->port
>> 9) & 1;
195 e
->trunk
= e
->port
& 0x3f;
197 e
->stackDev
= (e
->port
>> 6) & 0xf;
198 e
->port
= e
->port
& 0x3f;
201 e
->block_da
= !!(r
[2] & BIT(15));
202 e
->block_sa
= !!(r
[2] & BIT(16));
203 e
->suspended
= !!(r
[2] & BIT(13));
204 e
->next_hop
= !!(r
[2] & BIT(12));
205 e
->age
= (r
[2] >> 17) & 3;
210 e
->type
= L2_MULTICAST
;
211 e
->mc_portmask_index
= (r
[2]>>6) & 0xfff;
215 static u64
rtl930x_read_l2_entry_using_hash(u32 hash
, u32 position
, struct rtl838x_l2_entry
*e
)
219 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 0);
220 u32 idx
= (0 << 14) | (hash
<< 2) | position
;
223 rtl_table_read(q
, idx
);
224 for (i
= 0; i
< 3; i
++)
225 r
[i
] = sw_r32(rtl_table_data(q
, i
));
227 rtl_table_release(q
);
229 rtl930x_fill_l2_entry(r
, e
);
233 entry
= ((u64
)r
[0] << 32) | (r
[1] & 0xffff0000) | e
->vid
;
237 static u64
rtl930x_read_cam(int idx
, struct rtl838x_l2_entry
*e
)
241 struct table_reg
*q
= rtl_table_get(RTL9300_TBL_L2
, 1);
244 rtl_table_read(q
, idx
);
245 for (i
= 0; i
< 3; i
++)
246 r
[i
] = sw_r32(rtl_table_data(q
, i
));
248 rtl_table_release(q
);
250 rtl930x_fill_l2_entry(r
, e
);
254 entry
= ((u64
)r
[0] << 32) | (r
[1] & 0xffff0000) | e
->vid
;
259 u64
rtl930x_traffic_get(int source
)
262 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
264 rtl_table_read(r
, source
);
265 v
= sw_r32(rtl_table_data(r
, 0));
266 rtl_table_release(r
);
271 * Enable traffic between a source port and a destination port matrix
273 void rtl930x_traffic_set(int source
, u64 dest_matrix
)
275 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
277 sw_w32((dest_matrix
<< 3), rtl_table_data(r
, 0));
278 rtl_table_write(r
, source
);
279 rtl_table_release(r
);
282 void rtl930x_traffic_enable(int source
, int dest
)
284 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
285 rtl_table_read(r
, source
);
286 sw_w32_mask(0, BIT(dest
+ 3), rtl_table_data(r
, 0));
287 rtl_table_write(r
, source
);
288 rtl_table_release(r
);
291 void rtl930x_traffic_disable(int source
, int dest
)
293 struct table_reg
*r
= rtl_table_get(RTL9300_TBL_0
, 6);
294 rtl_table_read(r
, source
);
295 sw_w32_mask(BIT(dest
+ 3), 0, rtl_table_data(r
, 0));
296 rtl_table_write(r
, source
);
297 rtl_table_release(r
);
300 void rtl9300_dump_debug(void)
303 u16 r
= RTL930X_STAT_PRVTE_DROP_COUNTER0
;
305 for (i
= 0; i
< 10; i
++) {
306 pr_info("# %d %08x %08x %08x %08x %08x %08x %08x %08x\n", i
* 8,
307 sw_r32(r
), sw_r32(r
+ 4), sw_r32(r
+ 8), sw_r32(r
+ 12),
308 sw_r32(r
+ 16), sw_r32(r
+ 20), sw_r32(r
+ 24), sw_r32(r
+ 28));
311 pr_info("# %08x %08x %08x %08x %08x\n",
312 sw_r32(r
), sw_r32(r
+ 4), sw_r32(r
+ 8), sw_r32(r
+ 12), sw_r32(r
+ 16));
313 rtl930x_print_matrix();
314 pr_info("RTL930X_L2_PORT_SABLK_CTRL: %08x, RTL930X_L2_PORT_DABLK_CTRL %08x\n",
315 sw_r32(RTL930X_L2_PORT_SABLK_CTRL
), sw_r32(RTL930X_L2_PORT_DABLK_CTRL
)
320 irqreturn_t
rtl930x_switch_irq(int irq
, void *dev_id
)
322 struct dsa_switch
*ds
= dev_id
;
323 u32 status
= sw_r32(RTL930X_ISR_GLB
);
324 u32 ports
= sw_r32(RTL930X_ISR_PORT_LINK_STS_CHG
);
329 sw_w32(ports
, RTL930X_ISR_PORT_LINK_STS_CHG
);
330 pr_info("RTL9300 Link change: status: %x, ports %x\n", status
, ports
);
332 rtl9300_dump_debug();
334 for (i
= 0; i
< 28; i
++) {
335 if (ports
& BIT(i
)) {
336 /* Read the register twice because of issues with latency at least
337 * with the external RTL8226 PHY on the XGS1210 */
338 link
= sw_r32(RTL930X_MAC_LINK_STS
);
339 link
= sw_r32(RTL930X_MAC_LINK_STS
);
341 dsa_port_phylink_mac_change(ds
, i
, true);
343 dsa_port_phylink_mac_change(ds
, i
, false);
350 int rtl9300_sds_power(int mac
, int val
)
355 // TODO: these numbers are hard-coded for the Zyxel XGS1210 12 Switch
356 pr_info("SerDes: %s %d\n", __func__
, mac
);
360 mode
= 0x12; // HISGMII
364 mode
= 0x12; // HISGMII
368 mode
= 0x1b; // 10GR/1000BX auto
372 mode
= 0x1b; // 10GR/1000BX auto
380 rtl9300_sds_rst(sds_num
, mode
);
386 int rtl930x_write_phy(u32 port
, u32 page
, u32 reg
, u32 val
)
391 pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__
, port
, page
, reg
, val
);
393 if (port
> 63 || page
> 4095 || reg
> 31)
397 mutex_lock(&smi_lock
);
399 sw_w32(BIT(port
), RTL930X_SMI_ACCESS_PHY_CTRL_0
);
400 sw_w32_mask(0xffff << 16, val
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
401 v
= reg
<< 20 | page
<< 3 | 0x1f << 15 | BIT(2) | BIT(0);
402 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
405 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
411 mutex_unlock(&smi_lock
);
416 int rtl930x_read_phy(u32 port
, u32 page
, u32 reg
, u32
*val
)
421 // pr_info("In %s\n", __func__);
422 if (port
> 63 || page
> 4095 || reg
> 31)
425 mutex_lock(&smi_lock
);
427 sw_w32_mask(0xffff << 16, port
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
428 v
= reg
<< 20 | page
<< 3 | 0x1f << 15 | 1;
429 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
432 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
436 pr_debug("Error reading phy %d, register %d\n", port
, reg
);
439 *val
= (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2
) & 0xffff);
441 pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__
, port
, page
, reg
, *val
);
443 mutex_unlock(&smi_lock
);
450 * Write to an mmd register of the PHY
452 int rtl930x_write_mmd_phy(u32 port
, u32 devnum
, u32 regnum
, u32 val
)
457 mutex_lock(&smi_lock
);
460 sw_w32(BIT(port
), RTL930X_SMI_ACCESS_PHY_CTRL_0
);
463 sw_w32_mask(0xffff << 16, val
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
465 // Set MMD device number and register to write to
466 sw_w32(devnum
<< 16 | (regnum
& 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3
);
468 v
= BIT(2)| BIT(1)| BIT(0); // WRITE | MMD-access | EXEC
469 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
472 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
473 } while ( v
& BIT(0));
475 pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__
, port
, regnum
, val
, err
);
476 mutex_unlock(&smi_lock
);
481 * Read an mmd register of the PHY
483 int rtl930x_read_mmd_phy(u32 port
, u32 devnum
, u32 regnum
, u32
*val
)
488 mutex_lock(&smi_lock
);
491 sw_w32_mask(0xffff << 16, port
<< 16, RTL930X_SMI_ACCESS_PHY_CTRL_2
);
493 // Set MMD device number and register to write to
494 sw_w32(devnum
<< 16 | (regnum
& 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3
);
496 v
= BIT(1)| BIT(0); // MMD-access | EXEC
497 sw_w32(v
, RTL930X_SMI_ACCESS_PHY_CTRL_1
);
500 v
= sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1
);
502 // There is no error-checking via BIT 25 of v, as it does not seem to be set correctly
503 *val
= (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2
) & 0xffff);
504 pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__
, port
, regnum
, *val
, err
);
506 mutex_unlock(&smi_lock
);
513 * Calculate both the block 0 and the block 1 hash, and return in
514 * lower and higher word of the return value since only 12 bit of
515 * the hash are significant
517 u32
rtl930x_hash(struct rtl838x_switch_priv
*priv
, u64 seed
)
519 u32 k0
, k1
, h1
, h2
, h
;
521 k0
= (u32
) (((seed
>> 55) & 0x1f) ^ ((seed
>> 44) & 0x7ff)
522 ^ ((seed
>> 33) & 0x7ff) ^ ((seed
>> 22) & 0x7ff)
523 ^ ((seed
>> 11) & 0x7ff) ^ (seed
& 0x7ff));
525 h1
= (seed
>> 11) & 0x7ff;
526 h1
= ((h1
& 0x1f) << 6) | ((h1
>> 5) & 0x3f);
528 h2
= (seed
>> 33) & 0x7ff;
529 h2
= ((h2
& 0x3f) << 5)| ((h2
>> 6) & 0x3f);
531 k1
= (u32
) (((seed
<< 55) & 0x1f) ^ ((seed
>> 44) & 0x7ff) ^ h2
532 ^ ((seed
>> 22) & 0x7ff) ^ h1
535 // Algorithm choice for block 0
536 if (sw_r32(RTL930X_L2_CTRL
) & BIT(0))
541 /* Algorithm choice for block 1
542 * Since k0 and k1 are < 2048, adding 2048 will offset the hash into the second
544 * 2048 is in fact the hash-table size 16384 divided by 4 hashes per bucket
545 * divided by 2 to divide the hash space in 2
547 if (sw_r32(RTL930X_L2_CTRL
) & BIT(1))
548 h
|= (k1
+ 2048) << 16;
550 h
|= (k0
+ 2048) << 16;
555 const struct rtl838x_reg rtl930x_reg
= {
556 .mask_port_reg_be
= rtl838x_mask_port_reg
,
557 .set_port_reg_be
= rtl838x_set_port_reg
,
558 .get_port_reg_be
= rtl838x_get_port_reg
,
559 .mask_port_reg_le
= rtl838x_mask_port_reg
,
560 .set_port_reg_le
= rtl838x_set_port_reg
,
561 .get_port_reg_le
= rtl838x_get_port_reg
,
562 .stat_port_rst
= RTL930X_STAT_PORT_RST
,
563 .stat_rst
= RTL930X_STAT_RST
,
564 .stat_port_std_mib
= RTL930X_STAT_PORT_MIB_CNTR
,
565 .traffic_enable
= rtl930x_traffic_enable
,
566 .traffic_disable
= rtl930x_traffic_disable
,
567 .traffic_get
= rtl930x_traffic_get
,
568 .traffic_set
= rtl930x_traffic_set
,
569 .l2_ctrl_0
= RTL930X_L2_CTRL
,
570 .l2_ctrl_1
= RTL930X_L2_AGE_CTRL
,
571 .l2_port_aging_out
= RTL930X_L2_PORT_AGE_CTRL
,
572 .smi_poll_ctrl
= RTL930X_SMI_POLL_CTRL
, // TODO: Difference to RTL9300_SMI_PRVTE_POLLING_CTRL
573 .l2_tbl_flush_ctrl
= RTL930X_L2_TBL_FLUSH_CTRL
,
574 .exec_tbl0_cmd
= rtl930x_exec_tbl0_cmd
,
575 .exec_tbl1_cmd
= rtl930x_exec_tbl1_cmd
,
576 .tbl_access_data_0
= rtl930x_tbl_access_data_0
,
577 .isr_glb_src
= RTL930X_ISR_GLB
,
578 .isr_port_link_sts_chg
= RTL930X_ISR_PORT_LINK_STS_CHG
,
579 .imr_port_link_sts_chg
= RTL930X_IMR_PORT_LINK_STS_CHG
,
580 .imr_glb
= RTL930X_IMR_GLB
,
581 .vlan_tables_read
= rtl930x_vlan_tables_read
,
582 .vlan_set_tagged
= rtl930x_vlan_set_tagged
,
583 .vlan_set_untagged
= rtl930x_vlan_set_untagged
,
584 .vlan_profile_dump
= rtl930x_vlan_profile_dump
,
585 .stp_get
= rtl930x_stp_get
,
586 .stp_set
= rtl930x_stp_set
,
587 .mac_force_mode_ctrl
= rtl930x_mac_force_mode_ctrl
,
588 .mac_port_ctrl
= rtl930x_mac_port_ctrl
,
589 .l2_port_new_salrn
= rtl930x_l2_port_new_salrn
,
590 .l2_port_new_sa_fwd
= rtl930x_l2_port_new_sa_fwd
,
591 .mir_ctrl
= RTL930X_MIR_CTRL
,
592 .mir_dpm
= RTL930X_MIR_DPM_CTRL
,
593 .mir_spm
= RTL930X_MIR_SPM_CTRL
,
594 .mac_link_sts
= RTL930X_MAC_LINK_STS
,
595 .mac_link_dup_sts
= RTL930X_MAC_LINK_DUP_STS
,
596 .mac_link_spd_sts
= rtl930x_mac_link_spd_sts
,
597 .mac_rx_pause_sts
= RTL930X_MAC_RX_PAUSE_STS
,
598 .mac_tx_pause_sts
= RTL930X_MAC_TX_PAUSE_STS
,
599 .read_l2_entry_using_hash
= rtl930x_read_l2_entry_using_hash
,
600 .read_cam
= rtl930x_read_cam
,
601 .vlan_port_egr_filter
= RTL930X_VLAN_PORT_EGR_FLTR
,
602 .vlan_port_igr_filter
= RTL930X_VLAN_PORT_IGR_FLTR(0),
603 .vlan_port_pb
= RTL930X_VLAN_PORT_PB_VLAN
,
604 .vlan_port_tag_sts_ctrl
= RTL930X_VLAN_PORT_TAG_STS_CTRL
,
605 .trk_mbr_ctr
= rtl930x_trk_mbr_ctr
,
606 .rma_bpdu_fld_pmask
= RTL930X_RMA_BPDU_FLD_PMSK
,