1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2022 Schneider-Electric
4 *
5 * Clément Léger <clement.leger@bootlin.com>
6 */
7
8 #include <linux/clk.h>
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>
14 #include <linux/of.h>
15 #include <linux/of_mdio.h>
16 #include <net/dsa.h>
17
18 #include "rzn1_a5psw.h"
19
20 struct a5psw_stats {
21 u16 offset;
22 const char name[ETH_GSTRING_LEN];
23 };
24
25 #define STAT_DESC(_offset) { \
26 .offset = A5PSW_##_offset, \
27 .name = __stringify(_offset), \
28 }
29
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),
63 STAT_DESC(aDeferred),
64 STAT_DESC(aMultipleCollisions),
65 STAT_DESC(aSingleCollisions),
66 STAT_DESC(aLateCollisions),
67 STAT_DESC(aExcessiveCollisions),
68 STAT_DESC(aCarrierSenseErrors),
69 };
70
a5psw_reg_writel(struct a5psw * a5psw,int offset,u32 value)71 static void a5psw_reg_writel(struct a5psw *a5psw, int offset, u32 value)
72 {
73 writel(value, a5psw->base + offset);
74 }
75
a5psw_reg_readl(struct a5psw * a5psw,int offset)76 static u32 a5psw_reg_readl(struct a5psw *a5psw, int offset)
77 {
78 return readl(a5psw->base + offset);
79 }
80
a5psw_reg_rmw(struct a5psw * a5psw,int offset,u32 mask,u32 val)81 static void a5psw_reg_rmw(struct a5psw *a5psw, int offset, u32 mask, u32 val)
82 {
83 u32 reg;
84
85 spin_lock(&a5psw->reg_lock);
86
87 reg = a5psw_reg_readl(a5psw, offset);
88 reg &= ~mask;
89 reg |= val;
90 a5psw_reg_writel(a5psw, offset, reg);
91
92 spin_unlock(&a5psw->reg_lock);
93 }
94
a5psw_get_tag_protocol(struct dsa_switch * ds,int port,enum dsa_tag_protocol mp)95 static enum dsa_tag_protocol a5psw_get_tag_protocol(struct dsa_switch *ds,
96 int port,
97 enum dsa_tag_protocol mp)
98 {
99 return DSA_TAG_PROTO_RZN1_A5PSW;
100 }
101
a5psw_port_pattern_set(struct a5psw * a5psw,int port,int pattern,bool enable)102 static void a5psw_port_pattern_set(struct a5psw *a5psw, int port, int pattern,
103 bool enable)
104 {
105 u32 rx_match = 0;
106
107 if (enable)
108 rx_match |= A5PSW_RXMATCH_CONFIG_PATTERN(pattern);
109
110 a5psw_reg_rmw(a5psw, A5PSW_RXMATCH_CONFIG(port),
111 A5PSW_RXMATCH_CONFIG_PATTERN(pattern), rx_match);
112 }
113
a5psw_port_mgmtfwd_set(struct a5psw * a5psw,int port,bool enable)114 static void a5psw_port_mgmtfwd_set(struct a5psw *a5psw, int port, bool enable)
115 {
116 /* Enable "management forward" pattern matching, this will forward
117 * packets from this port only towards the management port and thus
118 * isolate the port.
119 */
120 a5psw_port_pattern_set(a5psw, port, A5PSW_PATTERN_MGMTFWD, enable);
121 }
122
a5psw_port_tx_enable(struct a5psw * a5psw,int port,bool enable)123 static void a5psw_port_tx_enable(struct a5psw *a5psw, int port, bool enable)
124 {
125 u32 mask = A5PSW_PORT_ENA_TX(port);
126 u32 reg = enable ? mask : 0;
127
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.
135 */
136 a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, mask, reg);
137 }
138
a5psw_port_enable_set(struct a5psw * a5psw,int port,bool enable)139 static void a5psw_port_enable_set(struct a5psw *a5psw, int port, bool enable)
140 {
141 u32 port_ena = 0;
142
143 if (enable)
144 port_ena |= A5PSW_PORT_ENA_TX_RX(port);
145
146 a5psw_reg_rmw(a5psw, A5PSW_PORT_ENA, A5PSW_PORT_ENA_TX_RX(port),
147 port_ena);
148 }
149
a5psw_lk_execute_ctrl(struct a5psw * a5psw,u32 * ctrl)150 static int a5psw_lk_execute_ctrl(struct a5psw *a5psw, u32 *ctrl)
151 {
152 int ret;
153
154 a5psw_reg_writel(a5psw, A5PSW_LK_ADDR_CTRL, *ctrl);
155
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);
159 if (ret)
160 dev_err(a5psw->dev, "LK_CTRL timeout waiting for BUSY bit\n");
161
162 return ret;
163 }
164
a5psw_port_fdb_flush(struct a5psw * a5psw,int port)165 static void a5psw_port_fdb_flush(struct a5psw *a5psw, int port)
166 {
167 u32 ctrl = A5PSW_LK_ADDR_CTRL_DELETE_PORT | BIT(port);
168
169 mutex_lock(&a5psw->lk_lock);
170 a5psw_lk_execute_ctrl(a5psw, &ctrl);
171 mutex_unlock(&a5psw->lk_lock);
172 }
173
a5psw_port_authorize_set(struct a5psw * a5psw,int port,bool authorize)174 static void a5psw_port_authorize_set(struct a5psw *a5psw, int port,
175 bool authorize)
176 {
177 u32 reg = a5psw_reg_readl(a5psw, A5PSW_AUTH_PORT(port));
178
179 if (authorize)
180 reg |= A5PSW_AUTH_PORT_AUTHORIZED;
181 else
182 reg &= ~A5PSW_AUTH_PORT_AUTHORIZED;
183
184 a5psw_reg_writel(a5psw, A5PSW_AUTH_PORT(port), reg);
185 }
186
a5psw_port_disable(struct dsa_switch * ds,int port)187 static void a5psw_port_disable(struct dsa_switch *ds, int port)
188 {
189 struct a5psw *a5psw = ds->priv;
190
191 a5psw_port_authorize_set(a5psw, port, false);
192 a5psw_port_enable_set(a5psw, port, false);
193 }
194
a5psw_port_enable(struct dsa_switch * ds,int port,struct phy_device * phy)195 static int a5psw_port_enable(struct dsa_switch *ds, int port,
196 struct phy_device *phy)
197 {
198 struct a5psw *a5psw = ds->priv;
199
200 a5psw_port_authorize_set(a5psw, port, true);
201 a5psw_port_enable_set(a5psw, port, true);
202
203 return 0;
204 }
205
a5psw_port_change_mtu(struct dsa_switch * ds,int port,int new_mtu)206 static int a5psw_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
207 {
208 struct a5psw *a5psw = ds->priv;
209
210 new_mtu += ETH_HLEN + A5PSW_EXTRA_MTU_LEN + ETH_FCS_LEN;
211 a5psw_reg_writel(a5psw, A5PSW_FRM_LENGTH(port), new_mtu);
212
213 return 0;
214 }
215
a5psw_port_max_mtu(struct dsa_switch * ds,int port)216 static int a5psw_port_max_mtu(struct dsa_switch *ds, int port)
217 {
218 return A5PSW_MAX_MTU;
219 }
220
a5psw_phylink_get_caps(struct dsa_switch * ds,int port,struct phylink_config * config)221 static void a5psw_phylink_get_caps(struct dsa_switch *ds, int port,
222 struct phylink_config *config)
223 {
224 unsigned long *intf = config->supported_interfaces;
225
226 config->mac_capabilities = MAC_1000FD;
227
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)
231 */
232 __set_bit(PHY_INTERFACE_MODE_GMII, intf);
233 } else {
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);
238 }
239 }
240
241 static struct phylink_pcs *
a5psw_phylink_mac_select_pcs(struct phylink_config * config,phy_interface_t interface)242 a5psw_phylink_mac_select_pcs(struct phylink_config *config,
243 phy_interface_t interface)
244 {
245 struct dsa_port *dp = dsa_phylink_to_port(config);
246 struct a5psw *a5psw = dp->ds->priv;
247
248 if (dsa_port_is_cpu(dp))
249 return NULL;
250
251 return a5psw->pcs[dp->index];
252 }
253
a5psw_phylink_mac_config(struct phylink_config * config,unsigned int mode,const struct phylink_link_state * state)254 static void a5psw_phylink_mac_config(struct phylink_config *config,
255 unsigned int mode,
256 const struct phylink_link_state *state)
257 {
258 }
259
a5psw_phylink_mac_link_down(struct phylink_config * config,unsigned int mode,phy_interface_t interface)260 static void a5psw_phylink_mac_link_down(struct phylink_config *config,
261 unsigned int mode,
262 phy_interface_t interface)
263 {
264 struct dsa_port *dp = dsa_phylink_to_port(config);
265 struct a5psw *a5psw = dp->ds->priv;
266 int port = dp->index;
267 u32 cmd_cfg;
268
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);
272 }
273
a5psw_phylink_mac_link_up(struct phylink_config * config,struct phy_device * phydev,unsigned int mode,phy_interface_t interface,int speed,int duplex,bool tx_pause,bool rx_pause)274 static void a5psw_phylink_mac_link_up(struct phylink_config *config,
275 struct phy_device *phydev,
276 unsigned int mode,
277 phy_interface_t interface,
278 int speed, int duplex, bool tx_pause,
279 bool rx_pause)
280 {
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;
285
286 if (speed == SPEED_1000)
287 cmd_cfg |= A5PSW_CMD_CFG_ETH_SPEED;
288
289 if (duplex == DUPLEX_HALF)
290 cmd_cfg |= A5PSW_CMD_CFG_HD_ENA;
291
292 cmd_cfg |= A5PSW_CMD_CFG_CNTL_FRM_ENA;
293
294 if (!rx_pause)
295 cmd_cfg &= ~A5PSW_CMD_CFG_PAUSE_IGNORE;
296
297 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(dp->index), cmd_cfg);
298 }
299
a5psw_set_ageing_time(struct dsa_switch * ds,unsigned int msecs)300 static int a5psw_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
301 {
302 struct a5psw *a5psw = ds->priv;
303 unsigned long rate;
304 u64 max, tmp;
305 u32 agetime;
306
307 rate = clk_get_rate(a5psw->clk);
308 max = div64_ul(((u64)A5PSW_LK_AGETIME_MASK * A5PSW_TABLE_ENTRIES * 1024),
309 rate) * 1000;
310 if (msecs > max)
311 return -EINVAL;
312
313 tmp = div_u64(rate, MSEC_PER_SEC);
314 agetime = div_u64(msecs * tmp, 1024 * A5PSW_TABLE_ENTRIES);
315
316 a5psw_reg_writel(a5psw, A5PSW_LK_AGETIME, agetime);
317
318 return 0;
319 }
320
a5psw_port_learning_set(struct a5psw * a5psw,int port,bool learn)321 static void a5psw_port_learning_set(struct a5psw *a5psw, int port, bool learn)
322 {
323 u32 mask = A5PSW_INPUT_LEARN_DIS(port);
324 u32 reg = !learn ? mask : 0;
325
326 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
327 }
328
a5psw_port_rx_block_set(struct a5psw * a5psw,int port,bool block)329 static void a5psw_port_rx_block_set(struct a5psw *a5psw, int port, bool block)
330 {
331 u32 mask = A5PSW_INPUT_LEARN_BLOCK(port);
332 u32 reg = block ? mask : 0;
333
334 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN, mask, reg);
335 }
336
a5psw_flooding_set_resolution(struct a5psw * a5psw,int port,bool set)337 static void a5psw_flooding_set_resolution(struct a5psw *a5psw, int port,
338 bool set)
339 {
340 static const u8 offsets[] = {
341 A5PSW_UCAST_DEF_MASK, A5PSW_BCAST_DEF_MASK, A5PSW_MCAST_DEF_MASK
342 };
343 int i;
344
345 for (i = 0; i < ARRAY_SIZE(offsets); i++)
346 a5psw_reg_rmw(a5psw, offsets[i], BIT(port),
347 set ? BIT(port) : 0);
348 }
349
a5psw_port_set_standalone(struct a5psw * a5psw,int port,bool standalone)350 static void a5psw_port_set_standalone(struct a5psw *a5psw, int port,
351 bool standalone)
352 {
353 a5psw_port_learning_set(a5psw, port, !standalone);
354 a5psw_flooding_set_resolution(a5psw, port, !standalone);
355 a5psw_port_mgmtfwd_set(a5psw, port, standalone);
356 }
357
a5psw_port_bridge_join(struct dsa_switch * ds,int port,struct dsa_bridge bridge,bool * tx_fwd_offload,struct netlink_ext_ack * extack)358 static int a5psw_port_bridge_join(struct dsa_switch *ds, int port,
359 struct dsa_bridge bridge,
360 bool *tx_fwd_offload,
361 struct netlink_ext_ack *extack)
362 {
363 struct a5psw *a5psw = ds->priv;
364
365 /* We only support 1 bridge device */
366 if (a5psw->br_dev && bridge.dev != a5psw->br_dev) {
367 NL_SET_ERR_MSG_MOD(extack,
368 "Forwarding offload supported for a single bridge");
369 return -EOPNOTSUPP;
370 }
371
372 a5psw->br_dev = bridge.dev;
373 a5psw_port_set_standalone(a5psw, port, false);
374
375 a5psw->bridged_ports |= BIT(port);
376
377 return 0;
378 }
379
a5psw_port_bridge_leave(struct dsa_switch * ds,int port,struct dsa_bridge bridge)380 static void a5psw_port_bridge_leave(struct dsa_switch *ds, int port,
381 struct dsa_bridge bridge)
382 {
383 struct a5psw *a5psw = ds->priv;
384
385 a5psw->bridged_ports &= ~BIT(port);
386
387 a5psw_port_set_standalone(a5psw, port, true);
388
389 /* No more ports bridged */
390 if (a5psw->bridged_ports == BIT(A5PSW_CPU_PORT))
391 a5psw->br_dev = NULL;
392 }
393
a5psw_port_pre_bridge_flags(struct dsa_switch * ds,int port,struct switchdev_brport_flags flags,struct netlink_ext_ack * extack)394 static int a5psw_port_pre_bridge_flags(struct dsa_switch *ds, int port,
395 struct switchdev_brport_flags flags,
396 struct netlink_ext_ack *extack)
397 {
398 if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD |
399 BR_BCAST_FLOOD))
400 return -EINVAL;
401
402 return 0;
403 }
404
405 static int
a5psw_port_bridge_flags(struct dsa_switch * ds,int port,struct switchdev_brport_flags flags,struct netlink_ext_ack * extack)406 a5psw_port_bridge_flags(struct dsa_switch *ds, int port,
407 struct switchdev_brport_flags flags,
408 struct netlink_ext_ack *extack)
409 {
410 struct a5psw *a5psw = ds->priv;
411 u32 val;
412
413 /* If a port is set as standalone, we do not want to be able to
414 * configure flooding nor learning which would result in joining the
415 * unique bridge. This can happen when a port leaves the bridge, in
416 * which case the DSA core will try to "clear" all flags for the
417 * standalone port (ie enable flooding, disable learning). In that case
418 * do not fail but do not apply the flags.
419 */
420 if (!(a5psw->bridged_ports & BIT(port)))
421 return 0;
422
423 if (flags.mask & BR_LEARNING) {
424 val = flags.val & BR_LEARNING ? 0 : A5PSW_INPUT_LEARN_DIS(port);
425 a5psw_reg_rmw(a5psw, A5PSW_INPUT_LEARN,
426 A5PSW_INPUT_LEARN_DIS(port), val);
427 }
428
429 if (flags.mask & BR_FLOOD) {
430 val = flags.val & BR_FLOOD ? BIT(port) : 0;
431 a5psw_reg_rmw(a5psw, A5PSW_UCAST_DEF_MASK, BIT(port), val);
432 }
433
434 if (flags.mask & BR_MCAST_FLOOD) {
435 val = flags.val & BR_MCAST_FLOOD ? BIT(port) : 0;
436 a5psw_reg_rmw(a5psw, A5PSW_MCAST_DEF_MASK, BIT(port), val);
437 }
438
439 if (flags.mask & BR_BCAST_FLOOD) {
440 val = flags.val & BR_BCAST_FLOOD ? BIT(port) : 0;
441 a5psw_reg_rmw(a5psw, A5PSW_BCAST_DEF_MASK, BIT(port), val);
442 }
443
444 return 0;
445 }
446
a5psw_port_stp_state_set(struct dsa_switch * ds,int port,u8 state)447 static void a5psw_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
448 {
449 bool learning_enabled, rx_enabled, tx_enabled;
450 struct dsa_port *dp = dsa_to_port(ds, port);
451 struct a5psw *a5psw = ds->priv;
452
453 switch (state) {
454 case BR_STATE_DISABLED:
455 case BR_STATE_BLOCKING:
456 case BR_STATE_LISTENING:
457 rx_enabled = false;
458 tx_enabled = false;
459 learning_enabled = false;
460 break;
461 case BR_STATE_LEARNING:
462 rx_enabled = false;
463 tx_enabled = false;
464 learning_enabled = dp->learning;
465 break;
466 case BR_STATE_FORWARDING:
467 rx_enabled = true;
468 tx_enabled = true;
469 learning_enabled = dp->learning;
470 break;
471 default:
472 dev_err(ds->dev, "invalid STP state: %d\n", state);
473 return;
474 }
475
476 a5psw_port_learning_set(a5psw, port, learning_enabled);
477 a5psw_port_rx_block_set(a5psw, port, !rx_enabled);
478 a5psw_port_tx_enable(a5psw, port, tx_enabled);
479 }
480
a5psw_port_fast_age(struct dsa_switch * ds,int port)481 static void a5psw_port_fast_age(struct dsa_switch *ds, int port)
482 {
483 struct a5psw *a5psw = ds->priv;
484
485 a5psw_port_fdb_flush(a5psw, port);
486 }
487
a5psw_lk_execute_lookup(struct a5psw * a5psw,union lk_data * lk_data,u16 * entry)488 static int a5psw_lk_execute_lookup(struct a5psw *a5psw, union lk_data *lk_data,
489 u16 *entry)
490 {
491 u32 ctrl;
492 int ret;
493
494 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_LO, lk_data->lo);
495 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data->hi);
496
497 ctrl = A5PSW_LK_ADDR_CTRL_LOOKUP;
498 ret = a5psw_lk_execute_ctrl(a5psw, &ctrl);
499 if (ret)
500 return ret;
501
502 *entry = ctrl & A5PSW_LK_ADDR_CTRL_ADDRESS;
503
504 return 0;
505 }
506
a5psw_port_fdb_add(struct dsa_switch * ds,int port,const unsigned char * addr,u16 vid,struct dsa_db db)507 static int a5psw_port_fdb_add(struct dsa_switch *ds, int port,
508 const unsigned char *addr, u16 vid,
509 struct dsa_db db)
510 {
511 struct a5psw *a5psw = ds->priv;
512 union lk_data lk_data = {0};
513 bool inc_learncount = false;
514 int ret = 0;
515 u16 entry;
516 u32 reg;
517
518 ether_addr_copy(lk_data.entry.mac, addr);
519 lk_data.entry.port_mask = BIT(port);
520
521 mutex_lock(&a5psw->lk_lock);
522
523 /* Set the value to be written in the lookup table */
524 ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry);
525 if (ret)
526 goto lk_unlock;
527
528 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI);
529 if (!lk_data.entry.valid) {
530 inc_learncount = true;
531 /* port_mask set to 0x1f when entry is not valid, clear it */
532 lk_data.entry.port_mask = 0;
533 lk_data.entry.prio = 0;
534 }
535
536 lk_data.entry.port_mask |= BIT(port);
537 lk_data.entry.is_static = 1;
538 lk_data.entry.valid = 1;
539
540 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi);
541
542 reg = A5PSW_LK_ADDR_CTRL_WRITE | entry;
543 ret = a5psw_lk_execute_ctrl(a5psw, ®);
544 if (ret)
545 goto lk_unlock;
546
547 if (inc_learncount) {
548 reg = A5PSW_LK_LEARNCOUNT_MODE_INC;
549 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg);
550 }
551
552 lk_unlock:
553 mutex_unlock(&a5psw->lk_lock);
554
555 return ret;
556 }
557
a5psw_port_fdb_del(struct dsa_switch * ds,int port,const unsigned char * addr,u16 vid,struct dsa_db db)558 static int a5psw_port_fdb_del(struct dsa_switch *ds, int port,
559 const unsigned char *addr, u16 vid,
560 struct dsa_db db)
561 {
562 struct a5psw *a5psw = ds->priv;
563 union lk_data lk_data = {0};
564 bool clear = false;
565 u16 entry;
566 u32 reg;
567 int ret;
568
569 ether_addr_copy(lk_data.entry.mac, addr);
570
571 mutex_lock(&a5psw->lk_lock);
572
573 ret = a5psw_lk_execute_lookup(a5psw, &lk_data, &entry);
574 if (ret)
575 goto lk_unlock;
576
577 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI);
578
579 /* Our hardware does not associate any VID to the FDB entries so this
580 * means that if two entries were added for the same mac but for
581 * different VID, then, on the deletion of the first one, we would also
582 * delete the second one. Since there is unfortunately nothing we can do
583 * about that, do not return an error...
584 */
585 if (!lk_data.entry.valid)
586 goto lk_unlock;
587
588 lk_data.entry.port_mask &= ~BIT(port);
589 /* If there is no more port in the mask, clear the entry */
590 if (lk_data.entry.port_mask == 0)
591 clear = true;
592
593 a5psw_reg_writel(a5psw, A5PSW_LK_DATA_HI, lk_data.hi);
594
595 reg = entry;
596 if (clear)
597 reg |= A5PSW_LK_ADDR_CTRL_CLEAR;
598 else
599 reg |= A5PSW_LK_ADDR_CTRL_WRITE;
600
601 ret = a5psw_lk_execute_ctrl(a5psw, ®);
602 if (ret)
603 goto lk_unlock;
604
605 /* Decrement LEARNCOUNT */
606 if (clear) {
607 reg = A5PSW_LK_LEARNCOUNT_MODE_DEC;
608 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg);
609 }
610
611 lk_unlock:
612 mutex_unlock(&a5psw->lk_lock);
613
614 return ret;
615 }
616
a5psw_port_fdb_dump(struct dsa_switch * ds,int port,dsa_fdb_dump_cb_t * cb,void * data)617 static int a5psw_port_fdb_dump(struct dsa_switch *ds, int port,
618 dsa_fdb_dump_cb_t *cb, void *data)
619 {
620 struct a5psw *a5psw = ds->priv;
621 union lk_data lk_data;
622 int i = 0, ret = 0;
623 u32 reg;
624
625 mutex_lock(&a5psw->lk_lock);
626
627 for (i = 0; i < A5PSW_TABLE_ENTRIES; i++) {
628 reg = A5PSW_LK_ADDR_CTRL_READ | A5PSW_LK_ADDR_CTRL_WAIT | i;
629
630 ret = a5psw_lk_execute_ctrl(a5psw, ®);
631 if (ret)
632 goto out_unlock;
633
634 lk_data.hi = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_HI);
635 /* If entry is not valid or does not contain the port, skip */
636 if (!lk_data.entry.valid ||
637 !(lk_data.entry.port_mask & BIT(port)))
638 continue;
639
640 lk_data.lo = a5psw_reg_readl(a5psw, A5PSW_LK_DATA_LO);
641
642 ret = cb(lk_data.entry.mac, 0, lk_data.entry.is_static, data);
643 if (ret)
644 goto out_unlock;
645 }
646
647 out_unlock:
648 mutex_unlock(&a5psw->lk_lock);
649
650 return ret;
651 }
652
a5psw_port_vlan_filtering(struct dsa_switch * ds,int port,bool vlan_filtering,struct netlink_ext_ack * extack)653 static int a5psw_port_vlan_filtering(struct dsa_switch *ds, int port,
654 bool vlan_filtering,
655 struct netlink_ext_ack *extack)
656 {
657 u32 mask = BIT(port + A5PSW_VLAN_VERI_SHIFT) |
658 BIT(port + A5PSW_VLAN_DISC_SHIFT);
659 u32 val = vlan_filtering ? mask : 0;
660 struct a5psw *a5psw = ds->priv;
661
662 /* Disable/enable vlan tagging */
663 a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE_ENA, BIT(port),
664 vlan_filtering ? BIT(port) : 0);
665
666 /* Disable/enable vlan input filtering */
667 a5psw_reg_rmw(a5psw, A5PSW_VLAN_VERIFY, mask, val);
668
669 return 0;
670 }
671
a5psw_find_vlan_entry(struct a5psw * a5psw,u16 vid)672 static int a5psw_find_vlan_entry(struct a5psw *a5psw, u16 vid)
673 {
674 u32 vlan_res;
675 int i;
676
677 /* Find vlan for this port */
678 for (i = 0; i < A5PSW_VLAN_COUNT; i++) {
679 vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i));
680 if (FIELD_GET(A5PSW_VLAN_RES_VLANID, vlan_res) == vid)
681 return i;
682 }
683
684 return -1;
685 }
686
a5psw_new_vlan_res_entry(struct a5psw * a5psw,u16 newvid)687 static int a5psw_new_vlan_res_entry(struct a5psw *a5psw, u16 newvid)
688 {
689 u32 vlan_res;
690 int i;
691
692 /* Find a free VLAN entry */
693 for (i = 0; i < A5PSW_VLAN_COUNT; i++) {
694 vlan_res = a5psw_reg_readl(a5psw, A5PSW_VLAN_RES(i));
695 if (!(FIELD_GET(A5PSW_VLAN_RES_PORTMASK, vlan_res))) {
696 vlan_res = FIELD_PREP(A5PSW_VLAN_RES_VLANID, newvid);
697 a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(i), vlan_res);
698 return i;
699 }
700 }
701
702 return -1;
703 }
704
a5psw_port_vlan_tagged_cfg(struct a5psw * a5psw,unsigned int vlan_res_id,int port,bool set)705 static void a5psw_port_vlan_tagged_cfg(struct a5psw *a5psw,
706 unsigned int vlan_res_id, int port,
707 bool set)
708 {
709 u32 mask = A5PSW_VLAN_RES_WR_PORTMASK | A5PSW_VLAN_RES_RD_TAGMASK |
710 BIT(port);
711 u32 vlan_res_off = A5PSW_VLAN_RES(vlan_res_id);
712 u32 val = A5PSW_VLAN_RES_WR_TAGMASK, reg;
713
714 if (set)
715 val |= BIT(port);
716
717 /* Toggle tag mask read */
718 a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK);
719 reg = a5psw_reg_readl(a5psw, vlan_res_off);
720 a5psw_reg_writel(a5psw, vlan_res_off, A5PSW_VLAN_RES_RD_TAGMASK);
721
722 reg &= ~mask;
723 reg |= val;
724 a5psw_reg_writel(a5psw, vlan_res_off, reg);
725 }
726
a5psw_port_vlan_cfg(struct a5psw * a5psw,unsigned int vlan_res_id,int port,bool set)727 static void a5psw_port_vlan_cfg(struct a5psw *a5psw, unsigned int vlan_res_id,
728 int port, bool set)
729 {
730 u32 mask = A5PSW_VLAN_RES_WR_TAGMASK | BIT(port);
731 u32 reg = A5PSW_VLAN_RES_WR_PORTMASK;
732
733 if (set)
734 reg |= BIT(port);
735
736 a5psw_reg_rmw(a5psw, A5PSW_VLAN_RES(vlan_res_id), mask, reg);
737 }
738
a5psw_port_vlan_add(struct dsa_switch * ds,int port,const struct switchdev_obj_port_vlan * vlan,struct netlink_ext_ack * extack)739 static int a5psw_port_vlan_add(struct dsa_switch *ds, int port,
740 const struct switchdev_obj_port_vlan *vlan,
741 struct netlink_ext_ack *extack)
742 {
743 bool tagged = !(vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED);
744 bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
745 struct a5psw *a5psw = ds->priv;
746 u16 vid = vlan->vid;
747 int vlan_res_id;
748
749 vlan_res_id = a5psw_find_vlan_entry(a5psw, vid);
750 if (vlan_res_id < 0) {
751 vlan_res_id = a5psw_new_vlan_res_entry(a5psw, vid);
752 if (vlan_res_id < 0)
753 return -ENOSPC;
754 }
755
756 a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, true);
757 if (tagged)
758 a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, true);
759
760 /* Configure port to tag with corresponding VID, but do not enable it
761 * yet: wait for vlan filtering to be enabled to enable vlan port
762 * tagging
763 */
764 if (pvid)
765 a5psw_reg_writel(a5psw, A5PSW_SYSTEM_TAGINFO(port), vid);
766
767 return 0;
768 }
769
a5psw_port_vlan_del(struct dsa_switch * ds,int port,const struct switchdev_obj_port_vlan * vlan)770 static int a5psw_port_vlan_del(struct dsa_switch *ds, int port,
771 const struct switchdev_obj_port_vlan *vlan)
772 {
773 struct a5psw *a5psw = ds->priv;
774 u16 vid = vlan->vid;
775 int vlan_res_id;
776
777 vlan_res_id = a5psw_find_vlan_entry(a5psw, vid);
778 if (vlan_res_id < 0)
779 return -EINVAL;
780
781 a5psw_port_vlan_cfg(a5psw, vlan_res_id, port, false);
782 a5psw_port_vlan_tagged_cfg(a5psw, vlan_res_id, port, false);
783
784 return 0;
785 }
786
a5psw_read_stat(struct a5psw * a5psw,u32 offset,int port)787 static u64 a5psw_read_stat(struct a5psw *a5psw, u32 offset, int port)
788 {
789 u32 reg_lo, reg_hi;
790
791 reg_lo = a5psw_reg_readl(a5psw, offset + A5PSW_PORT_OFFSET(port));
792 /* A5PSW_STATS_HIWORD is latched on stat read */
793 reg_hi = a5psw_reg_readl(a5psw, A5PSW_STATS_HIWORD);
794
795 return ((u64)reg_hi << 32) | reg_lo;
796 }
797
a5psw_get_strings(struct dsa_switch * ds,int port,u32 stringset,uint8_t * data)798 static void a5psw_get_strings(struct dsa_switch *ds, int port, u32 stringset,
799 uint8_t *data)
800 {
801 unsigned int u;
802
803 if (stringset != ETH_SS_STATS)
804 return;
805
806 for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++)
807 ethtool_puts(&data, a5psw_stats[u].name);
808 }
809
a5psw_get_ethtool_stats(struct dsa_switch * ds,int port,uint64_t * data)810 static void a5psw_get_ethtool_stats(struct dsa_switch *ds, int port,
811 uint64_t *data)
812 {
813 struct a5psw *a5psw = ds->priv;
814 unsigned int u;
815
816 for (u = 0; u < ARRAY_SIZE(a5psw_stats); u++)
817 data[u] = a5psw_read_stat(a5psw, a5psw_stats[u].offset, port);
818 }
819
a5psw_get_sset_count(struct dsa_switch * ds,int port,int sset)820 static int a5psw_get_sset_count(struct dsa_switch *ds, int port, int sset)
821 {
822 if (sset != ETH_SS_STATS)
823 return 0;
824
825 return ARRAY_SIZE(a5psw_stats);
826 }
827
a5psw_get_eth_mac_stats(struct dsa_switch * ds,int port,struct ethtool_eth_mac_stats * mac_stats)828 static void a5psw_get_eth_mac_stats(struct dsa_switch *ds, int port,
829 struct ethtool_eth_mac_stats *mac_stats)
830 {
831 struct a5psw *a5psw = ds->priv;
832
833 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
834 mac_stats->FramesTransmittedOK = RD(aFramesTransmittedOK);
835 mac_stats->SingleCollisionFrames = RD(aSingleCollisions);
836 mac_stats->MultipleCollisionFrames = RD(aMultipleCollisions);
837 mac_stats->FramesReceivedOK = RD(aFramesReceivedOK);
838 mac_stats->FrameCheckSequenceErrors = RD(aFrameCheckSequenceErrors);
839 mac_stats->AlignmentErrors = RD(aAlignmentErrors);
840 mac_stats->OctetsTransmittedOK = RD(aOctetsTransmittedOK);
841 mac_stats->FramesWithDeferredXmissions = RD(aDeferred);
842 mac_stats->LateCollisions = RD(aLateCollisions);
843 mac_stats->FramesAbortedDueToXSColls = RD(aExcessiveCollisions);
844 mac_stats->FramesLostDueToIntMACXmitError = RD(ifOutErrors);
845 mac_stats->CarrierSenseErrors = RD(aCarrierSenseErrors);
846 mac_stats->OctetsReceivedOK = RD(aOctetsReceivedOK);
847 mac_stats->FramesLostDueToIntMACRcvError = RD(ifInErrors);
848 mac_stats->MulticastFramesXmittedOK = RD(ifOutMulticastPkts);
849 mac_stats->BroadcastFramesXmittedOK = RD(ifOutBroadcastPkts);
850 mac_stats->FramesWithExcessiveDeferral = RD(aDeferred);
851 mac_stats->MulticastFramesReceivedOK = RD(ifInMulticastPkts);
852 mac_stats->BroadcastFramesReceivedOK = RD(ifInBroadcastPkts);
853 #undef RD
854 }
855
856 static const struct ethtool_rmon_hist_range a5psw_rmon_ranges[] = {
857 { 0, 64 },
858 { 65, 127 },
859 { 128, 255 },
860 { 256, 511 },
861 { 512, 1023 },
862 { 1024, 1518 },
863 { 1519, A5PSW_MAX_MTU },
864 {}
865 };
866
a5psw_get_rmon_stats(struct dsa_switch * ds,int port,struct ethtool_rmon_stats * rmon_stats,const struct ethtool_rmon_hist_range ** ranges)867 static void a5psw_get_rmon_stats(struct dsa_switch *ds, int port,
868 struct ethtool_rmon_stats *rmon_stats,
869 const struct ethtool_rmon_hist_range **ranges)
870 {
871 struct a5psw *a5psw = ds->priv;
872
873 #define RD(name) a5psw_read_stat(a5psw, A5PSW_##name, port)
874 rmon_stats->undersize_pkts = RD(etherStatsUndersizePkts);
875 rmon_stats->oversize_pkts = RD(etherStatsOversizePkts);
876 rmon_stats->fragments = RD(etherStatsFragments);
877 rmon_stats->jabbers = RD(etherStatsJabbers);
878 rmon_stats->hist[0] = RD(etherStatsPkts64Octets);
879 rmon_stats->hist[1] = RD(etherStatsPkts65to127Octets);
880 rmon_stats->hist[2] = RD(etherStatsPkts128to255Octets);
881 rmon_stats->hist[3] = RD(etherStatsPkts256to511Octets);
882 rmon_stats->hist[4] = RD(etherStatsPkts512to1023Octets);
883 rmon_stats->hist[5] = RD(etherStatsPkts1024to1518Octets);
884 rmon_stats->hist[6] = RD(etherStatsPkts1519toXOctets);
885 #undef RD
886
887 *ranges = a5psw_rmon_ranges;
888 }
889
a5psw_get_eth_ctrl_stats(struct dsa_switch * ds,int port,struct ethtool_eth_ctrl_stats * ctrl_stats)890 static void a5psw_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
891 struct ethtool_eth_ctrl_stats *ctrl_stats)
892 {
893 struct a5psw *a5psw = ds->priv;
894 u64 stat;
895
896 stat = a5psw_read_stat(a5psw, A5PSW_aTxPAUSEMACCtrlFrames, port);
897 ctrl_stats->MACControlFramesTransmitted = stat;
898 stat = a5psw_read_stat(a5psw, A5PSW_aRxPAUSEMACCtrlFrames, port);
899 ctrl_stats->MACControlFramesReceived = stat;
900 }
901
a5psw_vlan_setup(struct a5psw * a5psw,int port)902 static void a5psw_vlan_setup(struct a5psw *a5psw, int port)
903 {
904 u32 reg;
905
906 /* Enable TAG always mode for the port, this is actually controlled
907 * by VLAN_IN_MODE_ENA field which will be used for PVID insertion
908 */
909 reg = A5PSW_VLAN_IN_MODE_TAG_ALWAYS;
910 reg <<= A5PSW_VLAN_IN_MODE_PORT_SHIFT(port);
911 a5psw_reg_rmw(a5psw, A5PSW_VLAN_IN_MODE, A5PSW_VLAN_IN_MODE_PORT(port),
912 reg);
913
914 /* Set transparent mode for output frame manipulation, this will depend
915 * on the VLAN_RES configuration mode
916 */
917 reg = A5PSW_VLAN_OUT_MODE_TRANSPARENT;
918 reg <<= A5PSW_VLAN_OUT_MODE_PORT_SHIFT(port);
919 a5psw_reg_rmw(a5psw, A5PSW_VLAN_OUT_MODE,
920 A5PSW_VLAN_OUT_MODE_PORT(port), reg);
921 }
922
a5psw_setup(struct dsa_switch * ds)923 static int a5psw_setup(struct dsa_switch *ds)
924 {
925 struct a5psw *a5psw = ds->priv;
926 int port, vlan, ret;
927 struct dsa_port *dp;
928 u32 reg;
929
930 /* Validate that there is only 1 CPU port with index A5PSW_CPU_PORT */
931 dsa_switch_for_each_cpu_port(dp, ds) {
932 if (dp->index != A5PSW_CPU_PORT) {
933 dev_err(a5psw->dev, "Invalid CPU port\n");
934 return -EINVAL;
935 }
936 }
937
938 /* Configure management port */
939 reg = A5PSW_CPU_PORT | A5PSW_MGMT_CFG_ENABLE;
940 a5psw_reg_writel(a5psw, A5PSW_MGMT_CFG, reg);
941
942 /* Set pattern 0 to forward all frame to mgmt port */
943 a5psw_reg_writel(a5psw, A5PSW_PATTERN_CTRL(A5PSW_PATTERN_MGMTFWD),
944 A5PSW_PATTERN_CTRL_MGMTFWD);
945
946 /* Enable port tagging */
947 reg = FIELD_PREP(A5PSW_MGMT_TAG_CFG_TAGFIELD, ETH_P_DSA_A5PSW);
948 reg |= A5PSW_MGMT_TAG_CFG_ENABLE | A5PSW_MGMT_TAG_CFG_ALL_FRAMES;
949 a5psw_reg_writel(a5psw, A5PSW_MGMT_TAG_CFG, reg);
950
951 /* Enable normal switch operation */
952 reg = A5PSW_LK_ADDR_CTRL_BLOCKING | A5PSW_LK_ADDR_CTRL_LEARNING |
953 A5PSW_LK_ADDR_CTRL_AGEING | A5PSW_LK_ADDR_CTRL_ALLOW_MIGR |
954 A5PSW_LK_ADDR_CTRL_CLEAR_TABLE;
955 a5psw_reg_writel(a5psw, A5PSW_LK_CTRL, reg);
956
957 ret = readl_poll_timeout(a5psw->base + A5PSW_LK_CTRL, reg,
958 !(reg & A5PSW_LK_ADDR_CTRL_CLEAR_TABLE),
959 A5PSW_LK_BUSY_USEC_POLL, A5PSW_CTRL_TIMEOUT);
960 if (ret) {
961 dev_err(a5psw->dev, "Failed to clear lookup table\n");
962 return ret;
963 }
964
965 /* Reset learn count to 0 */
966 reg = A5PSW_LK_LEARNCOUNT_MODE_SET;
967 a5psw_reg_writel(a5psw, A5PSW_LK_LEARNCOUNT, reg);
968
969 /* Clear VLAN resource table */
970 reg = A5PSW_VLAN_RES_WR_PORTMASK | A5PSW_VLAN_RES_WR_TAGMASK;
971 for (vlan = 0; vlan < A5PSW_VLAN_COUNT; vlan++)
972 a5psw_reg_writel(a5psw, A5PSW_VLAN_RES(vlan), reg);
973
974 /* Reset all ports */
975 dsa_switch_for_each_port(dp, ds) {
976 port = dp->index;
977
978 /* Reset the port */
979 a5psw_reg_writel(a5psw, A5PSW_CMD_CFG(port),
980 A5PSW_CMD_CFG_SW_RESET);
981
982 /* Enable only CPU port */
983 a5psw_port_enable_set(a5psw, port, dsa_port_is_cpu(dp));
984
985 if (dsa_port_is_unused(dp))
986 continue;
987
988 /* Enable egress flooding and learning for CPU port */
989 if (dsa_port_is_cpu(dp)) {
990 a5psw_flooding_set_resolution(a5psw, port, true);
991 a5psw_port_learning_set(a5psw, port, true);
992 }
993
994 /* Enable standalone mode for user ports */
995 if (dsa_port_is_user(dp))
996 a5psw_port_set_standalone(a5psw, port, true);
997
998 a5psw_vlan_setup(a5psw, port);
999 }
1000
1001 return 0;
1002 }
1003
1004 static const struct phylink_mac_ops a5psw_phylink_mac_ops = {
1005 .mac_select_pcs = a5psw_phylink_mac_select_pcs,
1006 .mac_config = a5psw_phylink_mac_config,
1007 .mac_link_down = a5psw_phylink_mac_link_down,
1008 .mac_link_up = a5psw_phylink_mac_link_up,
1009 };
1010
1011 static const struct dsa_switch_ops a5psw_switch_ops = {
1012 .get_tag_protocol = a5psw_get_tag_protocol,
1013 .setup = a5psw_setup,
1014 .port_disable = a5psw_port_disable,
1015 .port_enable = a5psw_port_enable,
1016 .phylink_get_caps = a5psw_phylink_get_caps,
1017 .port_change_mtu = a5psw_port_change_mtu,
1018 .port_max_mtu = a5psw_port_max_mtu,
1019 .get_sset_count = a5psw_get_sset_count,
1020 .get_strings = a5psw_get_strings,
1021 .get_ethtool_stats = a5psw_get_ethtool_stats,
1022 .get_eth_mac_stats = a5psw_get_eth_mac_stats,
1023 .get_eth_ctrl_stats = a5psw_get_eth_ctrl_stats,
1024 .get_rmon_stats = a5psw_get_rmon_stats,
1025 .set_ageing_time = a5psw_set_ageing_time,
1026 .port_bridge_join = a5psw_port_bridge_join,
1027 .port_bridge_leave = a5psw_port_bridge_leave,
1028 .port_pre_bridge_flags = a5psw_port_pre_bridge_flags,
1029 .port_bridge_flags = a5psw_port_bridge_flags,
1030 .port_stp_state_set = a5psw_port_stp_state_set,
1031 .port_fast_age = a5psw_port_fast_age,
1032 .port_vlan_filtering = a5psw_port_vlan_filtering,
1033 .port_vlan_add = a5psw_port_vlan_add,
1034 .port_vlan_del = a5psw_port_vlan_del,
1035 .port_fdb_add = a5psw_port_fdb_add,
1036 .port_fdb_del = a5psw_port_fdb_del,
1037 .port_fdb_dump = a5psw_port_fdb_dump,
1038 };
1039
a5psw_mdio_wait_busy(struct a5psw * a5psw)1040 static int a5psw_mdio_wait_busy(struct a5psw *a5psw)
1041 {
1042 u32 status;
1043 int err;
1044
1045 err = readl_poll_timeout(a5psw->base + A5PSW_MDIO_CFG_STATUS, status,
1046 !(status & A5PSW_MDIO_CFG_STATUS_BUSY), 10,
1047 1000 * USEC_PER_MSEC);
1048 if (err)
1049 dev_err(a5psw->dev, "MDIO command timeout\n");
1050
1051 return err;
1052 }
1053
a5psw_mdio_read(struct mii_bus * bus,int phy_id,int phy_reg)1054 static int a5psw_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
1055 {
1056 struct a5psw *a5psw = bus->priv;
1057 u32 cmd, status;
1058 int ret;
1059
1060 cmd = A5PSW_MDIO_COMMAND_READ;
1061 cmd |= FIELD_PREP(A5PSW_MDIO_COMMAND_REG_ADDR, phy_reg);
1062 cmd |= FIELD_PREP(A5PSW_MDIO_COMMAND_PHY_ADDR, phy_id);
1063
1064 a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd);
1065
1066 ret = a5psw_mdio_wait_busy(a5psw);
1067 if (ret)
1068 return ret;
1069
1070 ret = a5psw_reg_readl(a5psw, A5PSW_MDIO_DATA) & A5PSW_MDIO_DATA_MASK;
1071
1072 status = a5psw_reg_readl(a5psw, A5PSW_MDIO_CFG_STATUS);
1073 if (status & A5PSW_MDIO_CFG_STATUS_READERR)
1074 return -EIO;
1075
1076 return ret;
1077 }
1078
a5psw_mdio_write(struct mii_bus * bus,int phy_id,int phy_reg,u16 phy_data)1079 static int a5psw_mdio_write(struct mii_bus *bus, int phy_id, int phy_reg,
1080 u16 phy_data)
1081 {
1082 struct a5psw *a5psw = bus->priv;
1083 u32 cmd;
1084
1085 cmd = FIELD_PREP(A5PSW_MDIO_COMMAND_REG_ADDR, phy_reg);
1086 cmd |= FIELD_PREP(A5PSW_MDIO_COMMAND_PHY_ADDR, phy_id);
1087
1088 a5psw_reg_writel(a5psw, A5PSW_MDIO_COMMAND, cmd);
1089 a5psw_reg_writel(a5psw, A5PSW_MDIO_DATA, phy_data);
1090
1091 return a5psw_mdio_wait_busy(a5psw);
1092 }
1093
a5psw_mdio_config(struct a5psw * a5psw,u32 mdio_freq)1094 static int a5psw_mdio_config(struct a5psw *a5psw, u32 mdio_freq)
1095 {
1096 unsigned long rate;
1097 unsigned long div;
1098 u32 cfgstatus;
1099
1100 rate = clk_get_rate(a5psw->hclk);
1101 div = ((rate / mdio_freq) / 2);
1102 if (div > FIELD_MAX(A5PSW_MDIO_CFG_STATUS_CLKDIV) ||
1103 div < A5PSW_MDIO_CLK_DIV_MIN) {
1104 dev_err(a5psw->dev, "MDIO clock div %ld out of range\n", div);
1105 return -ERANGE;
1106 }
1107
1108 cfgstatus = FIELD_PREP(A5PSW_MDIO_CFG_STATUS_CLKDIV, div);
1109
1110 a5psw_reg_writel(a5psw, A5PSW_MDIO_CFG_STATUS, cfgstatus);
1111
1112 return 0;
1113 }
1114
a5psw_probe_mdio(struct a5psw * a5psw,struct device_node * node)1115 static int a5psw_probe_mdio(struct a5psw *a5psw, struct device_node *node)
1116 {
1117 struct device *dev = a5psw->dev;
1118 struct mii_bus *bus;
1119 u32 mdio_freq;
1120 int ret;
1121
1122 if (of_property_read_u32(node, "clock-frequency", &mdio_freq))
1123 mdio_freq = A5PSW_MDIO_DEF_FREQ;
1124
1125 ret = a5psw_mdio_config(a5psw, mdio_freq);
1126 if (ret)
1127 return ret;
1128
1129 bus = devm_mdiobus_alloc(dev);
1130 if (!bus)
1131 return -ENOMEM;
1132
1133 bus->name = "a5psw_mdio";
1134 bus->read = a5psw_mdio_read;
1135 bus->write = a5psw_mdio_write;
1136 bus->priv = a5psw;
1137 bus->parent = dev;
1138 snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
1139
1140 a5psw->mii_bus = bus;
1141
1142 return devm_of_mdiobus_register(dev, bus, node);
1143 }
1144
a5psw_pcs_free(struct a5psw * a5psw)1145 static void a5psw_pcs_free(struct a5psw *a5psw)
1146 {
1147 int i;
1148
1149 for (i = 0; i < ARRAY_SIZE(a5psw->pcs); i++) {
1150 if (a5psw->pcs[i])
1151 miic_destroy(a5psw->pcs[i]);
1152 }
1153 }
1154
a5psw_pcs_get(struct a5psw * a5psw)1155 static int a5psw_pcs_get(struct a5psw *a5psw)
1156 {
1157 struct device_node *ports, *port, *pcs_node;
1158 struct phylink_pcs *pcs;
1159 int ret;
1160 u32 reg;
1161
1162 ports = of_get_child_by_name(a5psw->dev->of_node, "ethernet-ports");
1163 if (!ports)
1164 return -EINVAL;
1165
1166 for_each_available_child_of_node(ports, port) {
1167 pcs_node = of_parse_phandle(port, "pcs-handle", 0);
1168 if (!pcs_node)
1169 continue;
1170
1171 if (of_property_read_u32(port, "reg", ®)) {
1172 ret = -EINVAL;
1173 goto free_pcs;
1174 }
1175
1176 if (reg >= ARRAY_SIZE(a5psw->pcs)) {
1177 ret = -ENODEV;
1178 goto free_pcs;
1179 }
1180
1181 pcs = miic_create(a5psw->dev, pcs_node);
1182 if (IS_ERR(pcs)) {
1183 dev_err(a5psw->dev, "Failed to create PCS for port %d\n",
1184 reg);
1185 ret = PTR_ERR(pcs);
1186 goto free_pcs;
1187 }
1188
1189 a5psw->pcs[reg] = pcs;
1190 of_node_put(pcs_node);
1191 }
1192 of_node_put(ports);
1193
1194 return 0;
1195
1196 free_pcs:
1197 of_node_put(pcs_node);
1198 of_node_put(port);
1199 of_node_put(ports);
1200 a5psw_pcs_free(a5psw);
1201
1202 return ret;
1203 }
1204
a5psw_probe(struct platform_device * pdev)1205 static int a5psw_probe(struct platform_device *pdev)
1206 {
1207 struct device *dev = &pdev->dev;
1208 struct device_node *mdio;
1209 struct dsa_switch *ds;
1210 struct a5psw *a5psw;
1211 int ret;
1212
1213 a5psw = devm_kzalloc(dev, sizeof(*a5psw), GFP_KERNEL);
1214 if (!a5psw)
1215 return -ENOMEM;
1216
1217 a5psw->dev = dev;
1218 mutex_init(&a5psw->lk_lock);
1219 spin_lock_init(&a5psw->reg_lock);
1220 a5psw->base = devm_platform_ioremap_resource(pdev, 0);
1221 if (IS_ERR(a5psw->base))
1222 return PTR_ERR(a5psw->base);
1223
1224 a5psw->bridged_ports = BIT(A5PSW_CPU_PORT);
1225
1226 ret = a5psw_pcs_get(a5psw);
1227 if (ret)
1228 return ret;
1229
1230 a5psw->hclk = devm_clk_get_enabled(dev, "hclk");
1231 if (IS_ERR(a5psw->hclk)) {
1232 dev_err(dev, "failed get hclk clock\n");
1233 ret = PTR_ERR(a5psw->hclk);
1234 goto free_pcs;
1235 }
1236
1237 a5psw->clk = devm_clk_get_enabled(dev, "clk");
1238 if (IS_ERR(a5psw->clk)) {
1239 dev_err(dev, "failed get clk_switch clock\n");
1240 ret = PTR_ERR(a5psw->clk);
1241 goto free_pcs;
1242 }
1243
1244 mdio = of_get_available_child_by_name(dev->of_node, "mdio");
1245 if (mdio) {
1246 ret = a5psw_probe_mdio(a5psw, mdio);
1247 of_node_put(mdio);
1248 if (ret) {
1249 dev_err(dev, "Failed to register MDIO: %d\n", ret);
1250 goto free_pcs;
1251 }
1252 }
1253
1254 ds = &a5psw->ds;
1255 ds->dev = dev;
1256 ds->num_ports = A5PSW_PORTS_NUM;
1257 ds->ops = &a5psw_switch_ops;
1258 ds->phylink_mac_ops = &a5psw_phylink_mac_ops;
1259 ds->priv = a5psw;
1260
1261 ret = dsa_register_switch(ds);
1262 if (ret) {
1263 dev_err(dev, "Failed to register DSA switch: %d\n", ret);
1264 goto free_pcs;
1265 }
1266
1267 return 0;
1268
1269 free_pcs:
1270 a5psw_pcs_free(a5psw);
1271
1272 return ret;
1273 }
1274
a5psw_remove(struct platform_device * pdev)1275 static void a5psw_remove(struct platform_device *pdev)
1276 {
1277 struct a5psw *a5psw = platform_get_drvdata(pdev);
1278
1279 if (!a5psw)
1280 return;
1281
1282 dsa_unregister_switch(&a5psw->ds);
1283 a5psw_pcs_free(a5psw);
1284 }
1285
a5psw_shutdown(struct platform_device * pdev)1286 static void a5psw_shutdown(struct platform_device *pdev)
1287 {
1288 struct a5psw *a5psw = platform_get_drvdata(pdev);
1289
1290 if (!a5psw)
1291 return;
1292
1293 dsa_switch_shutdown(&a5psw->ds);
1294
1295 platform_set_drvdata(pdev, NULL);
1296 }
1297
1298 static const struct of_device_id a5psw_of_mtable[] = {
1299 { .compatible = "renesas,rzn1-a5psw", },
1300 { /* sentinel */ },
1301 };
1302 MODULE_DEVICE_TABLE(of, a5psw_of_mtable);
1303
1304 static struct platform_driver a5psw_driver = {
1305 .driver = {
1306 .name = "rzn1_a5psw",
1307 .of_match_table = a5psw_of_mtable,
1308 },
1309 .probe = a5psw_probe,
1310 .remove = a5psw_remove,
1311 .shutdown = a5psw_shutdown,
1312 };
1313 module_platform_driver(a5psw_driver);
1314
1315 MODULE_LICENSE("GPL");
1316 MODULE_DESCRIPTION("Renesas RZ/N1 Advanced 5-port Switch driver");
1317 MODULE_AUTHOR("Clément Léger <clement.leger@bootlin.com>");
1318