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