1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2022 Schneider-Electric
5 * Clément Léger <clement.leger@bootlin.com>
9 #include <linux/etherdevice.h>
10 #include <linux/if_bridge.h>
11 #include <linux/if_ether.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
15 #include <linux/of_mdio.h>
18 #include "rzn1_a5psw.h"
22 const char name
[ETH_GSTRING_LEN
];
25 #define STAT_DESC(_offset) { \
26 .offset = A5PSW_##_offset, \
27 .name = __stringify(_offset), \
30 static const struct a5psw_stats a5psw_stats
[] = {
31 STAT_DESC(aFramesTransmittedOK
),
32 STAT_DESC(aFramesReceivedOK
),
33 STAT_DESC(aFrameCheckSequenceErrors
),
34 STAT_DESC(aAlignmentErrors
),
35 STAT_DESC(aOctetsTransmittedOK
),
36 STAT_DESC(aOctetsReceivedOK
),
37 STAT_DESC(aTxPAUSEMACCtrlFrames
),
38 STAT_DESC(aRxPAUSEMACCtrlFrames
),
39 STAT_DESC(ifInErrors
),
40 STAT_DESC(ifOutErrors
),
41 STAT_DESC(ifInUcastPkts
),
42 STAT_DESC(ifInMulticastPkts
),
43 STAT_DESC(ifInBroadcastPkts
),
44 STAT_DESC(ifOutDiscards
),
45 STAT_DESC(ifOutUcastPkts
),
46 STAT_DESC(ifOutMulticastPkts
),
47 STAT_DESC(ifOutBroadcastPkts
),
48 STAT_DESC(etherStatsDropEvents
),
49 STAT_DESC(etherStatsOctets
),
50 STAT_DESC(etherStatsPkts
),
51 STAT_DESC(etherStatsUndersizePkts
),
52 STAT_DESC(etherStatsOversizePkts
),
53 STAT_DESC(etherStatsPkts64Octets
),
54 STAT_DESC(etherStatsPkts65to127Octets
),
55 STAT_DESC(etherStatsPkts128to255Octets
),
56 STAT_DESC(etherStatsPkts256to511Octets
),
57 STAT_DESC(etherStatsPkts1024to1518Octets
),
58 STAT_DESC(etherStatsPkts1519toXOctets
),
59 STAT_DESC(etherStatsJabbers
),
60 STAT_DESC(etherStatsFragments
),
61 STAT_DESC(VLANReceived
),
62 STAT_DESC(VLANTransmitted
),
64 STAT_DESC(aMultipleCollisions
),
65 STAT_DESC(aSingleCollisions
),
66 STAT_DESC(aLateCollisions
),
67 STAT_DESC(aExcessiveCollisions
),
68 STAT_DESC(aCarrierSenseErrors
),
71 static void a5psw_reg_writel(struct a5psw
*a5psw
, int offset
, u32 value
)
73 writel(value
, a5psw
->base
+ offset
);
76 static u32
a5psw_reg_readl(struct a5psw
*a5psw
, int offset
)
78 return readl(a5psw
->base
+ offset
);
81 static void a5psw_reg_rmw(struct a5psw
*a5psw
, int offset
, u32 mask
, u32 val
)
85 spin_lock(&a5psw
->reg_lock
);
87 reg
= a5psw_reg_readl(a5psw
, offset
);
90 a5psw_reg_writel(a5psw
, offset
, reg
);
92 spin_unlock(&a5psw
->reg_lock
);
95 static enum dsa_tag_protocol
a5psw_get_tag_protocol(struct dsa_switch
*ds
,
97 enum dsa_tag_protocol mp
)
99 return DSA_TAG_PROTO_RZN1_A5PSW
;
102 static void a5psw_port_pattern_set(struct a5psw
*a5psw
, int port
, int pattern
,
108 rx_match
|= A5PSW_RXMATCH_CONFIG_PATTERN(pattern
);
110 a5psw_reg_rmw(a5psw
, A5PSW_RXMATCH_CONFIG(port
),
111 A5PSW_RXMATCH_CONFIG_PATTERN(pattern
), rx_match
);
114 static void a5psw_port_mgmtfwd_set(struct a5psw
*a5psw
, int port
, bool enable
)
116 /* Enable "management forward" pattern matching, this will forward
117 * packets from this port only towards the management port and thus
120 a5psw_port_pattern_set(a5psw
, port
, A5PSW_PATTERN_MGMTFWD
, enable
);
123 static void a5psw_port_tx_enable(struct a5psw
*a5psw
, int port
, bool enable
)
125 u32 mask
= A5PSW_PORT_ENA_TX(port
);
126 u32 reg
= enable
? mask
: 0;
128 /* Even though the port TX is disabled through TXENA bit in the
129 * PORT_ENA register, it can still send BPDUs. This depends on the tag
130 * configuration added when sending packets from the CPU port to the
131 * switch port. Indeed, when using forced forwarding without filtering,
132 * even disabled ports will be able to send packets that are tagged.
133 * This allows to implement STP support when ports are in a state where
134 * forwarding traffic should be stopped but BPDUs should still be sent.
136 a5psw_reg_rmw(a5psw
, A5PSW_PORT_ENA
, mask
, reg
);
139 static void a5psw_port_enable_set(struct a5psw
*a5psw
, int port
, bool enable
)
144 port_ena
|= A5PSW_PORT_ENA_TX_RX(port
);
146 a5psw_reg_rmw(a5psw
, A5PSW_PORT_ENA
, A5PSW_PORT_ENA_TX_RX(port
),
150 static int a5psw_lk_execute_ctrl(struct a5psw
*a5psw
, u32
*ctrl
)
154 a5psw_reg_writel(a5psw
, A5PSW_LK_ADDR_CTRL
, *ctrl
);
156 ret
= readl_poll_timeout(a5psw
->base
+ A5PSW_LK_ADDR_CTRL
, *ctrl
,
157 !(*ctrl
& A5PSW_LK_ADDR_CTRL_BUSY
),
158 A5PSW_LK_BUSY_USEC_POLL
, A5PSW_CTRL_TIMEOUT
);
160 dev_err(a5psw
->dev
, "LK_CTRL timeout waiting for BUSY bit\n");
165 static void a5psw_port_fdb_flush(struct a5psw
*a5psw
, int port
)
167 u32 ctrl
= A5PSW_LK_ADDR_CTRL_DELETE_PORT
| BIT(port
);
169 mutex_lock(&a5psw
->lk_lock
);
170 a5psw_lk_execute_ctrl(a5psw
, &ctrl
);
171 mutex_unlock(&a5psw
->lk_lock
);
174 static void a5psw_port_authorize_set(struct a5psw
*a5psw
, int port
,
177 u32 reg
= a5psw_reg_readl(a5psw
, A5PSW_AUTH_PORT(port
));
180 reg
|= A5PSW_AUTH_PORT_AUTHORIZED
;
182 reg
&= ~A5PSW_AUTH_PORT_AUTHORIZED
;
184 a5psw_reg_writel(a5psw
, A5PSW_AUTH_PORT(port
), reg
);
187 static void a5psw_port_disable(struct dsa_switch
*ds
, int port
)
189 struct a5psw
*a5psw
= ds
->priv
;
191 a5psw_port_authorize_set(a5psw
, port
, false);
192 a5psw_port_enable_set(a5psw
, port
, false);
195 static int a5psw_port_enable(struct dsa_switch
*ds
, int port
,
196 struct phy_device
*phy
)
198 struct a5psw
*a5psw
= ds
->priv
;
200 a5psw_port_authorize_set(a5psw
, port
, true);
201 a5psw_port_enable_set(a5psw
, port
, true);
206 static int a5psw_port_change_mtu(struct dsa_switch
*ds
, int port
, int new_mtu
)
208 struct a5psw
*a5psw
= ds
->priv
;
210 new_mtu
+= ETH_HLEN
+ A5PSW_EXTRA_MTU_LEN
+ ETH_FCS_LEN
;
211 a5psw_reg_writel(a5psw
, A5PSW_FRM_LENGTH(port
), new_mtu
);
216 static int a5psw_port_max_mtu(struct dsa_switch
*ds
, int port
)
218 return A5PSW_MAX_MTU
;
221 static void a5psw_phylink_get_caps(struct dsa_switch
*ds
, int port
,
222 struct phylink_config
*config
)
224 unsigned long *intf
= config
->supported_interfaces
;
226 config
->mac_capabilities
= MAC_1000FD
;
228 if (dsa_is_cpu_port(ds
, port
)) {
229 /* GMII is used internally and GMAC2 is connected to the switch
230 * using 1000Mbps Full-Duplex mode only (cf ethernet manual)
232 __set_bit(PHY_INTERFACE_MODE_GMII
, intf
);
234 config
->mac_capabilities
|= MAC_100
| MAC_10
;
235 phy_interface_set_rgmii(intf
);
236 __set_bit(PHY_INTERFACE_MODE_RMII
, intf
);
237 __set_bit(PHY_INTERFACE_MODE_MII
, intf
);
241 static struct phylink_pcs
*
242 a5psw_phylink_mac_select_pcs(struct phylink_config
*config
,
243 phy_interface_t interface
)
245 struct dsa_port
*dp
= dsa_phylink_to_port(config
);
246 struct a5psw
*a5psw
= dp
->ds
->priv
;
248 if (dsa_port_is_cpu(dp
))
251 return a5psw
->pcs
[dp
->index
];
254 static void a5psw_phylink_mac_config(struct phylink_config
*config
,
256 const struct phylink_link_state
*state
)
260 static void a5psw_phylink_mac_link_down(struct phylink_config
*config
,
262 phy_interface_t interface
)
264 struct dsa_port
*dp
= dsa_phylink_to_port(config
);
265 struct a5psw
*a5psw
= dp
->ds
->priv
;
266 int port
= dp
->index
;
269 cmd_cfg
= a5psw_reg_readl(a5psw
, A5PSW_CMD_CFG(port
));
270 cmd_cfg
&= ~(A5PSW_CMD_CFG_RX_ENA
| A5PSW_CMD_CFG_TX_ENA
);
271 a5psw_reg_writel(a5psw
, A5PSW_CMD_CFG(port
), cmd_cfg
);
274 static void a5psw_phylink_mac_link_up(struct phylink_config
*config
,
275 struct phy_device
*phydev
,
277 phy_interface_t interface
,
278 int speed
, int duplex
, bool tx_pause
,
281 u32 cmd_cfg
= A5PSW_CMD_CFG_RX_ENA
| A5PSW_CMD_CFG_TX_ENA
|
282 A5PSW_CMD_CFG_TX_CRC_APPEND
;
283 struct dsa_port
*dp
= dsa_phylink_to_port(config
);
284 struct a5psw
*a5psw
= dp
->ds
->priv
;
286 if (speed
== SPEED_1000
)
287 cmd_cfg
|= A5PSW_CMD_CFG_ETH_SPEED
;
289 if (duplex
== DUPLEX_HALF
)
290 cmd_cfg
|= A5PSW_CMD_CFG_HD_ENA
;
292 cmd_cfg
|= A5PSW_CMD_CFG_CNTL_FRM_ENA
;
295 cmd_cfg
&= ~A5PSW_CMD_CFG_PAUSE_IGNORE
;
297 a5psw_reg_writel(a5psw
, A5PSW_CMD_CFG(dp
->index
), cmd_cfg
);
300 static int a5psw_set_ageing_time(struct dsa_switch
*ds
, unsigned int msecs
)
302 struct a5psw
*a5psw
= ds
->priv
;
307 rate
= clk_get_rate(a5psw
->clk
);
308 max
= div64_ul(((u64
)A5PSW_LK_AGETIME_MASK
* A5PSW_TABLE_ENTRIES
* 1024),
313 tmp
= div_u64(rate
, MSEC_PER_SEC
);
314 agetime
= div_u64(msecs
* tmp
, 1024 * A5PSW_TABLE_ENTRIES
);
316 a5psw_reg_writel(a5psw
, A5PSW_LK_AGETIME
, agetime
);
321 static void a5psw_port_learning_set(struct a5psw
*a5psw
, int port
, bool learn
)
323 u32 mask
= A5PSW_INPUT_LEARN_DIS(port
);
324 u32 reg
= !learn
? mask
: 0;
326 a5psw_reg_rmw(a5psw
, A5PSW_INPUT_LEARN
, mask
, reg
);
329 static void a5psw_port_rx_block_set(struct a5psw
*a5psw
, int port
, bool block
)
331 u32 mask
= A5PSW_INPUT_LEARN_BLOCK(port
);
332 u32 reg
= block
? mask
: 0;
334 a5psw_reg_rmw(a5psw
, A5PSW_INPUT_LEARN
, mask
, reg
);
337 static void a5psw_flooding_set_resolution(struct a5psw
*a5psw
, int port
,
340 u8 offsets
[] = {A5PSW_UCAST_DEF_MASK
, A5PSW_BCAST_DEF_MASK
,
341 A5PSW_MCAST_DEF_MASK
};
344 for (i
= 0; i
< ARRAY_SIZE(offsets
); i
++)
345 a5psw_reg_rmw(a5psw
, offsets
[i
], BIT(port
),
346 set
? BIT(port
) : 0);
349 static void a5psw_port_set_standalone(struct a5psw
*a5psw
, int port
,
352 a5psw_port_learning_set(a5psw
, port
, !standalone
);
353 a5psw_flooding_set_resolution(a5psw
, port
, !standalone
);
354 a5psw_port_mgmtfwd_set(a5psw
, port
, standalone
);
357 static int a5psw_port_bridge_join(struct dsa_switch
*ds
, int port
,
358 struct dsa_bridge bridge
,
359 bool *tx_fwd_offload
,
360 struct netlink_ext_ack
*extack
)
362 struct a5psw
*a5psw
= ds
->priv
;
364 /* We only support 1 bridge device */
365 if (a5psw
->br_dev
&& bridge
.dev
!= a5psw
->br_dev
) {
366 NL_SET_ERR_MSG_MOD(extack
,
367 "Forwarding offload supported for a single bridge");
371 a5psw
->br_dev
= bridge
.dev
;
372 a5psw_port_set_standalone(a5psw
, port
, false);
374 a5psw
->bridged_ports
|= BIT(port
);
379 static void a5psw_port_bridge_leave(struct dsa_switch
*ds
, int port
,
380 struct dsa_bridge bridge
)
382 struct a5psw
*a5psw
= ds
->priv
;
384 a5psw
->bridged_ports
&= ~BIT(port
);
386 a5psw_port_set_standalone(a5psw
, port
, true);
388 /* No more ports bridged */
389 if (a5psw
->bridged_ports
== BIT(A5PSW_CPU_PORT
))
390 a5psw
->br_dev
= NULL
;
393 static int a5psw_port_pre_bridge_flags(struct dsa_switch
*ds
, int port
,
394 struct switchdev_brport_flags flags
,
395 struct netlink_ext_ack
*extack
)
397 if (flags
.mask
& ~(BR_LEARNING
| BR_FLOOD
| BR_MCAST_FLOOD
|
405 a5psw_port_bridge_flags(struct dsa_switch
*ds
, int port
,
406 struct switchdev_brport_flags flags
,
407 struct netlink_ext_ack
*extack
)
409 struct a5psw
*a5psw
= ds
->priv
;
412 /* If a port is set as standalone, we do not want to be able to
413 * configure flooding nor learning which would result in joining the
414 * unique bridge. This can happen when a port leaves the bridge, in
415 * which case the DSA core will try to "clear" all flags for the
416 * standalone port (ie enable flooding, disable learning). In that case
417 * do not fail but do not apply the flags.
419 if (!(a5psw
->bridged_ports
& BIT(port
)))
422 if (flags
.mask
& BR_LEARNING
) {
423 val
= flags
.val
& BR_LEARNING
? 0 : A5PSW_INPUT_LEARN_DIS(port
);
424 a5psw_reg_rmw(a5psw
, A5PSW_INPUT_LEARN
,
425 A5PSW_INPUT_LEARN_DIS(port
), val
);
428 if (flags
.mask
& BR_FLOOD
) {
429 val
= flags
.val
& BR_FLOOD
? BIT(port
) : 0;
430 a5psw_reg_rmw(a5psw
, A5PSW_UCAST_DEF_MASK
, BIT(port
), val
);
433 if (flags
.mask
& BR_MCAST_FLOOD
) {
434 val
= flags
.val
& BR_MCAST_FLOOD
? BIT(port
) : 0;
435 a5psw_reg_rmw(a5psw
, A5PSW_MCAST_DEF_MASK
, BIT(port
), val
);
438 if (flags
.mask
& BR_BCAST_FLOOD
) {
439 val
= flags
.val
& BR_BCAST_FLOOD
? BIT(port
) : 0;
440 a5psw_reg_rmw(a5psw
, A5PSW_BCAST_DEF_MASK
, BIT(port
), val
);
446 static void a5psw_port_stp_state_set(struct dsa_switch
*ds
, int port
, u8 state
)
448 bool learning_enabled
, rx_enabled
, tx_enabled
;
449 struct dsa_port
*dp
= dsa_to_port(ds
, port
);
450 struct a5psw
*a5psw
= ds
->priv
;
453 case BR_STATE_DISABLED
:
454 case BR_STATE_BLOCKING
:
455 case BR_STATE_LISTENING
:
458 learning_enabled
= false;
460 case BR_STATE_LEARNING
:
463 learning_enabled
= dp
->learning
;
465 case BR_STATE_FORWARDING
:
468 learning_enabled
= dp
->learning
;
471 dev_err(ds
->dev
, "invalid STP state: %d\n", state
);
475 a5psw_port_learning_set(a5psw
, port
, learning_enabled
);
476 a5psw_port_rx_block_set(a5psw
, port
, !rx_enabled
);
477 a5psw_port_tx_enable(a5psw
, port
, tx_enabled
);
480 static void a5psw_port_fast_age(struct dsa_switch
*ds
, int port
)
482 struct a5psw
*a5psw
= ds
->priv
;
484 a5psw_port_fdb_flush(a5psw
, port
);
487 static int a5psw_lk_execute_lookup(struct a5psw
*a5psw
, union lk_data
*lk_data
,
493 a5psw_reg_writel(a5psw
, A5PSW_LK_DATA_LO
, lk_data
->lo
);
494 a5psw_reg_writel(a5psw
, A5PSW_LK_DATA_HI
, lk_data
->hi
);
496 ctrl
= A5PSW_LK_ADDR_CTRL_LOOKUP
;
497 ret
= a5psw_lk_execute_ctrl(a5psw
, &ctrl
);
501 *entry
= ctrl
& A5PSW_LK_ADDR_CTRL_ADDRESS
;
506 static int a5psw_port_fdb_add(struct dsa_switch
*ds
, int port
,
507 const unsigned char *addr
, u16 vid
,
510 struct a5psw
*a5psw
= ds
->priv
;
511 union lk_data lk_data
= {0};
512 bool inc_learncount
= false;
517 ether_addr_copy(lk_data
.entry
.mac
, addr
);
518 lk_data
.entry
.port_mask
= BIT(port
);
520 mutex_lock(&a5psw
->lk_lock
);
522 /* Set the value to be written in the lookup table */
523 ret
= a5psw_lk_execute_lookup(a5psw
, &lk_data
, &entry
);
527 lk_data
.hi
= a5psw_reg_readl(a5psw
, A5PSW_LK_DATA_HI
);
528 if (!lk_data
.entry
.valid
) {
529 inc_learncount
= true;
530 /* port_mask set to 0x1f when entry is not valid, clear it */
531 lk_data
.entry
.port_mask
= 0;
532 lk_data
.entry
.prio
= 0;
535 lk_data
.entry
.port_mask
|= BIT(port
);
536 lk_data
.entry
.is_static
= 1;
537 lk_data
.entry
.valid
= 1;
539 a5psw_reg_writel(a5psw
, A5PSW_LK_DATA_HI
, lk_data
.hi
);
541 reg
= A5PSW_LK_ADDR_CTRL_WRITE
| entry
;
542 ret
= a5psw_lk_execute_ctrl(a5psw
, ®
);
546 if (inc_learncount
) {
547 reg
= A5PSW_LK_LEARNCOUNT_MODE_INC
;
548 a5psw_reg_writel(a5psw
, A5PSW_LK_LEARNCOUNT
, reg
);
552 mutex_unlock(&a5psw
->lk_lock
);
557 static int a5psw_port_fdb_del(struct dsa_switch
*ds
, int port
,
558 const unsigned char *addr
, u16 vid
,
561 struct a5psw
*a5psw
= ds
->priv
;
562 union lk_data lk_data
= {0};
568 ether_addr_copy(lk_data
.entry
.mac
, addr
);
570 mutex_lock(&a5psw
->lk_lock
);
572 ret
= a5psw_lk_execute_lookup(a5psw
, &lk_data
, &entry
);
576 lk_data
.hi
= a5psw_reg_readl(a5psw
, A5PSW_LK_DATA_HI
);
578 /* Our hardware does not associate any VID to the FDB entries so this
579 * means that if two entries were added for the same mac but for
580 * different VID, then, on the deletion of the first one, we would also
581 * delete the second one. Since there is unfortunately nothing we can do
582 * about that, do not return an error...
584 if (!lk_data
.entry
.valid
)
587 lk_data
.entry
.port_mask
&= ~BIT(port
);
588 /* If there is no more port in the mask, clear the entry */
589 if (lk_data
.entry
.port_mask
== 0)
592 a5psw_reg_writel(a5psw
, A5PSW_LK_DATA_HI
, lk_data
.hi
);
596 reg
|= A5PSW_LK_ADDR_CTRL_CLEAR
;
598 reg
|= A5PSW_LK_ADDR_CTRL_WRITE
;
600 ret
= a5psw_lk_execute_ctrl(a5psw
, ®
);
604 /* Decrement LEARNCOUNT */
606 reg
= A5PSW_LK_LEARNCOUNT_MODE_DEC
;
607 a5psw_reg_writel(a5psw
, A5PSW_LK_LEARNCOUNT
, reg
);
611 mutex_unlock(&a5psw
->lk_lock
);
616 static int a5psw_port_fdb_dump(struct dsa_switch
*ds
, int port
,
617 dsa_fdb_dump_cb_t
*cb
, void *data
)
619 struct a5psw
*a5psw
= ds
->priv
;
620 union lk_data lk_data
;
624 mutex_lock(&a5psw
->lk_lock
);
626 for (i
= 0; i
< A5PSW_TABLE_ENTRIES
; i
++) {
627 reg
= A5PSW_LK_ADDR_CTRL_READ
| A5PSW_LK_ADDR_CTRL_WAIT
| i
;
629 ret
= a5psw_lk_execute_ctrl(a5psw
, ®
);
633 lk_data
.hi
= a5psw_reg_readl(a5psw
, A5PSW_LK_DATA_HI
);
634 /* If entry is not valid or does not contain the port, skip */
635 if (!lk_data
.entry
.valid
||
636 !(lk_data
.entry
.port_mask
& BIT(port
)))
639 lk_data
.lo
= a5psw_reg_readl(a5psw
, A5PSW_LK_DATA_LO
);
641 ret
= cb(lk_data
.entry
.mac
, 0, lk_data
.entry
.is_static
, data
);
647 mutex_unlock(&a5psw
->lk_lock
);
652 static int a5psw_port_vlan_filtering(struct dsa_switch
*ds
, int port
,
654 struct netlink_ext_ack
*extack
)
656 u32 mask
= BIT(port
+ A5PSW_VLAN_VERI_SHIFT
) |
657 BIT(port
+ A5PSW_VLAN_DISC_SHIFT
);
658 u32 val
= vlan_filtering
? mask
: 0;
659 struct a5psw
*a5psw
= ds
->priv
;
661 /* Disable/enable vlan tagging */
662 a5psw_reg_rmw(a5psw
, A5PSW_VLAN_IN_MODE_ENA
, BIT(port
),
663 vlan_filtering
? BIT(port
) : 0);
665 /* Disable/enable vlan input filtering */
666 a5psw_reg_rmw(a5psw
, A5PSW_VLAN_VERIFY
, mask
, val
);
671 static int a5psw_find_vlan_entry(struct a5psw
*a5psw
, u16 vid
)
676 /* Find vlan for this port */
677 for (i
= 0; i
< A5PSW_VLAN_COUNT
; i
++) {
678 vlan_res
= a5psw_reg_readl(a5psw
, A5PSW_VLAN_RES(i
));
679 if (FIELD_GET(A5PSW_VLAN_RES_VLANID
, vlan_res
) == vid
)
686 static int a5psw_new_vlan_res_entry(struct a5psw
*a5psw
, u16 newvid
)
691 /* Find a free VLAN entry */
692 for (i
= 0; i
< A5PSW_VLAN_COUNT
; i
++) {
693 vlan_res
= a5psw_reg_readl(a5psw
, A5PSW_VLAN_RES(i
));
694 if (!(FIELD_GET(A5PSW_VLAN_RES_PORTMASK
, vlan_res
))) {
695 vlan_res
= FIELD_PREP(A5PSW_VLAN_RES_VLANID
, newvid
);
696 a5psw_reg_writel(a5psw
, A5PSW_VLAN_RES(i
), vlan_res
);
704 static void a5psw_port_vlan_tagged_cfg(struct a5psw
*a5psw
,
705 unsigned int vlan_res_id
, int port
,
708 u32 mask
= A5PSW_VLAN_RES_WR_PORTMASK
| A5PSW_VLAN_RES_RD_TAGMASK
|
710 u32 vlan_res_off
= A5PSW_VLAN_RES(vlan_res_id
);
711 u32 val
= A5PSW_VLAN_RES_WR_TAGMASK
, reg
;
716 /* Toggle tag mask read */
717 a5psw_reg_writel(a5psw
, vlan_res_off
, A5PSW_VLAN_RES_RD_TAGMASK
);
718 reg
= a5psw_reg_readl(a5psw
, vlan_res_off
);
719 a5psw_reg_writel(a5psw
, vlan_res_off
, A5PSW_VLAN_RES_RD_TAGMASK
);
723 a5psw_reg_writel(a5psw
, vlan_res_off
, reg
);
726 static void a5psw_port_vlan_cfg(struct a5psw
*a5psw
, unsigned int vlan_res_id
,
729 u32 mask
= A5PSW_VLAN_RES_WR_TAGMASK
| BIT(port
);
730 u32 reg
= A5PSW_VLAN_RES_WR_PORTMASK
;
735 a5psw_reg_rmw(a5psw
, A5PSW_VLAN_RES(vlan_res_id
), mask
, reg
);
738 static int a5psw_port_vlan_add(struct dsa_switch
*ds
, int port
,
739 const struct switchdev_obj_port_vlan
*vlan
,
740 struct netlink_ext_ack
*extack
)
742 bool tagged
= !(vlan
->flags
& BRIDGE_VLAN_INFO_UNTAGGED
);
743 bool pvid
= vlan
->flags
& BRIDGE_VLAN_INFO_PVID
;
744 struct a5psw
*a5psw
= ds
->priv
;
748 vlan_res_id
= a5psw_find_vlan_entry(a5psw
, vid
);
749 if (vlan_res_id
< 0) {
750 vlan_res_id
= a5psw_new_vlan_res_entry(a5psw
, vid
);
755 a5psw_port_vlan_cfg(a5psw
, vlan_res_id
, port
, true);
757 a5psw_port_vlan_tagged_cfg(a5psw
, vlan_res_id
, port
, true);
759 /* Configure port to tag with corresponding VID, but do not enable it
760 * yet: wait for vlan filtering to be enabled to enable vlan port
764 a5psw_reg_writel(a5psw
, A5PSW_SYSTEM_TAGINFO(port
), vid
);
769 static int a5psw_port_vlan_del(struct dsa_switch
*ds
, int port
,
770 const struct switchdev_obj_port_vlan
*vlan
)
772 struct a5psw
*a5psw
= ds
->priv
;
776 vlan_res_id
= a5psw_find_vlan_entry(a5psw
, vid
);
780 a5psw_port_vlan_cfg(a5psw
, vlan_res_id
, port
, false);
781 a5psw_port_vlan_tagged_cfg(a5psw
, vlan_res_id
, port
, false);
786 static u64
a5psw_read_stat(struct a5psw
*a5psw
, u32 offset
, int port
)
790 reg_lo
= a5psw_reg_readl(a5psw
, offset
+ A5PSW_PORT_OFFSET(port
));
791 /* A5PSW_STATS_HIWORD is latched on stat read */
792 reg_hi
= a5psw_reg_readl(a5psw
, A5PSW_STATS_HIWORD
);
794 return ((u64
)reg_hi
<< 32) | reg_lo
;
797 static void a5psw_get_strings(struct dsa_switch
*ds
, int port
, u32 stringset
,
802 if (stringset
!= ETH_SS_STATS
)
805 for (u
= 0; u
< ARRAY_SIZE(a5psw_stats
); u
++)
806 ethtool_puts(&data
, a5psw_stats
[u
].name
);
809 static void a5psw_get_ethtool_stats(struct dsa_switch
*ds
, int port
,
812 struct a5psw
*a5psw
= ds
->priv
;
815 for (u
= 0; u
< ARRAY_SIZE(a5psw_stats
); u
++)
816 data
[u
] = a5psw_read_stat(a5psw
, a5psw_stats
[u
].offset
, port
);
819 static int a5psw_get_sset_count(struct dsa_switch
*ds
, int port
, int sset
)
821 if (sset
!= ETH_SS_STATS
)
824 return ARRAY_SIZE(a5psw_stats
);
827 static void a5psw_get_eth_mac_stats(struct dsa_switch
*ds
, int port
,
828 struct ethtool_eth_mac_stats
*mac_stats
)
830 struct a5psw
*a5psw
= ds
->priv
;
832 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
833 mac_stats
->FramesTransmittedOK
= RD(aFramesTransmittedOK
);
834 mac_stats
->SingleCollisionFrames
= RD(aSingleCollisions
);
835 mac_stats
->MultipleCollisionFrames
= RD(aMultipleCollisions
);
836 mac_stats
->FramesReceivedOK
= RD(aFramesReceivedOK
);
837 mac_stats
->FrameCheckSequenceErrors
= RD(aFrameCheckSequenceErrors
);
838 mac_stats
->AlignmentErrors
= RD(aAlignmentErrors
);
839 mac_stats
->OctetsTransmittedOK
= RD(aOctetsTransmittedOK
);
840 mac_stats
->FramesWithDeferredXmissions
= RD(aDeferred
);
841 mac_stats
->LateCollisions
= RD(aLateCollisions
);
842 mac_stats
->FramesAbortedDueToXSColls
= RD(aExcessiveCollisions
);
843 mac_stats
->FramesLostDueToIntMACXmitError
= RD(ifOutErrors
);
844 mac_stats
->CarrierSenseErrors
= RD(aCarrierSenseErrors
);
845 mac_stats
->OctetsReceivedOK
= RD(aOctetsReceivedOK
);
846 mac_stats
->FramesLostDueToIntMACRcvError
= RD(ifInErrors
);
847 mac_stats
->MulticastFramesXmittedOK
= RD(ifOutMulticastPkts
);
848 mac_stats
->BroadcastFramesXmittedOK
= RD(ifOutBroadcastPkts
);
849 mac_stats
->FramesWithExcessiveDeferral
= RD(aDeferred
);
850 mac_stats
->MulticastFramesReceivedOK
= RD(ifInMulticastPkts
);
851 mac_stats
->BroadcastFramesReceivedOK
= RD(ifInBroadcastPkts
);
855 static const struct ethtool_rmon_hist_range a5psw_rmon_ranges
[] = {
862 { 1519, A5PSW_MAX_MTU
},
866 static void a5psw_get_rmon_stats(struct dsa_switch
*ds
, int port
,
867 struct ethtool_rmon_stats
*rmon_stats
,
868 const struct ethtool_rmon_hist_range
**ranges
)
870 struct a5psw
*a5psw
= ds
->priv
;
872 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
873 rmon_stats
->undersize_pkts
= RD(etherStatsUndersizePkts
);
874 rmon_stats
->oversize_pkts
= RD(etherStatsOversizePkts
);
875 rmon_stats
->fragments
= RD(etherStatsFragments
);
876 rmon_stats
->jabbers
= RD(etherStatsJabbers
);
877 rmon_stats
->hist
[0] = RD(etherStatsPkts64Octets
);
878 rmon_stats
->hist
[1] = RD(etherStatsPkts65to127Octets
);
879 rmon_stats
->hist
[2] = RD(etherStatsPkts128to255Octets
);
880 rmon_stats
->hist
[3] = RD(etherStatsPkts256to511Octets
);
881 rmon_stats
->hist
[4] = RD(etherStatsPkts512to1023Octets
);
882 rmon_stats
->hist
[5] = RD(etherStatsPkts1024to1518Octets
);
883 rmon_stats
->hist
[6] = RD(etherStatsPkts1519toXOctets
);
886 *ranges
= a5psw_rmon_ranges
;
889 static void a5psw_get_eth_ctrl_stats(struct dsa_switch
*ds
, int port
,
890 struct ethtool_eth_ctrl_stats
*ctrl_stats
)
892 struct a5psw
*a5psw
= ds
->priv
;
895 stat
= a5psw_read_stat(a5psw
, A5PSW_aTxPAUSEMACCtrlFrames
, port
);
896 ctrl_stats
->MACControlFramesTransmitted
= stat
;
897 stat
= a5psw_read_stat(a5psw
, A5PSW_aRxPAUSEMACCtrlFrames
, port
);
898 ctrl_stats
->MACControlFramesReceived
= stat
;
901 static void a5psw_vlan_setup(struct a5psw
*a5psw
, int port
)
905 /* Enable TAG always mode for the port, this is actually controlled
906 * by VLAN_IN_MODE_ENA field which will be used for PVID insertion
908 reg
= A5PSW_VLAN_IN_MODE_TAG_ALWAYS
;
909 reg
<<= A5PSW_VLAN_IN_MODE_PORT_SHIFT(port
);
910 a5psw_reg_rmw(a5psw
, A5PSW_VLAN_IN_MODE
, A5PSW_VLAN_IN_MODE_PORT(port
),
913 /* Set transparent mode for output frame manipulation, this will depend
914 * on the VLAN_RES configuration mode
916 reg
= A5PSW_VLAN_OUT_MODE_TRANSPARENT
;
917 reg
<<= A5PSW_VLAN_OUT_MODE_PORT_SHIFT(port
);
918 a5psw_reg_rmw(a5psw
, A5PSW_VLAN_OUT_MODE
,
919 A5PSW_VLAN_OUT_MODE_PORT(port
), reg
);
922 static int a5psw_setup(struct dsa_switch
*ds
)
924 struct a5psw
*a5psw
= ds
->priv
;
929 /* Validate that there is only 1 CPU port with index A5PSW_CPU_PORT */
930 dsa_switch_for_each_cpu_port(dp
, ds
) {
931 if (dp
->index
!= A5PSW_CPU_PORT
) {
932 dev_err(a5psw
->dev
, "Invalid CPU port\n");
937 /* Configure management port */
938 reg
= A5PSW_CPU_PORT
| A5PSW_MGMT_CFG_ENABLE
;
939 a5psw_reg_writel(a5psw
, A5PSW_MGMT_CFG
, reg
);
941 /* Set pattern 0 to forward all frame to mgmt port */
942 a5psw_reg_writel(a5psw
, A5PSW_PATTERN_CTRL(A5PSW_PATTERN_MGMTFWD
),
943 A5PSW_PATTERN_CTRL_MGMTFWD
);
945 /* Enable port tagging */
946 reg
= FIELD_PREP(A5PSW_MGMT_TAG_CFG_TAGFIELD
, ETH_P_DSA_A5PSW
);
947 reg
|= A5PSW_MGMT_TAG_CFG_ENABLE
| A5PSW_MGMT_TAG_CFG_ALL_FRAMES
;
948 a5psw_reg_writel(a5psw
, A5PSW_MGMT_TAG_CFG
, reg
);
950 /* Enable normal switch operation */
951 reg
= A5PSW_LK_ADDR_CTRL_BLOCKING
| A5PSW_LK_ADDR_CTRL_LEARNING
|
952 A5PSW_LK_ADDR_CTRL_AGEING
| A5PSW_LK_ADDR_CTRL_ALLOW_MIGR
|
953 A5PSW_LK_ADDR_CTRL_CLEAR_TABLE
;
954 a5psw_reg_writel(a5psw
, A5PSW_LK_CTRL
, reg
);
956 ret
= readl_poll_timeout(a5psw
->base
+ A5PSW_LK_CTRL
, reg
,
957 !(reg
& A5PSW_LK_ADDR_CTRL_CLEAR_TABLE
),
958 A5PSW_LK_BUSY_USEC_POLL
, A5PSW_CTRL_TIMEOUT
);
960 dev_err(a5psw
->dev
, "Failed to clear lookup table\n");
964 /* Reset learn count to 0 */
965 reg
= A5PSW_LK_LEARNCOUNT_MODE_SET
;
966 a5psw_reg_writel(a5psw
, A5PSW_LK_LEARNCOUNT
, reg
);
968 /* Clear VLAN resource table */
969 reg
= A5PSW_VLAN_RES_WR_PORTMASK
| A5PSW_VLAN_RES_WR_TAGMASK
;
970 for (vlan
= 0; vlan
< A5PSW_VLAN_COUNT
; vlan
++)
971 a5psw_reg_writel(a5psw
, A5PSW_VLAN_RES(vlan
), reg
);
973 /* Reset all ports */
974 dsa_switch_for_each_port(dp
, ds
) {
978 a5psw_reg_writel(a5psw
, A5PSW_CMD_CFG(port
),
979 A5PSW_CMD_CFG_SW_RESET
);
981 /* Enable only CPU port */
982 a5psw_port_enable_set(a5psw
, port
, dsa_port_is_cpu(dp
));
984 if (dsa_port_is_unused(dp
))
987 /* Enable egress flooding and learning for CPU port */
988 if (dsa_port_is_cpu(dp
)) {
989 a5psw_flooding_set_resolution(a5psw
, port
, true);
990 a5psw_port_learning_set(a5psw
, port
, true);
993 /* Enable standalone mode for user ports */
994 if (dsa_port_is_user(dp
))
995 a5psw_port_set_standalone(a5psw
, port
, true);
997 a5psw_vlan_setup(a5psw
, port
);
1003 static const struct phylink_mac_ops a5psw_phylink_mac_ops
= {
1004 .mac_select_pcs
= a5psw_phylink_mac_select_pcs
,
1005 .mac_config
= a5psw_phylink_mac_config
,
1006 .mac_link_down
= a5psw_phylink_mac_link_down
,
1007 .mac_link_up
= a5psw_phylink_mac_link_up
,
1010 static const struct dsa_switch_ops a5psw_switch_ops
= {
1011 .get_tag_protocol
= a5psw_get_tag_protocol
,
1012 .setup
= a5psw_setup
,
1013 .port_disable
= a5psw_port_disable
,
1014 .port_enable
= a5psw_port_enable
,
1015 .phylink_get_caps
= a5psw_phylink_get_caps
,
1016 .port_change_mtu
= a5psw_port_change_mtu
,
1017 .port_max_mtu
= a5psw_port_max_mtu
,
1018 .get_sset_count
= a5psw_get_sset_count
,
1019 .get_strings
= a5psw_get_strings
,
1020 .get_ethtool_stats
= a5psw_get_ethtool_stats
,
1021 .get_eth_mac_stats
= a5psw_get_eth_mac_stats
,
1022 .get_eth_ctrl_stats
= a5psw_get_eth_ctrl_stats
,
1023 .get_rmon_stats
= a5psw_get_rmon_stats
,
1024 .set_ageing_time
= a5psw_set_ageing_time
,
1025 .port_bridge_join
= a5psw_port_bridge_join
,
1026 .port_bridge_leave
= a5psw_port_bridge_leave
,
1027 .port_pre_bridge_flags
= a5psw_port_pre_bridge_flags
,
1028 .port_bridge_flags
= a5psw_port_bridge_flags
,
1029 .port_stp_state_set
= a5psw_port_stp_state_set
,
1030 .port_fast_age
= a5psw_port_fast_age
,
1031 .port_vlan_filtering
= a5psw_port_vlan_filtering
,
1032 .port_vlan_add
= a5psw_port_vlan_add
,
1033 .port_vlan_del
= a5psw_port_vlan_del
,
1034 .port_fdb_add
= a5psw_port_fdb_add
,
1035 .port_fdb_del
= a5psw_port_fdb_del
,
1036 .port_fdb_dump
= a5psw_port_fdb_dump
,
1039 static int a5psw_mdio_wait_busy(struct a5psw
*a5psw
)
1044 err
= readl_poll_timeout(a5psw
->base
+ A5PSW_MDIO_CFG_STATUS
, status
,
1045 !(status
& A5PSW_MDIO_CFG_STATUS_BUSY
), 10,
1046 1000 * USEC_PER_MSEC
);
1048 dev_err(a5psw
->dev
, "MDIO command timeout\n");
1053 static int a5psw_mdio_read(struct mii_bus
*bus
, int phy_id
, int phy_reg
)
1055 struct a5psw
*a5psw
= bus
->priv
;
1059 cmd
= A5PSW_MDIO_COMMAND_READ
;
1060 cmd
|= FIELD_PREP(A5PSW_MDIO_COMMAND_REG_ADDR
, phy_reg
);
1061 cmd
|= FIELD_PREP(A5PSW_MDIO_COMMAND_PHY_ADDR
, phy_id
);
1063 a5psw_reg_writel(a5psw
, A5PSW_MDIO_COMMAND
, cmd
);
1065 ret
= a5psw_mdio_wait_busy(a5psw
);
1069 ret
= a5psw_reg_readl(a5psw
, A5PSW_MDIO_DATA
) & A5PSW_MDIO_DATA_MASK
;
1071 status
= a5psw_reg_readl(a5psw
, A5PSW_MDIO_CFG_STATUS
);
1072 if (status
& A5PSW_MDIO_CFG_STATUS_READERR
)
1078 static int a5psw_mdio_write(struct mii_bus
*bus
, int phy_id
, int phy_reg
,
1081 struct a5psw
*a5psw
= bus
->priv
;
1084 cmd
= FIELD_PREP(A5PSW_MDIO_COMMAND_REG_ADDR
, phy_reg
);
1085 cmd
|= FIELD_PREP(A5PSW_MDIO_COMMAND_PHY_ADDR
, phy_id
);
1087 a5psw_reg_writel(a5psw
, A5PSW_MDIO_COMMAND
, cmd
);
1088 a5psw_reg_writel(a5psw
, A5PSW_MDIO_DATA
, phy_data
);
1090 return a5psw_mdio_wait_busy(a5psw
);
1093 static int a5psw_mdio_config(struct a5psw
*a5psw
, u32 mdio_freq
)
1099 rate
= clk_get_rate(a5psw
->hclk
);
1100 div
= ((rate
/ mdio_freq
) / 2);
1101 if (div
> FIELD_MAX(A5PSW_MDIO_CFG_STATUS_CLKDIV
) ||
1102 div
< A5PSW_MDIO_CLK_DIV_MIN
) {
1103 dev_err(a5psw
->dev
, "MDIO clock div %ld out of range\n", div
);
1107 cfgstatus
= FIELD_PREP(A5PSW_MDIO_CFG_STATUS_CLKDIV
, div
);
1109 a5psw_reg_writel(a5psw
, A5PSW_MDIO_CFG_STATUS
, cfgstatus
);
1114 static int a5psw_probe_mdio(struct a5psw
*a5psw
, struct device_node
*node
)
1116 struct device
*dev
= a5psw
->dev
;
1117 struct mii_bus
*bus
;
1121 if (of_property_read_u32(node
, "clock-frequency", &mdio_freq
))
1122 mdio_freq
= A5PSW_MDIO_DEF_FREQ
;
1124 ret
= a5psw_mdio_config(a5psw
, mdio_freq
);
1128 bus
= devm_mdiobus_alloc(dev
);
1132 bus
->name
= "a5psw_mdio";
1133 bus
->read
= a5psw_mdio_read
;
1134 bus
->write
= a5psw_mdio_write
;
1137 snprintf(bus
->id
, MII_BUS_ID_SIZE
, "%s", dev_name(dev
));
1139 a5psw
->mii_bus
= bus
;
1141 return devm_of_mdiobus_register(dev
, bus
, node
);
1144 static void a5psw_pcs_free(struct a5psw
*a5psw
)
1148 for (i
= 0; i
< ARRAY_SIZE(a5psw
->pcs
); i
++) {
1150 miic_destroy(a5psw
->pcs
[i
]);
1154 static int a5psw_pcs_get(struct a5psw
*a5psw
)
1156 struct device_node
*ports
, *port
, *pcs_node
;
1157 struct phylink_pcs
*pcs
;
1161 ports
= of_get_child_by_name(a5psw
->dev
->of_node
, "ethernet-ports");
1165 for_each_available_child_of_node(ports
, port
) {
1166 pcs_node
= of_parse_phandle(port
, "pcs-handle", 0);
1170 if (of_property_read_u32(port
, "reg", ®
)) {
1175 if (reg
>= ARRAY_SIZE(a5psw
->pcs
)) {
1180 pcs
= miic_create(a5psw
->dev
, pcs_node
);
1182 dev_err(a5psw
->dev
, "Failed to create PCS for port %d\n",
1188 a5psw
->pcs
[reg
] = pcs
;
1189 of_node_put(pcs_node
);
1196 of_node_put(pcs_node
);
1199 a5psw_pcs_free(a5psw
);
1204 static int a5psw_probe(struct platform_device
*pdev
)
1206 struct device
*dev
= &pdev
->dev
;
1207 struct device_node
*mdio
;
1208 struct dsa_switch
*ds
;
1209 struct a5psw
*a5psw
;
1212 a5psw
= devm_kzalloc(dev
, sizeof(*a5psw
), GFP_KERNEL
);
1217 mutex_init(&a5psw
->lk_lock
);
1218 spin_lock_init(&a5psw
->reg_lock
);
1219 a5psw
->base
= devm_platform_ioremap_resource(pdev
, 0);
1220 if (IS_ERR(a5psw
->base
))
1221 return PTR_ERR(a5psw
->base
);
1223 a5psw
->bridged_ports
= BIT(A5PSW_CPU_PORT
);
1225 ret
= a5psw_pcs_get(a5psw
);
1229 a5psw
->hclk
= devm_clk_get(dev
, "hclk");
1230 if (IS_ERR(a5psw
->hclk
)) {
1231 dev_err(dev
, "failed get hclk clock\n");
1232 ret
= PTR_ERR(a5psw
->hclk
);
1236 a5psw
->clk
= devm_clk_get(dev
, "clk");
1237 if (IS_ERR(a5psw
->clk
)) {
1238 dev_err(dev
, "failed get clk_switch clock\n");
1239 ret
= PTR_ERR(a5psw
->clk
);
1243 ret
= clk_prepare_enable(a5psw
->clk
);
1247 ret
= clk_prepare_enable(a5psw
->hclk
);
1251 mdio
= of_get_child_by_name(dev
->of_node
, "mdio");
1252 if (of_device_is_available(mdio
)) {
1253 ret
= a5psw_probe_mdio(a5psw
, mdio
);
1256 dev_err(dev
, "Failed to register MDIO: %d\n", ret
);
1265 ds
->num_ports
= A5PSW_PORTS_NUM
;
1266 ds
->ops
= &a5psw_switch_ops
;
1267 ds
->phylink_mac_ops
= &a5psw_phylink_mac_ops
;
1270 ret
= dsa_register_switch(ds
);
1272 dev_err(dev
, "Failed to register DSA switch: %d\n", ret
);
1279 clk_disable_unprepare(a5psw
->hclk
);
1281 clk_disable_unprepare(a5psw
->clk
);
1283 a5psw_pcs_free(a5psw
);
1288 static void a5psw_remove(struct platform_device
*pdev
)
1290 struct a5psw
*a5psw
= platform_get_drvdata(pdev
);
1295 dsa_unregister_switch(&a5psw
->ds
);
1296 a5psw_pcs_free(a5psw
);
1297 clk_disable_unprepare(a5psw
->hclk
);
1298 clk_disable_unprepare(a5psw
->clk
);
1301 static void a5psw_shutdown(struct platform_device
*pdev
)
1303 struct a5psw
*a5psw
= platform_get_drvdata(pdev
);
1308 dsa_switch_shutdown(&a5psw
->ds
);
1310 platform_set_drvdata(pdev
, NULL
);
1313 static const struct of_device_id a5psw_of_mtable
[] = {
1314 { .compatible
= "renesas,rzn1-a5psw", },
1317 MODULE_DEVICE_TABLE(of
, a5psw_of_mtable
);
1319 static struct platform_driver a5psw_driver
= {
1321 .name
= "rzn1_a5psw",
1322 .of_match_table
= a5psw_of_mtable
,
1324 .probe
= a5psw_probe
,
1325 .remove
= a5psw_remove
,
1326 .shutdown
= a5psw_shutdown
,
1328 module_platform_driver(a5psw_driver
);
1330 MODULE_LICENSE("GPL");
1331 MODULE_DESCRIPTION("Renesas RZ/N1 Advanced 5-port Switch driver");
1332 MODULE_AUTHOR("Clément Léger <clement.leger@bootlin.com>");