• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_xfer.h"
19 #include "mscc_mac_table.h"
20 #include "mscc_miim.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 static const char * const regs_names[] = {
140 	"port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
141 	"port8", "port9", "port10", "port11", "port12", "port13", "port14",
142 	"port15", "port16", "port17", "port18", "port19", "port20", "port21",
143 	"port22", "port23",
144 	"sys", "ana", "rew", "gcb", "qs", "hsio",
145 };
146 
147 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
148 #define MAX_PORT 24
149 
150 enum luton_ctrl_regs {
151 	SYS = MAX_PORT,
152 	ANA,
153 	REW,
154 	GCB,
155 	QS,
156 	HSIO
157 };
158 
159 #define MIN_INT_PORT	0
160 #define PORT10		10
161 #define PORT11		11
162 #define MAX_INT_PORT	12
163 #define MIN_EXT_PORT	MAX_INT_PORT
164 #define MAX_EXT_PORT	MAX_PORT
165 
166 #define LUTON_MIIM_BUS_COUNT 2
167 
168 struct luton_phy_port_t {
169 	size_t phy_addr;
170 	struct mii_dev *bus;
171 	u8 serdes_index;
172 	u8 phy_mode;
173 };
174 
175 struct luton_private {
176 	void __iomem *regs[REGS_NAMES_COUNT];
177 	struct mii_dev *bus[LUTON_MIIM_BUS_COUNT];
178 	struct luton_phy_port_t ports[MAX_PORT];
179 };
180 
181 static const unsigned long luton_regs_qs[] = {
182 	[MSCC_QS_XTR_RD] = 0x18,
183 	[MSCC_QS_XTR_FLUSH] = 0x28,
184 	[MSCC_QS_XTR_DATA_PRESENT] = 0x2c,
185 	[MSCC_QS_INJ_WR] = 0x3c,
186 	[MSCC_QS_INJ_CTRL] = 0x44,
187 };
188 
189 static const unsigned long luton_regs_ana_table[] = {
190 	[MSCC_ANA_TABLES_MACHDATA] = 0x11b0,
191 	[MSCC_ANA_TABLES_MACLDATA] = 0x11b4,
192 	[MSCC_ANA_TABLES_MACACCESS] = 0x11b8,
193 };
194 
195 static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
196 static int miim_count = -1;
197 
luton_stop(struct udevice * dev)198 static void luton_stop(struct udevice *dev)
199 {
200 	struct luton_private *priv = dev_get_priv(dev);
201 
202 	/*
203 	 * Switch core only reset affects VCORE-III bus and MIPS frequency
204 	 * and thereby also the DDR SDRAM controller. The workaround is to
205 	 * not to redirect any trafic to the CPU after the data transfer.
206 	 */
207 	writel(GENMASK(9, 2), priv->regs[SYS] + SYS_SCH_CPU);
208 }
209 
luton_cpu_capture_setup(struct luton_private * priv)210 static void luton_cpu_capture_setup(struct luton_private *priv)
211 {
212 	int i;
213 
214 	/* map the 8 CPU extraction queues to CPU port 26 */
215 	writel(0x0, priv->regs[SYS] + SYS_SCH_CPU);
216 
217 	for (i = 0; i <= 1; i++) {
218 		/*
219 		 * One to one mapping from CPU Queue number to Group extraction
220 		 * number
221 		 */
222 		writel(QS_XTR_MAP_ENA | (QS_XTR_MAP_GRP * i),
223 		       priv->regs[QS] + QS_XTR_MAP(i));
224 
225 		/* Enable IFH insertion/parsing on CPU ports */
226 		setbits_le32(priv->regs[REW] + REW_PORT_CFG(CPU_PORT + i),
227 			     REW_PORT_CFG_IFH_INSERT_ENA);
228 
229 		/* Enable IFH parsing on CPU port 0 and 1 */
230 		setbits_le32(priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i),
231 			     SYS_PORT_MODE_INCL_INJ_HDR);
232 	}
233 
234 	/* Make VLAN aware for CPU traffic */
235 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
236 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
237 	       MAC_VID,
238 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
239 
240 	/* Disable learning (only RECV_ENA must be set) */
241 	writel(ANA_PORT_PORT_CFG_RECV_ENA,
242 	       priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
243 
244 	/* Enable switching to/from cpu port */
245 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(CPU_PORT),
246 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
247 
248 	setbits_le32(priv->regs[SYS] + SYS_EGR_NO_SHARING, BIT(CPU_PORT));
249 }
250 
luton_gmii_port_init(struct luton_private * priv,int port)251 static void luton_gmii_port_init(struct luton_private *priv, int port)
252 {
253 	void __iomem *regs = priv->regs[port];
254 
255 	writel(0, regs + DEV_GMII_PORT_MODE_CLK);
256 
257 	/* Enable MAC RX and TX */
258 	writel(DEV_GMII_MAC_CFG_MAC_ENA_RX_ENA |
259 	       DEV_GMII_MAC_CFG_MAC_ENA_TX_ENA,
260 	       regs + DEV_GMII_MAC_CFG_MAC_ENA);
261 
262 	/* Make VLAN aware for CPU traffic */
263 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
264 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
265 	       MAC_VID,
266 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
267 
268 	/* Enable switching to/from port */
269 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
270 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
271 }
272 
luton_port_init(struct luton_private * priv,int port)273 static void luton_port_init(struct luton_private *priv, int port)
274 {
275 	void __iomem *regs = priv->regs[port];
276 
277 	writel(0, regs + DEV_PORT_MODE_CLK);
278 
279 	/* Enable MAC RX and TX */
280 	writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
281 	       DEV_MAC_CFG_MAC_ENA_TX_ENA,
282 	       regs + DEV_MAC_CFG_MAC_ENA);
283 
284 	/* Make VLAN aware for CPU traffic */
285 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
286 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
287 	       MAC_VID,
288 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
289 
290 	/* Enable switching to/from port */
291 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
292 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
293 }
294 
luton_ext_port_init(struct luton_private * priv,int port)295 static void luton_ext_port_init(struct luton_private *priv, int port)
296 {
297 	void __iomem *regs = priv->regs[port];
298 
299 	/* Enable PCS */
300 	writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
301 	       regs + DEV_PCS1G_CFG_PCS1G_CFG);
302 
303 	/* Disable Signal Detect */
304 	writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
305 
306 	/* Enable MAC RX and TX */
307 	writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
308 	       DEV_MAC_CFG_MAC_ENA_TX_ENA,
309 	       regs + DEV_MAC_CFG_MAC_ENA);
310 
311 	/* Clear sgmii_mode_ena */
312 	writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
313 
314 	/*
315 	 * Clear sw_resolve_ena(bit 0) and set adv_ability to
316 	 * something meaningful just in case
317 	 */
318 	writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
319 	       regs + DEV_PCS1G_CFG_PCS1G_ANEG);
320 
321 	/* Set MAC IFG Gaps */
322 	writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(7) |
323 	       DEV_MAC_CFG_MAC_IFG_RX_IFG1(1) |
324 	       DEV_MAC_CFG_MAC_IFG_RX_IFG2(5),
325 	       regs + DEV_MAC_CFG_MAC_IFG);
326 
327 	/* Set link speed and release all resets */
328 	writel(DEV_PORT_MODE_CLK_LINK_SPEED_1000,
329 	       regs + DEV_PORT_MODE_CLK);
330 
331 	/* Make VLAN aware for CPU traffic */
332 	writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
333 	       ANA_PORT_VLAN_CFG_POP_CNT(1) |
334 	       MAC_VID,
335 	       priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
336 
337 	/* Enable switching to/from port */
338 	setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
339 		     SYS_SWITCH_PORT_MODE_PORT_ENA);
340 }
341 
serdes6g_write(void __iomem * base,u32 addr)342 static void serdes6g_write(void __iomem *base, u32 addr)
343 {
344 	u32 data;
345 
346 	writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
347 	       HSIO_MCB_SERDES6G_CFG_ADDR(addr),
348 	       base + HSIO_MCB_SERDES6G_CFG);
349 
350 	do {
351 		data = readl(base + HSIO_MCB_SERDES6G_CFG);
352 	} while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
353 }
354 
serdes6g_setup(void __iomem * base,uint32_t addr,phy_interface_t interface)355 static void serdes6g_setup(void __iomem *base, uint32_t addr,
356 			   phy_interface_t interface)
357 {
358 	writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
359 	       HSIO_RCOMP_CFG_CFG0_RUN_CAL,
360 	       base + HSIO_RCOMP_CFG_CFG0);
361 
362 	while (readl(base + HSIO_RCOMP_STATUS) &
363 	       HSIO_RCOMP_STATUS_BUSY)
364 		;
365 
366 	writel(HSIO_SERDES6G_ANA_CFG_OB_CFG_SR(0xb) |
367 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_SR_H |
368 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_POST0(0x10) |
369 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_POL |
370 	       HSIO_SERDES6G_ANA_CFG_OB_CFG_ENA1V_MODE,
371 	       base + HSIO_SERDES6G_ANA_CFG_OB_CFG);
372 	writel(HSIO_SERDES6G_ANA_CFG_OB_CFG1_LEV(0x18) |
373 	       HSIO_SERDES6G_ANA_CFG_OB_CFG1_ENA_CAS(0x1),
374 	       base + HSIO_SERDES6G_ANA_CFG_OB_CFG1);
375 	writel(HSIO_SERDES6G_ANA_CFG_IB_CFG_RESISTOR_CTRL(0xc) |
376 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_VBCOM(0x4) |
377 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_VBAC(0x5) |
378 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_RT(0xf) |
379 	       HSIO_SERDES6G_ANA_CFG_IB_CFG_RF(0x4),
380 	       base + HSIO_SERDES6G_ANA_CFG_IB_CFG);
381 	writel(HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST |
382 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSDC |
383 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSAC |
384 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_ANEG_MODE |
385 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_CHF |
386 	       HSIO_SERDES6G_ANA_CFG_IB_CFG1_C(0x4),
387 	       base + HSIO_SERDES6G_ANA_CFG_IB_CFG1);
388 	writel(HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_ANA(0x5) |
389 	       HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_HYST(0x5) |
390 	       HSIO_SERDES6G_ANA_CFG_DES_CFG_MBTR_CTRL(0x2) |
391 	       HSIO_SERDES6G_ANA_CFG_DES_CFG_PHS_CTRL(0x6),
392 	       base + HSIO_SERDES6G_ANA_CFG_DES_CFG);
393 	writel(HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_ENA |
394 	       HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_CTRL_DATA(0x78),
395 	       base + HSIO_SERDES6G_ANA_CFG_PLL_CFG);
396 	writel(HSIO_SERDES6G_ANA_CFG_COMMON_CFG_IF_MODE(0x30) |
397 	       HSIO_SERDES6G_ANA_CFG_COMMON_CFG_ENA_LANE,
398 	       base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
399 	/*
400 	 * There are 4 serdes6g, configure all except serdes6g0, therefore
401 	 * the address is b1110
402 	 */
403 	serdes6g_write(base, addr);
404 
405 	writel(readl(base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG) |
406 	       HSIO_SERDES6G_ANA_CFG_COMMON_CFG_SYS_RST,
407 	       base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
408 	serdes6g_write(base, addr);
409 
410 	clrbits_le32(base + HSIO_SERDES6G_ANA_CFG_IB_CFG1,
411 		     HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST);
412 	writel(HSIO_SERDES6G_DIG_CFG_MISC_CFG_LANE_RST,
413 	       base + HSIO_SERDES6G_DIG_CFG_MISC_CFG);
414 	serdes6g_write(base, addr);
415 }
416 
serdes_setup(struct luton_private * priv)417 static void serdes_setup(struct luton_private *priv)
418 {
419 	size_t mask;
420 	int i = 0;
421 
422 	for (i = 0; i < MAX_PORT; ++i) {
423 		if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
424 			continue;
425 
426 		mask = BIT(priv->ports[i].serdes_index);
427 		serdes6g_setup(priv->regs[HSIO], mask, priv->ports[i].phy_mode);
428 	}
429 }
430 
luton_switch_init(struct luton_private * priv)431 static int luton_switch_init(struct luton_private *priv)
432 {
433 	setbits_le32(priv->regs[HSIO] + HSIO_PLL5G_CFG_PLL5G_CFG2, BIT(1));
434 	clrbits_le32(priv->regs[HSIO] + HSIO_PLL5G_CFG_PLL5G_CFG2, BIT(1));
435 
436 	/* Reset switch & memories */
437 	writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
438 	       priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
439 
440 	/* Wait to complete */
441 	if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
442 			      SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
443 		printf("Timeout in memory reset\n");
444 	}
445 
446 	/* Enable switch core */
447 	setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
448 		     SYS_SYSTEM_RST_CORE_ENA);
449 
450 	/* Setup the Serdes macros */
451 	serdes_setup(priv);
452 
453 	return 0;
454 }
455 
luton_initialize(struct luton_private * priv)456 static int luton_initialize(struct luton_private *priv)
457 {
458 	int ret, i;
459 
460 	/* Initialize switch memories, enable core */
461 	ret = luton_switch_init(priv);
462 	if (ret)
463 		return ret;
464 
465 	/*
466 	 * Disable port-to-port by switching
467 	 * Put front ports in "port isolation modes" - i.e. they can't send
468 	 * to other ports - via the PGID sorce masks.
469 	 */
470 	for (i = 0; i < MAX_PORT; i++)
471 		writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
472 
473 	/* Flush queues */
474 	mscc_flush(priv->regs[QS], luton_regs_qs);
475 
476 	/* Setup frame ageing - "2 sec" - The unit is 4ns on Luton*/
477 	writel(2000000000 / 4,
478 	       priv->regs[SYS] + SYS_FRM_AGING);
479 
480 	for (i = 0; i < MAX_PORT; i++) {
481 		if (i < PORT10)
482 			luton_gmii_port_init(priv, i);
483 		else
484 			if (i == PORT10 || i == PORT11)
485 				luton_port_init(priv, i);
486 			else
487 				luton_ext_port_init(priv, i);
488 	}
489 
490 	luton_cpu_capture_setup(priv);
491 
492 	return 0;
493 }
494 
luton_write_hwaddr(struct udevice * dev)495 static int luton_write_hwaddr(struct udevice *dev)
496 {
497 	struct luton_private *priv = dev_get_priv(dev);
498 	struct eth_pdata *pdata = dev_get_platdata(dev);
499 
500 	mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
501 			   pdata->enetaddr, PGID_UNICAST);
502 
503 	writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
504 
505 	return 0;
506 }
507 
luton_start(struct udevice * dev)508 static int luton_start(struct udevice *dev)
509 {
510 	struct luton_private *priv = dev_get_priv(dev);
511 	struct eth_pdata *pdata = dev_get_platdata(dev);
512 	const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
513 					      0xff };
514 	int ret;
515 
516 	ret = luton_initialize(priv);
517 	if (ret)
518 		return ret;
519 
520 	/* Set MAC address tables entries for CPU redirection */
521 	mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
522 			   mac, PGID_BROADCAST);
523 
524 	writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
525 	       priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
526 
527 	mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
528 			   pdata->enetaddr, PGID_UNICAST);
529 
530 	writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
531 
532 	return 0;
533 }
534 
luton_send(struct udevice * dev,void * packet,int length)535 static int luton_send(struct udevice *dev, void *packet, int length)
536 {
537 	struct luton_private *priv = dev_get_priv(dev);
538 	u32 ifh[IFH_LEN];
539 	int port = BIT(0);	/* use port 0 */
540 	u32 *buf = packet;
541 
542 	ifh[0] = IFH_INJ_BYPASS | port;
543 	ifh[1] = (IFH_TAG_TYPE_C << 16);
544 
545 	return mscc_send(priv->regs[QS], luton_regs_qs,
546 			 ifh, IFH_LEN, buf, length);
547 }
548 
luton_recv(struct udevice * dev,int flags,uchar ** packetp)549 static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
550 {
551 	struct luton_private *priv = dev_get_priv(dev);
552 	u32 *rxbuf = (u32 *)net_rx_packets[0];
553 	int byte_cnt = 0;
554 
555 	byte_cnt = mscc_recv(priv->regs[QS], luton_regs_qs, rxbuf, IFH_LEN,
556 			     true);
557 
558 	*packetp = net_rx_packets[0];
559 
560 	return byte_cnt;
561 }
562 
get_mdiobus(phys_addr_t base,unsigned long size)563 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
564 {
565 	int i = 0;
566 
567 	for (i = 0; i < LUTON_MIIM_BUS_COUNT; ++i)
568 		if (miim[i].miim_base == base && miim[i].miim_size == size)
569 			return miim[i].bus;
570 
571 	return NULL;
572 }
573 
add_port_entry(struct luton_private * priv,size_t index,size_t phy_addr,struct mii_dev * bus,u8 serdes_index,u8 phy_mode)574 static void add_port_entry(struct luton_private *priv, size_t index,
575 			   size_t phy_addr, struct mii_dev *bus,
576 			   u8 serdes_index, u8 phy_mode)
577 {
578 	priv->ports[index].phy_addr = phy_addr;
579 	priv->ports[index].bus = bus;
580 	priv->ports[index].serdes_index = serdes_index;
581 	priv->ports[index].phy_mode = phy_mode;
582 }
583 
luton_probe(struct udevice * dev)584 static int luton_probe(struct udevice *dev)
585 {
586 	struct luton_private *priv = dev_get_priv(dev);
587 	int i, ret;
588 	struct resource res;
589 	fdt32_t faddr;
590 	phys_addr_t addr_base;
591 	unsigned long addr_size;
592 	ofnode eth_node, node, mdio_node;
593 	size_t phy_addr;
594 	struct mii_dev *bus;
595 	struct ofnode_phandle_args phandle;
596 	struct phy_device *phy;
597 
598 	if (!priv)
599 		return -EINVAL;
600 
601 	/* Get registers and map them to the private structure */
602 	for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
603 		priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
604 		if (!priv->regs[i]) {
605 			debug
606 			    ("Error can't get regs base addresses for %s\n",
607 			     regs_names[i]);
608 			return -ENOMEM;
609 		}
610 	}
611 
612 	/* Release reset in the CU-PHY */
613 	writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
614 
615 	/* Ports with ext phy don't need to reset clk */
616 	for (i = 0; i < MAX_INT_PORT; i++) {
617 		if (i < PORT10)
618 			clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
619 				     DEV_GMII_PORT_MODE_CLK_PHY_RST);
620 		else
621 			clrbits_le32(priv->regs[i] + DEV_PORT_MODE_CLK,
622 				     DEV_PORT_MODE_CLK_PHY_RST);
623 	}
624 
625 	/* Wait for internal PHY to be ready */
626 	if (wait_for_bit_le32(priv->regs[GCB] + GCB_MISC_STAT,
627 			      GCB_MISC_STAT_PHY_READY, true, 500, false))
628 		return -EACCES;
629 
630 
631 	/* Initialize miim buses */
632 	memset(&miim, 0x0, sizeof(miim) * LUTON_MIIM_BUS_COUNT);
633 
634 	/* iterate all the ports and find out on which bus they are */
635 	i = 0;
636 	eth_node = dev_read_first_subnode(dev);
637 	for (node = ofnode_first_subnode(eth_node);
638 	     ofnode_valid(node);
639 	     node = ofnode_next_subnode(node)) {
640 		if (ofnode_read_resource(node, 0, &res))
641 			return -ENOMEM;
642 		i = res.start;
643 
644 		ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
645 						     0, 0, &phandle);
646 		if (ret)
647 			continue;
648 
649 		/* Get phy address on mdio bus */
650 		if (ofnode_read_resource(phandle.node, 0, &res))
651 			return -ENOMEM;
652 		phy_addr = res.start;
653 
654 		/* Get mdio node */
655 		mdio_node = ofnode_get_parent(phandle.node);
656 
657 		if (ofnode_read_resource(mdio_node, 0, &res))
658 			return -ENOMEM;
659 		faddr = cpu_to_fdt32(res.start);
660 
661 		addr_base = ofnode_translate_address(mdio_node, &faddr);
662 		addr_size = res.end - res.start;
663 
664 		/* If the bus is new then create a new bus */
665 		if (!get_mdiobus(addr_base, addr_size))
666 			priv->bus[miim_count] =
667 				mscc_mdiobus_init(miim, &miim_count, addr_base,
668 						  addr_size);
669 
670 		/* Connect mdio bus with the port */
671 		bus = get_mdiobus(addr_base, addr_size);
672 
673 		/* Get serdes info */
674 		ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
675 						     3, 0, &phandle);
676 		if (ret)
677 			add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
678 		else
679 			add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
680 				       phandle.args[2]);
681 	}
682 
683 	for (i = 0; i < MAX_PORT; i++) {
684 		if (!priv->ports[i].bus)
685 			continue;
686 
687 		phy = phy_connect(priv->ports[i].bus,
688 				  priv->ports[i].phy_addr, dev,
689 				  PHY_INTERFACE_MODE_NONE);
690 		if (phy && i >= MAX_INT_PORT)
691 			board_phy_config(phy);
692 	}
693 
694 	/*
695 	 * coma_mode is need on only one phy, because all the other phys
696 	 * will be affected.
697 	 */
698 	mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0x10);
699 	mscc_miim_write(priv->ports[0].bus, 0, 0, 14, 0x800);
700 	mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0);
701 
702 	return 0;
703 }
704 
luton_remove(struct udevice * dev)705 static int luton_remove(struct udevice *dev)
706 {
707 	struct luton_private *priv = dev_get_priv(dev);
708 	int i;
709 
710 	for (i = 0; i < LUTON_MIIM_BUS_COUNT; i++) {
711 		mdio_unregister(priv->bus[i]);
712 		mdio_free(priv->bus[i]);
713 	}
714 
715 	return 0;
716 }
717 
718 static const struct eth_ops luton_ops = {
719 	.start        = luton_start,
720 	.stop         = luton_stop,
721 	.send         = luton_send,
722 	.recv         = luton_recv,
723 	.write_hwaddr = luton_write_hwaddr,
724 };
725 
726 static const struct udevice_id mscc_luton_ids[] = {
727 	{.compatible = "mscc,vsc7527-switch", },
728 	{ /* Sentinel */ }
729 };
730 
731 U_BOOT_DRIVER(luton) = {
732 	.name     = "luton-switch",
733 	.id       = UCLASS_ETH,
734 	.of_match = mscc_luton_ids,
735 	.probe	  = luton_probe,
736 	.remove	  = luton_remove,
737 	.ops	  = &luton_ops,
738 	.priv_auto_alloc_size = sizeof(struct luton_private),
739 	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
740 };
741