1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
3 * Copyright (c) 2019 Microsemi Corporation
10 #include <dm/of_access.h>
11 #include <dm/of_addr.h>
12 #include <fdt_support.h>
13 #include <linux/bitops.h>
15 #include <linux/ioport.h>
20 #include "mscc_xfer.h"
21 #include "mscc_mac_table.h"
22 #include "mscc_miim.h"
24 #define ANA_PORT_VLAN_CFG(x) (0x00 + 0x80 * (x))
25 #define ANA_PORT_VLAN_CFG_AWARE_ENA BIT(20)
26 #define ANA_PORT_VLAN_CFG_POP_CNT(x) ((x) << 18)
27 #define ANA_PORT_CPU_FWD_CFG(x) (0x50 + 0x80 * (x))
28 #define ANA_PORT_CPU_FWD_CFG_SRC_COPY_ENA BIT(1)
29 #define ANA_PORT_PORT_CFG(x) (0x60 + 0x80 * (x))
30 #define ANA_PORT_PORT_CFG_RECV_ENA BIT(5)
31 #define ANA_PGID(x) (0x1000 + 4 * (x))
33 #define SYS_FRM_AGING 0x8300
35 #define SYS_SYSTEM_RST_CFG 0x81b0
36 #define SYS_SYSTEM_RST_MEM_INIT BIT(0)
37 #define SYS_SYSTEM_RST_MEM_ENA BIT(1)
38 #define SYS_SYSTEM_RST_CORE_ENA BIT(2)
39 #define SYS_PORT_MODE(x) (0x81bc + 0x4 * (x))
40 #define SYS_PORT_MODE_INCL_INJ_HDR BIT(0)
41 #define SYS_SWITCH_PORT_MODE(x) (0x8294 + 0x4 * (x))
42 #define SYS_SWITCH_PORT_MODE_PORT_ENA BIT(3)
43 #define SYS_EGR_NO_SHARING 0x8378
44 #define SYS_SCH_CPU 0x85a0
46 #define REW_PORT_CFG(x) (0x8 + 0x80 * (x))
47 #define REW_PORT_CFG_IFH_INSERT_ENA BIT(7)
49 #define GCB_DEVCPU_RST_SOFT_CHIP_RST 0x90
50 #define GCB_DEVCPU_RST_SOFT_CHIP_RST_SOFT_PHY BIT(1)
51 #define GCB_MISC_STAT 0x11c
52 #define GCB_MISC_STAT_PHY_READY BIT(3)
54 #define QS_XTR_MAP(x) (0x10 + 4 * (x))
55 #define QS_XTR_MAP_GRP BIT(4)
56 #define QS_XTR_MAP_ENA BIT(0)
58 #define HSIO_PLL5G_CFG_PLL5G_CFG2 0x8
60 #define HSIO_RCOMP_CFG_CFG0 0x20
61 #define HSIO_RCOMP_CFG_CFG0_MODE_SEL(x) ((x) << 8)
62 #define HSIO_RCOMP_CFG_CFG0_RUN_CAL BIT(12)
63 #define HSIO_RCOMP_STATUS 0x24
64 #define HSIO_RCOMP_STATUS_BUSY BIT(12)
65 #define HSIO_RCOMP_STATUS_RCOMP_M GENMASK(3, 0)
66 #define HSIO_SERDES6G_ANA_CFG_DES_CFG 0x64
67 #define HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_ANA(x) ((x) << 1)
68 #define HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_HYST(x) ((x) << 5)
69 #define HSIO_SERDES6G_ANA_CFG_DES_CFG_MBTR_CTRL(x) ((x) << 10)
70 #define HSIO_SERDES6G_ANA_CFG_DES_CFG_PHS_CTRL(x) ((x) << 13)
71 #define HSIO_SERDES6G_ANA_CFG_IB_CFG 0x68
72 #define HSIO_SERDES6G_ANA_CFG_IB_CFG_RESISTOR_CTRL(x) (x)
73 #define HSIO_SERDES6G_ANA_CFG_IB_CFG_VBCOM(x) ((x) << 4)
74 #define HSIO_SERDES6G_ANA_CFG_IB_CFG_VBAC(x) ((x) << 7)
75 #define HSIO_SERDES6G_ANA_CFG_IB_CFG_RT(x) ((x) << 9)
76 #define HSIO_SERDES6G_ANA_CFG_IB_CFG_RF(x) ((x) << 14)
77 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1 0x6c
78 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST BIT(0)
79 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSDC BIT(2)
80 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSAC BIT(3)
81 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1_ANEG_MODE BIT(6)
82 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1_CHF BIT(7)
83 #define HSIO_SERDES6G_ANA_CFG_IB_CFG1_C(x) ((x) << 8)
84 #define HSIO_SERDES6G_ANA_CFG_OB_CFG 0x70
85 #define HSIO_SERDES6G_ANA_CFG_OB_CFG_SR(x) ((x) << 4)
86 #define HSIO_SERDES6G_ANA_CFG_OB_CFG_SR_H BIT(8)
87 #define HSIO_SERDES6G_ANA_CFG_OB_CFG_POST0(x) ((x) << 23)
88 #define HSIO_SERDES6G_ANA_CFG_OB_CFG_POL BIT(29)
89 #define HSIO_SERDES6G_ANA_CFG_OB_CFG_ENA1V_MODE BIT(30)
90 #define HSIO_SERDES6G_ANA_CFG_OB_CFG1 0x74
91 #define HSIO_SERDES6G_ANA_CFG_OB_CFG1_LEV(x) (x)
92 #define HSIO_SERDES6G_ANA_CFG_OB_CFG1_ENA_CAS(x) ((x) << 6)
93 #define HSIO_SERDES6G_ANA_CFG_COMMON_CFG 0x7c
94 #define HSIO_SERDES6G_ANA_CFG_COMMON_CFG_IF_MODE(x) (x)
95 #define HSIO_SERDES6G_ANA_CFG_COMMON_CFG_ENA_LANE BIT(18)
96 #define HSIO_SERDES6G_ANA_CFG_COMMON_CFG_SYS_RST BIT(31)
97 #define HSIO_SERDES6G_ANA_CFG_PLL_CFG 0x80
98 #define HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_ENA BIT(7)
99 #define HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_CTRL_DATA(x) ((x) << 8)
100 #define HSIO_SERDES6G_ANA_CFG_SER_CFG 0x84
101 #define HSIO_SERDES6G_DIG_CFG_MISC_CFG 0x88
102 #define HSIO_SERDES6G_DIG_CFG_MISC_CFG_LANE_RST BIT(0)
103 #define HSIO_MCB_SERDES6G_CFG 0xac
104 #define HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT BIT(31)
105 #define HSIO_MCB_SERDES6G_CFG_ADDR(x) (x)
107 #define DEV_GMII_PORT_MODE_CLK 0x0
108 #define DEV_GMII_PORT_MODE_CLK_PHY_RST BIT(0)
109 #define DEV_GMII_MAC_CFG_MAC_ENA 0xc
110 #define DEV_GMII_MAC_CFG_MAC_ENA_RX_ENA BIT(4)
111 #define DEV_GMII_MAC_CFG_MAC_ENA_TX_ENA BIT(0)
113 #define DEV_PORT_MODE_CLK 0x4
114 #define DEV_PORT_MODE_CLK_PHY_RST BIT(2)
115 #define DEV_PORT_MODE_CLK_LINK_SPEED_1000 1
116 #define DEV_MAC_CFG_MAC_ENA 0x10
117 #define DEV_MAC_CFG_MAC_ENA_RX_ENA BIT(4)
118 #define DEV_MAC_CFG_MAC_ENA_TX_ENA BIT(0)
119 #define DEV_MAC_CFG_MAC_IFG 0x24
120 #define DEV_MAC_CFG_MAC_IFG_TX_IFG(x) ((x) << 8)
121 #define DEV_MAC_CFG_MAC_IFG_RX_IFG2(x) ((x) << 4)
122 #define DEV_MAC_CFG_MAC_IFG_RX_IFG1(x) (x)
123 #define DEV_PCS1G_CFG_PCS1G_CFG 0x40
124 #define DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA BIT(0)
125 #define DEV_PCS1G_CFG_PCS1G_MODE 0x44
126 #define DEV_PCS1G_CFG_PCS1G_SD 0x48
127 #define DEV_PCS1G_CFG_PCS1G_ANEG 0x4c
128 #define DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
130 #define IFH_INJ_BYPASS BIT(31)
131 #define IFH_TAG_TYPE_C 0
134 #define INTERNAL_PORT_MSK 0xFFFFFF
137 #define PGID_BROADCAST 28
138 #define PGID_UNICAST 29
141 static const char * const regs_names[] = {
142 "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
143 "port8", "port9", "port10", "port11", "port12", "port13", "port14",
144 "port15", "port16", "port17", "port18", "port19", "port20", "port21",
146 "sys", "ana", "rew", "gcb", "qs", "hsio",
149 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
152 enum luton_ctrl_regs {
161 #define MIN_INT_PORT 0
164 #define MAX_INT_PORT 12
165 #define MIN_EXT_PORT MAX_INT_PORT
166 #define MAX_EXT_PORT MAX_PORT
168 #define LUTON_MIIM_BUS_COUNT 2
170 struct luton_phy_port_t {
177 struct luton_private {
178 void __iomem *regs[REGS_NAMES_COUNT];
179 struct mii_dev *bus[LUTON_MIIM_BUS_COUNT];
180 struct luton_phy_port_t ports[MAX_PORT];
183 static const unsigned long luton_regs_qs[] = {
184 [MSCC_QS_XTR_RD] = 0x18,
185 [MSCC_QS_XTR_FLUSH] = 0x28,
186 [MSCC_QS_XTR_DATA_PRESENT] = 0x2c,
187 [MSCC_QS_INJ_WR] = 0x3c,
188 [MSCC_QS_INJ_CTRL] = 0x44,
191 static const unsigned long luton_regs_ana_table[] = {
192 [MSCC_ANA_TABLES_MACHDATA] = 0x11b0,
193 [MSCC_ANA_TABLES_MACLDATA] = 0x11b4,
194 [MSCC_ANA_TABLES_MACACCESS] = 0x11b8,
197 static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
198 static int miim_count = -1;
200 static void luton_stop(struct udevice *dev)
202 struct luton_private *priv = dev_get_priv(dev);
205 * Switch core only reset affects VCORE-III bus and MIPS frequency
206 * and thereby also the DDR SDRAM controller. The workaround is to
207 * not to redirect any trafic to the CPU after the data transfer.
209 writel(GENMASK(9, 2), priv->regs[SYS] + SYS_SCH_CPU);
212 static void luton_cpu_capture_setup(struct luton_private *priv)
216 /* map the 8 CPU extraction queues to CPU port 26 */
217 writel(0x0, priv->regs[SYS] + SYS_SCH_CPU);
219 for (i = 0; i <= 1; i++) {
221 * One to one mapping from CPU Queue number to Group extraction
224 writel(QS_XTR_MAP_ENA | (QS_XTR_MAP_GRP * i),
225 priv->regs[QS] + QS_XTR_MAP(i));
227 /* Enable IFH insertion/parsing on CPU ports */
228 setbits_le32(priv->regs[REW] + REW_PORT_CFG(CPU_PORT + i),
229 REW_PORT_CFG_IFH_INSERT_ENA);
231 /* Enable IFH parsing on CPU port 0 and 1 */
232 setbits_le32(priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i),
233 SYS_PORT_MODE_INCL_INJ_HDR);
236 /* Make VLAN aware for CPU traffic */
237 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
238 ANA_PORT_VLAN_CFG_POP_CNT(1) |
240 priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
242 /* Disable learning (only RECV_ENA must be set) */
243 writel(ANA_PORT_PORT_CFG_RECV_ENA,
244 priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
246 /* Enable switching to/from cpu port */
247 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(CPU_PORT),
248 SYS_SWITCH_PORT_MODE_PORT_ENA);
250 setbits_le32(priv->regs[SYS] + SYS_EGR_NO_SHARING, BIT(CPU_PORT));
253 static void luton_gmii_port_init(struct luton_private *priv, int port)
255 void __iomem *regs = priv->regs[port];
257 writel(0, regs + DEV_GMII_PORT_MODE_CLK);
259 /* Enable MAC RX and TX */
260 writel(DEV_GMII_MAC_CFG_MAC_ENA_RX_ENA |
261 DEV_GMII_MAC_CFG_MAC_ENA_TX_ENA,
262 regs + DEV_GMII_MAC_CFG_MAC_ENA);
264 /* Make VLAN aware for CPU traffic */
265 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
266 ANA_PORT_VLAN_CFG_POP_CNT(1) |
268 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
270 /* Enable switching to/from port */
271 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
272 SYS_SWITCH_PORT_MODE_PORT_ENA);
275 static void luton_port_init(struct luton_private *priv, int port)
277 void __iomem *regs = priv->regs[port];
279 writel(0, regs + DEV_PORT_MODE_CLK);
281 /* Enable MAC RX and TX */
282 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
283 DEV_MAC_CFG_MAC_ENA_TX_ENA,
284 regs + DEV_MAC_CFG_MAC_ENA);
286 /* Make VLAN aware for CPU traffic */
287 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
288 ANA_PORT_VLAN_CFG_POP_CNT(1) |
290 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
292 /* Enable switching to/from port */
293 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
294 SYS_SWITCH_PORT_MODE_PORT_ENA);
297 static void luton_ext_port_init(struct luton_private *priv, int port)
299 void __iomem *regs = priv->regs[port];
302 writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
303 regs + DEV_PCS1G_CFG_PCS1G_CFG);
305 /* Disable Signal Detect */
306 writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
308 /* Enable MAC RX and TX */
309 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
310 DEV_MAC_CFG_MAC_ENA_TX_ENA,
311 regs + DEV_MAC_CFG_MAC_ENA);
313 /* Clear sgmii_mode_ena */
314 writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
317 * Clear sw_resolve_ena(bit 0) and set adv_ability to
318 * something meaningful just in case
320 writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
321 regs + DEV_PCS1G_CFG_PCS1G_ANEG);
323 /* Set MAC IFG Gaps */
324 writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(7) |
325 DEV_MAC_CFG_MAC_IFG_RX_IFG1(1) |
326 DEV_MAC_CFG_MAC_IFG_RX_IFG2(5),
327 regs + DEV_MAC_CFG_MAC_IFG);
329 /* Set link speed and release all resets */
330 writel(DEV_PORT_MODE_CLK_LINK_SPEED_1000,
331 regs + DEV_PORT_MODE_CLK);
333 /* Make VLAN aware for CPU traffic */
334 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
335 ANA_PORT_VLAN_CFG_POP_CNT(1) |
337 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
339 /* Enable switching to/from port */
340 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
341 SYS_SWITCH_PORT_MODE_PORT_ENA);
344 static void serdes6g_write(void __iomem *base, u32 addr)
348 writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
349 HSIO_MCB_SERDES6G_CFG_ADDR(addr),
350 base + HSIO_MCB_SERDES6G_CFG);
353 data = readl(base + HSIO_MCB_SERDES6G_CFG);
354 } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
357 static void serdes6g_setup(void __iomem *base, uint32_t addr,
358 phy_interface_t interface)
360 writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
361 HSIO_RCOMP_CFG_CFG0_RUN_CAL,
362 base + HSIO_RCOMP_CFG_CFG0);
364 while (readl(base + HSIO_RCOMP_STATUS) &
365 HSIO_RCOMP_STATUS_BUSY)
368 writel(HSIO_SERDES6G_ANA_CFG_OB_CFG_SR(0xb) |
369 HSIO_SERDES6G_ANA_CFG_OB_CFG_SR_H |
370 HSIO_SERDES6G_ANA_CFG_OB_CFG_POST0(0x10) |
371 HSIO_SERDES6G_ANA_CFG_OB_CFG_POL |
372 HSIO_SERDES6G_ANA_CFG_OB_CFG_ENA1V_MODE,
373 base + HSIO_SERDES6G_ANA_CFG_OB_CFG);
374 writel(HSIO_SERDES6G_ANA_CFG_OB_CFG1_LEV(0x18) |
375 HSIO_SERDES6G_ANA_CFG_OB_CFG1_ENA_CAS(0x1),
376 base + HSIO_SERDES6G_ANA_CFG_OB_CFG1);
377 writel(HSIO_SERDES6G_ANA_CFG_IB_CFG_RESISTOR_CTRL(0xc) |
378 HSIO_SERDES6G_ANA_CFG_IB_CFG_VBCOM(0x4) |
379 HSIO_SERDES6G_ANA_CFG_IB_CFG_VBAC(0x5) |
380 HSIO_SERDES6G_ANA_CFG_IB_CFG_RT(0xf) |
381 HSIO_SERDES6G_ANA_CFG_IB_CFG_RF(0x4),
382 base + HSIO_SERDES6G_ANA_CFG_IB_CFG);
383 writel(HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST |
384 HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSDC |
385 HSIO_SERDES6G_ANA_CFG_IB_CFG1_ENA_OFFSAC |
386 HSIO_SERDES6G_ANA_CFG_IB_CFG1_ANEG_MODE |
387 HSIO_SERDES6G_ANA_CFG_IB_CFG1_CHF |
388 HSIO_SERDES6G_ANA_CFG_IB_CFG1_C(0x4),
389 base + HSIO_SERDES6G_ANA_CFG_IB_CFG1);
390 writel(HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_ANA(0x5) |
391 HSIO_SERDES6G_ANA_CFG_DES_CFG_BW_HYST(0x5) |
392 HSIO_SERDES6G_ANA_CFG_DES_CFG_MBTR_CTRL(0x2) |
393 HSIO_SERDES6G_ANA_CFG_DES_CFG_PHS_CTRL(0x6),
394 base + HSIO_SERDES6G_ANA_CFG_DES_CFG);
395 writel(HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_ENA |
396 HSIO_SERDES6G_ANA_CFG_PLL_CFG_FSM_CTRL_DATA(0x78),
397 base + HSIO_SERDES6G_ANA_CFG_PLL_CFG);
398 writel(HSIO_SERDES6G_ANA_CFG_COMMON_CFG_IF_MODE(0x30) |
399 HSIO_SERDES6G_ANA_CFG_COMMON_CFG_ENA_LANE,
400 base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
402 * There are 4 serdes6g, configure all except serdes6g0, therefore
403 * the address is b1110
405 serdes6g_write(base, addr);
407 writel(readl(base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG) |
408 HSIO_SERDES6G_ANA_CFG_COMMON_CFG_SYS_RST,
409 base + HSIO_SERDES6G_ANA_CFG_COMMON_CFG);
410 serdes6g_write(base, addr);
412 clrbits_le32(base + HSIO_SERDES6G_ANA_CFG_IB_CFG1,
413 HSIO_SERDES6G_ANA_CFG_IB_CFG1_RST);
414 writel(HSIO_SERDES6G_DIG_CFG_MISC_CFG_LANE_RST,
415 base + HSIO_SERDES6G_DIG_CFG_MISC_CFG);
416 serdes6g_write(base, addr);
419 static void serdes_setup(struct luton_private *priv)
424 for (i = 0; i < MAX_PORT; ++i) {
425 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
428 mask = BIT(priv->ports[i].serdes_index);
429 serdes6g_setup(priv->regs[HSIO], mask, priv->ports[i].phy_mode);
433 static int luton_switch_init(struct luton_private *priv)
435 setbits_le32(priv->regs[HSIO] + HSIO_PLL5G_CFG_PLL5G_CFG2, BIT(1));
436 clrbits_le32(priv->regs[HSIO] + HSIO_PLL5G_CFG_PLL5G_CFG2, BIT(1));
438 /* Reset switch & memories */
439 writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
440 priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
442 /* Wait to complete */
443 if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
444 SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
445 printf("Timeout in memory reset\n");
448 /* Enable switch core */
449 setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
450 SYS_SYSTEM_RST_CORE_ENA);
452 /* Setup the Serdes macros */
458 static int luton_initialize(struct luton_private *priv)
462 /* Initialize switch memories, enable core */
463 ret = luton_switch_init(priv);
468 * Disable port-to-port by switching
469 * Put front ports in "port isolation modes" - i.e. they can't send
470 * to other ports - via the PGID sorce masks.
472 for (i = 0; i < MAX_PORT; i++)
473 writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
476 mscc_flush(priv->regs[QS], luton_regs_qs);
478 /* Setup frame ageing - "2 sec" - The unit is 4ns on Luton*/
479 writel(2000000000 / 4,
480 priv->regs[SYS] + SYS_FRM_AGING);
482 for (i = 0; i < MAX_PORT; i++) {
484 luton_gmii_port_init(priv, i);
486 if (i == PORT10 || i == PORT11)
487 luton_port_init(priv, i);
489 luton_ext_port_init(priv, i);
492 luton_cpu_capture_setup(priv);
497 static int luton_write_hwaddr(struct udevice *dev)
499 struct luton_private *priv = dev_get_priv(dev);
500 struct eth_pdata *pdata = dev_get_platdata(dev);
502 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
503 pdata->enetaddr, PGID_UNICAST);
505 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
510 static int luton_start(struct udevice *dev)
512 struct luton_private *priv = dev_get_priv(dev);
513 struct eth_pdata *pdata = dev_get_platdata(dev);
514 const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
518 ret = luton_initialize(priv);
522 /* Set MAC address tables entries for CPU redirection */
523 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
524 mac, PGID_BROADCAST);
526 writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
527 priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
529 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
530 pdata->enetaddr, PGID_UNICAST);
532 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
537 static int luton_send(struct udevice *dev, void *packet, int length)
539 struct luton_private *priv = dev_get_priv(dev);
541 int port = BIT(0); /* use port 0 */
544 ifh[0] = IFH_INJ_BYPASS | port;
545 ifh[1] = (IFH_TAG_TYPE_C << 16);
547 return mscc_send(priv->regs[QS], luton_regs_qs,
548 ifh, IFH_LEN, buf, length);
551 static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
553 struct luton_private *priv = dev_get_priv(dev);
554 u32 *rxbuf = (u32 *)net_rx_packets[0];
557 byte_cnt = mscc_recv(priv->regs[QS], luton_regs_qs, rxbuf, IFH_LEN,
560 *packetp = net_rx_packets[0];
565 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
569 for (i = 0; i < LUTON_MIIM_BUS_COUNT; ++i)
570 if (miim[i].miim_base == base && miim[i].miim_size == size)
576 static void add_port_entry(struct luton_private *priv, size_t index,
577 size_t phy_addr, struct mii_dev *bus,
578 u8 serdes_index, u8 phy_mode)
580 priv->ports[index].phy_addr = phy_addr;
581 priv->ports[index].bus = bus;
582 priv->ports[index].serdes_index = serdes_index;
583 priv->ports[index].phy_mode = phy_mode;
586 static int luton_probe(struct udevice *dev)
588 struct luton_private *priv = dev_get_priv(dev);
592 phys_addr_t addr_base;
593 unsigned long addr_size;
594 ofnode eth_node, node, mdio_node;
597 struct ofnode_phandle_args phandle;
598 struct phy_device *phy;
603 /* Get registers and map them to the private structure */
604 for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
605 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
606 if (!priv->regs[i]) {
608 ("Error can't get regs base addresses for %s\n",
614 /* Release reset in the CU-PHY */
615 writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
617 /* Ports with ext phy don't need to reset clk */
618 for (i = 0; i < MAX_INT_PORT; i++) {
620 clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
621 DEV_GMII_PORT_MODE_CLK_PHY_RST);
623 clrbits_le32(priv->regs[i] + DEV_PORT_MODE_CLK,
624 DEV_PORT_MODE_CLK_PHY_RST);
627 /* Wait for internal PHY to be ready */
628 if (wait_for_bit_le32(priv->regs[GCB] + GCB_MISC_STAT,
629 GCB_MISC_STAT_PHY_READY, true, 500, false))
633 /* Initialize miim buses */
634 memset(&miim, 0x0, sizeof(miim) * LUTON_MIIM_BUS_COUNT);
636 /* iterate all the ports and find out on which bus they are */
638 eth_node = dev_read_first_subnode(dev);
639 for (node = ofnode_first_subnode(eth_node);
641 node = ofnode_next_subnode(node)) {
642 if (ofnode_read_resource(node, 0, &res))
646 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
651 /* Get phy address on mdio bus */
652 if (ofnode_read_resource(phandle.node, 0, &res))
654 phy_addr = res.start;
657 mdio_node = ofnode_get_parent(phandle.node);
659 if (ofnode_read_resource(mdio_node, 0, &res))
661 faddr = cpu_to_fdt32(res.start);
663 addr_base = ofnode_translate_address(mdio_node, &faddr);
664 addr_size = res.end - res.start;
666 /* If the bus is new then create a new bus */
667 if (!get_mdiobus(addr_base, addr_size))
668 priv->bus[miim_count] =
669 mscc_mdiobus_init(miim, &miim_count, addr_base,
672 /* Connect mdio bus with the port */
673 bus = get_mdiobus(addr_base, addr_size);
675 /* Get serdes info */
676 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
679 add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
681 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
685 for (i = 0; i < MAX_PORT; i++) {
686 if (!priv->ports[i].bus)
689 phy = phy_connect(priv->ports[i].bus,
690 priv->ports[i].phy_addr, dev,
691 PHY_INTERFACE_MODE_NONE);
692 if (phy && i >= MAX_INT_PORT)
693 board_phy_config(phy);
697 * coma_mode is need on only one phy, because all the other phys
700 mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0x10);
701 mscc_miim_write(priv->ports[0].bus, 0, 0, 14, 0x800);
702 mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0);
707 static int luton_remove(struct udevice *dev)
709 struct luton_private *priv = dev_get_priv(dev);
712 for (i = 0; i < LUTON_MIIM_BUS_COUNT; i++) {
713 mdio_unregister(priv->bus[i]);
714 mdio_free(priv->bus[i]);
720 static const struct eth_ops luton_ops = {
721 .start = luton_start,
725 .write_hwaddr = luton_write_hwaddr,
728 static const struct udevice_id mscc_luton_ids[] = {
729 {.compatible = "mscc,vsc7527-switch", },
733 U_BOOT_DRIVER(luton) = {
734 .name = "luton-switch",
736 .of_match = mscc_luton_ids,
737 .probe = luton_probe,
738 .remove = luton_remove,
740 .priv_auto_alloc_size = sizeof(struct luton_private),
741 .platdata_auto_alloc_size = sizeof(struct eth_pdata),