xref: /linux/drivers/net/dsa/lantiq/lantiq_gswip.c (revision 720412c4aebc91fdb6c880353a9465ab36a26614)
1cb477c30SDaniel Golle // SPDX-License-Identifier: GPL-2.0
2cb477c30SDaniel Golle /*
3cb477c30SDaniel Golle  * Lantiq / Intel GSWIP switch driver for VRX200, xRX300 and xRX330 SoCs
4cb477c30SDaniel Golle  *
5cb477c30SDaniel Golle  * Copyright (C) 2010 Lantiq Deutschland
6cb477c30SDaniel Golle  * Copyright (C) 2012 John Crispin <john@phrozen.org>
7cb477c30SDaniel Golle  * Copyright (C) 2017 - 2019 Hauke Mehrtens <hauke@hauke-m.de>
8cb477c30SDaniel Golle  *
9cb477c30SDaniel Golle  * The VLAN and bridge model the GSWIP hardware uses does not directly
10cb477c30SDaniel Golle  * matches the model DSA uses.
11cb477c30SDaniel Golle  *
12cb477c30SDaniel Golle  * The hardware has 64 possible table entries for bridges with one VLAN
13cb477c30SDaniel Golle  * ID, one flow id and a list of ports for each bridge. All entries which
14cb477c30SDaniel Golle  * match the same flow ID are combined in the mac learning table, they
15cb477c30SDaniel Golle  * act as one global bridge.
16cb477c30SDaniel Golle  * The hardware does not support VLAN filter on the port, but on the
17cb477c30SDaniel Golle  * bridge, this driver converts the DSA model to the hardware.
18cb477c30SDaniel Golle  *
19cb477c30SDaniel Golle  * The CPU gets all the exception frames which do not match any forwarding
20cb477c30SDaniel Golle  * rule and the CPU port is also added to all bridges. This makes it possible
21cb477c30SDaniel Golle  * to handle all the special cases easily in software.
22cb477c30SDaniel Golle  * At the initialization the driver allocates one bridge table entry for
23cb477c30SDaniel Golle  * each switch port which is used when the port is used without an
24cb477c30SDaniel Golle  * explicit bridge. This prevents the frames from being forwarded
25cb477c30SDaniel Golle  * between all LAN ports by default.
26cb477c30SDaniel Golle  */
27cb477c30SDaniel Golle 
28cb477c30SDaniel Golle #include "lantiq_gswip.h"
29cb477c30SDaniel Golle #include "lantiq_pce.h"
30cb477c30SDaniel Golle 
31cb477c30SDaniel Golle #include <linux/delay.h>
32cb477c30SDaniel Golle #include <linux/etherdevice.h>
33cb477c30SDaniel Golle #include <linux/firmware.h>
34cb477c30SDaniel Golle #include <linux/if_bridge.h>
35cb477c30SDaniel Golle #include <linux/if_vlan.h>
36cb477c30SDaniel Golle #include <linux/iopoll.h>
37cb477c30SDaniel Golle #include <linux/mfd/syscon.h>
38cb477c30SDaniel Golle #include <linux/module.h>
39cb477c30SDaniel Golle #include <linux/of_mdio.h>
40cb477c30SDaniel Golle #include <linux/of_net.h>
41cb477c30SDaniel Golle #include <linux/of_platform.h>
42cb477c30SDaniel Golle #include <linux/phy.h>
43cb477c30SDaniel Golle #include <linux/phylink.h>
44cb477c30SDaniel Golle #include <dt-bindings/mips/lantiq_rcu_gphy.h>
45cb477c30SDaniel Golle 
46cb477c30SDaniel Golle struct xway_gphy_match_data {
47cb477c30SDaniel Golle 	char *fe_firmware_name;
48cb477c30SDaniel Golle 	char *ge_firmware_name;
49cb477c30SDaniel Golle };
50cb477c30SDaniel Golle 
51cb477c30SDaniel Golle struct gswip_pce_table_entry {
52cb477c30SDaniel Golle 	u16 index;      // PCE_TBL_ADDR.ADDR = pData->table_index
53cb477c30SDaniel Golle 	u16 table;      // PCE_TBL_CTRL.ADDR = pData->table
54cb477c30SDaniel Golle 	u16 key[8];
55cb477c30SDaniel Golle 	u16 val[5];
56cb477c30SDaniel Golle 	u16 mask;
57cb477c30SDaniel Golle 	u8 gmap;
58cb477c30SDaniel Golle 	bool type;
59cb477c30SDaniel Golle 	bool valid;
60cb477c30SDaniel Golle 	bool key_mode;
61cb477c30SDaniel Golle };
62cb477c30SDaniel Golle 
63cb477c30SDaniel Golle struct gswip_rmon_cnt_desc {
64cb477c30SDaniel Golle 	unsigned int size;
65cb477c30SDaniel Golle 	unsigned int offset;
66cb477c30SDaniel Golle 	const char *name;
67cb477c30SDaniel Golle };
68cb477c30SDaniel Golle 
69cb477c30SDaniel Golle #define MIB_DESC(_size, _offset, _name) {.size = _size, .offset = _offset, .name = _name}
70cb477c30SDaniel Golle 
71cb477c30SDaniel Golle static const struct gswip_rmon_cnt_desc gswip_rmon_cnt[] = {
72cb477c30SDaniel Golle 	/** Receive Packet Count (only packets that are accepted and not discarded). */
73cb477c30SDaniel Golle 	MIB_DESC(1, 0x1F, "RxGoodPkts"),
74cb477c30SDaniel Golle 	MIB_DESC(1, 0x23, "RxUnicastPkts"),
75cb477c30SDaniel Golle 	MIB_DESC(1, 0x22, "RxMulticastPkts"),
76cb477c30SDaniel Golle 	MIB_DESC(1, 0x21, "RxFCSErrorPkts"),
77cb477c30SDaniel Golle 	MIB_DESC(1, 0x1D, "RxUnderSizeGoodPkts"),
78cb477c30SDaniel Golle 	MIB_DESC(1, 0x1E, "RxUnderSizeErrorPkts"),
79cb477c30SDaniel Golle 	MIB_DESC(1, 0x1B, "RxOversizeGoodPkts"),
80cb477c30SDaniel Golle 	MIB_DESC(1, 0x1C, "RxOversizeErrorPkts"),
81cb477c30SDaniel Golle 	MIB_DESC(1, 0x20, "RxGoodPausePkts"),
82cb477c30SDaniel Golle 	MIB_DESC(1, 0x1A, "RxAlignErrorPkts"),
83cb477c30SDaniel Golle 	MIB_DESC(1, 0x12, "Rx64BytePkts"),
84cb477c30SDaniel Golle 	MIB_DESC(1, 0x13, "Rx127BytePkts"),
85cb477c30SDaniel Golle 	MIB_DESC(1, 0x14, "Rx255BytePkts"),
86cb477c30SDaniel Golle 	MIB_DESC(1, 0x15, "Rx511BytePkts"),
87cb477c30SDaniel Golle 	MIB_DESC(1, 0x16, "Rx1023BytePkts"),
88cb477c30SDaniel Golle 	/** Receive Size 1024-1522 (or more, if configured) Packet Count. */
89cb477c30SDaniel Golle 	MIB_DESC(1, 0x17, "RxMaxBytePkts"),
90cb477c30SDaniel Golle 	MIB_DESC(1, 0x18, "RxDroppedPkts"),
91cb477c30SDaniel Golle 	MIB_DESC(1, 0x19, "RxFilteredPkts"),
92cb477c30SDaniel Golle 	MIB_DESC(2, 0x24, "RxGoodBytes"),
93cb477c30SDaniel Golle 	MIB_DESC(2, 0x26, "RxBadBytes"),
94cb477c30SDaniel Golle 	MIB_DESC(1, 0x11, "TxAcmDroppedPkts"),
95cb477c30SDaniel Golle 	MIB_DESC(1, 0x0C, "TxGoodPkts"),
96cb477c30SDaniel Golle 	MIB_DESC(1, 0x06, "TxUnicastPkts"),
97cb477c30SDaniel Golle 	MIB_DESC(1, 0x07, "TxMulticastPkts"),
98cb477c30SDaniel Golle 	MIB_DESC(1, 0x00, "Tx64BytePkts"),
99cb477c30SDaniel Golle 	MIB_DESC(1, 0x01, "Tx127BytePkts"),
100cb477c30SDaniel Golle 	MIB_DESC(1, 0x02, "Tx255BytePkts"),
101cb477c30SDaniel Golle 	MIB_DESC(1, 0x03, "Tx511BytePkts"),
102cb477c30SDaniel Golle 	MIB_DESC(1, 0x04, "Tx1023BytePkts"),
103cb477c30SDaniel Golle 	/** Transmit Size 1024-1522 (or more, if configured) Packet Count. */
104cb477c30SDaniel Golle 	MIB_DESC(1, 0x05, "TxMaxBytePkts"),
105cb477c30SDaniel Golle 	MIB_DESC(1, 0x08, "TxSingleCollCount"),
106cb477c30SDaniel Golle 	MIB_DESC(1, 0x09, "TxMultCollCount"),
107cb477c30SDaniel Golle 	MIB_DESC(1, 0x0A, "TxLateCollCount"),
108cb477c30SDaniel Golle 	MIB_DESC(1, 0x0B, "TxExcessCollCount"),
109cb477c30SDaniel Golle 	MIB_DESC(1, 0x0D, "TxPauseCount"),
110cb477c30SDaniel Golle 	MIB_DESC(1, 0x10, "TxDroppedPkts"),
111cb477c30SDaniel Golle 	MIB_DESC(2, 0x0E, "TxGoodBytes"),
112cb477c30SDaniel Golle };
113cb477c30SDaniel Golle 
114cb477c30SDaniel Golle static u32 gswip_switch_r(struct gswip_priv *priv, u32 offset)
115cb477c30SDaniel Golle {
116cb477c30SDaniel Golle 	return __raw_readl(priv->gswip + (offset * 4));
117cb477c30SDaniel Golle }
118cb477c30SDaniel Golle 
119cb477c30SDaniel Golle static void gswip_switch_w(struct gswip_priv *priv, u32 val, u32 offset)
120cb477c30SDaniel Golle {
121cb477c30SDaniel Golle 	__raw_writel(val, priv->gswip + (offset * 4));
122cb477c30SDaniel Golle }
123cb477c30SDaniel Golle 
124cb477c30SDaniel Golle static void gswip_switch_mask(struct gswip_priv *priv, u32 clear, u32 set,
125cb477c30SDaniel Golle 			      u32 offset)
126cb477c30SDaniel Golle {
127cb477c30SDaniel Golle 	u32 val = gswip_switch_r(priv, offset);
128cb477c30SDaniel Golle 
129cb477c30SDaniel Golle 	val &= ~(clear);
130cb477c30SDaniel Golle 	val |= set;
131cb477c30SDaniel Golle 	gswip_switch_w(priv, val, offset);
132cb477c30SDaniel Golle }
133cb477c30SDaniel Golle 
134cb477c30SDaniel Golle static u32 gswip_switch_r_timeout(struct gswip_priv *priv, u32 offset,
135cb477c30SDaniel Golle 				  u32 cleared)
136cb477c30SDaniel Golle {
137cb477c30SDaniel Golle 	u32 val;
138cb477c30SDaniel Golle 
139cb477c30SDaniel Golle 	return readx_poll_timeout(__raw_readl, priv->gswip + (offset * 4), val,
140cb477c30SDaniel Golle 				  (val & cleared) == 0, 20, 50000);
141cb477c30SDaniel Golle }
142cb477c30SDaniel Golle 
143cb477c30SDaniel Golle static u32 gswip_mdio_r(struct gswip_priv *priv, u32 offset)
144cb477c30SDaniel Golle {
145cb477c30SDaniel Golle 	return __raw_readl(priv->mdio + (offset * 4));
146cb477c30SDaniel Golle }
147cb477c30SDaniel Golle 
148cb477c30SDaniel Golle static void gswip_mdio_w(struct gswip_priv *priv, u32 val, u32 offset)
149cb477c30SDaniel Golle {
150cb477c30SDaniel Golle 	__raw_writel(val, priv->mdio + (offset * 4));
151cb477c30SDaniel Golle }
152cb477c30SDaniel Golle 
153cb477c30SDaniel Golle static void gswip_mdio_mask(struct gswip_priv *priv, u32 clear, u32 set,
154cb477c30SDaniel Golle 			    u32 offset)
155cb477c30SDaniel Golle {
156cb477c30SDaniel Golle 	u32 val = gswip_mdio_r(priv, offset);
157cb477c30SDaniel Golle 
158cb477c30SDaniel Golle 	val &= ~(clear);
159cb477c30SDaniel Golle 	val |= set;
160cb477c30SDaniel Golle 	gswip_mdio_w(priv, val, offset);
161cb477c30SDaniel Golle }
162cb477c30SDaniel Golle 
163cb477c30SDaniel Golle static u32 gswip_mii_r(struct gswip_priv *priv, u32 offset)
164cb477c30SDaniel Golle {
165cb477c30SDaniel Golle 	return __raw_readl(priv->mii + (offset * 4));
166cb477c30SDaniel Golle }
167cb477c30SDaniel Golle 
168cb477c30SDaniel Golle static void gswip_mii_w(struct gswip_priv *priv, u32 val, u32 offset)
169cb477c30SDaniel Golle {
170cb477c30SDaniel Golle 	__raw_writel(val, priv->mii + (offset * 4));
171cb477c30SDaniel Golle }
172cb477c30SDaniel Golle 
173cb477c30SDaniel Golle static void gswip_mii_mask(struct gswip_priv *priv, u32 clear, u32 set,
174cb477c30SDaniel Golle 			   u32 offset)
175cb477c30SDaniel Golle {
176cb477c30SDaniel Golle 	u32 val = gswip_mii_r(priv, offset);
177cb477c30SDaniel Golle 
178cb477c30SDaniel Golle 	val &= ~(clear);
179cb477c30SDaniel Golle 	val |= set;
180cb477c30SDaniel Golle 	gswip_mii_w(priv, val, offset);
181cb477c30SDaniel Golle }
182cb477c30SDaniel Golle 
183cb477c30SDaniel Golle static void gswip_mii_mask_cfg(struct gswip_priv *priv, u32 clear, u32 set,
184cb477c30SDaniel Golle 			       int port)
185cb477c30SDaniel Golle {
18651578203SDaniel Golle 	int reg_port;
18751578203SDaniel Golle 
188cb477c30SDaniel Golle 	/* MII_CFG register only exists for MII ports */
189cb477c30SDaniel Golle 	if (!(priv->hw_info->mii_ports & BIT(port)))
190cb477c30SDaniel Golle 		return;
191cb477c30SDaniel Golle 
19251578203SDaniel Golle 	reg_port = port + priv->hw_info->mii_port_reg_offset;
19351578203SDaniel Golle 
19451578203SDaniel Golle 	gswip_mii_mask(priv, clear, set, GSWIP_MII_CFGp(reg_port));
195cb477c30SDaniel Golle }
196cb477c30SDaniel Golle 
197cb477c30SDaniel Golle static void gswip_mii_mask_pcdu(struct gswip_priv *priv, u32 clear, u32 set,
198cb477c30SDaniel Golle 				int port)
199cb477c30SDaniel Golle {
20051578203SDaniel Golle 	int reg_port;
20151578203SDaniel Golle 
202cb477c30SDaniel Golle 	/* MII_PCDU register only exists for MII ports */
203cb477c30SDaniel Golle 	if (!(priv->hw_info->mii_ports & BIT(port)))
204cb477c30SDaniel Golle 		return;
205cb477c30SDaniel Golle 
20651578203SDaniel Golle 	reg_port = port + priv->hw_info->mii_port_reg_offset;
20751578203SDaniel Golle 
20851578203SDaniel Golle 	switch (reg_port) {
209cb477c30SDaniel Golle 	case 0:
210cb477c30SDaniel Golle 		gswip_mii_mask(priv, clear, set, GSWIP_MII_PCDU0);
211cb477c30SDaniel Golle 		break;
212cb477c30SDaniel Golle 	case 1:
213cb477c30SDaniel Golle 		gswip_mii_mask(priv, clear, set, GSWIP_MII_PCDU1);
214cb477c30SDaniel Golle 		break;
215cb477c30SDaniel Golle 	case 5:
216cb477c30SDaniel Golle 		gswip_mii_mask(priv, clear, set, GSWIP_MII_PCDU5);
217cb477c30SDaniel Golle 		break;
218cb477c30SDaniel Golle 	}
219cb477c30SDaniel Golle }
220cb477c30SDaniel Golle 
221cb477c30SDaniel Golle static int gswip_mdio_poll(struct gswip_priv *priv)
222cb477c30SDaniel Golle {
223cb477c30SDaniel Golle 	int cnt = 100;
224cb477c30SDaniel Golle 
225cb477c30SDaniel Golle 	while (likely(cnt--)) {
226cb477c30SDaniel Golle 		u32 ctrl = gswip_mdio_r(priv, GSWIP_MDIO_CTRL);
227cb477c30SDaniel Golle 
228cb477c30SDaniel Golle 		if ((ctrl & GSWIP_MDIO_CTRL_BUSY) == 0)
229cb477c30SDaniel Golle 			return 0;
230cb477c30SDaniel Golle 		usleep_range(20, 40);
231cb477c30SDaniel Golle 	}
232cb477c30SDaniel Golle 
233cb477c30SDaniel Golle 	return -ETIMEDOUT;
234cb477c30SDaniel Golle }
235cb477c30SDaniel Golle 
236cb477c30SDaniel Golle static int gswip_mdio_wr(struct mii_bus *bus, int addr, int reg, u16 val)
237cb477c30SDaniel Golle {
238cb477c30SDaniel Golle 	struct gswip_priv *priv = bus->priv;
239cb477c30SDaniel Golle 	int err;
240cb477c30SDaniel Golle 
241cb477c30SDaniel Golle 	err = gswip_mdio_poll(priv);
242cb477c30SDaniel Golle 	if (err) {
243cb477c30SDaniel Golle 		dev_err(&bus->dev, "waiting for MDIO bus busy timed out\n");
244cb477c30SDaniel Golle 		return err;
245cb477c30SDaniel Golle 	}
246cb477c30SDaniel Golle 
247cb477c30SDaniel Golle 	gswip_mdio_w(priv, val, GSWIP_MDIO_WRITE);
248cb477c30SDaniel Golle 	gswip_mdio_w(priv, GSWIP_MDIO_CTRL_BUSY | GSWIP_MDIO_CTRL_WR |
249cb477c30SDaniel Golle 		((addr & GSWIP_MDIO_CTRL_PHYAD_MASK) << GSWIP_MDIO_CTRL_PHYAD_SHIFT) |
250cb477c30SDaniel Golle 		(reg & GSWIP_MDIO_CTRL_REGAD_MASK),
251cb477c30SDaniel Golle 		GSWIP_MDIO_CTRL);
252cb477c30SDaniel Golle 
253cb477c30SDaniel Golle 	return 0;
254cb477c30SDaniel Golle }
255cb477c30SDaniel Golle 
256cb477c30SDaniel Golle static int gswip_mdio_rd(struct mii_bus *bus, int addr, int reg)
257cb477c30SDaniel Golle {
258cb477c30SDaniel Golle 	struct gswip_priv *priv = bus->priv;
259cb477c30SDaniel Golle 	int err;
260cb477c30SDaniel Golle 
261cb477c30SDaniel Golle 	err = gswip_mdio_poll(priv);
262cb477c30SDaniel Golle 	if (err) {
263cb477c30SDaniel Golle 		dev_err(&bus->dev, "waiting for MDIO bus busy timed out\n");
264cb477c30SDaniel Golle 		return err;
265cb477c30SDaniel Golle 	}
266cb477c30SDaniel Golle 
267cb477c30SDaniel Golle 	gswip_mdio_w(priv, GSWIP_MDIO_CTRL_BUSY | GSWIP_MDIO_CTRL_RD |
268cb477c30SDaniel Golle 		((addr & GSWIP_MDIO_CTRL_PHYAD_MASK) << GSWIP_MDIO_CTRL_PHYAD_SHIFT) |
269cb477c30SDaniel Golle 		(reg & GSWIP_MDIO_CTRL_REGAD_MASK),
270cb477c30SDaniel Golle 		GSWIP_MDIO_CTRL);
271cb477c30SDaniel Golle 
272cb477c30SDaniel Golle 	err = gswip_mdio_poll(priv);
273cb477c30SDaniel Golle 	if (err) {
274cb477c30SDaniel Golle 		dev_err(&bus->dev, "waiting for MDIO bus busy timed out\n");
275cb477c30SDaniel Golle 		return err;
276cb477c30SDaniel Golle 	}
277cb477c30SDaniel Golle 
278cb477c30SDaniel Golle 	return gswip_mdio_r(priv, GSWIP_MDIO_READ);
279cb477c30SDaniel Golle }
280cb477c30SDaniel Golle 
281cb477c30SDaniel Golle static int gswip_mdio(struct gswip_priv *priv)
282cb477c30SDaniel Golle {
283cb477c30SDaniel Golle 	struct device_node *mdio_np, *switch_np = priv->dev->of_node;
284cb477c30SDaniel Golle 	struct device *dev = priv->dev;
285cb477c30SDaniel Golle 	struct mii_bus *bus;
286cb477c30SDaniel Golle 	int err = 0;
287cb477c30SDaniel Golle 
288cb477c30SDaniel Golle 	mdio_np = of_get_compatible_child(switch_np, "lantiq,xrx200-mdio");
289*720412c4SDaniel Golle 	if (!mdio_np)
290*720412c4SDaniel Golle 		mdio_np = of_get_child_by_name(switch_np, "mdio");
291*720412c4SDaniel Golle 
292cb477c30SDaniel Golle 	if (!of_device_is_available(mdio_np))
293cb477c30SDaniel Golle 		goto out_put_node;
294cb477c30SDaniel Golle 
295cb477c30SDaniel Golle 	bus = devm_mdiobus_alloc(dev);
296cb477c30SDaniel Golle 	if (!bus) {
297cb477c30SDaniel Golle 		err = -ENOMEM;
298cb477c30SDaniel Golle 		goto out_put_node;
299cb477c30SDaniel Golle 	}
300cb477c30SDaniel Golle 
301cb477c30SDaniel Golle 	bus->priv = priv;
302cb477c30SDaniel Golle 	bus->read = gswip_mdio_rd;
303cb477c30SDaniel Golle 	bus->write = gswip_mdio_wr;
304cb477c30SDaniel Golle 	bus->name = "lantiq,xrx200-mdio";
305cb477c30SDaniel Golle 	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(priv->dev));
306cb477c30SDaniel Golle 	bus->parent = priv->dev;
307cb477c30SDaniel Golle 
308cb477c30SDaniel Golle 	err = devm_of_mdiobus_register(dev, bus, mdio_np);
309cb477c30SDaniel Golle 
310cb477c30SDaniel Golle out_put_node:
311cb477c30SDaniel Golle 	of_node_put(mdio_np);
312cb477c30SDaniel Golle 
313cb477c30SDaniel Golle 	return err;
314cb477c30SDaniel Golle }
315cb477c30SDaniel Golle 
316cb477c30SDaniel Golle static int gswip_pce_table_entry_read(struct gswip_priv *priv,
317cb477c30SDaniel Golle 				      struct gswip_pce_table_entry *tbl)
318cb477c30SDaniel Golle {
319cb477c30SDaniel Golle 	int i;
320cb477c30SDaniel Golle 	int err;
321cb477c30SDaniel Golle 	u16 crtl;
322cb477c30SDaniel Golle 	u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSRD :
323cb477c30SDaniel Golle 					GSWIP_PCE_TBL_CTRL_OPMOD_ADRD;
324cb477c30SDaniel Golle 
325cb477c30SDaniel Golle 	mutex_lock(&priv->pce_table_lock);
326cb477c30SDaniel Golle 
327cb477c30SDaniel Golle 	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
328cb477c30SDaniel Golle 				     GSWIP_PCE_TBL_CTRL_BAS);
329cb477c30SDaniel Golle 	if (err) {
330cb477c30SDaniel Golle 		mutex_unlock(&priv->pce_table_lock);
331cb477c30SDaniel Golle 		return err;
332cb477c30SDaniel Golle 	}
333cb477c30SDaniel Golle 
334cb477c30SDaniel Golle 	gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR);
335cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
336cb477c30SDaniel Golle 				GSWIP_PCE_TBL_CTRL_OPMOD_MASK,
337cb477c30SDaniel Golle 			  tbl->table | addr_mode | GSWIP_PCE_TBL_CTRL_BAS,
338cb477c30SDaniel Golle 			  GSWIP_PCE_TBL_CTRL);
339cb477c30SDaniel Golle 
340cb477c30SDaniel Golle 	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
341cb477c30SDaniel Golle 				     GSWIP_PCE_TBL_CTRL_BAS);
342cb477c30SDaniel Golle 	if (err) {
343cb477c30SDaniel Golle 		mutex_unlock(&priv->pce_table_lock);
344cb477c30SDaniel Golle 		return err;
345cb477c30SDaniel Golle 	}
346cb477c30SDaniel Golle 
347cb477c30SDaniel Golle 	for (i = 0; i < ARRAY_SIZE(tbl->key); i++)
348cb477c30SDaniel Golle 		tbl->key[i] = gswip_switch_r(priv, GSWIP_PCE_TBL_KEY(i));
349cb477c30SDaniel Golle 
350cb477c30SDaniel Golle 	for (i = 0; i < ARRAY_SIZE(tbl->val); i++)
351cb477c30SDaniel Golle 		tbl->val[i] = gswip_switch_r(priv, GSWIP_PCE_TBL_VAL(i));
352cb477c30SDaniel Golle 
353cb477c30SDaniel Golle 	tbl->mask = gswip_switch_r(priv, GSWIP_PCE_TBL_MASK);
354cb477c30SDaniel Golle 
355cb477c30SDaniel Golle 	crtl = gswip_switch_r(priv, GSWIP_PCE_TBL_CTRL);
356cb477c30SDaniel Golle 
357cb477c30SDaniel Golle 	tbl->type = !!(crtl & GSWIP_PCE_TBL_CTRL_TYPE);
358cb477c30SDaniel Golle 	tbl->valid = !!(crtl & GSWIP_PCE_TBL_CTRL_VLD);
359cb477c30SDaniel Golle 	tbl->gmap = (crtl & GSWIP_PCE_TBL_CTRL_GMAP_MASK) >> 7;
360cb477c30SDaniel Golle 
361cb477c30SDaniel Golle 	mutex_unlock(&priv->pce_table_lock);
362cb477c30SDaniel Golle 
363cb477c30SDaniel Golle 	return 0;
364cb477c30SDaniel Golle }
365cb477c30SDaniel Golle 
366cb477c30SDaniel Golle static int gswip_pce_table_entry_write(struct gswip_priv *priv,
367cb477c30SDaniel Golle 				       struct gswip_pce_table_entry *tbl)
368cb477c30SDaniel Golle {
369cb477c30SDaniel Golle 	int i;
370cb477c30SDaniel Golle 	int err;
371cb477c30SDaniel Golle 	u16 crtl;
372cb477c30SDaniel Golle 	u16 addr_mode = tbl->key_mode ? GSWIP_PCE_TBL_CTRL_OPMOD_KSWR :
373cb477c30SDaniel Golle 					GSWIP_PCE_TBL_CTRL_OPMOD_ADWR;
374cb477c30SDaniel Golle 
375cb477c30SDaniel Golle 	mutex_lock(&priv->pce_table_lock);
376cb477c30SDaniel Golle 
377cb477c30SDaniel Golle 	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
378cb477c30SDaniel Golle 				     GSWIP_PCE_TBL_CTRL_BAS);
379cb477c30SDaniel Golle 	if (err) {
380cb477c30SDaniel Golle 		mutex_unlock(&priv->pce_table_lock);
381cb477c30SDaniel Golle 		return err;
382cb477c30SDaniel Golle 	}
383cb477c30SDaniel Golle 
384cb477c30SDaniel Golle 	gswip_switch_w(priv, tbl->index, GSWIP_PCE_TBL_ADDR);
385cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
386cb477c30SDaniel Golle 				GSWIP_PCE_TBL_CTRL_OPMOD_MASK,
387cb477c30SDaniel Golle 			  tbl->table | addr_mode,
388cb477c30SDaniel Golle 			  GSWIP_PCE_TBL_CTRL);
389cb477c30SDaniel Golle 
390cb477c30SDaniel Golle 	for (i = 0; i < ARRAY_SIZE(tbl->key); i++)
391cb477c30SDaniel Golle 		gswip_switch_w(priv, tbl->key[i], GSWIP_PCE_TBL_KEY(i));
392cb477c30SDaniel Golle 
393cb477c30SDaniel Golle 	for (i = 0; i < ARRAY_SIZE(tbl->val); i++)
394cb477c30SDaniel Golle 		gswip_switch_w(priv, tbl->val[i], GSWIP_PCE_TBL_VAL(i));
395cb477c30SDaniel Golle 
396cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
397cb477c30SDaniel Golle 				GSWIP_PCE_TBL_CTRL_OPMOD_MASK,
398cb477c30SDaniel Golle 			  tbl->table | addr_mode,
399cb477c30SDaniel Golle 			  GSWIP_PCE_TBL_CTRL);
400cb477c30SDaniel Golle 
401cb477c30SDaniel Golle 	gswip_switch_w(priv, tbl->mask, GSWIP_PCE_TBL_MASK);
402cb477c30SDaniel Golle 
403cb477c30SDaniel Golle 	crtl = gswip_switch_r(priv, GSWIP_PCE_TBL_CTRL);
404cb477c30SDaniel Golle 	crtl &= ~(GSWIP_PCE_TBL_CTRL_TYPE | GSWIP_PCE_TBL_CTRL_VLD |
405cb477c30SDaniel Golle 		  GSWIP_PCE_TBL_CTRL_GMAP_MASK);
406cb477c30SDaniel Golle 	if (tbl->type)
407cb477c30SDaniel Golle 		crtl |= GSWIP_PCE_TBL_CTRL_TYPE;
408cb477c30SDaniel Golle 	if (tbl->valid)
409cb477c30SDaniel Golle 		crtl |= GSWIP_PCE_TBL_CTRL_VLD;
410cb477c30SDaniel Golle 	crtl |= (tbl->gmap << 7) & GSWIP_PCE_TBL_CTRL_GMAP_MASK;
411cb477c30SDaniel Golle 	crtl |= GSWIP_PCE_TBL_CTRL_BAS;
412cb477c30SDaniel Golle 	gswip_switch_w(priv, crtl, GSWIP_PCE_TBL_CTRL);
413cb477c30SDaniel Golle 
414cb477c30SDaniel Golle 	err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
415cb477c30SDaniel Golle 				     GSWIP_PCE_TBL_CTRL_BAS);
416cb477c30SDaniel Golle 
417cb477c30SDaniel Golle 	mutex_unlock(&priv->pce_table_lock);
418cb477c30SDaniel Golle 
419cb477c30SDaniel Golle 	return err;
420cb477c30SDaniel Golle }
421cb477c30SDaniel Golle 
422cb477c30SDaniel Golle /* Add the LAN port into a bridge with the CPU port by
423cb477c30SDaniel Golle  * default. This prevents automatic forwarding of
424cb477c30SDaniel Golle  * packages between the LAN ports when no explicit
425cb477c30SDaniel Golle  * bridge is configured.
426cb477c30SDaniel Golle  */
427cb477c30SDaniel Golle static int gswip_add_single_port_br(struct gswip_priv *priv, int port, bool add)
428cb477c30SDaniel Golle {
429cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_active = {0,};
430cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_mapping = {0,};
431cb477c30SDaniel Golle 	int err;
432cb477c30SDaniel Golle 
433cb477c30SDaniel Golle 	vlan_active.index = port + 1;
434cb477c30SDaniel Golle 	vlan_active.table = GSWIP_TABLE_ACTIVE_VLAN;
435cb477c30SDaniel Golle 	vlan_active.key[0] = 0; /* vid */
436cb477c30SDaniel Golle 	vlan_active.val[0] = port + 1 /* fid */;
437cb477c30SDaniel Golle 	vlan_active.valid = add;
438cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_active);
439cb477c30SDaniel Golle 	if (err) {
440cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write active VLAN: %d\n", err);
441cb477c30SDaniel Golle 		return err;
442cb477c30SDaniel Golle 	}
443cb477c30SDaniel Golle 
444cb477c30SDaniel Golle 	if (!add)
445cb477c30SDaniel Golle 		return 0;
446cb477c30SDaniel Golle 
447cb477c30SDaniel Golle 	vlan_mapping.index = port + 1;
448cb477c30SDaniel Golle 	vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
449cb477c30SDaniel Golle 	vlan_mapping.val[0] = 0 /* vid */;
450cb477c30SDaniel Golle 	vlan_mapping.val[1] = BIT(port) | dsa_cpu_ports(priv->ds);
451cb477c30SDaniel Golle 	vlan_mapping.val[2] = 0;
452cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_mapping);
453cb477c30SDaniel Golle 	if (err) {
454cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err);
455cb477c30SDaniel Golle 		return err;
456cb477c30SDaniel Golle 	}
457cb477c30SDaniel Golle 
458cb477c30SDaniel Golle 	return 0;
459cb477c30SDaniel Golle }
460cb477c30SDaniel Golle 
461cb477c30SDaniel Golle static int gswip_port_enable(struct dsa_switch *ds, int port,
462cb477c30SDaniel Golle 			     struct phy_device *phydev)
463cb477c30SDaniel Golle {
464cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
465cb477c30SDaniel Golle 	int err;
466cb477c30SDaniel Golle 
467cb477c30SDaniel Golle 	if (!dsa_is_cpu_port(ds, port)) {
468cb477c30SDaniel Golle 		u32 mdio_phy = 0;
469cb477c30SDaniel Golle 
470cb477c30SDaniel Golle 		err = gswip_add_single_port_br(priv, port, true);
471cb477c30SDaniel Golle 		if (err)
472cb477c30SDaniel Golle 			return err;
473cb477c30SDaniel Golle 
474cb477c30SDaniel Golle 		if (phydev)
475cb477c30SDaniel Golle 			mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK;
476cb477c30SDaniel Golle 
477cb477c30SDaniel Golle 		gswip_mdio_mask(priv, GSWIP_MDIO_PHY_ADDR_MASK, mdio_phy,
478cb477c30SDaniel Golle 				GSWIP_MDIO_PHYp(port));
479cb477c30SDaniel Golle 	}
480cb477c30SDaniel Golle 
481cb477c30SDaniel Golle 	/* RMON Counter Enable for port */
482cb477c30SDaniel Golle 	gswip_switch_w(priv, GSWIP_BM_PCFG_CNTEN, GSWIP_BM_PCFGp(port));
483cb477c30SDaniel Golle 
484cb477c30SDaniel Golle 	/* enable port fetch/store dma & VLAN Modification */
485cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_EN |
486cb477c30SDaniel Golle 				   GSWIP_FDMA_PCTRL_VLANMOD_BOTH,
487cb477c30SDaniel Golle 			 GSWIP_FDMA_PCTRLp(port));
488cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_SDMA_PCTRL_EN,
489cb477c30SDaniel Golle 			  GSWIP_SDMA_PCTRLp(port));
490cb477c30SDaniel Golle 
491cb477c30SDaniel Golle 	return 0;
492cb477c30SDaniel Golle }
493cb477c30SDaniel Golle 
494cb477c30SDaniel Golle static void gswip_port_disable(struct dsa_switch *ds, int port)
495cb477c30SDaniel Golle {
496cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
497cb477c30SDaniel Golle 
498cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_FDMA_PCTRL_EN, 0,
499cb477c30SDaniel Golle 			  GSWIP_FDMA_PCTRLp(port));
500cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_SDMA_PCTRL_EN, 0,
501cb477c30SDaniel Golle 			  GSWIP_SDMA_PCTRLp(port));
502cb477c30SDaniel Golle }
503cb477c30SDaniel Golle 
504cb477c30SDaniel Golle static int gswip_pce_load_microcode(struct gswip_priv *priv)
505cb477c30SDaniel Golle {
506cb477c30SDaniel Golle 	int i;
507cb477c30SDaniel Golle 	int err;
508cb477c30SDaniel Golle 
509cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_PCE_TBL_CTRL_ADDR_MASK |
510cb477c30SDaniel Golle 				GSWIP_PCE_TBL_CTRL_OPMOD_MASK,
511cb477c30SDaniel Golle 			  GSWIP_PCE_TBL_CTRL_OPMOD_ADWR, GSWIP_PCE_TBL_CTRL);
512cb477c30SDaniel Golle 	gswip_switch_w(priv, 0, GSWIP_PCE_TBL_MASK);
513cb477c30SDaniel Golle 
514cb477c30SDaniel Golle 	for (i = 0; i < priv->hw_info->pce_microcode_size; i++) {
515cb477c30SDaniel Golle 		gswip_switch_w(priv, i, GSWIP_PCE_TBL_ADDR);
516cb477c30SDaniel Golle 		gswip_switch_w(priv, (*priv->hw_info->pce_microcode)[i].val_0,
517cb477c30SDaniel Golle 			       GSWIP_PCE_TBL_VAL(0));
518cb477c30SDaniel Golle 		gswip_switch_w(priv, (*priv->hw_info->pce_microcode)[i].val_1,
519cb477c30SDaniel Golle 			       GSWIP_PCE_TBL_VAL(1));
520cb477c30SDaniel Golle 		gswip_switch_w(priv, (*priv->hw_info->pce_microcode)[i].val_2,
521cb477c30SDaniel Golle 			       GSWIP_PCE_TBL_VAL(2));
522cb477c30SDaniel Golle 		gswip_switch_w(priv, (*priv->hw_info->pce_microcode)[i].val_3,
523cb477c30SDaniel Golle 			       GSWIP_PCE_TBL_VAL(3));
524cb477c30SDaniel Golle 
525cb477c30SDaniel Golle 		/* start the table access: */
526cb477c30SDaniel Golle 		gswip_switch_mask(priv, 0, GSWIP_PCE_TBL_CTRL_BAS,
527cb477c30SDaniel Golle 				  GSWIP_PCE_TBL_CTRL);
528cb477c30SDaniel Golle 		err = gswip_switch_r_timeout(priv, GSWIP_PCE_TBL_CTRL,
529cb477c30SDaniel Golle 					     GSWIP_PCE_TBL_CTRL_BAS);
530cb477c30SDaniel Golle 		if (err)
531cb477c30SDaniel Golle 			return err;
532cb477c30SDaniel Golle 	}
533cb477c30SDaniel Golle 
534cb477c30SDaniel Golle 	/* tell the switch that the microcode is loaded */
535cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_PCE_GCTRL_0_MC_VALID,
536cb477c30SDaniel Golle 			  GSWIP_PCE_GCTRL_0);
537cb477c30SDaniel Golle 
538cb477c30SDaniel Golle 	return 0;
539cb477c30SDaniel Golle }
540cb477c30SDaniel Golle 
541cb477c30SDaniel Golle static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port,
542cb477c30SDaniel Golle 				     bool vlan_filtering,
543cb477c30SDaniel Golle 				     struct netlink_ext_ack *extack)
544cb477c30SDaniel Golle {
545cb477c30SDaniel Golle 	struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port));
546cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
547cb477c30SDaniel Golle 
548cb477c30SDaniel Golle 	/* Do not allow changing the VLAN filtering options while in bridge */
549cb477c30SDaniel Golle 	if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) {
550cb477c30SDaniel Golle 		NL_SET_ERR_MSG_MOD(extack,
551cb477c30SDaniel Golle 				   "Dynamic toggling of vlan_filtering not supported");
552cb477c30SDaniel Golle 		return -EIO;
553cb477c30SDaniel Golle 	}
554cb477c30SDaniel Golle 
555cb477c30SDaniel Golle 	if (vlan_filtering) {
556cb477c30SDaniel Golle 		/* Use tag based VLAN */
557cb477c30SDaniel Golle 		gswip_switch_mask(priv,
558cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL_VSR,
559cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL_UVR | GSWIP_PCE_VCTRL_VIMR |
560cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL_VEMR,
561cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL(port));
562cb477c30SDaniel Golle 		gswip_switch_mask(priv, GSWIP_PCE_PCTRL_0_TVM, 0,
563cb477c30SDaniel Golle 				  GSWIP_PCE_PCTRL_0p(port));
564cb477c30SDaniel Golle 	} else {
565cb477c30SDaniel Golle 		/* Use port based VLAN */
566cb477c30SDaniel Golle 		gswip_switch_mask(priv,
567cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL_UVR | GSWIP_PCE_VCTRL_VIMR |
568cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL_VEMR,
569cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL_VSR,
570cb477c30SDaniel Golle 				  GSWIP_PCE_VCTRL(port));
571cb477c30SDaniel Golle 		gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_TVM,
572cb477c30SDaniel Golle 				  GSWIP_PCE_PCTRL_0p(port));
573cb477c30SDaniel Golle 	}
574cb477c30SDaniel Golle 
575cb477c30SDaniel Golle 	return 0;
576cb477c30SDaniel Golle }
577cb477c30SDaniel Golle 
578cb477c30SDaniel Golle static int gswip_setup(struct dsa_switch *ds)
579cb477c30SDaniel Golle {
580cb477c30SDaniel Golle 	unsigned int cpu_ports = dsa_cpu_ports(ds);
581cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
582cb477c30SDaniel Golle 	struct dsa_port *cpu_dp;
583cb477c30SDaniel Golle 	int err, i;
584cb477c30SDaniel Golle 
585cb477c30SDaniel Golle 	gswip_switch_w(priv, GSWIP_SWRES_R0, GSWIP_SWRES);
586cb477c30SDaniel Golle 	usleep_range(5000, 10000);
587cb477c30SDaniel Golle 	gswip_switch_w(priv, 0, GSWIP_SWRES);
588cb477c30SDaniel Golle 
589cb477c30SDaniel Golle 	/* disable port fetch/store dma on all ports */
590cb477c30SDaniel Golle 	for (i = 0; i < priv->hw_info->max_ports; i++) {
591cb477c30SDaniel Golle 		gswip_port_disable(ds, i);
592cb477c30SDaniel Golle 		gswip_port_vlan_filtering(ds, i, false, NULL);
593cb477c30SDaniel Golle 	}
594cb477c30SDaniel Golle 
595cb477c30SDaniel Golle 	/* enable Switch */
596cb477c30SDaniel Golle 	gswip_mdio_mask(priv, 0, GSWIP_MDIO_GLOB_ENABLE, GSWIP_MDIO_GLOB);
597cb477c30SDaniel Golle 
598cb477c30SDaniel Golle 	err = gswip_pce_load_microcode(priv);
599cb477c30SDaniel Golle 	if (err) {
600cb477c30SDaniel Golle 		dev_err(priv->dev, "writing PCE microcode failed, %i\n", err);
601cb477c30SDaniel Golle 		return err;
602cb477c30SDaniel Golle 	}
603cb477c30SDaniel Golle 
604cb477c30SDaniel Golle 	/* Default unknown Broadcast/Multicast/Unicast port maps */
605cb477c30SDaniel Golle 	gswip_switch_w(priv, cpu_ports, GSWIP_PCE_PMAP1);
606cb477c30SDaniel Golle 	gswip_switch_w(priv, cpu_ports, GSWIP_PCE_PMAP2);
607cb477c30SDaniel Golle 	gswip_switch_w(priv, cpu_ports, GSWIP_PCE_PMAP3);
608cb477c30SDaniel Golle 
609cb477c30SDaniel Golle 	/* Deactivate MDIO PHY auto polling. Some PHYs as the AR8030 have an
610cb477c30SDaniel Golle 	 * interoperability problem with this auto polling mechanism because
611cb477c30SDaniel Golle 	 * their status registers think that the link is in a different state
612cb477c30SDaniel Golle 	 * than it actually is. For the AR8030 it has the BMSR_ESTATEN bit set
613cb477c30SDaniel Golle 	 * as well as ESTATUS_1000_TFULL and ESTATUS_1000_XFULL. This makes the
614cb477c30SDaniel Golle 	 * auto polling state machine consider the link being negotiated with
615cb477c30SDaniel Golle 	 * 1Gbit/s. Since the PHY itself is a Fast Ethernet RMII PHY this leads
616cb477c30SDaniel Golle 	 * to the switch port being completely dead (RX and TX are both not
617cb477c30SDaniel Golle 	 * working).
618cb477c30SDaniel Golle 	 * Also with various other PHY / port combinations (PHY11G GPHY, PHY22F
619cb477c30SDaniel Golle 	 * GPHY, external RGMII PEF7071/7072) any traffic would stop. Sometimes
620cb477c30SDaniel Golle 	 * it would work fine for a few minutes to hours and then stop, on
621cb477c30SDaniel Golle 	 * other device it would no traffic could be sent or received at all.
622cb477c30SDaniel Golle 	 * Testing shows that when PHY auto polling is disabled these problems
623cb477c30SDaniel Golle 	 * go away.
624cb477c30SDaniel Golle 	 */
625cb477c30SDaniel Golle 	gswip_mdio_w(priv, 0x0, GSWIP_MDIO_MDC_CFG0);
626cb477c30SDaniel Golle 
627cb477c30SDaniel Golle 	/* Configure the MDIO Clock 2.5 MHz */
628cb477c30SDaniel Golle 	gswip_mdio_mask(priv, 0xff, 0x09, GSWIP_MDIO_MDC_CFG1);
629cb477c30SDaniel Golle 
630cb477c30SDaniel Golle 	/* Disable the xMII interface and clear it's isolation bit */
631cb477c30SDaniel Golle 	for (i = 0; i < priv->hw_info->max_ports; i++)
632cb477c30SDaniel Golle 		gswip_mii_mask_cfg(priv,
633cb477c30SDaniel Golle 				   GSWIP_MII_CFG_EN | GSWIP_MII_CFG_ISOLATE,
634cb477c30SDaniel Golle 				   0, i);
635cb477c30SDaniel Golle 
636cb477c30SDaniel Golle 	dsa_switch_for_each_cpu_port(cpu_dp, ds) {
637cb477c30SDaniel Golle 		/* enable special tag insertion on cpu port */
638cb477c30SDaniel Golle 		gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN,
639cb477c30SDaniel Golle 				  GSWIP_FDMA_PCTRLp(cpu_dp->index));
640cb477c30SDaniel Golle 
641cb477c30SDaniel Golle 		/* accept special tag in ingress direction */
642cb477c30SDaniel Golle 		gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
643cb477c30SDaniel Golle 				  GSWIP_PCE_PCTRL_0p(cpu_dp->index));
644cb477c30SDaniel Golle 	}
645cb477c30SDaniel Golle 
646cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
647cb477c30SDaniel Golle 			  GSWIP_BM_QUEUE_GCTRL);
648cb477c30SDaniel Golle 
649cb477c30SDaniel Golle 	/* VLAN aware Switching */
650cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_PCE_GCTRL_0_VLAN, GSWIP_PCE_GCTRL_0);
651cb477c30SDaniel Golle 
652cb477c30SDaniel Golle 	/* Flush MAC Table */
653cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_PCE_GCTRL_0_MTFL, GSWIP_PCE_GCTRL_0);
654cb477c30SDaniel Golle 
655cb477c30SDaniel Golle 	err = gswip_switch_r_timeout(priv, GSWIP_PCE_GCTRL_0,
656cb477c30SDaniel Golle 				     GSWIP_PCE_GCTRL_0_MTFL);
657cb477c30SDaniel Golle 	if (err) {
658cb477c30SDaniel Golle 		dev_err(priv->dev, "MAC flushing didn't finish\n");
659cb477c30SDaniel Golle 		return err;
660cb477c30SDaniel Golle 	}
661cb477c30SDaniel Golle 
662cb477c30SDaniel Golle 	ds->mtu_enforcement_ingress = true;
663cb477c30SDaniel Golle 
664cb477c30SDaniel Golle 	ds->configure_vlan_while_not_filtering = false;
665cb477c30SDaniel Golle 
666cb477c30SDaniel Golle 	return 0;
667cb477c30SDaniel Golle }
668cb477c30SDaniel Golle 
669cb477c30SDaniel Golle static enum dsa_tag_protocol gswip_get_tag_protocol(struct dsa_switch *ds,
670cb477c30SDaniel Golle 						    int port,
671cb477c30SDaniel Golle 						    enum dsa_tag_protocol mp)
672cb477c30SDaniel Golle {
673cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
674cb477c30SDaniel Golle 
675cb477c30SDaniel Golle 	return priv->hw_info->tag_protocol;
676cb477c30SDaniel Golle }
677cb477c30SDaniel Golle 
678cb477c30SDaniel Golle static int gswip_vlan_active_create(struct gswip_priv *priv,
679cb477c30SDaniel Golle 				    struct net_device *bridge,
680cb477c30SDaniel Golle 				    int fid, u16 vid)
681cb477c30SDaniel Golle {
682cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_active = {0,};
683cb477c30SDaniel Golle 	unsigned int max_ports = priv->hw_info->max_ports;
684cb477c30SDaniel Golle 	int idx = -1;
685cb477c30SDaniel Golle 	int err;
686cb477c30SDaniel Golle 	int i;
687cb477c30SDaniel Golle 
688cb477c30SDaniel Golle 	/* Look for a free slot */
689cb477c30SDaniel Golle 	for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
690cb477c30SDaniel Golle 		if (!priv->vlans[i].bridge) {
691cb477c30SDaniel Golle 			idx = i;
692cb477c30SDaniel Golle 			break;
693cb477c30SDaniel Golle 		}
694cb477c30SDaniel Golle 	}
695cb477c30SDaniel Golle 
696cb477c30SDaniel Golle 	if (idx == -1)
697cb477c30SDaniel Golle 		return -ENOSPC;
698cb477c30SDaniel Golle 
699cb477c30SDaniel Golle 	if (fid == -1)
700cb477c30SDaniel Golle 		fid = idx;
701cb477c30SDaniel Golle 
702cb477c30SDaniel Golle 	vlan_active.index = idx;
703cb477c30SDaniel Golle 	vlan_active.table = GSWIP_TABLE_ACTIVE_VLAN;
704cb477c30SDaniel Golle 	vlan_active.key[0] = vid;
705cb477c30SDaniel Golle 	vlan_active.val[0] = fid;
706cb477c30SDaniel Golle 	vlan_active.valid = true;
707cb477c30SDaniel Golle 
708cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_active);
709cb477c30SDaniel Golle 	if (err) {
710cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write active VLAN: %d\n",	err);
711cb477c30SDaniel Golle 		return err;
712cb477c30SDaniel Golle 	}
713cb477c30SDaniel Golle 
714cb477c30SDaniel Golle 	priv->vlans[idx].bridge = bridge;
715cb477c30SDaniel Golle 	priv->vlans[idx].vid = vid;
716cb477c30SDaniel Golle 	priv->vlans[idx].fid = fid;
717cb477c30SDaniel Golle 
718cb477c30SDaniel Golle 	return idx;
719cb477c30SDaniel Golle }
720cb477c30SDaniel Golle 
721cb477c30SDaniel Golle static int gswip_vlan_active_remove(struct gswip_priv *priv, int idx)
722cb477c30SDaniel Golle {
723cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_active = {0,};
724cb477c30SDaniel Golle 	int err;
725cb477c30SDaniel Golle 
726cb477c30SDaniel Golle 	vlan_active.index = idx;
727cb477c30SDaniel Golle 	vlan_active.table = GSWIP_TABLE_ACTIVE_VLAN;
728cb477c30SDaniel Golle 	vlan_active.valid = false;
729cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_active);
730cb477c30SDaniel Golle 	if (err)
731cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to delete active VLAN: %d\n", err);
732cb477c30SDaniel Golle 	priv->vlans[idx].bridge = NULL;
733cb477c30SDaniel Golle 
734cb477c30SDaniel Golle 	return err;
735cb477c30SDaniel Golle }
736cb477c30SDaniel Golle 
737cb477c30SDaniel Golle static int gswip_vlan_add_unaware(struct gswip_priv *priv,
738cb477c30SDaniel Golle 				  struct net_device *bridge, int port)
739cb477c30SDaniel Golle {
740cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_mapping = {0,};
741cb477c30SDaniel Golle 	unsigned int max_ports = priv->hw_info->max_ports;
742cb477c30SDaniel Golle 	bool active_vlan_created = false;
743cb477c30SDaniel Golle 	int idx = -1;
744cb477c30SDaniel Golle 	int i;
745cb477c30SDaniel Golle 	int err;
746cb477c30SDaniel Golle 
747cb477c30SDaniel Golle 	/* Check if there is already a page for this bridge */
748cb477c30SDaniel Golle 	for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
749cb477c30SDaniel Golle 		if (priv->vlans[i].bridge == bridge) {
750cb477c30SDaniel Golle 			idx = i;
751cb477c30SDaniel Golle 			break;
752cb477c30SDaniel Golle 		}
753cb477c30SDaniel Golle 	}
754cb477c30SDaniel Golle 
755cb477c30SDaniel Golle 	/* If this bridge is not programmed yet, add a Active VLAN table
756cb477c30SDaniel Golle 	 * entry in a free slot and prepare the VLAN mapping table entry.
757cb477c30SDaniel Golle 	 */
758cb477c30SDaniel Golle 	if (idx == -1) {
759cb477c30SDaniel Golle 		idx = gswip_vlan_active_create(priv, bridge, -1, 0);
760cb477c30SDaniel Golle 		if (idx < 0)
761cb477c30SDaniel Golle 			return idx;
762cb477c30SDaniel Golle 		active_vlan_created = true;
763cb477c30SDaniel Golle 
764cb477c30SDaniel Golle 		vlan_mapping.index = idx;
765cb477c30SDaniel Golle 		vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
766cb477c30SDaniel Golle 		/* VLAN ID byte, maps to the VLAN ID of vlan active table */
767cb477c30SDaniel Golle 		vlan_mapping.val[0] = 0;
768cb477c30SDaniel Golle 	} else {
769cb477c30SDaniel Golle 		/* Read the existing VLAN mapping entry from the switch */
770cb477c30SDaniel Golle 		vlan_mapping.index = idx;
771cb477c30SDaniel Golle 		vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
772cb477c30SDaniel Golle 		err = gswip_pce_table_entry_read(priv, &vlan_mapping);
773cb477c30SDaniel Golle 		if (err) {
774cb477c30SDaniel Golle 			dev_err(priv->dev, "failed to read VLAN mapping: %d\n",
775cb477c30SDaniel Golle 				err);
776cb477c30SDaniel Golle 			return err;
777cb477c30SDaniel Golle 		}
778cb477c30SDaniel Golle 	}
779cb477c30SDaniel Golle 
780cb477c30SDaniel Golle 	/* Update the VLAN mapping entry and write it to the switch */
781cb477c30SDaniel Golle 	vlan_mapping.val[1] |= dsa_cpu_ports(priv->ds);
782cb477c30SDaniel Golle 	vlan_mapping.val[1] |= BIT(port);
783cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_mapping);
784cb477c30SDaniel Golle 	if (err) {
785cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err);
786cb477c30SDaniel Golle 		/* In case an Active VLAN was creaetd delete it again */
787cb477c30SDaniel Golle 		if (active_vlan_created)
788cb477c30SDaniel Golle 			gswip_vlan_active_remove(priv, idx);
789cb477c30SDaniel Golle 		return err;
790cb477c30SDaniel Golle 	}
791cb477c30SDaniel Golle 
792cb477c30SDaniel Golle 	gswip_switch_w(priv, 0, GSWIP_PCE_DEFPVID(port));
793cb477c30SDaniel Golle 	return 0;
794cb477c30SDaniel Golle }
795cb477c30SDaniel Golle 
796cb477c30SDaniel Golle static int gswip_vlan_add_aware(struct gswip_priv *priv,
797cb477c30SDaniel Golle 				struct net_device *bridge, int port,
798cb477c30SDaniel Golle 				u16 vid, bool untagged,
799cb477c30SDaniel Golle 				bool pvid)
800cb477c30SDaniel Golle {
801cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_mapping = {0,};
802cb477c30SDaniel Golle 	unsigned int max_ports = priv->hw_info->max_ports;
803cb477c30SDaniel Golle 	unsigned int cpu_ports = dsa_cpu_ports(priv->ds);
804cb477c30SDaniel Golle 	bool active_vlan_created = false;
805cb477c30SDaniel Golle 	int idx = -1;
806cb477c30SDaniel Golle 	int fid = -1;
807cb477c30SDaniel Golle 	int i;
808cb477c30SDaniel Golle 	int err;
809cb477c30SDaniel Golle 
810cb477c30SDaniel Golle 	/* Check if there is already a page for this bridge */
811cb477c30SDaniel Golle 	for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
812cb477c30SDaniel Golle 		if (priv->vlans[i].bridge == bridge) {
813cb477c30SDaniel Golle 			if (fid != -1 && fid != priv->vlans[i].fid)
814cb477c30SDaniel Golle 				dev_err(priv->dev, "one bridge with multiple flow ids\n");
815cb477c30SDaniel Golle 			fid = priv->vlans[i].fid;
816cb477c30SDaniel Golle 			if (priv->vlans[i].vid == vid) {
817cb477c30SDaniel Golle 				idx = i;
818cb477c30SDaniel Golle 				break;
819cb477c30SDaniel Golle 			}
820cb477c30SDaniel Golle 		}
821cb477c30SDaniel Golle 	}
822cb477c30SDaniel Golle 
823cb477c30SDaniel Golle 	/* If this bridge is not programmed yet, add a Active VLAN table
824cb477c30SDaniel Golle 	 * entry in a free slot and prepare the VLAN mapping table entry.
825cb477c30SDaniel Golle 	 */
826cb477c30SDaniel Golle 	if (idx == -1) {
827cb477c30SDaniel Golle 		idx = gswip_vlan_active_create(priv, bridge, fid, vid);
828cb477c30SDaniel Golle 		if (idx < 0)
829cb477c30SDaniel Golle 			return idx;
830cb477c30SDaniel Golle 		active_vlan_created = true;
831cb477c30SDaniel Golle 
832cb477c30SDaniel Golle 		vlan_mapping.index = idx;
833cb477c30SDaniel Golle 		vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
834cb477c30SDaniel Golle 		/* VLAN ID byte, maps to the VLAN ID of vlan active table */
835cb477c30SDaniel Golle 		vlan_mapping.val[0] = vid;
836cb477c30SDaniel Golle 	} else {
837cb477c30SDaniel Golle 		/* Read the existing VLAN mapping entry from the switch */
838cb477c30SDaniel Golle 		vlan_mapping.index = idx;
839cb477c30SDaniel Golle 		vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
840cb477c30SDaniel Golle 		err = gswip_pce_table_entry_read(priv, &vlan_mapping);
841cb477c30SDaniel Golle 		if (err) {
842cb477c30SDaniel Golle 			dev_err(priv->dev, "failed to read VLAN mapping: %d\n",
843cb477c30SDaniel Golle 				err);
844cb477c30SDaniel Golle 			return err;
845cb477c30SDaniel Golle 		}
846cb477c30SDaniel Golle 	}
847cb477c30SDaniel Golle 
848cb477c30SDaniel Golle 	vlan_mapping.val[0] = vid;
849cb477c30SDaniel Golle 	/* Update the VLAN mapping entry and write it to the switch */
850cb477c30SDaniel Golle 	vlan_mapping.val[1] |= cpu_ports;
851cb477c30SDaniel Golle 	vlan_mapping.val[2] |= cpu_ports;
852cb477c30SDaniel Golle 	vlan_mapping.val[1] |= BIT(port);
853cb477c30SDaniel Golle 	if (untagged)
854cb477c30SDaniel Golle 		vlan_mapping.val[2] &= ~BIT(port);
855cb477c30SDaniel Golle 	else
856cb477c30SDaniel Golle 		vlan_mapping.val[2] |= BIT(port);
857cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_mapping);
858cb477c30SDaniel Golle 	if (err) {
859cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err);
860cb477c30SDaniel Golle 		/* In case an Active VLAN was creaetd delete it again */
861cb477c30SDaniel Golle 		if (active_vlan_created)
862cb477c30SDaniel Golle 			gswip_vlan_active_remove(priv, idx);
863cb477c30SDaniel Golle 		return err;
864cb477c30SDaniel Golle 	}
865cb477c30SDaniel Golle 
866cb477c30SDaniel Golle 	if (pvid)
867cb477c30SDaniel Golle 		gswip_switch_w(priv, idx, GSWIP_PCE_DEFPVID(port));
868cb477c30SDaniel Golle 
869cb477c30SDaniel Golle 	return 0;
870cb477c30SDaniel Golle }
871cb477c30SDaniel Golle 
872cb477c30SDaniel Golle static int gswip_vlan_remove(struct gswip_priv *priv,
873cb477c30SDaniel Golle 			     struct net_device *bridge, int port,
874cb477c30SDaniel Golle 			     u16 vid, bool pvid, bool vlan_aware)
875cb477c30SDaniel Golle {
876cb477c30SDaniel Golle 	struct gswip_pce_table_entry vlan_mapping = {0,};
877cb477c30SDaniel Golle 	unsigned int max_ports = priv->hw_info->max_ports;
878cb477c30SDaniel Golle 	int idx = -1;
879cb477c30SDaniel Golle 	int i;
880cb477c30SDaniel Golle 	int err;
881cb477c30SDaniel Golle 
882cb477c30SDaniel Golle 	/* Check if there is already a page for this bridge */
883cb477c30SDaniel Golle 	for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
884cb477c30SDaniel Golle 		if (priv->vlans[i].bridge == bridge &&
885cb477c30SDaniel Golle 		    (!vlan_aware || priv->vlans[i].vid == vid)) {
886cb477c30SDaniel Golle 			idx = i;
887cb477c30SDaniel Golle 			break;
888cb477c30SDaniel Golle 		}
889cb477c30SDaniel Golle 	}
890cb477c30SDaniel Golle 
891cb477c30SDaniel Golle 	if (idx == -1) {
892cb477c30SDaniel Golle 		dev_err(priv->dev, "bridge to leave does not exists\n");
893cb477c30SDaniel Golle 		return -ENOENT;
894cb477c30SDaniel Golle 	}
895cb477c30SDaniel Golle 
896cb477c30SDaniel Golle 	vlan_mapping.index = idx;
897cb477c30SDaniel Golle 	vlan_mapping.table = GSWIP_TABLE_VLAN_MAPPING;
898cb477c30SDaniel Golle 	err = gswip_pce_table_entry_read(priv, &vlan_mapping);
899cb477c30SDaniel Golle 	if (err) {
900cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to read VLAN mapping: %d\n",	err);
901cb477c30SDaniel Golle 		return err;
902cb477c30SDaniel Golle 	}
903cb477c30SDaniel Golle 
904cb477c30SDaniel Golle 	vlan_mapping.val[1] &= ~BIT(port);
905cb477c30SDaniel Golle 	vlan_mapping.val[2] &= ~BIT(port);
906cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &vlan_mapping);
907cb477c30SDaniel Golle 	if (err) {
908cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write VLAN mapping: %d\n", err);
909cb477c30SDaniel Golle 		return err;
910cb477c30SDaniel Golle 	}
911cb477c30SDaniel Golle 
912cb477c30SDaniel Golle 	/* In case all ports are removed from the bridge, remove the VLAN */
913cb477c30SDaniel Golle 	if (!(vlan_mapping.val[1] & ~dsa_cpu_ports(priv->ds))) {
914cb477c30SDaniel Golle 		err = gswip_vlan_active_remove(priv, idx);
915cb477c30SDaniel Golle 		if (err) {
916cb477c30SDaniel Golle 			dev_err(priv->dev, "failed to write active VLAN: %d\n",
917cb477c30SDaniel Golle 				err);
918cb477c30SDaniel Golle 			return err;
919cb477c30SDaniel Golle 		}
920cb477c30SDaniel Golle 	}
921cb477c30SDaniel Golle 
922cb477c30SDaniel Golle 	/* GSWIP 2.2 (GRX300) and later program here the VID directly. */
923cb477c30SDaniel Golle 	if (pvid)
924cb477c30SDaniel Golle 		gswip_switch_w(priv, 0, GSWIP_PCE_DEFPVID(port));
925cb477c30SDaniel Golle 
926cb477c30SDaniel Golle 	return 0;
927cb477c30SDaniel Golle }
928cb477c30SDaniel Golle 
929cb477c30SDaniel Golle static int gswip_port_bridge_join(struct dsa_switch *ds, int port,
930cb477c30SDaniel Golle 				  struct dsa_bridge bridge,
931cb477c30SDaniel Golle 				  bool *tx_fwd_offload,
932cb477c30SDaniel Golle 				  struct netlink_ext_ack *extack)
933cb477c30SDaniel Golle {
934cb477c30SDaniel Golle 	struct net_device *br = bridge.dev;
935cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
936cb477c30SDaniel Golle 	int err;
937cb477c30SDaniel Golle 
938cb477c30SDaniel Golle 	/* When the bridge uses VLAN filtering we have to configure VLAN
939cb477c30SDaniel Golle 	 * specific bridges. No bridge is configured here.
940cb477c30SDaniel Golle 	 */
941cb477c30SDaniel Golle 	if (!br_vlan_enabled(br)) {
942cb477c30SDaniel Golle 		err = gswip_vlan_add_unaware(priv, br, port);
943cb477c30SDaniel Golle 		if (err)
944cb477c30SDaniel Golle 			return err;
945cb477c30SDaniel Golle 		priv->port_vlan_filter &= ~BIT(port);
946cb477c30SDaniel Golle 	} else {
947cb477c30SDaniel Golle 		priv->port_vlan_filter |= BIT(port);
948cb477c30SDaniel Golle 	}
949cb477c30SDaniel Golle 	return gswip_add_single_port_br(priv, port, false);
950cb477c30SDaniel Golle }
951cb477c30SDaniel Golle 
952cb477c30SDaniel Golle static void gswip_port_bridge_leave(struct dsa_switch *ds, int port,
953cb477c30SDaniel Golle 				    struct dsa_bridge bridge)
954cb477c30SDaniel Golle {
955cb477c30SDaniel Golle 	struct net_device *br = bridge.dev;
956cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
957cb477c30SDaniel Golle 
958cb477c30SDaniel Golle 	gswip_add_single_port_br(priv, port, true);
959cb477c30SDaniel Golle 
960cb477c30SDaniel Golle 	/* When the bridge uses VLAN filtering we have to configure VLAN
961cb477c30SDaniel Golle 	 * specific bridges. No bridge is configured here.
962cb477c30SDaniel Golle 	 */
963cb477c30SDaniel Golle 	if (!br_vlan_enabled(br))
964cb477c30SDaniel Golle 		gswip_vlan_remove(priv, br, port, 0, true, false);
965cb477c30SDaniel Golle }
966cb477c30SDaniel Golle 
967cb477c30SDaniel Golle static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port,
968cb477c30SDaniel Golle 				   const struct switchdev_obj_port_vlan *vlan,
969cb477c30SDaniel Golle 				   struct netlink_ext_ack *extack)
970cb477c30SDaniel Golle {
971cb477c30SDaniel Golle 	struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port));
972cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
973cb477c30SDaniel Golle 	unsigned int max_ports = priv->hw_info->max_ports;
974cb477c30SDaniel Golle 	int pos = max_ports;
975cb477c30SDaniel Golle 	int i, idx = -1;
976cb477c30SDaniel Golle 
977cb477c30SDaniel Golle 	/* We only support VLAN filtering on bridges */
978cb477c30SDaniel Golle 	if (!dsa_is_cpu_port(ds, port) && !bridge)
979cb477c30SDaniel Golle 		return -EOPNOTSUPP;
980cb477c30SDaniel Golle 
981cb477c30SDaniel Golle 	/* Check if there is already a page for this VLAN */
982cb477c30SDaniel Golle 	for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
983cb477c30SDaniel Golle 		if (priv->vlans[i].bridge == bridge &&
984cb477c30SDaniel Golle 		    priv->vlans[i].vid == vlan->vid) {
985cb477c30SDaniel Golle 			idx = i;
986cb477c30SDaniel Golle 			break;
987cb477c30SDaniel Golle 		}
988cb477c30SDaniel Golle 	}
989cb477c30SDaniel Golle 
990cb477c30SDaniel Golle 	/* If this VLAN is not programmed yet, we have to reserve
991cb477c30SDaniel Golle 	 * one entry in the VLAN table. Make sure we start at the
992cb477c30SDaniel Golle 	 * next position round.
993cb477c30SDaniel Golle 	 */
994cb477c30SDaniel Golle 	if (idx == -1) {
995cb477c30SDaniel Golle 		/* Look for a free slot */
996cb477c30SDaniel Golle 		for (; pos < ARRAY_SIZE(priv->vlans); pos++) {
997cb477c30SDaniel Golle 			if (!priv->vlans[pos].bridge) {
998cb477c30SDaniel Golle 				idx = pos;
999cb477c30SDaniel Golle 				pos++;
1000cb477c30SDaniel Golle 				break;
1001cb477c30SDaniel Golle 			}
1002cb477c30SDaniel Golle 		}
1003cb477c30SDaniel Golle 
1004cb477c30SDaniel Golle 		if (idx == -1) {
1005cb477c30SDaniel Golle 			NL_SET_ERR_MSG_MOD(extack, "No slot in VLAN table");
1006cb477c30SDaniel Golle 			return -ENOSPC;
1007cb477c30SDaniel Golle 		}
1008cb477c30SDaniel Golle 	}
1009cb477c30SDaniel Golle 
1010cb477c30SDaniel Golle 	return 0;
1011cb477c30SDaniel Golle }
1012cb477c30SDaniel Golle 
1013cb477c30SDaniel Golle static int gswip_port_vlan_add(struct dsa_switch *ds, int port,
1014cb477c30SDaniel Golle 			       const struct switchdev_obj_port_vlan *vlan,
1015cb477c30SDaniel Golle 			       struct netlink_ext_ack *extack)
1016cb477c30SDaniel Golle {
1017cb477c30SDaniel Golle 	struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port));
1018cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1019cb477c30SDaniel Golle 	bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
1020cb477c30SDaniel Golle 	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1021cb477c30SDaniel Golle 	int err;
1022cb477c30SDaniel Golle 
1023cb477c30SDaniel Golle 	err = gswip_port_vlan_prepare(ds, port, vlan, extack);
1024cb477c30SDaniel Golle 	if (err)
1025cb477c30SDaniel Golle 		return err;
1026cb477c30SDaniel Golle 
1027cb477c30SDaniel Golle 	/* We have to receive all packets on the CPU port and should not
1028cb477c30SDaniel Golle 	 * do any VLAN filtering here. This is also called with bridge
1029cb477c30SDaniel Golle 	 * NULL and then we do not know for which bridge to configure
1030cb477c30SDaniel Golle 	 * this.
1031cb477c30SDaniel Golle 	 */
1032cb477c30SDaniel Golle 	if (dsa_is_cpu_port(ds, port))
1033cb477c30SDaniel Golle 		return 0;
1034cb477c30SDaniel Golle 
1035cb477c30SDaniel Golle 	return gswip_vlan_add_aware(priv, bridge, port, vlan->vid,
1036cb477c30SDaniel Golle 				    untagged, pvid);
1037cb477c30SDaniel Golle }
1038cb477c30SDaniel Golle 
1039cb477c30SDaniel Golle static int gswip_port_vlan_del(struct dsa_switch *ds, int port,
1040cb477c30SDaniel Golle 			       const struct switchdev_obj_port_vlan *vlan)
1041cb477c30SDaniel Golle {
1042cb477c30SDaniel Golle 	struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port));
1043cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1044cb477c30SDaniel Golle 	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
1045cb477c30SDaniel Golle 
1046cb477c30SDaniel Golle 	/* We have to receive all packets on the CPU port and should not
1047cb477c30SDaniel Golle 	 * do any VLAN filtering here. This is also called with bridge
1048cb477c30SDaniel Golle 	 * NULL and then we do not know for which bridge to configure
1049cb477c30SDaniel Golle 	 * this.
1050cb477c30SDaniel Golle 	 */
1051cb477c30SDaniel Golle 	if (dsa_is_cpu_port(ds, port))
1052cb477c30SDaniel Golle 		return 0;
1053cb477c30SDaniel Golle 
1054cb477c30SDaniel Golle 	return gswip_vlan_remove(priv, bridge, port, vlan->vid, pvid, true);
1055cb477c30SDaniel Golle }
1056cb477c30SDaniel Golle 
1057cb477c30SDaniel Golle static void gswip_port_fast_age(struct dsa_switch *ds, int port)
1058cb477c30SDaniel Golle {
1059cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1060cb477c30SDaniel Golle 	struct gswip_pce_table_entry mac_bridge = {0,};
1061cb477c30SDaniel Golle 	int i;
1062cb477c30SDaniel Golle 	int err;
1063cb477c30SDaniel Golle 
1064cb477c30SDaniel Golle 	for (i = 0; i < 2048; i++) {
1065cb477c30SDaniel Golle 		mac_bridge.table = GSWIP_TABLE_MAC_BRIDGE;
1066cb477c30SDaniel Golle 		mac_bridge.index = i;
1067cb477c30SDaniel Golle 
1068cb477c30SDaniel Golle 		err = gswip_pce_table_entry_read(priv, &mac_bridge);
1069cb477c30SDaniel Golle 		if (err) {
1070cb477c30SDaniel Golle 			dev_err(priv->dev, "failed to read mac bridge: %d\n",
1071cb477c30SDaniel Golle 				err);
1072cb477c30SDaniel Golle 			return;
1073cb477c30SDaniel Golle 		}
1074cb477c30SDaniel Golle 
1075cb477c30SDaniel Golle 		if (!mac_bridge.valid)
1076cb477c30SDaniel Golle 			continue;
1077cb477c30SDaniel Golle 
1078cb477c30SDaniel Golle 		if (mac_bridge.val[1] & GSWIP_TABLE_MAC_BRIDGE_VAL1_STATIC)
1079cb477c30SDaniel Golle 			continue;
1080cb477c30SDaniel Golle 
1081cb477c30SDaniel Golle 		if (port != FIELD_GET(GSWIP_TABLE_MAC_BRIDGE_VAL0_PORT,
1082cb477c30SDaniel Golle 				      mac_bridge.val[0]))
1083cb477c30SDaniel Golle 			continue;
1084cb477c30SDaniel Golle 
1085cb477c30SDaniel Golle 		mac_bridge.valid = false;
1086cb477c30SDaniel Golle 		err = gswip_pce_table_entry_write(priv, &mac_bridge);
1087cb477c30SDaniel Golle 		if (err) {
1088cb477c30SDaniel Golle 			dev_err(priv->dev, "failed to write mac bridge: %d\n",
1089cb477c30SDaniel Golle 				err);
1090cb477c30SDaniel Golle 			return;
1091cb477c30SDaniel Golle 		}
1092cb477c30SDaniel Golle 	}
1093cb477c30SDaniel Golle }
1094cb477c30SDaniel Golle 
1095cb477c30SDaniel Golle static void gswip_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
1096cb477c30SDaniel Golle {
1097cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1098cb477c30SDaniel Golle 	u32 stp_state;
1099cb477c30SDaniel Golle 
1100cb477c30SDaniel Golle 	switch (state) {
1101cb477c30SDaniel Golle 	case BR_STATE_DISABLED:
1102cb477c30SDaniel Golle 		gswip_switch_mask(priv, GSWIP_SDMA_PCTRL_EN, 0,
1103cb477c30SDaniel Golle 				  GSWIP_SDMA_PCTRLp(port));
1104cb477c30SDaniel Golle 		return;
1105cb477c30SDaniel Golle 	case BR_STATE_BLOCKING:
1106cb477c30SDaniel Golle 	case BR_STATE_LISTENING:
1107cb477c30SDaniel Golle 		stp_state = GSWIP_PCE_PCTRL_0_PSTATE_LISTEN;
1108cb477c30SDaniel Golle 		break;
1109cb477c30SDaniel Golle 	case BR_STATE_LEARNING:
1110cb477c30SDaniel Golle 		stp_state = GSWIP_PCE_PCTRL_0_PSTATE_LEARNING;
1111cb477c30SDaniel Golle 		break;
1112cb477c30SDaniel Golle 	case BR_STATE_FORWARDING:
1113cb477c30SDaniel Golle 		stp_state = GSWIP_PCE_PCTRL_0_PSTATE_FORWARDING;
1114cb477c30SDaniel Golle 		break;
1115cb477c30SDaniel Golle 	default:
1116cb477c30SDaniel Golle 		dev_err(priv->dev, "invalid STP state: %d\n", state);
1117cb477c30SDaniel Golle 		return;
1118cb477c30SDaniel Golle 	}
1119cb477c30SDaniel Golle 
1120cb477c30SDaniel Golle 	gswip_switch_mask(priv, 0, GSWIP_SDMA_PCTRL_EN,
1121cb477c30SDaniel Golle 			  GSWIP_SDMA_PCTRLp(port));
1122cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_PCE_PCTRL_0_PSTATE_MASK, stp_state,
1123cb477c30SDaniel Golle 			  GSWIP_PCE_PCTRL_0p(port));
1124cb477c30SDaniel Golle }
1125cb477c30SDaniel Golle 
1126cb477c30SDaniel Golle static int gswip_port_fdb(struct dsa_switch *ds, int port,
1127cb477c30SDaniel Golle 			  const unsigned char *addr, u16 vid, bool add)
1128cb477c30SDaniel Golle {
1129cb477c30SDaniel Golle 	struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port));
1130cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1131cb477c30SDaniel Golle 	struct gswip_pce_table_entry mac_bridge = {0,};
1132cb477c30SDaniel Golle 	unsigned int max_ports = priv->hw_info->max_ports;
1133cb477c30SDaniel Golle 	int fid = -1;
1134cb477c30SDaniel Golle 	int i;
1135cb477c30SDaniel Golle 	int err;
1136cb477c30SDaniel Golle 
1137cb477c30SDaniel Golle 	if (!bridge)
1138cb477c30SDaniel Golle 		return -EINVAL;
1139cb477c30SDaniel Golle 
1140cb477c30SDaniel Golle 	for (i = max_ports; i < ARRAY_SIZE(priv->vlans); i++) {
1141cb477c30SDaniel Golle 		if (priv->vlans[i].bridge == bridge) {
1142cb477c30SDaniel Golle 			fid = priv->vlans[i].fid;
1143cb477c30SDaniel Golle 			break;
1144cb477c30SDaniel Golle 		}
1145cb477c30SDaniel Golle 	}
1146cb477c30SDaniel Golle 
1147cb477c30SDaniel Golle 	if (fid == -1) {
1148cb477c30SDaniel Golle 		dev_err(priv->dev, "no FID found for bridge %s\n",
1149cb477c30SDaniel Golle 			bridge->name);
1150cb477c30SDaniel Golle 		return -EINVAL;
1151cb477c30SDaniel Golle 	}
1152cb477c30SDaniel Golle 
1153cb477c30SDaniel Golle 	mac_bridge.table = GSWIP_TABLE_MAC_BRIDGE;
1154cb477c30SDaniel Golle 	mac_bridge.key_mode = true;
1155cb477c30SDaniel Golle 	mac_bridge.key[0] = addr[5] | (addr[4] << 8);
1156cb477c30SDaniel Golle 	mac_bridge.key[1] = addr[3] | (addr[2] << 8);
1157cb477c30SDaniel Golle 	mac_bridge.key[2] = addr[1] | (addr[0] << 8);
1158cb477c30SDaniel Golle 	mac_bridge.key[3] = FIELD_PREP(GSWIP_TABLE_MAC_BRIDGE_KEY3_FID, fid);
1159cb477c30SDaniel Golle 	mac_bridge.val[0] = add ? BIT(port) : 0; /* port map */
1160cb477c30SDaniel Golle 	mac_bridge.val[1] = GSWIP_TABLE_MAC_BRIDGE_VAL1_STATIC;
1161cb477c30SDaniel Golle 	mac_bridge.valid = add;
1162cb477c30SDaniel Golle 
1163cb477c30SDaniel Golle 	err = gswip_pce_table_entry_write(priv, &mac_bridge);
1164cb477c30SDaniel Golle 	if (err)
1165cb477c30SDaniel Golle 		dev_err(priv->dev, "failed to write mac bridge: %d\n", err);
1166cb477c30SDaniel Golle 
1167cb477c30SDaniel Golle 	return err;
1168cb477c30SDaniel Golle }
1169cb477c30SDaniel Golle 
1170cb477c30SDaniel Golle static int gswip_port_fdb_add(struct dsa_switch *ds, int port,
1171cb477c30SDaniel Golle 			      const unsigned char *addr, u16 vid,
1172cb477c30SDaniel Golle 			      struct dsa_db db)
1173cb477c30SDaniel Golle {
1174cb477c30SDaniel Golle 	return gswip_port_fdb(ds, port, addr, vid, true);
1175cb477c30SDaniel Golle }
1176cb477c30SDaniel Golle 
1177cb477c30SDaniel Golle static int gswip_port_fdb_del(struct dsa_switch *ds, int port,
1178cb477c30SDaniel Golle 			      const unsigned char *addr, u16 vid,
1179cb477c30SDaniel Golle 			      struct dsa_db db)
1180cb477c30SDaniel Golle {
1181cb477c30SDaniel Golle 	return gswip_port_fdb(ds, port, addr, vid, false);
1182cb477c30SDaniel Golle }
1183cb477c30SDaniel Golle 
1184cb477c30SDaniel Golle static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
1185cb477c30SDaniel Golle 			       dsa_fdb_dump_cb_t *cb, void *data)
1186cb477c30SDaniel Golle {
1187cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1188cb477c30SDaniel Golle 	struct gswip_pce_table_entry mac_bridge = {0,};
1189cb477c30SDaniel Golle 	unsigned char addr[ETH_ALEN];
1190cb477c30SDaniel Golle 	int i;
1191cb477c30SDaniel Golle 	int err;
1192cb477c30SDaniel Golle 
1193cb477c30SDaniel Golle 	for (i = 0; i < 2048; i++) {
1194cb477c30SDaniel Golle 		mac_bridge.table = GSWIP_TABLE_MAC_BRIDGE;
1195cb477c30SDaniel Golle 		mac_bridge.index = i;
1196cb477c30SDaniel Golle 
1197cb477c30SDaniel Golle 		err = gswip_pce_table_entry_read(priv, &mac_bridge);
1198cb477c30SDaniel Golle 		if (err) {
1199cb477c30SDaniel Golle 			dev_err(priv->dev,
1200cb477c30SDaniel Golle 				"failed to read mac bridge entry %d: %d\n",
1201cb477c30SDaniel Golle 				i, err);
1202cb477c30SDaniel Golle 			return err;
1203cb477c30SDaniel Golle 		}
1204cb477c30SDaniel Golle 
1205cb477c30SDaniel Golle 		if (!mac_bridge.valid)
1206cb477c30SDaniel Golle 			continue;
1207cb477c30SDaniel Golle 
1208cb477c30SDaniel Golle 		addr[5] = mac_bridge.key[0] & 0xff;
1209cb477c30SDaniel Golle 		addr[4] = (mac_bridge.key[0] >> 8) & 0xff;
1210cb477c30SDaniel Golle 		addr[3] = mac_bridge.key[1] & 0xff;
1211cb477c30SDaniel Golle 		addr[2] = (mac_bridge.key[1] >> 8) & 0xff;
1212cb477c30SDaniel Golle 		addr[1] = mac_bridge.key[2] & 0xff;
1213cb477c30SDaniel Golle 		addr[0] = (mac_bridge.key[2] >> 8) & 0xff;
1214cb477c30SDaniel Golle 		if (mac_bridge.val[1] & GSWIP_TABLE_MAC_BRIDGE_VAL1_STATIC) {
1215cb477c30SDaniel Golle 			if (mac_bridge.val[0] & BIT(port)) {
1216cb477c30SDaniel Golle 				err = cb(addr, 0, true, data);
1217cb477c30SDaniel Golle 				if (err)
1218cb477c30SDaniel Golle 					return err;
1219cb477c30SDaniel Golle 			}
1220cb477c30SDaniel Golle 		} else {
1221cb477c30SDaniel Golle 			if (port == FIELD_GET(GSWIP_TABLE_MAC_BRIDGE_VAL0_PORT,
1222cb477c30SDaniel Golle 					      mac_bridge.val[0])) {
1223cb477c30SDaniel Golle 				err = cb(addr, 0, false, data);
1224cb477c30SDaniel Golle 				if (err)
1225cb477c30SDaniel Golle 					return err;
1226cb477c30SDaniel Golle 			}
1227cb477c30SDaniel Golle 		}
1228cb477c30SDaniel Golle 	}
1229cb477c30SDaniel Golle 	return 0;
1230cb477c30SDaniel Golle }
1231cb477c30SDaniel Golle 
1232cb477c30SDaniel Golle static int gswip_port_max_mtu(struct dsa_switch *ds, int port)
1233cb477c30SDaniel Golle {
1234cb477c30SDaniel Golle 	/* Includes 8 bytes for special header. */
1235cb477c30SDaniel Golle 	return GSWIP_MAX_PACKET_LENGTH - VLAN_ETH_HLEN - ETH_FCS_LEN;
1236cb477c30SDaniel Golle }
1237cb477c30SDaniel Golle 
1238cb477c30SDaniel Golle static int gswip_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
1239cb477c30SDaniel Golle {
1240cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1241cb477c30SDaniel Golle 
1242cb477c30SDaniel Golle 	/* CPU port always has maximum mtu of user ports, so use it to set
1243cb477c30SDaniel Golle 	 * switch frame size, including 8 byte special header.
1244cb477c30SDaniel Golle 	 */
1245cb477c30SDaniel Golle 	if (dsa_is_cpu_port(ds, port)) {
1246cb477c30SDaniel Golle 		new_mtu += 8;
1247cb477c30SDaniel Golle 		gswip_switch_w(priv, VLAN_ETH_HLEN + new_mtu + ETH_FCS_LEN,
1248cb477c30SDaniel Golle 			       GSWIP_MAC_FLEN);
1249cb477c30SDaniel Golle 	}
1250cb477c30SDaniel Golle 
1251cb477c30SDaniel Golle 	/* Enable MLEN for ports with non-standard MTUs, including the special
1252cb477c30SDaniel Golle 	 * header on the CPU port added above.
1253cb477c30SDaniel Golle 	 */
1254cb477c30SDaniel Golle 	if (new_mtu != ETH_DATA_LEN)
1255cb477c30SDaniel Golle 		gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
1256cb477c30SDaniel Golle 				  GSWIP_MAC_CTRL_2p(port));
1257cb477c30SDaniel Golle 	else
1258cb477c30SDaniel Golle 		gswip_switch_mask(priv, GSWIP_MAC_CTRL_2_MLEN, 0,
1259cb477c30SDaniel Golle 				  GSWIP_MAC_CTRL_2p(port));
1260cb477c30SDaniel Golle 
1261cb477c30SDaniel Golle 	return 0;
1262cb477c30SDaniel Golle }
1263cb477c30SDaniel Golle 
1264cb477c30SDaniel Golle static void gswip_xrx200_phylink_get_caps(struct dsa_switch *ds, int port,
1265cb477c30SDaniel Golle 					  struct phylink_config *config)
1266cb477c30SDaniel Golle {
1267cb477c30SDaniel Golle 	switch (port) {
1268cb477c30SDaniel Golle 	case 0:
1269cb477c30SDaniel Golle 	case 1:
1270cb477c30SDaniel Golle 		phy_interface_set_rgmii(config->supported_interfaces);
1271cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_MII,
1272cb477c30SDaniel Golle 			  config->supported_interfaces);
1273cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_REVMII,
1274cb477c30SDaniel Golle 			  config->supported_interfaces);
1275cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_RMII,
1276cb477c30SDaniel Golle 			  config->supported_interfaces);
1277cb477c30SDaniel Golle 		break;
1278cb477c30SDaniel Golle 
1279cb477c30SDaniel Golle 	case 2:
1280cb477c30SDaniel Golle 	case 3:
1281cb477c30SDaniel Golle 	case 4:
1282cb477c30SDaniel Golle 	case 6:
1283cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_INTERNAL,
1284cb477c30SDaniel Golle 			  config->supported_interfaces);
1285cb477c30SDaniel Golle 		break;
1286cb477c30SDaniel Golle 
1287cb477c30SDaniel Golle 	case 5:
1288cb477c30SDaniel Golle 		phy_interface_set_rgmii(config->supported_interfaces);
1289cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_INTERNAL,
1290cb477c30SDaniel Golle 			  config->supported_interfaces);
1291cb477c30SDaniel Golle 		break;
1292cb477c30SDaniel Golle 	}
1293cb477c30SDaniel Golle 
1294cb477c30SDaniel Golle 	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
1295cb477c30SDaniel Golle 		MAC_10 | MAC_100 | MAC_1000;
1296cb477c30SDaniel Golle }
1297cb477c30SDaniel Golle 
1298cb477c30SDaniel Golle static void gswip_xrx300_phylink_get_caps(struct dsa_switch *ds, int port,
1299cb477c30SDaniel Golle 					  struct phylink_config *config)
1300cb477c30SDaniel Golle {
1301cb477c30SDaniel Golle 	switch (port) {
1302cb477c30SDaniel Golle 	case 0:
1303cb477c30SDaniel Golle 		phy_interface_set_rgmii(config->supported_interfaces);
1304cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_GMII,
1305cb477c30SDaniel Golle 			  config->supported_interfaces);
1306cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_RMII,
1307cb477c30SDaniel Golle 			  config->supported_interfaces);
1308cb477c30SDaniel Golle 		break;
1309cb477c30SDaniel Golle 
1310cb477c30SDaniel Golle 	case 1:
1311cb477c30SDaniel Golle 	case 2:
1312cb477c30SDaniel Golle 	case 3:
1313cb477c30SDaniel Golle 	case 4:
1314cb477c30SDaniel Golle 	case 6:
1315cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_INTERNAL,
1316cb477c30SDaniel Golle 			  config->supported_interfaces);
1317cb477c30SDaniel Golle 		break;
1318cb477c30SDaniel Golle 
1319cb477c30SDaniel Golle 	case 5:
1320cb477c30SDaniel Golle 		phy_interface_set_rgmii(config->supported_interfaces);
1321cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_INTERNAL,
1322cb477c30SDaniel Golle 			  config->supported_interfaces);
1323cb477c30SDaniel Golle 		__set_bit(PHY_INTERFACE_MODE_RMII,
1324cb477c30SDaniel Golle 			  config->supported_interfaces);
1325cb477c30SDaniel Golle 		break;
1326cb477c30SDaniel Golle 	}
1327cb477c30SDaniel Golle 
1328cb477c30SDaniel Golle 	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
1329cb477c30SDaniel Golle 		MAC_10 | MAC_100 | MAC_1000;
1330cb477c30SDaniel Golle }
1331cb477c30SDaniel Golle 
1332cb477c30SDaniel Golle static void gswip_phylink_get_caps(struct dsa_switch *ds, int port,
1333cb477c30SDaniel Golle 				   struct phylink_config *config)
1334cb477c30SDaniel Golle {
1335cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1336cb477c30SDaniel Golle 
1337cb477c30SDaniel Golle 	priv->hw_info->phylink_get_caps(ds, port, config);
1338cb477c30SDaniel Golle }
1339cb477c30SDaniel Golle 
1340cb477c30SDaniel Golle static void gswip_port_set_link(struct gswip_priv *priv, int port, bool link)
1341cb477c30SDaniel Golle {
1342cb477c30SDaniel Golle 	u32 mdio_phy;
1343cb477c30SDaniel Golle 
1344cb477c30SDaniel Golle 	if (link)
1345cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_LINK_UP;
1346cb477c30SDaniel Golle 	else
1347cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_LINK_DOWN;
1348cb477c30SDaniel Golle 
1349cb477c30SDaniel Golle 	gswip_mdio_mask(priv, GSWIP_MDIO_PHY_LINK_MASK, mdio_phy,
1350cb477c30SDaniel Golle 			GSWIP_MDIO_PHYp(port));
1351cb477c30SDaniel Golle }
1352cb477c30SDaniel Golle 
1353cb477c30SDaniel Golle static void gswip_port_set_speed(struct gswip_priv *priv, int port, int speed,
1354cb477c30SDaniel Golle 				 phy_interface_t interface)
1355cb477c30SDaniel Golle {
1356cb477c30SDaniel Golle 	u32 mdio_phy = 0, mii_cfg = 0, mac_ctrl_0 = 0;
1357cb477c30SDaniel Golle 
1358cb477c30SDaniel Golle 	switch (speed) {
1359cb477c30SDaniel Golle 	case SPEED_10:
1360cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_SPEED_M10;
1361cb477c30SDaniel Golle 
1362cb477c30SDaniel Golle 		if (interface == PHY_INTERFACE_MODE_RMII)
1363cb477c30SDaniel Golle 			mii_cfg = GSWIP_MII_CFG_RATE_M50;
1364cb477c30SDaniel Golle 		else
1365cb477c30SDaniel Golle 			mii_cfg = GSWIP_MII_CFG_RATE_M2P5;
1366cb477c30SDaniel Golle 
1367cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_MII;
1368cb477c30SDaniel Golle 		break;
1369cb477c30SDaniel Golle 
1370cb477c30SDaniel Golle 	case SPEED_100:
1371cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_SPEED_M100;
1372cb477c30SDaniel Golle 
1373cb477c30SDaniel Golle 		if (interface == PHY_INTERFACE_MODE_RMII)
1374cb477c30SDaniel Golle 			mii_cfg = GSWIP_MII_CFG_RATE_M50;
1375cb477c30SDaniel Golle 		else
1376cb477c30SDaniel Golle 			mii_cfg = GSWIP_MII_CFG_RATE_M25;
1377cb477c30SDaniel Golle 
1378cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_MII;
1379cb477c30SDaniel Golle 		break;
1380cb477c30SDaniel Golle 
1381cb477c30SDaniel Golle 	case SPEED_1000:
1382cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_SPEED_G1;
1383cb477c30SDaniel Golle 
1384cb477c30SDaniel Golle 		mii_cfg = GSWIP_MII_CFG_RATE_M125;
1385cb477c30SDaniel Golle 
1386cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_RGMII;
1387cb477c30SDaniel Golle 		break;
1388cb477c30SDaniel Golle 	}
1389cb477c30SDaniel Golle 
1390cb477c30SDaniel Golle 	gswip_mdio_mask(priv, GSWIP_MDIO_PHY_SPEED_MASK, mdio_phy,
1391cb477c30SDaniel Golle 			GSWIP_MDIO_PHYp(port));
1392cb477c30SDaniel Golle 	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_RATE_MASK, mii_cfg, port);
1393cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_GMII_MASK, mac_ctrl_0,
1394cb477c30SDaniel Golle 			  GSWIP_MAC_CTRL_0p(port));
1395cb477c30SDaniel Golle }
1396cb477c30SDaniel Golle 
1397cb477c30SDaniel Golle static void gswip_port_set_duplex(struct gswip_priv *priv, int port, int duplex)
1398cb477c30SDaniel Golle {
1399cb477c30SDaniel Golle 	u32 mac_ctrl_0, mdio_phy;
1400cb477c30SDaniel Golle 
1401cb477c30SDaniel Golle 	if (duplex == DUPLEX_FULL) {
1402cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FDUP_EN;
1403cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_FDUP_EN;
1404cb477c30SDaniel Golle 	} else {
1405cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FDUP_DIS;
1406cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_FDUP_DIS;
1407cb477c30SDaniel Golle 	}
1408cb477c30SDaniel Golle 
1409cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_FDUP_MASK, mac_ctrl_0,
1410cb477c30SDaniel Golle 			  GSWIP_MAC_CTRL_0p(port));
1411cb477c30SDaniel Golle 	gswip_mdio_mask(priv, GSWIP_MDIO_PHY_FDUP_MASK, mdio_phy,
1412cb477c30SDaniel Golle 			GSWIP_MDIO_PHYp(port));
1413cb477c30SDaniel Golle }
1414cb477c30SDaniel Golle 
1415cb477c30SDaniel Golle static void gswip_port_set_pause(struct gswip_priv *priv, int port,
1416cb477c30SDaniel Golle 				 bool tx_pause, bool rx_pause)
1417cb477c30SDaniel Golle {
1418cb477c30SDaniel Golle 	u32 mac_ctrl_0, mdio_phy;
1419cb477c30SDaniel Golle 
1420cb477c30SDaniel Golle 	if (tx_pause && rx_pause) {
1421cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_RXTX;
1422cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_FCONTX_EN |
1423cb477c30SDaniel Golle 			   GSWIP_MDIO_PHY_FCONRX_EN;
1424cb477c30SDaniel Golle 	} else if (tx_pause) {
1425cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_TX;
1426cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_FCONTX_EN |
1427cb477c30SDaniel Golle 			   GSWIP_MDIO_PHY_FCONRX_DIS;
1428cb477c30SDaniel Golle 	} else if (rx_pause) {
1429cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_RX;
1430cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_FCONTX_DIS |
1431cb477c30SDaniel Golle 			   GSWIP_MDIO_PHY_FCONRX_EN;
1432cb477c30SDaniel Golle 	} else {
1433cb477c30SDaniel Golle 		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_NONE;
1434cb477c30SDaniel Golle 		mdio_phy = GSWIP_MDIO_PHY_FCONTX_DIS |
1435cb477c30SDaniel Golle 			   GSWIP_MDIO_PHY_FCONRX_DIS;
1436cb477c30SDaniel Golle 	}
1437cb477c30SDaniel Golle 
1438cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_FCON_MASK,
1439cb477c30SDaniel Golle 			  mac_ctrl_0, GSWIP_MAC_CTRL_0p(port));
1440cb477c30SDaniel Golle 	gswip_mdio_mask(priv,
1441cb477c30SDaniel Golle 			GSWIP_MDIO_PHY_FCONTX_MASK |
1442cb477c30SDaniel Golle 			GSWIP_MDIO_PHY_FCONRX_MASK,
1443cb477c30SDaniel Golle 			mdio_phy, GSWIP_MDIO_PHYp(port));
1444cb477c30SDaniel Golle }
1445cb477c30SDaniel Golle 
1446cb477c30SDaniel Golle static void gswip_phylink_mac_config(struct phylink_config *config,
1447cb477c30SDaniel Golle 				     unsigned int mode,
1448cb477c30SDaniel Golle 				     const struct phylink_link_state *state)
1449cb477c30SDaniel Golle {
1450cb477c30SDaniel Golle 	struct dsa_port *dp = dsa_phylink_to_port(config);
1451cb477c30SDaniel Golle 	struct gswip_priv *priv = dp->ds->priv;
1452cb477c30SDaniel Golle 	int port = dp->index;
1453cb477c30SDaniel Golle 	u32 miicfg = 0;
1454cb477c30SDaniel Golle 
1455cb477c30SDaniel Golle 	miicfg |= GSWIP_MII_CFG_LDCLKDIS;
1456cb477c30SDaniel Golle 
1457cb477c30SDaniel Golle 	switch (state->interface) {
145817420a7fSDaniel Golle 	case PHY_INTERFACE_MODE_SGMII:
145917420a7fSDaniel Golle 	case PHY_INTERFACE_MODE_1000BASEX:
146017420a7fSDaniel Golle 	case PHY_INTERFACE_MODE_2500BASEX:
146117420a7fSDaniel Golle 		return;
1462cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_MII:
1463cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_INTERNAL:
1464cb477c30SDaniel Golle 		miicfg |= GSWIP_MII_CFG_MODE_MIIM;
1465cb477c30SDaniel Golle 		break;
1466cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_REVMII:
1467cb477c30SDaniel Golle 		miicfg |= GSWIP_MII_CFG_MODE_MIIP;
1468cb477c30SDaniel Golle 		break;
1469cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RMII:
1470cb477c30SDaniel Golle 		miicfg |= GSWIP_MII_CFG_MODE_RMIIM;
1471cb477c30SDaniel Golle 		break;
1472cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII:
1473cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII_ID:
1474cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII_RXID:
1475cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII_TXID:
1476cb477c30SDaniel Golle 		miicfg |= GSWIP_MII_CFG_MODE_RGMII;
1477cb477c30SDaniel Golle 		break;
1478cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_GMII:
1479cb477c30SDaniel Golle 		miicfg |= GSWIP_MII_CFG_MODE_GMII;
1480cb477c30SDaniel Golle 		break;
1481cb477c30SDaniel Golle 	default:
1482cb477c30SDaniel Golle 		dev_err(dp->ds->dev,
1483cb477c30SDaniel Golle 			"Unsupported interface: %d\n", state->interface);
1484cb477c30SDaniel Golle 		return;
1485cb477c30SDaniel Golle 	}
1486cb477c30SDaniel Golle 
1487cb477c30SDaniel Golle 	gswip_mii_mask_cfg(priv,
1488cb477c30SDaniel Golle 			   GSWIP_MII_CFG_MODE_MASK | GSWIP_MII_CFG_RMII_CLK |
1489cb477c30SDaniel Golle 			   GSWIP_MII_CFG_RGMII_IBS | GSWIP_MII_CFG_LDCLKDIS,
1490cb477c30SDaniel Golle 			   miicfg, port);
1491cb477c30SDaniel Golle 
1492cb477c30SDaniel Golle 	switch (state->interface) {
1493cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII_ID:
1494cb477c30SDaniel Golle 		gswip_mii_mask_pcdu(priv, GSWIP_MII_PCDU_TXDLY_MASK |
1495cb477c30SDaniel Golle 					  GSWIP_MII_PCDU_RXDLY_MASK, 0, port);
1496cb477c30SDaniel Golle 		break;
1497cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII_RXID:
1498cb477c30SDaniel Golle 		gswip_mii_mask_pcdu(priv, GSWIP_MII_PCDU_RXDLY_MASK, 0, port);
1499cb477c30SDaniel Golle 		break;
1500cb477c30SDaniel Golle 	case PHY_INTERFACE_MODE_RGMII_TXID:
1501cb477c30SDaniel Golle 		gswip_mii_mask_pcdu(priv, GSWIP_MII_PCDU_TXDLY_MASK, 0, port);
1502cb477c30SDaniel Golle 		break;
1503cb477c30SDaniel Golle 	default:
1504cb477c30SDaniel Golle 		break;
1505cb477c30SDaniel Golle 	}
1506cb477c30SDaniel Golle }
1507cb477c30SDaniel Golle 
1508cb477c30SDaniel Golle static void gswip_phylink_mac_link_down(struct phylink_config *config,
1509cb477c30SDaniel Golle 					unsigned int mode,
1510cb477c30SDaniel Golle 					phy_interface_t interface)
1511cb477c30SDaniel Golle {
1512cb477c30SDaniel Golle 	struct dsa_port *dp = dsa_phylink_to_port(config);
1513cb477c30SDaniel Golle 	struct gswip_priv *priv = dp->ds->priv;
1514cb477c30SDaniel Golle 	int port = dp->index;
1515cb477c30SDaniel Golle 
1516cb477c30SDaniel Golle 	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, port);
1517cb477c30SDaniel Golle 
1518cb477c30SDaniel Golle 	if (!dsa_port_is_cpu(dp))
1519cb477c30SDaniel Golle 		gswip_port_set_link(priv, port, false);
1520cb477c30SDaniel Golle }
1521cb477c30SDaniel Golle 
1522cb477c30SDaniel Golle static void gswip_phylink_mac_link_up(struct phylink_config *config,
1523cb477c30SDaniel Golle 				      struct phy_device *phydev,
1524cb477c30SDaniel Golle 				      unsigned int mode,
1525cb477c30SDaniel Golle 				      phy_interface_t interface,
1526cb477c30SDaniel Golle 				      int speed, int duplex,
1527cb477c30SDaniel Golle 				      bool tx_pause, bool rx_pause)
1528cb477c30SDaniel Golle {
1529cb477c30SDaniel Golle 	struct dsa_port *dp = dsa_phylink_to_port(config);
1530cb477c30SDaniel Golle 	struct gswip_priv *priv = dp->ds->priv;
1531cb477c30SDaniel Golle 	int port = dp->index;
1532cb477c30SDaniel Golle 
1533cb477c30SDaniel Golle 	if (!dsa_port_is_cpu(dp)) {
1534cb477c30SDaniel Golle 		gswip_port_set_link(priv, port, true);
1535cb477c30SDaniel Golle 		gswip_port_set_speed(priv, port, speed, interface);
1536cb477c30SDaniel Golle 		gswip_port_set_duplex(priv, port, duplex);
1537cb477c30SDaniel Golle 		gswip_port_set_pause(priv, port, tx_pause, rx_pause);
1538cb477c30SDaniel Golle 	}
1539cb477c30SDaniel Golle 
1540cb477c30SDaniel Golle 	gswip_mii_mask_cfg(priv, 0, GSWIP_MII_CFG_EN, port);
1541cb477c30SDaniel Golle }
1542cb477c30SDaniel Golle 
1543cb477c30SDaniel Golle static void gswip_get_strings(struct dsa_switch *ds, int port, u32 stringset,
1544cb477c30SDaniel Golle 			      uint8_t *data)
1545cb477c30SDaniel Golle {
1546cb477c30SDaniel Golle 	int i;
1547cb477c30SDaniel Golle 
1548cb477c30SDaniel Golle 	if (stringset != ETH_SS_STATS)
1549cb477c30SDaniel Golle 		return;
1550cb477c30SDaniel Golle 
1551cb477c30SDaniel Golle 	for (i = 0; i < ARRAY_SIZE(gswip_rmon_cnt); i++)
1552cb477c30SDaniel Golle 		ethtool_puts(&data, gswip_rmon_cnt[i].name);
1553cb477c30SDaniel Golle }
1554cb477c30SDaniel Golle 
1555cb477c30SDaniel Golle static u32 gswip_bcm_ram_entry_read(struct gswip_priv *priv, u32 table,
1556cb477c30SDaniel Golle 				    u32 index)
1557cb477c30SDaniel Golle {
1558cb477c30SDaniel Golle 	u32 result;
1559cb477c30SDaniel Golle 	int err;
1560cb477c30SDaniel Golle 
1561cb477c30SDaniel Golle 	gswip_switch_w(priv, index, GSWIP_BM_RAM_ADDR);
1562cb477c30SDaniel Golle 	gswip_switch_mask(priv, GSWIP_BM_RAM_CTRL_ADDR_MASK |
1563cb477c30SDaniel Golle 				GSWIP_BM_RAM_CTRL_OPMOD,
1564cb477c30SDaniel Golle 			      table | GSWIP_BM_RAM_CTRL_BAS,
1565cb477c30SDaniel Golle 			      GSWIP_BM_RAM_CTRL);
1566cb477c30SDaniel Golle 
1567cb477c30SDaniel Golle 	err = gswip_switch_r_timeout(priv, GSWIP_BM_RAM_CTRL,
1568cb477c30SDaniel Golle 				     GSWIP_BM_RAM_CTRL_BAS);
1569cb477c30SDaniel Golle 	if (err) {
1570cb477c30SDaniel Golle 		dev_err(priv->dev, "timeout while reading table: %u, index: %u\n",
1571cb477c30SDaniel Golle 			table, index);
1572cb477c30SDaniel Golle 		return 0;
1573cb477c30SDaniel Golle 	}
1574cb477c30SDaniel Golle 
1575cb477c30SDaniel Golle 	result = gswip_switch_r(priv, GSWIP_BM_RAM_VAL(0));
1576cb477c30SDaniel Golle 	result |= gswip_switch_r(priv, GSWIP_BM_RAM_VAL(1)) << 16;
1577cb477c30SDaniel Golle 
1578cb477c30SDaniel Golle 	return result;
1579cb477c30SDaniel Golle }
1580cb477c30SDaniel Golle 
1581cb477c30SDaniel Golle static void gswip_get_ethtool_stats(struct dsa_switch *ds, int port,
1582cb477c30SDaniel Golle 				    uint64_t *data)
1583cb477c30SDaniel Golle {
1584cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1585cb477c30SDaniel Golle 	const struct gswip_rmon_cnt_desc *rmon_cnt;
1586cb477c30SDaniel Golle 	int i;
1587cb477c30SDaniel Golle 	u64 high;
1588cb477c30SDaniel Golle 
1589cb477c30SDaniel Golle 	for (i = 0; i < ARRAY_SIZE(gswip_rmon_cnt); i++) {
1590cb477c30SDaniel Golle 		rmon_cnt = &gswip_rmon_cnt[i];
1591cb477c30SDaniel Golle 
1592cb477c30SDaniel Golle 		data[i] = gswip_bcm_ram_entry_read(priv, port,
1593cb477c30SDaniel Golle 						   rmon_cnt->offset);
1594cb477c30SDaniel Golle 		if (rmon_cnt->size == 2) {
1595cb477c30SDaniel Golle 			high = gswip_bcm_ram_entry_read(priv, port,
1596cb477c30SDaniel Golle 							rmon_cnt->offset + 1);
1597cb477c30SDaniel Golle 			data[i] |= high << 32;
1598cb477c30SDaniel Golle 		}
1599cb477c30SDaniel Golle 	}
1600cb477c30SDaniel Golle }
1601cb477c30SDaniel Golle 
1602cb477c30SDaniel Golle static int gswip_get_sset_count(struct dsa_switch *ds, int port, int sset)
1603cb477c30SDaniel Golle {
1604cb477c30SDaniel Golle 	if (sset != ETH_SS_STATS)
1605cb477c30SDaniel Golle 		return 0;
1606cb477c30SDaniel Golle 
1607cb477c30SDaniel Golle 	return ARRAY_SIZE(gswip_rmon_cnt);
1608cb477c30SDaniel Golle }
1609cb477c30SDaniel Golle 
16107a1eaef0SDaniel Golle static struct phylink_pcs *gswip_phylink_mac_select_pcs(struct phylink_config *config,
16117a1eaef0SDaniel Golle 							phy_interface_t interface)
16127a1eaef0SDaniel Golle {
16137a1eaef0SDaniel Golle 	struct dsa_port *dp = dsa_phylink_to_port(config);
16147a1eaef0SDaniel Golle 	struct gswip_priv *priv = dp->ds->priv;
16157a1eaef0SDaniel Golle 
16167a1eaef0SDaniel Golle 	if (priv->hw_info->mac_select_pcs)
16177a1eaef0SDaniel Golle 		return priv->hw_info->mac_select_pcs(config, interface);
16187a1eaef0SDaniel Golle 
16197a1eaef0SDaniel Golle 	return NULL;
16207a1eaef0SDaniel Golle }
16217a1eaef0SDaniel Golle 
1622cb477c30SDaniel Golle static const struct phylink_mac_ops gswip_phylink_mac_ops = {
1623cb477c30SDaniel Golle 	.mac_config		= gswip_phylink_mac_config,
1624cb477c30SDaniel Golle 	.mac_link_down		= gswip_phylink_mac_link_down,
1625cb477c30SDaniel Golle 	.mac_link_up		= gswip_phylink_mac_link_up,
16267a1eaef0SDaniel Golle 	.mac_select_pcs		= gswip_phylink_mac_select_pcs,
1627cb477c30SDaniel Golle };
1628cb477c30SDaniel Golle 
1629cb477c30SDaniel Golle static const struct dsa_switch_ops gswip_switch_ops = {
1630cb477c30SDaniel Golle 	.get_tag_protocol	= gswip_get_tag_protocol,
1631cb477c30SDaniel Golle 	.setup			= gswip_setup,
1632cb477c30SDaniel Golle 	.port_enable		= gswip_port_enable,
1633cb477c30SDaniel Golle 	.port_disable		= gswip_port_disable,
1634cb477c30SDaniel Golle 	.port_bridge_join	= gswip_port_bridge_join,
1635cb477c30SDaniel Golle 	.port_bridge_leave	= gswip_port_bridge_leave,
1636cb477c30SDaniel Golle 	.port_fast_age		= gswip_port_fast_age,
1637cb477c30SDaniel Golle 	.port_vlan_filtering	= gswip_port_vlan_filtering,
1638cb477c30SDaniel Golle 	.port_vlan_add		= gswip_port_vlan_add,
1639cb477c30SDaniel Golle 	.port_vlan_del		= gswip_port_vlan_del,
1640cb477c30SDaniel Golle 	.port_stp_state_set	= gswip_port_stp_state_set,
1641cb477c30SDaniel Golle 	.port_fdb_add		= gswip_port_fdb_add,
1642cb477c30SDaniel Golle 	.port_fdb_del		= gswip_port_fdb_del,
1643cb477c30SDaniel Golle 	.port_fdb_dump		= gswip_port_fdb_dump,
1644cb477c30SDaniel Golle 	.port_change_mtu	= gswip_port_change_mtu,
1645cb477c30SDaniel Golle 	.port_max_mtu		= gswip_port_max_mtu,
1646cb477c30SDaniel Golle 	.phylink_get_caps	= gswip_phylink_get_caps,
1647cb477c30SDaniel Golle 	.get_strings		= gswip_get_strings,
1648cb477c30SDaniel Golle 	.get_ethtool_stats	= gswip_get_ethtool_stats,
1649cb477c30SDaniel Golle 	.get_sset_count		= gswip_get_sset_count,
1650cb477c30SDaniel Golle };
1651cb477c30SDaniel Golle 
1652cb477c30SDaniel Golle static const struct xway_gphy_match_data xrx200a1x_gphy_data = {
1653cb477c30SDaniel Golle 	.fe_firmware_name = "lantiq/xrx200_phy22f_a14.bin",
1654cb477c30SDaniel Golle 	.ge_firmware_name = "lantiq/xrx200_phy11g_a14.bin",
1655cb477c30SDaniel Golle };
1656cb477c30SDaniel Golle 
1657cb477c30SDaniel Golle static const struct xway_gphy_match_data xrx200a2x_gphy_data = {
1658cb477c30SDaniel Golle 	.fe_firmware_name = "lantiq/xrx200_phy22f_a22.bin",
1659cb477c30SDaniel Golle 	.ge_firmware_name = "lantiq/xrx200_phy11g_a22.bin",
1660cb477c30SDaniel Golle };
1661cb477c30SDaniel Golle 
1662cb477c30SDaniel Golle static const struct xway_gphy_match_data xrx300_gphy_data = {
1663cb477c30SDaniel Golle 	.fe_firmware_name = "lantiq/xrx300_phy22f_a21.bin",
1664cb477c30SDaniel Golle 	.ge_firmware_name = "lantiq/xrx300_phy11g_a21.bin",
1665cb477c30SDaniel Golle };
1666cb477c30SDaniel Golle 
1667cb477c30SDaniel Golle static const struct of_device_id xway_gphy_match[] __maybe_unused = {
1668cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx200-gphy-fw", .data = NULL },
1669cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx200a1x-gphy-fw", .data = &xrx200a1x_gphy_data },
1670cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx200a2x-gphy-fw", .data = &xrx200a2x_gphy_data },
1671cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx300-gphy-fw", .data = &xrx300_gphy_data },
1672cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx330-gphy-fw", .data = &xrx300_gphy_data },
1673cb477c30SDaniel Golle 	{},
1674cb477c30SDaniel Golle };
1675cb477c30SDaniel Golle 
1676cb477c30SDaniel Golle static int gswip_gphy_fw_load(struct gswip_priv *priv, struct gswip_gphy_fw *gphy_fw)
1677cb477c30SDaniel Golle {
1678cb477c30SDaniel Golle 	struct device *dev = priv->dev;
1679cb477c30SDaniel Golle 	const struct firmware *fw;
1680cb477c30SDaniel Golle 	void *fw_addr;
1681cb477c30SDaniel Golle 	dma_addr_t dma_addr;
1682cb477c30SDaniel Golle 	dma_addr_t dev_addr;
1683cb477c30SDaniel Golle 	size_t size;
1684cb477c30SDaniel Golle 	int ret;
1685cb477c30SDaniel Golle 
1686cb477c30SDaniel Golle 	ret = clk_prepare_enable(gphy_fw->clk_gate);
1687cb477c30SDaniel Golle 	if (ret)
1688cb477c30SDaniel Golle 		return ret;
1689cb477c30SDaniel Golle 
1690cb477c30SDaniel Golle 	reset_control_assert(gphy_fw->reset);
1691cb477c30SDaniel Golle 
1692cb477c30SDaniel Golle 	/* The vendor BSP uses a 200ms delay after asserting the reset line.
1693cb477c30SDaniel Golle 	 * Without this some users are observing that the PHY is not coming up
1694cb477c30SDaniel Golle 	 * on the MDIO bus.
1695cb477c30SDaniel Golle 	 */
1696cb477c30SDaniel Golle 	msleep(200);
1697cb477c30SDaniel Golle 
1698cb477c30SDaniel Golle 	ret = request_firmware(&fw, gphy_fw->fw_name, dev);
1699cb477c30SDaniel Golle 	if (ret)
1700cb477c30SDaniel Golle 		return dev_err_probe(dev, ret, "failed to load firmware: %s\n",
1701cb477c30SDaniel Golle 				     gphy_fw->fw_name);
1702cb477c30SDaniel Golle 
1703cb477c30SDaniel Golle 	/* GPHY cores need the firmware code in a persistent and contiguous
1704cb477c30SDaniel Golle 	 * memory area with a 16 kB boundary aligned start address.
1705cb477c30SDaniel Golle 	 */
1706cb477c30SDaniel Golle 	size = fw->size + XRX200_GPHY_FW_ALIGN;
1707cb477c30SDaniel Golle 
1708cb477c30SDaniel Golle 	fw_addr = dmam_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL);
1709cb477c30SDaniel Golle 	if (fw_addr) {
1710cb477c30SDaniel Golle 		fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
1711cb477c30SDaniel Golle 		dev_addr = ALIGN(dma_addr, XRX200_GPHY_FW_ALIGN);
1712cb477c30SDaniel Golle 		memcpy(fw_addr, fw->data, fw->size);
1713cb477c30SDaniel Golle 	} else {
1714cb477c30SDaniel Golle 		release_firmware(fw);
1715cb477c30SDaniel Golle 		return -ENOMEM;
1716cb477c30SDaniel Golle 	}
1717cb477c30SDaniel Golle 
1718cb477c30SDaniel Golle 	release_firmware(fw);
1719cb477c30SDaniel Golle 
1720cb477c30SDaniel Golle 	ret = regmap_write(priv->rcu_regmap, gphy_fw->fw_addr_offset, dev_addr);
1721cb477c30SDaniel Golle 	if (ret)
1722cb477c30SDaniel Golle 		return ret;
1723cb477c30SDaniel Golle 
1724cb477c30SDaniel Golle 	reset_control_deassert(gphy_fw->reset);
1725cb477c30SDaniel Golle 
1726cb477c30SDaniel Golle 	return ret;
1727cb477c30SDaniel Golle }
1728cb477c30SDaniel Golle 
1729cb477c30SDaniel Golle static int gswip_gphy_fw_probe(struct gswip_priv *priv,
1730cb477c30SDaniel Golle 			       struct gswip_gphy_fw *gphy_fw,
1731cb477c30SDaniel Golle 			       struct device_node *gphy_fw_np, int i)
1732cb477c30SDaniel Golle {
1733cb477c30SDaniel Golle 	struct device *dev = priv->dev;
1734cb477c30SDaniel Golle 	u32 gphy_mode;
1735cb477c30SDaniel Golle 	int ret;
1736cb477c30SDaniel Golle 	char gphyname[10];
1737cb477c30SDaniel Golle 
1738cb477c30SDaniel Golle 	snprintf(gphyname, sizeof(gphyname), "gphy%d", i);
1739cb477c30SDaniel Golle 
1740cb477c30SDaniel Golle 	gphy_fw->clk_gate = devm_clk_get(dev, gphyname);
1741cb477c30SDaniel Golle 	if (IS_ERR(gphy_fw->clk_gate)) {
1742cb477c30SDaniel Golle 		return dev_err_probe(dev, PTR_ERR(gphy_fw->clk_gate),
1743cb477c30SDaniel Golle 				     "Failed to lookup gate clock\n");
1744cb477c30SDaniel Golle 	}
1745cb477c30SDaniel Golle 
1746cb477c30SDaniel Golle 	ret = of_property_read_u32(gphy_fw_np, "reg", &gphy_fw->fw_addr_offset);
1747cb477c30SDaniel Golle 	if (ret)
1748cb477c30SDaniel Golle 		return ret;
1749cb477c30SDaniel Golle 
1750cb477c30SDaniel Golle 	ret = of_property_read_u32(gphy_fw_np, "lantiq,gphy-mode", &gphy_mode);
1751cb477c30SDaniel Golle 	/* Default to GE mode */
1752cb477c30SDaniel Golle 	if (ret)
1753cb477c30SDaniel Golle 		gphy_mode = GPHY_MODE_GE;
1754cb477c30SDaniel Golle 
1755cb477c30SDaniel Golle 	switch (gphy_mode) {
1756cb477c30SDaniel Golle 	case GPHY_MODE_FE:
1757cb477c30SDaniel Golle 		gphy_fw->fw_name = priv->gphy_fw_name_cfg->fe_firmware_name;
1758cb477c30SDaniel Golle 		break;
1759cb477c30SDaniel Golle 	case GPHY_MODE_GE:
1760cb477c30SDaniel Golle 		gphy_fw->fw_name = priv->gphy_fw_name_cfg->ge_firmware_name;
1761cb477c30SDaniel Golle 		break;
1762cb477c30SDaniel Golle 	default:
1763cb477c30SDaniel Golle 		return dev_err_probe(dev, -EINVAL, "Unknown GPHY mode %d\n",
1764cb477c30SDaniel Golle 				     gphy_mode);
1765cb477c30SDaniel Golle 	}
1766cb477c30SDaniel Golle 
1767cb477c30SDaniel Golle 	gphy_fw->reset = of_reset_control_array_get_exclusive(gphy_fw_np);
1768cb477c30SDaniel Golle 	if (IS_ERR(gphy_fw->reset))
1769cb477c30SDaniel Golle 		return dev_err_probe(dev, PTR_ERR(gphy_fw->reset),
1770cb477c30SDaniel Golle 				     "Failed to lookup gphy reset\n");
1771cb477c30SDaniel Golle 
1772cb477c30SDaniel Golle 	return gswip_gphy_fw_load(priv, gphy_fw);
1773cb477c30SDaniel Golle }
1774cb477c30SDaniel Golle 
1775cb477c30SDaniel Golle static void gswip_gphy_fw_remove(struct gswip_priv *priv,
1776cb477c30SDaniel Golle 				 struct gswip_gphy_fw *gphy_fw)
1777cb477c30SDaniel Golle {
1778cb477c30SDaniel Golle 	int ret;
1779cb477c30SDaniel Golle 
1780cb477c30SDaniel Golle 	/* check if the device was fully probed */
1781cb477c30SDaniel Golle 	if (!gphy_fw->fw_name)
1782cb477c30SDaniel Golle 		return;
1783cb477c30SDaniel Golle 
1784cb477c30SDaniel Golle 	ret = regmap_write(priv->rcu_regmap, gphy_fw->fw_addr_offset, 0);
1785cb477c30SDaniel Golle 	if (ret)
1786cb477c30SDaniel Golle 		dev_err(priv->dev, "can not reset GPHY FW pointer\n");
1787cb477c30SDaniel Golle 
1788cb477c30SDaniel Golle 	clk_disable_unprepare(gphy_fw->clk_gate);
1789cb477c30SDaniel Golle 
1790cb477c30SDaniel Golle 	reset_control_put(gphy_fw->reset);
1791cb477c30SDaniel Golle }
1792cb477c30SDaniel Golle 
1793cb477c30SDaniel Golle static int gswip_gphy_fw_list(struct gswip_priv *priv,
1794cb477c30SDaniel Golle 			      struct device_node *gphy_fw_list_np, u32 version)
1795cb477c30SDaniel Golle {
1796cb477c30SDaniel Golle 	struct device *dev = priv->dev;
1797cb477c30SDaniel Golle 	struct device_node *gphy_fw_np;
1798cb477c30SDaniel Golle 	const struct of_device_id *match;
1799cb477c30SDaniel Golle 	int err;
1800cb477c30SDaniel Golle 	int i = 0;
1801cb477c30SDaniel Golle 
1802cb477c30SDaniel Golle 	/* The VRX200 rev 1.1 uses the GSWIP 2.0 and needs the older
1803cb477c30SDaniel Golle 	 * GPHY firmware. The VRX200 rev 1.2 uses the GSWIP 2.1 and also
1804cb477c30SDaniel Golle 	 * needs a different GPHY firmware.
1805cb477c30SDaniel Golle 	 */
1806cb477c30SDaniel Golle 	if (of_device_is_compatible(gphy_fw_list_np, "lantiq,xrx200-gphy-fw")) {
1807cb477c30SDaniel Golle 		switch (version) {
1808cb477c30SDaniel Golle 		case GSWIP_VERSION_2_0:
1809cb477c30SDaniel Golle 			priv->gphy_fw_name_cfg = &xrx200a1x_gphy_data;
1810cb477c30SDaniel Golle 			break;
1811cb477c30SDaniel Golle 		case GSWIP_VERSION_2_1:
1812cb477c30SDaniel Golle 			priv->gphy_fw_name_cfg = &xrx200a2x_gphy_data;
1813cb477c30SDaniel Golle 			break;
1814cb477c30SDaniel Golle 		default:
1815cb477c30SDaniel Golle 			return dev_err_probe(dev, -ENOENT,
1816cb477c30SDaniel Golle 					     "unknown GSWIP version: 0x%x\n",
1817cb477c30SDaniel Golle 					     version);
1818cb477c30SDaniel Golle 		}
1819cb477c30SDaniel Golle 	}
1820cb477c30SDaniel Golle 
1821cb477c30SDaniel Golle 	match = of_match_node(xway_gphy_match, gphy_fw_list_np);
1822cb477c30SDaniel Golle 	if (match && match->data)
1823cb477c30SDaniel Golle 		priv->gphy_fw_name_cfg = match->data;
1824cb477c30SDaniel Golle 
1825cb477c30SDaniel Golle 	if (!priv->gphy_fw_name_cfg)
1826cb477c30SDaniel Golle 		return dev_err_probe(dev, -ENOENT,
1827cb477c30SDaniel Golle 				     "GPHY compatible type not supported\n");
1828cb477c30SDaniel Golle 
1829cb477c30SDaniel Golle 	priv->num_gphy_fw = of_get_available_child_count(gphy_fw_list_np);
1830cb477c30SDaniel Golle 	if (!priv->num_gphy_fw)
1831cb477c30SDaniel Golle 		return -ENOENT;
1832cb477c30SDaniel Golle 
1833cb477c30SDaniel Golle 	priv->rcu_regmap = syscon_regmap_lookup_by_phandle(gphy_fw_list_np,
1834cb477c30SDaniel Golle 							   "lantiq,rcu");
1835cb477c30SDaniel Golle 	if (IS_ERR(priv->rcu_regmap))
1836cb477c30SDaniel Golle 		return PTR_ERR(priv->rcu_regmap);
1837cb477c30SDaniel Golle 
1838cb477c30SDaniel Golle 	priv->gphy_fw = devm_kmalloc_array(dev, priv->num_gphy_fw,
1839cb477c30SDaniel Golle 					   sizeof(*priv->gphy_fw),
1840cb477c30SDaniel Golle 					   GFP_KERNEL | __GFP_ZERO);
1841cb477c30SDaniel Golle 	if (!priv->gphy_fw)
1842cb477c30SDaniel Golle 		return -ENOMEM;
1843cb477c30SDaniel Golle 
1844cb477c30SDaniel Golle 	for_each_available_child_of_node(gphy_fw_list_np, gphy_fw_np) {
1845cb477c30SDaniel Golle 		err = gswip_gphy_fw_probe(priv, &priv->gphy_fw[i],
1846cb477c30SDaniel Golle 					  gphy_fw_np, i);
1847cb477c30SDaniel Golle 		if (err) {
1848cb477c30SDaniel Golle 			of_node_put(gphy_fw_np);
1849cb477c30SDaniel Golle 			goto remove_gphy;
1850cb477c30SDaniel Golle 		}
1851cb477c30SDaniel Golle 		i++;
1852cb477c30SDaniel Golle 	}
1853cb477c30SDaniel Golle 
1854cb477c30SDaniel Golle 	/* The standalone PHY11G requires 300ms to be fully
1855cb477c30SDaniel Golle 	 * initialized and ready for any MDIO communication after being
1856cb477c30SDaniel Golle 	 * taken out of reset. For the SoC-internal GPHY variant there
1857cb477c30SDaniel Golle 	 * is no (known) documentation for the minimum time after a
1858cb477c30SDaniel Golle 	 * reset. Use the same value as for the standalone variant as
1859cb477c30SDaniel Golle 	 * some users have reported internal PHYs not being detected
1860cb477c30SDaniel Golle 	 * without any delay.
1861cb477c30SDaniel Golle 	 */
1862cb477c30SDaniel Golle 	msleep(300);
1863cb477c30SDaniel Golle 
1864cb477c30SDaniel Golle 	return 0;
1865cb477c30SDaniel Golle 
1866cb477c30SDaniel Golle remove_gphy:
1867cb477c30SDaniel Golle 	for (i = 0; i < priv->num_gphy_fw; i++)
1868cb477c30SDaniel Golle 		gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]);
1869cb477c30SDaniel Golle 	return err;
1870cb477c30SDaniel Golle }
1871cb477c30SDaniel Golle 
1872cb477c30SDaniel Golle static int gswip_validate_cpu_port(struct dsa_switch *ds)
1873cb477c30SDaniel Golle {
1874cb477c30SDaniel Golle 	struct gswip_priv *priv = ds->priv;
1875cb477c30SDaniel Golle 	struct dsa_port *cpu_dp;
1876cb477c30SDaniel Golle 	int cpu_port = -1;
1877cb477c30SDaniel Golle 
1878cb477c30SDaniel Golle 	dsa_switch_for_each_cpu_port(cpu_dp, ds) {
1879cb477c30SDaniel Golle 		if (cpu_port != -1)
1880cb477c30SDaniel Golle 			return dev_err_probe(ds->dev, -EINVAL,
1881cb477c30SDaniel Golle 					     "only a single CPU port is supported\n");
1882cb477c30SDaniel Golle 
1883cb477c30SDaniel Golle 		cpu_port = cpu_dp->index;
1884cb477c30SDaniel Golle 	}
1885cb477c30SDaniel Golle 
1886cb477c30SDaniel Golle 	if (cpu_port == -1)
1887cb477c30SDaniel Golle 		return dev_err_probe(ds->dev, -EINVAL, "no CPU port defined\n");
1888cb477c30SDaniel Golle 
1889cb477c30SDaniel Golle 	if (BIT(cpu_port) & ~priv->hw_info->allowed_cpu_ports)
1890cb477c30SDaniel Golle 		return dev_err_probe(ds->dev, -EINVAL,
1891cb477c30SDaniel Golle 				     "unsupported CPU port defined\n");
1892cb477c30SDaniel Golle 
1893cb477c30SDaniel Golle 	return 0;
1894cb477c30SDaniel Golle }
1895cb477c30SDaniel Golle 
1896cb477c30SDaniel Golle static int gswip_probe(struct platform_device *pdev)
1897cb477c30SDaniel Golle {
1898cb477c30SDaniel Golle 	struct device_node *np, *gphy_fw_np;
1899cb477c30SDaniel Golle 	struct device *dev = &pdev->dev;
1900cb477c30SDaniel Golle 	struct gswip_priv *priv;
1901cb477c30SDaniel Golle 	int err;
1902cb477c30SDaniel Golle 	int i;
1903cb477c30SDaniel Golle 	u32 version;
1904cb477c30SDaniel Golle 
1905cb477c30SDaniel Golle 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1906cb477c30SDaniel Golle 	if (!priv)
1907cb477c30SDaniel Golle 		return -ENOMEM;
1908cb477c30SDaniel Golle 
1909cb477c30SDaniel Golle 	priv->gswip = devm_platform_ioremap_resource(pdev, 0);
1910cb477c30SDaniel Golle 	if (IS_ERR(priv->gswip))
1911cb477c30SDaniel Golle 		return PTR_ERR(priv->gswip);
1912cb477c30SDaniel Golle 
1913cb477c30SDaniel Golle 	priv->mdio = devm_platform_ioremap_resource(pdev, 1);
1914cb477c30SDaniel Golle 	if (IS_ERR(priv->mdio))
1915cb477c30SDaniel Golle 		return PTR_ERR(priv->mdio);
1916cb477c30SDaniel Golle 
1917cb477c30SDaniel Golle 	priv->mii = devm_platform_ioremap_resource(pdev, 2);
1918cb477c30SDaniel Golle 	if (IS_ERR(priv->mii))
1919cb477c30SDaniel Golle 		return PTR_ERR(priv->mii);
1920cb477c30SDaniel Golle 
1921cb477c30SDaniel Golle 	priv->hw_info = of_device_get_match_data(dev);
1922cb477c30SDaniel Golle 	if (!priv->hw_info)
1923cb477c30SDaniel Golle 		return -EINVAL;
1924cb477c30SDaniel Golle 
1925cb477c30SDaniel Golle 	priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
1926cb477c30SDaniel Golle 	if (!priv->ds)
1927cb477c30SDaniel Golle 		return -ENOMEM;
1928cb477c30SDaniel Golle 
1929cb477c30SDaniel Golle 	priv->ds->dev = dev;
1930cb477c30SDaniel Golle 	priv->ds->num_ports = priv->hw_info->max_ports;
1931cb477c30SDaniel Golle 	priv->ds->priv = priv;
1932cb477c30SDaniel Golle 	priv->ds->ops = &gswip_switch_ops;
1933cb477c30SDaniel Golle 	priv->ds->phylink_mac_ops = &gswip_phylink_mac_ops;
1934cb477c30SDaniel Golle 	priv->dev = dev;
1935cb477c30SDaniel Golle 	mutex_init(&priv->pce_table_lock);
1936cb477c30SDaniel Golle 	version = gswip_switch_r(priv, GSWIP_VERSION);
1937cb477c30SDaniel Golle 
1938cb477c30SDaniel Golle 	/* The hardware has the 'major/minor' version bytes in the wrong order
1939cb477c30SDaniel Golle 	 * preventing numerical comparisons. Construct a 16-bit unsigned integer
1940cb477c30SDaniel Golle 	 * having the REV field as most significant byte and the MOD field as
1941cb477c30SDaniel Golle 	 * least significant byte. This is effectively swapping the two bytes of
1942cb477c30SDaniel Golle 	 * the version variable, but other than using swab16 it doesn't affect
1943cb477c30SDaniel Golle 	 * the source variable.
1944cb477c30SDaniel Golle 	 */
1945cb477c30SDaniel Golle 	priv->version = GSWIP_VERSION_REV(version) << 8 |
1946cb477c30SDaniel Golle 			GSWIP_VERSION_MOD(version);
1947cb477c30SDaniel Golle 
1948cb477c30SDaniel Golle 	np = dev->of_node;
1949cb477c30SDaniel Golle 	switch (version) {
1950cb477c30SDaniel Golle 	case GSWIP_VERSION_2_0:
1951cb477c30SDaniel Golle 	case GSWIP_VERSION_2_1:
1952cb477c30SDaniel Golle 		if (!of_device_is_compatible(np, "lantiq,xrx200-gswip"))
1953cb477c30SDaniel Golle 			return -EINVAL;
1954cb477c30SDaniel Golle 		break;
1955cb477c30SDaniel Golle 	case GSWIP_VERSION_2_2:
1956cb477c30SDaniel Golle 	case GSWIP_VERSION_2_2_ETC:
1957cb477c30SDaniel Golle 		if (!of_device_is_compatible(np, "lantiq,xrx300-gswip") &&
1958cb477c30SDaniel Golle 		    !of_device_is_compatible(np, "lantiq,xrx330-gswip"))
1959cb477c30SDaniel Golle 			return -EINVAL;
1960cb477c30SDaniel Golle 		break;
1961cb477c30SDaniel Golle 	default:
1962cb477c30SDaniel Golle 		return dev_err_probe(dev, -ENOENT,
1963cb477c30SDaniel Golle 				     "unknown GSWIP version: 0x%x\n", version);
1964cb477c30SDaniel Golle 	}
1965cb477c30SDaniel Golle 
1966cb477c30SDaniel Golle 	/* bring up the mdio bus */
1967cb477c30SDaniel Golle 	gphy_fw_np = of_get_compatible_child(dev->of_node, "lantiq,gphy-fw");
1968cb477c30SDaniel Golle 	if (gphy_fw_np) {
1969cb477c30SDaniel Golle 		err = gswip_gphy_fw_list(priv, gphy_fw_np, version);
1970cb477c30SDaniel Golle 		of_node_put(gphy_fw_np);
1971cb477c30SDaniel Golle 		if (err)
1972cb477c30SDaniel Golle 			return dev_err_probe(dev, err,
1973cb477c30SDaniel Golle 					     "gphy fw probe failed\n");
1974cb477c30SDaniel Golle 	}
1975cb477c30SDaniel Golle 
1976cb477c30SDaniel Golle 	/* bring up the mdio bus */
1977cb477c30SDaniel Golle 	err = gswip_mdio(priv);
1978cb477c30SDaniel Golle 	if (err) {
1979cb477c30SDaniel Golle 		dev_err_probe(dev, err, "mdio probe failed\n");
1980cb477c30SDaniel Golle 		goto gphy_fw_remove;
1981cb477c30SDaniel Golle 	}
1982cb477c30SDaniel Golle 
1983cb477c30SDaniel Golle 	err = dsa_register_switch(priv->ds);
1984cb477c30SDaniel Golle 	if (err) {
1985cb477c30SDaniel Golle 		dev_err_probe(dev, err, "dsa switch registration failed\n");
1986cb477c30SDaniel Golle 		goto gphy_fw_remove;
1987cb477c30SDaniel Golle 	}
1988cb477c30SDaniel Golle 
1989cb477c30SDaniel Golle 	err = gswip_validate_cpu_port(priv->ds);
1990cb477c30SDaniel Golle 	if (err)
1991cb477c30SDaniel Golle 		goto disable_switch;
1992cb477c30SDaniel Golle 
1993cb477c30SDaniel Golle 	platform_set_drvdata(pdev, priv);
1994cb477c30SDaniel Golle 
1995cb477c30SDaniel Golle 	dev_info(dev, "probed GSWIP version %lx mod %lx\n",
1996cb477c30SDaniel Golle 		 GSWIP_VERSION_REV(version), GSWIP_VERSION_MOD(version));
1997cb477c30SDaniel Golle 	return 0;
1998cb477c30SDaniel Golle 
1999cb477c30SDaniel Golle disable_switch:
2000cb477c30SDaniel Golle 	gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
2001cb477c30SDaniel Golle 	dsa_unregister_switch(priv->ds);
2002cb477c30SDaniel Golle gphy_fw_remove:
2003cb477c30SDaniel Golle 	for (i = 0; i < priv->num_gphy_fw; i++)
2004cb477c30SDaniel Golle 		gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]);
2005cb477c30SDaniel Golle 	return err;
2006cb477c30SDaniel Golle }
2007cb477c30SDaniel Golle 
2008cb477c30SDaniel Golle static void gswip_remove(struct platform_device *pdev)
2009cb477c30SDaniel Golle {
2010cb477c30SDaniel Golle 	struct gswip_priv *priv = platform_get_drvdata(pdev);
2011cb477c30SDaniel Golle 	int i;
2012cb477c30SDaniel Golle 
2013cb477c30SDaniel Golle 	if (!priv)
2014cb477c30SDaniel Golle 		return;
2015cb477c30SDaniel Golle 
2016cb477c30SDaniel Golle 	/* disable the switch */
2017cb477c30SDaniel Golle 	gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
2018cb477c30SDaniel Golle 
2019cb477c30SDaniel Golle 	dsa_unregister_switch(priv->ds);
2020cb477c30SDaniel Golle 
2021cb477c30SDaniel Golle 	for (i = 0; i < priv->num_gphy_fw; i++)
2022cb477c30SDaniel Golle 		gswip_gphy_fw_remove(priv, &priv->gphy_fw[i]);
2023cb477c30SDaniel Golle }
2024cb477c30SDaniel Golle 
2025cb477c30SDaniel Golle static void gswip_shutdown(struct platform_device *pdev)
2026cb477c30SDaniel Golle {
2027cb477c30SDaniel Golle 	struct gswip_priv *priv = platform_get_drvdata(pdev);
2028cb477c30SDaniel Golle 
2029cb477c30SDaniel Golle 	if (!priv)
2030cb477c30SDaniel Golle 		return;
2031cb477c30SDaniel Golle 
2032cb477c30SDaniel Golle 	dsa_switch_shutdown(priv->ds);
2033cb477c30SDaniel Golle 
2034cb477c30SDaniel Golle 	platform_set_drvdata(pdev, NULL);
2035cb477c30SDaniel Golle }
2036cb477c30SDaniel Golle 
2037cb477c30SDaniel Golle static const struct gswip_hw_info gswip_xrx200 = {
2038cb477c30SDaniel Golle 	.max_ports = 7,
2039cb477c30SDaniel Golle 	.allowed_cpu_ports = BIT(6),
2040cb477c30SDaniel Golle 	.mii_ports = BIT(0) | BIT(1) | BIT(5),
204151578203SDaniel Golle 	.mii_port_reg_offset = 0,
2042cb477c30SDaniel Golle 	.phylink_get_caps = gswip_xrx200_phylink_get_caps,
2043cb477c30SDaniel Golle 	.pce_microcode = &gswip_pce_microcode,
2044cb477c30SDaniel Golle 	.pce_microcode_size = ARRAY_SIZE(gswip_pce_microcode),
2045cb477c30SDaniel Golle 	.tag_protocol = DSA_TAG_PROTO_GSWIP,
2046cb477c30SDaniel Golle };
2047cb477c30SDaniel Golle 
2048cb477c30SDaniel Golle static const struct gswip_hw_info gswip_xrx300 = {
2049cb477c30SDaniel Golle 	.max_ports = 7,
2050cb477c30SDaniel Golle 	.allowed_cpu_ports = BIT(6),
2051cb477c30SDaniel Golle 	.mii_ports = BIT(0) | BIT(5),
205251578203SDaniel Golle 	.mii_port_reg_offset = 0,
2053cb477c30SDaniel Golle 	.phylink_get_caps = gswip_xrx300_phylink_get_caps,
2054cb477c30SDaniel Golle 	.pce_microcode = &gswip_pce_microcode,
2055cb477c30SDaniel Golle 	.pce_microcode_size = ARRAY_SIZE(gswip_pce_microcode),
2056cb477c30SDaniel Golle 	.tag_protocol = DSA_TAG_PROTO_GSWIP,
2057cb477c30SDaniel Golle };
2058cb477c30SDaniel Golle 
2059cb477c30SDaniel Golle static const struct of_device_id gswip_of_match[] = {
2060cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },
2061cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },
2062cb477c30SDaniel Golle 	{ .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },
2063cb477c30SDaniel Golle 	{},
2064cb477c30SDaniel Golle };
2065cb477c30SDaniel Golle MODULE_DEVICE_TABLE(of, gswip_of_match);
2066cb477c30SDaniel Golle 
2067cb477c30SDaniel Golle static struct platform_driver gswip_driver = {
2068cb477c30SDaniel Golle 	.probe = gswip_probe,
2069cb477c30SDaniel Golle 	.remove = gswip_remove,
2070cb477c30SDaniel Golle 	.shutdown = gswip_shutdown,
2071cb477c30SDaniel Golle 	.driver = {
2072cb477c30SDaniel Golle 		.name = "gswip",
2073cb477c30SDaniel Golle 		.of_match_table = gswip_of_match,
2074cb477c30SDaniel Golle 	},
2075cb477c30SDaniel Golle };
2076cb477c30SDaniel Golle 
2077cb477c30SDaniel Golle module_platform_driver(gswip_driver);
2078cb477c30SDaniel Golle 
2079cb477c30SDaniel Golle MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin");
2080cb477c30SDaniel Golle MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin");
2081cb477c30SDaniel Golle MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin");
2082cb477c30SDaniel Golle MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin");
2083cb477c30SDaniel Golle MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin");
2084cb477c30SDaniel Golle MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin");
2085cb477c30SDaniel Golle MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
2086cb477c30SDaniel Golle MODULE_DESCRIPTION("Lantiq / Intel GSWIP driver");
2087cb477c30SDaniel Golle MODULE_LICENSE("GPL v2");
2088