1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3  * Copyright (c) 2019 Microsemi Corporation
4  */
5 
6 #include <common.h>
7 #include <config.h>
8 #include <dm.h>
9 #include <dm/of_access.h>
10 #include <dm/of_addr.h>
11 #include <fdt_support.h>
12 #include <linux/io.h>
13 #include <linux/ioport.h>
14 #include <miiphy.h>
15 #include <net.h>
16 #include <wait_bit.h>
17 
18 #include "mscc_miim.h"
19 #include "mscc_xfer.h"
20 #include "mscc_mac_table.h"
21 
22 #define ANA_PORT_VLAN_CFG(x)		(0x00 + 0x80 * (x))
23 #define		ANA_PORT_VLAN_CFG_AWARE_ENA	BIT(20)
24 #define		ANA_PORT_VLAN_CFG_POP_CNT(x)	((x) << 18)
25 #define ANA_PORT_CPU_FWD_CFG(x)		(0x50 + 0x80 * (x))
26 #define		ANA_PORT_CPU_FWD_CFG_SRC_COPY_ENA	BIT(1)
27 #define ANA_PORT_PORT_CFG(x)		(0x60 + 0x80 * (x))
28 #define		ANA_PORT_PORT_CFG_RECV_ENA	BIT(5)
29 #define ANA_PGID(x)			(0x1000 + 4 * (x))
30 
31 #define SYS_FRM_AGING			0x8300
32 
33 #define SYS_SYSTEM_RST_CFG		0x81b0
34 #define		SYS_SYSTEM_RST_MEM_INIT		BIT(0)
35 #define		SYS_SYSTEM_RST_MEM_ENA		BIT(1)
36 #define		SYS_SYSTEM_RST_CORE_ENA		BIT(2)
37 #define SYS_PORT_MODE(x)		(0x81bc + 0x4 * (x))
38 #define		SYS_PORT_MODE_INCL_INJ_HDR	BIT(0)
39 #define SYS_SWITCH_PORT_MODE(x)		(0x8294 + 0x4 * (x))
40 #define		SYS_SWITCH_PORT_MODE_PORT_ENA	BIT(3)
41 #define SYS_EGR_NO_SHARING		0x8378
42 #define SYS_SCH_CPU			0x85a0
43 
44 #define REW_PORT_CFG(x)			(0x8 + 0x80 * (x))
45 #define		REW_PORT_CFG_IFH_INSERT_ENA	BIT(7)
46 
47 #define GCB_DEVCPU_RST_SOFT_CHIP_RST	0x90
48 #define		GCB_DEVCPU_RST_SOFT_CHIP_RST_SOFT_PHY	BIT(1)
49 #define GCB_MISC_STAT			0x11c
50 #define		GCB_MISC_STAT_PHY_READY			BIT(3)
51 
52 #define	QS_XTR_MAP(x)			(0x10 + 4 * (x))
53 #define		QS_XTR_MAP_GRP			BIT(4)
54 #define		QS_XTR_MAP_ENA			BIT(0)
55 
56 #define HSIO_PLL5G_CFG_PLL5G_CFG2	0x8
57 
58 #define HSIO_RCOMP_CFG_CFG0		0x20
59 #define		HSIO_RCOMP_CFG_CFG0_MODE_SEL(x)			((x) << 8)
60 #define		HSIO_RCOMP_CFG_CFG0_RUN_CAL			BIT(12)
61 #define HSIO_RCOMP_STATUS		0x24
62 #define		HSIO_RCOMP_STATUS_BUSY				BIT(12)
63 #define		HSIO_RCOMP_STATUS_RCOMP_M			GENMASK(3, 0)
64 #define HSIO_SERDES6G_ANA_CFG_DES_CFG	0x64
65 #define		HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_ANA(x)		((x) << 1)
66 #define		HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_HYST(x)	((x) << 5)
67 #define		HSIO_SERDES6G_ANA_CFG_DES_CFG_MBTR_CTRL(x)	((x) << 10)
68 #define		HSIO_SERDES6G_ANA_CFG_DES_CFG_PHS_CTRL(x)	((x) << 13)
69 #define HSIO_SERDES6G_ANA_CFG_IB_CFG	0x68
70 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG_RESISTOR_CTRL(x)	(x)
71 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG_VBCOM(x)		((x) << 4)
72 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG_VBAC(x)		((x) << 7)
73 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG_RT(x)		((x) << 9)
74 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG_RF(x)		((x) << 14)
75 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1	0x6c
76 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST		BIT(0)
77 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSDC	BIT(2)
78 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSAC	BIT(3)
79 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG1_ANEG_MODE	BIT(6)
80 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG1_CHF		BIT(7)
81 #define		HSIO_SERDES6G_ANA_CFG_IB_CFG1_C(x)		((x) << 8)
82 #define HSIO_SERDES6G_ANA_CFG_OB_CFG	0x70
83 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG_SR(x)		((x) << 4)
84 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG_SR_H		BIT(8)
85 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG_POST0(x)		((x) << 23)
86 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG_POL		BIT(29)
87 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG_ENA1V_MODE	BIT(30)
88 #define HSIO_SERDES6G_ANA_CFG_OB_CFG1	0x74
89 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG1_LEV(x)		(x)
90 #define		HSIO_SERDES6G_ANA_CFG_OB_CFG1_ENA_CAS(x)	((x) << 6)
91 #define HSIO_SERDES6G_ANA_CFG_COMMON_CFG 0x7c
92 #define		HSIO_SERDES6G_ANA_CFG_COMMON_CFG_IF_MODE(x)	(x)
93 #define		HSIO_SERDES6G_ANA_CFG_COMMON_CFG_ENA_LANE	BIT(18)
94 #define		HSIO_SERDES6G_ANA_CFG_COMMON_CFG_SYS_RST	BIT(31)
95 #define HSIO_SERDES6G_ANA_CFG_PLL_CFG	0x80
96 #define		HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_ENA		BIT(7)
97 #define		HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_CTRL_DATA(x)	((x) << 8)
98 #define HSIO_SERDES6G_ANA_CFG_SER_CFG	0x84
99 #define HSIO_SERDES6G_DIG_CFG_MISC_CFG	0x88
100 #define		HSIO_SERDES6G_DIG_CFG_MISC_CFG_LANE_RST		BIT(0)
101 #define HSIO_MCB_SERDES6G_CFG		0xac
102 #define		HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT		BIT(31)
103 #define		HSIO_MCB_SERDES6G_CFG_ADDR(x)			(x)
104 
105 #define DEV_GMII_PORT_MODE_CLK		0x0
106 #define		DEV_GMII_PORT_MODE_CLK_PHY_RST	BIT(0)
107 #define DEV_GMII_MAC_CFG_MAC_ENA	0xc
108 #define		DEV_GMII_MAC_CFG_MAC_ENA_RX_ENA		BIT(4)
109 #define		DEV_GMII_MAC_CFG_MAC_ENA_TX_ENA		BIT(0)
110 
111 #define DEV_PORT_MODE_CLK		0x4
112 #define		DEV_PORT_MODE_CLK_PHY_RST		BIT(2)
113 #define		DEV_PORT_MODE_CLK_LINK_SPEED_1000	1
114 #define DEV_MAC_CFG_MAC_ENA		0x10
115 #define		DEV_MAC_CFG_MAC_ENA_RX_ENA		BIT(4)
116 #define		DEV_MAC_CFG_MAC_ENA_TX_ENA		BIT(0)
117 #define DEV_MAC_CFG_MAC_IFG		0x24
118 #define		DEV_MAC_CFG_MAC_IFG_TX_IFG(x)		((x) << 8)
119 #define		DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)		((x) << 4)
120 #define		DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)		(x)
121 #define DEV_PCS1G_CFG_PCS1G_CFG		0x40
122 #define		DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA		BIT(0)
123 #define DEV_PCS1G_CFG_PCS1G_MODE	0x44
124 #define DEV_PCS1G_CFG_PCS1G_SD		0x48
125 #define DEV_PCS1G_CFG_PCS1G_ANEG	0x4c
126 #define		DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x)	((x) << 16)
127 
128 #define IFH_INJ_BYPASS		BIT(31)
129 #define IFH_TAG_TYPE_C		0
130 #define MAC_VID			1
131 #define CPU_PORT		26
132 #define INTERNAL_PORT_MSK	0xFFFFFF
133 #define IFH_LEN			2
134 #define ETH_ALEN		6
135 #define PGID_BROADCAST		28
136 #define PGID_UNICAST		29
137 #define PGID_SRC		80
138 
139 enum luton_target {
140 	PORT0,
141 	PORT1,
142 	PORT2,
143 	PORT3,
144 	PORT4,
145 	PORT5,
146 	PORT6,
147 	PORT7,
148 	PORT8,
149 	PORT9,
150 	PORT10,
151 	PORT11,
152 	PORT12,
153 	PORT13,
154 	PORT14,
155 	PORT15,
156 	PORT16,
157 	PORT17,
158 	PORT18,
159 	PORT19,
160 	PORT20,
161 	PORT21,
162 	PORT22,
163 	PORT23,
164 	SYS,
165 	ANA,
166 	REW,
167 	GCB,
168 	QS,
169 	HSIO,
170 	TARGET_MAX,
171 };
172 
173 #define MAX_PORT (PORT23 - PORT0 + 1)
174 
175 #define MIN_INT_PORT PORT0
176 #define MAX_INT_PORT (PORT11 - PORT0  + 1)
177 #define MIN_EXT_PORT PORT12
178 #define MAX_EXT_PORT MAX_PORT
179 
180 enum luton_mdio_target {
181 	MIIM,
182 	TARGET_MDIO_MAX,
183 };
184 
185 enum luton_phy_id {
186 	INTERNAL,
187 	EXTERNAL,
188 	NUM_PHY,
189 };
190 
191 struct luton_private {
192 	void __iomem *regs[TARGET_MAX];
193 	struct mii_dev *bus[NUM_PHY];
194 };
195 
196 static const unsigned long luton_regs_qs[] = {
197 	[MSCC_QS_XTR_RD] = 0x18,
198 	[MSCC_QS_XTR_FLUSH] = 0x28,
199 	[MSCC_QS_XTR_DATA_PRESENT] = 0x2c,
200 	[MSCC_QS_INJ_WR] = 0x3c,
201 	[MSCC_QS_INJ_CTRL] = 0x44,
202 };
203 
204 static const unsigned long luton_regs_ana_table[] = {
205 	[MSCC_ANA_TABLES_MACHDATA] = 0x11b0,
206 	[MSCC_ANA_TABLES_MACLDATA] = 0x11b4,
207 	[MSCC_ANA_TABLES_MACACCESS] = 0x11b8,
208 };
209 
210 static struct mscc_miim_dev miim[NUM_PHY];
211 
212 static struct mii_dev *luton_mdiobus_init(struct udevice *dev,
213 					  int mdiobus_id)
214 {
215 	unsigned long phy_size[NUM_PHY];
216 	phys_addr_t phy_base[NUM_PHY];
217 	struct ofnode_phandle_args phandle;
218 	ofnode eth_node, node, mdio_node;
219 	struct resource res;
220 	struct mii_dev *bus;
221 	fdt32_t faddr;
222 	int i;
223 
224 	bus = mdio_alloc();
225 	if (!bus)
226 		return NULL;
227 
228 	/* gather only the first mdio bus */
229 	eth_node = dev_read_first_subnode(dev);
230 	node = ofnode_first_subnode(eth_node);
231 	ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
232 				       &phandle);
233 	mdio_node = ofnode_get_parent(phandle.node);
234 
235 	for (i = 0; i < TARGET_MDIO_MAX; i++) {
236 		if (ofnode_read_resource(mdio_node, i, &res)) {
237 			pr_err("%s: get OF resource failed\n", __func__);
238 			return NULL;
239 		}
240 
241 		faddr = cpu_to_fdt32(res.start);
242 		phy_base[i] = ofnode_translate_address(mdio_node, &faddr);
243 		phy_size[i] = res.end - res.start;
244 	}
245 
246 	strcpy(bus->name, "miim-internal");
247 	miim[mdiobus_id].regs = ioremap(phy_base[mdiobus_id],
248 					phy_size[mdiobus_id]);
249 	bus->priv = &miim[mdiobus_id];
250 	bus->read = mscc_miim_read;
251 	bus->write = mscc_miim_write;
252 
253 	if (mdio_register(bus))
254 		return NULL;
255 	else
256 		return bus;
257 }
258 
259 static void luton_stop(struct udevice *dev)
260 {
261 	struct luton_private *priv = dev_get_priv(dev);
262 
263 	/*
264 	 * Switch core only reset affects VCORE-III bus and MIPS frequency
265 	 * and thereby also the DDR SDRAM controller. The workaround is to
266 	 * not to redirect any trafic to the CPU after the data transfer.
267 	 */
268 	writel(GENMASK(9, 2), priv->regs[SYS] + SYS_SCH_CPU);
269 }
270 
271 static void luton_cpu_capture_setup(struct luton_private *priv)
272 {
273 	int i;
274 
275 	/* map the 8 CPU extraction queues to CPU port 26 */
276 	writel(0x0, priv->regs[SYS] + SYS_SCH_CPU);
277 
278 	for (i = 0; i <= 1; i++) {
279 		/*
280 		 * One to one mapping from CPU Queue number to Group extraction
281 		 * number
282 		 */
283 		writel(QS_XTR_MAP_ENA | (QS_XTR_MAP_GRP * i),
284 		       priv->regs[QS] + QS_XTR_MAP(i));
285 
286 		/* Enable IFH insertion/parsing on CPU ports */
287 		setbits_le32(priv->regs[REW] + REW_PORT_CFG(CPU_PORT + i),
288 			     REW_PORT_CFG_IFH_INSERT_ENA);
289 
290 		/* Enable IFH parsing on CPU port 0 and 1 */
291 		setbits_le32(priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i),
292 			     SYS_PORT_MODE_INCL_INJ_HDR);
293 	}
294 
295 	/* Make VLAN aware for CPU traffic */
296 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
297 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
298 	       MAC_VID,
299 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
300 
301 	/* Disable learning (only RECV_ENA must be set) */
302 	writel(ANA_PORT_PORT_CFG_RECV_ENA,
303 	       priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
304 
305 	/* Enable switching to/from cpu port */
306 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(CPU_PORT),
307 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
308 
309 	setbits_le32(priv->regs[SYS] + SYS_EGR_NO_SHARING, BIT(CPU_PORT));
310 }
311 
312 static void luton_gmii_port_init(struct luton_private *priv, int port)
313 {
314 	void __iomem *regs = priv->regs[port];
315 
316 	writel(0, regs + DEV_GMII_PORT_MODE_CLK);
317 
318 	/* Enable MAC RX and TX */
319 	writel(DEV_GMII_MAC_CFG_MAC_ENA_RX_ENA |
320 	       DEV_GMII_MAC_CFG_MAC_ENA_TX_ENA,
321 	       regs + DEV_GMII_MAC_CFG_MAC_ENA);
322 
323 	/* Make VLAN aware for CPU traffic */
324 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
325 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
326 	       MAC_VID,
327 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
328 
329 	/* Enable switching to/from port */
330 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port - PORT0),
331 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
332 }
333 
334 static void luton_port_init(struct luton_private *priv, int port)
335 {
336 	void __iomem *regs = priv->regs[port];
337 
338 	writel(0, regs + DEV_PORT_MODE_CLK);
339 
340 	/* Enable MAC RX and TX */
341 	writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
342 	       DEV_MAC_CFG_MAC_ENA_TX_ENA,
343 	       regs + DEV_MAC_CFG_MAC_ENA);
344 
345 	/* Make VLAN aware for CPU traffic */
346 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
347 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
348 	       MAC_VID,
349 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
350 
351 	/* Enable switching to/from port */
352 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port - PORT0),
353 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
354 }
355 
356 static void luton_ext_port_init(struct luton_private *priv, int port)
357 {
358 	void __iomem *regs = priv->regs[port];
359 
360 	/* Enable PCS */
361 	writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
362 	       regs + DEV_PCS1G_CFG_PCS1G_CFG);
363 
364 	/* Disable Signal Detect */
365 	writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
366 
367 	/* Enable MAC RX and TX */
368 	writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
369 	       DEV_MAC_CFG_MAC_ENA_TX_ENA,
370 	       regs + DEV_MAC_CFG_MAC_ENA);
371 
372 	/* Clear sgmii_mode_ena */
373 	writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
374 
375 	/*
376 	 * Clear sw_resolve_ena(bit 0) and set adv_ability to
377 	 * something meaningful just in case
378 	 */
379 	writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
380 	       regs + DEV_PCS1G_CFG_PCS1G_ANEG);
381 
382 	/* Set MAC IFG Gaps */
383 	writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(7) |
384 	       DEV_MAC_CFG_MAC_IFG_RX_IFG1(1) |
385 	       DEV_MAC_CFG_MAC_IFG_RX_IFG2(5),
386 	       regs + DEV_MAC_CFG_MAC_IFG);
387 
388 	/* Set link speed and release all resets */
389 	writel(DEV_PORT_MODE_CLK_LINK_SPEED_1000,
390 	       regs + DEV_PORT_MODE_CLK);
391 
392 	/* Make VLAN aware for CPU traffic */
393 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
394 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
395 	       MAC_VID,
396 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(port - PORT0));
397 
398 	/* Enable switching to/from port */
399 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port - PORT0),
400 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
401 }
402 
403 static void serdes6g_write(struct luton_private *priv, u32 addr)
404 {
405 	u32 data;
406 
407 	writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
408 	       HSIO_MCB_SERDES6G_CFG_ADDR(addr),
409 	       priv->regs[HSIO] + HSIO_MCB_SERDES6G_CFG);
410 
411 	do {
412 		data = readl(priv->regs[HSIO] + HSIO_MCB_SERDES6G_CFG);
413 	} while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
414 
415 	mdelay(100);
416 }
417 
418 static void serdes6g_cfg(struct luton_private *priv)
419 {
420 	writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
421 	       HSIO_RCOMP_CFG_CFG0_RUN_CAL,
422 	       priv->regs[HSIO] + HSIO_RCOMP_CFG_CFG0);
423 
424 	while (readl(priv->regs[HSIO] + HSIO_RCOMP_STATUS) &
425 	       HSIO_RCOMP_STATUS_BUSY)
426 		;
427 
428 	writel(HSIO_SERDES6G_ANA_CFG_OB_CFG_SR(0xb) |
429 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_SR_H |
430 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_POST0(0x10) |
431 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_POL |
432 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_ENA1V_MODE,
433 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_OB_CFG);
434 	writel(HSIO_SERDES6G_ANA_CFG_OB_CFG1_LEV(0x18) |
435 	       HSIO_SERDES6G_ANA_CFG_OB_CFG1_ENA_CAS(0x1),
436 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_OB_CFG1);
437 	writel(HSIO_SERDES6G_ANA_CFG_IB_CFG_RESISTOR_CTRL(0xc) |
438 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_VBCOM(0x4) |
439 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_VBAC(0x5) |
440 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_RT(0xf) |
441 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_RF(0x4),
442 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_IB_CFG);
443 	writel(HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST |
444 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSDC |
445 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSAC |
446 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_ANEG_MODE |
447 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_CHF |
448 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_C(0x4),
449 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_IB_CFG1);
450 	writel(HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_ANA(0x5) |
451 	       HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_HYST(0x5) |
452 	       HSIO_SERDES6G_ANA_CFG_DES_CFG_MBTR_CTRL(0x2) |
453 	       HSIO_SERDES6G_ANA_CFG_DES_CFG_PHS_CTRL(0x6),
454 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_DES_CFG);
455 	writel(HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_ENA |
456 	       HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_CTRL_DATA(0x78),
457 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_PLL_CFG);
458 	writel(HSIO_SERDES6G_ANA_CFG_COMMON_CFG_IF_MODE(0x30) |
459 	       HSIO_SERDES6G_ANA_CFG_COMMON_CFG_ENA_LANE,
460 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
461 	/*
462 	 * There are 4 serdes6g, configure all except serdes6g0, therefore
463 	 * the address is b1110
464 	 */
465 	serdes6g_write(priv, 0xe);
466 
467 	writel(readl(priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_COMMON_CFG) |
468 	       HSIO_SERDES6G_ANA_CFG_COMMON_CFG_SYS_RST,
469 	       priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
470 	serdes6g_write(priv, 0xe);
471 
472 	clrbits_le32(priv->regs[HSIO] + HSIO_SERDES6G_ANA_CFG_IB_CFG1,
473 		     HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST);
474 	writel(HSIO_SERDES6G_DIG_CFG_MISC_CFG_LANE_RST,
475 	       priv->regs[HSIO] + HSIO_SERDES6G_DIG_CFG_MISC_CFG);
476 	serdes6g_write(priv, 0xe);
477 }
478 
479 static int luton_switch_init(struct luton_private *priv)
480 {
481 	setbits_le32(priv->regs[HSIO] + HSIO_PLL5G_CFG_PLL5G_CFG2, BIT(1));
482 	clrbits_le32(priv->regs[HSIO] + HSIO_PLL5G_CFG_PLL5G_CFG2, BIT(1));
483 
484 	/* Reset switch & memories */
485 	writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
486 	       priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
487 
488 	/* Wait to complete */
489 	if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
490 			      SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
491 		printf("Timeout in memory reset\n");
492 	}
493 
494 	/* Enable switch core */
495 	setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
496 		     SYS_SYSTEM_RST_CORE_ENA);
497 
498 	/* Setup the Serdes6g macros */
499 	serdes6g_cfg(priv);
500 
501 	return 0;
502 }
503 
504 static int luton_initialize(struct luton_private *priv)
505 {
506 	int ret, i;
507 
508 	/* Initialize switch memories, enable core */
509 	ret = luton_switch_init(priv);
510 	if (ret)
511 		return ret;
512 
513 	/*
514 	 * Disable port-to-port by switching
515 	 * Put front ports in "port isolation modes" - i.e. they can't send
516 	 * to other ports - via the PGID sorce masks.
517 	 */
518 	for (i = 0; i < MAX_PORT; i++)
519 		writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
520 
521 	/* Flush queues */
522 	mscc_flush(priv->regs[QS], luton_regs_qs);
523 
524 	/* Setup frame ageing - "2 sec" - The unit is 4ns on Luton*/
525 	writel(2000000000 / 4,
526 	       priv->regs[SYS] + SYS_FRM_AGING);
527 
528 	for (i = PORT0; i < MAX_PORT; i++) {
529 		if (i < PORT10)
530 			luton_gmii_port_init(priv, i);
531 		else
532 			if (i == PORT10 || i == PORT11)
533 				luton_port_init(priv, i);
534 			else
535 				luton_ext_port_init(priv, i);
536 	}
537 
538 	luton_cpu_capture_setup(priv);
539 
540 	return 0;
541 }
542 
543 static int luton_write_hwaddr(struct udevice *dev)
544 {
545 	struct luton_private *priv = dev_get_priv(dev);
546 	struct eth_pdata *pdata = dev_get_platdata(dev);
547 
548 	mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
549 			   pdata->enetaddr, PGID_UNICAST);
550 
551 	writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
552 
553 	return 0;
554 }
555 
556 static int luton_start(struct udevice *dev)
557 {
558 	struct luton_private *priv = dev_get_priv(dev);
559 	struct eth_pdata *pdata = dev_get_platdata(dev);
560 	const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
561 					      0xff };
562 	int ret;
563 
564 	ret = luton_initialize(priv);
565 	if (ret)
566 		return ret;
567 
568 	/* Set MAC address tables entries for CPU redirection */
569 	mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
570 			   mac, PGID_BROADCAST);
571 
572 	writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
573 	       priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
574 
575 	mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
576 			   pdata->enetaddr, PGID_UNICAST);
577 
578 	writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
579 
580 	return 0;
581 }
582 
583 static int luton_send(struct udevice *dev, void *packet, int length)
584 {
585 	struct luton_private *priv = dev_get_priv(dev);
586 	u32 ifh[IFH_LEN];
587 	int port = BIT(0);	/* use port 0 */
588 	u32 *buf = packet;
589 
590 	ifh[0] = IFH_INJ_BYPASS | port;
591 	ifh[1] = (IFH_TAG_TYPE_C << 16);
592 
593 	return mscc_send(priv->regs[QS], luton_regs_qs,
594 			 ifh, IFH_LEN, buf, length);
595 }
596 
597 static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
598 {
599 	struct luton_private *priv = dev_get_priv(dev);
600 	u32 *rxbuf = (u32 *)net_rx_packets[0];
601 	int byte_cnt = 0;
602 
603 	byte_cnt = mscc_recv(priv->regs[QS], luton_regs_qs, rxbuf, IFH_LEN,
604 			     true);
605 
606 	*packetp = net_rx_packets[0];
607 
608 	return byte_cnt;
609 }
610 
611 static int luton_probe(struct udevice *dev)
612 {
613 	struct luton_private *priv = dev_get_priv(dev);
614 	int i;
615 
616 	struct {
617 		enum luton_target id;
618 		char *name;
619 	} reg[] = {
620 		{ PORT0, "port0" },
621 		{ PORT1, "port1" },
622 		{ PORT2, "port2" },
623 		{ PORT3, "port3" },
624 		{ PORT4, "port4" },
625 		{ PORT5, "port5" },
626 		{ PORT6, "port6" },
627 		{ PORT7, "port7" },
628 		{ PORT8, "port8" },
629 		{ PORT9, "port9" },
630 		{ PORT10, "port10" },
631 		{ PORT11, "port11" },
632 		{ PORT12, "port12" },
633 		{ PORT13, "port13" },
634 		{ PORT14, "port14" },
635 		{ PORT15, "port15" },
636 		{ PORT16, "port16" },
637 		{ PORT17, "port17" },
638 		{ PORT18, "port18" },
639 		{ PORT19, "port19" },
640 		{ PORT20, "port20" },
641 		{ PORT21, "port21" },
642 		{ PORT22, "port22" },
643 		{ PORT23, "port23" },
644 		{ SYS, "sys" },
645 		{ ANA, "ana" },
646 		{ REW, "rew" },
647 		{ GCB, "gcb" },
648 		{ QS, "qs" },
649 		{ HSIO, "hsio" },
650 	};
651 
652 	if (!priv)
653 		return -EINVAL;
654 
655 	for (i = 0; i < ARRAY_SIZE(reg); i++) {
656 		priv->regs[reg[i].id] = dev_remap_addr_name(dev, reg[i].name);
657 		if (!priv->regs[reg[i].id]) {
658 			debug
659 			    ("Error can't get regs base addresses for %s\n",
660 			     reg[i].name);
661 			return -ENOMEM;
662 		}
663 	}
664 
665 	/* Release reset in the CU-PHY */
666 	writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
667 
668 	/* Ports with ext phy don't need to reset clk */
669 	for (i = PORT0; i < MAX_INT_PORT; i++) {
670 		if (i < PORT10)
671 			clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
672 				     DEV_GMII_PORT_MODE_CLK_PHY_RST);
673 		else
674 			clrbits_le32(priv->regs[i] + DEV_PORT_MODE_CLK,
675 				     DEV_PORT_MODE_CLK_PHY_RST);
676 	}
677 
678 	/* Wait for internal PHY to be ready */
679 	if (wait_for_bit_le32(priv->regs[GCB] + GCB_MISC_STAT,
680 			      GCB_MISC_STAT_PHY_READY, true, 500, false))
681 		return -EACCES;
682 
683 	priv->bus[INTERNAL] = luton_mdiobus_init(dev, INTERNAL);
684 
685 	for (i = 0; i < MAX_INT_PORT; i++) {
686 		phy_connect(priv->bus[INTERNAL], i, dev,
687 			    PHY_INTERFACE_MODE_NONE);
688 	}
689 
690 	/*
691 	 * coma_mode is need on only one phy, because all the other phys
692 	 * will be affected.
693 	 */
694 	mscc_miim_write(priv->bus[INTERNAL], 0, 0, 31, 0x10);
695 	mscc_miim_write(priv->bus[INTERNAL], 0, 0, 14, 0x800);
696 	mscc_miim_write(priv->bus[INTERNAL], 0, 0, 31, 0);
697 
698 	return 0;
699 }
700 
701 static int luton_remove(struct udevice *dev)
702 {
703 	struct luton_private *priv = dev_get_priv(dev);
704 	int i;
705 
706 	for (i = 0; i < NUM_PHY; i++) {
707 		mdio_unregister(priv->bus[i]);
708 		mdio_free(priv->bus[i]);
709 	}
710 
711 	return 0;
712 }
713 
714 static const struct eth_ops luton_ops = {
715 	.start        = luton_start,
716 	.stop         = luton_stop,
717 	.send         = luton_send,
718 	.recv         = luton_recv,
719 	.write_hwaddr = luton_write_hwaddr,
720 };
721 
722 static const struct udevice_id mscc_luton_ids[] = {
723 	{.compatible = "mscc,vsc7527-switch", },
724 	{ /* Sentinel */ }
725 };
726 
727 U_BOOT_DRIVER(luton) = {
728 	.name     = "luton-switch",
729 	.id       = UCLASS_ETH,
730 	.of_match = mscc_luton_ids,
731 	.probe	  = luton_probe,
732 	.remove	  = luton_remove,
733 	.ops	  = &luton_ops,
734 	.priv_auto_alloc_size = sizeof(struct luton_private),
735 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
736 };
737