1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
3 * Copyright (c) 2019 Microsemi Corporation
9 #include <dm/of_access.h>
10 #include <dm/of_addr.h>
11 #include <fdt_support.h>
13 #include <linux/ioport.h>
18 #include "mscc_xfer.h"
19 #include "mscc_mac_table.h"
20 #include "mscc_miim.h"
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))
31 #define SYS_FRM_AGING 0x8300
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
44 #define REW_PORT_CFG(x) (0x8 + 0x80 * (x))
45 #define REW_PORT_CFG_IFH_INSERT_ENA BIT(7)
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)
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)
56 #define HSIO_PLL5G_CFG_PLL5G_CFG2 0x8
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)
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)
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)
128 #define IFH_INJ_BYPASS BIT(31)
129 #define IFH_TAG_TYPE_C 0
132 #define INTERNAL_PORT_MSK 0xFFFFFF
135 #define PGID_BROADCAST 28
136 #define PGID_UNICAST 29
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",
144 "sys", "ana", "rew", "gcb", "qs", "hsio",
147 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
150 enum luton_ctrl_regs {
159 #define MIN_INT_PORT 0
162 #define MAX_INT_PORT 12
163 #define MIN_EXT_PORT MAX_INT_PORT
164 #define MAX_EXT_PORT MAX_PORT
166 #define LUTON_MIIM_BUS_COUNT 2
168 struct luton_phy_port_t {
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];
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,
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,
195 static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
196 static int miim_count = -1;
198 static void luton_stop(struct udevice *dev)
200 struct luton_private *priv = dev_get_priv(dev);
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.
207 writel(GENMASK(9, 2), priv->regs[SYS] + SYS_SCH_CPU);
210 static void luton_cpu_capture_setup(struct luton_private *priv)
214 /* map the 8 CPU extraction queues to CPU port 26 */
215 writel(0x0, priv->regs[SYS] + SYS_SCH_CPU);
217 for (i = 0; i <= 1; i++) {
219 * One to one mapping from CPU Queue number to Group extraction
222 writel(QS_XTR_MAP_ENA | (QS_XTR_MAP_GRP * i),
223 priv->regs[QS] + QS_XTR_MAP(i));
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);
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);
234 /* Make VLAN aware for CPU traffic */
235 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
236 ANA_PORT_VLAN_CFG_POP_CNT(1) |
238 priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
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));
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);
248 setbits_le32(priv->regs[SYS] + SYS_EGR_NO_SHARING, BIT(CPU_PORT));
251 static void luton_gmii_port_init(struct luton_private *priv, int port)
253 void __iomem *regs = priv->regs[port];
255 writel(0, regs + DEV_GMII_PORT_MODE_CLK);
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);
262 /* Make VLAN aware for CPU traffic */
263 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
264 ANA_PORT_VLAN_CFG_POP_CNT(1) |
266 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
268 /* Enable switching to/from port */
269 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
270 SYS_SWITCH_PORT_MODE_PORT_ENA);
273 static void luton_port_init(struct luton_private *priv, int port)
275 void __iomem *regs = priv->regs[port];
277 writel(0, regs + DEV_PORT_MODE_CLK);
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);
284 /* Make VLAN aware for CPU traffic */
285 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
286 ANA_PORT_VLAN_CFG_POP_CNT(1) |
288 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
290 /* Enable switching to/from port */
291 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
292 SYS_SWITCH_PORT_MODE_PORT_ENA);
295 static void luton_ext_port_init(struct luton_private *priv, int port)
297 void __iomem *regs = priv->regs[port];
300 writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
301 regs + DEV_PCS1G_CFG_PCS1G_CFG);
303 /* Disable Signal Detect */
304 writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
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);
311 /* Clear sgmii_mode_ena */
312 writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
315 * Clear sw_resolve_ena(bit 0) and set adv_ability to
316 * something meaningful just in case
318 writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
319 regs + DEV_PCS1G_CFG_PCS1G_ANEG);
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);
327 /* Set link speed and release all resets */
328 writel(DEV_PORT_MODE_CLK_LINK_SPEED_1000,
329 regs + DEV_PORT_MODE_CLK);
331 /* Make VLAN aware for CPU traffic */
332 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
333 ANA_PORT_VLAN_CFG_POP_CNT(1) |
335 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
337 /* Enable switching to/from port */
338 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
339 SYS_SWITCH_PORT_MODE_PORT_ENA);
342 static void serdes6g_write(void __iomem *base, u32 addr)
346 writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
347 HSIO_MCB_SERDES6G_CFG_ADDR(addr),
348 base + HSIO_MCB_SERDES6G_CFG);
351 data = readl(base + HSIO_MCB_SERDES6G_CFG);
352 } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
355 static void serdes6g_setup(void __iomem *base, uint32_t addr,
356 phy_interface_t interface)
358 writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
359 HSIO_RCOMP_CFG_CFG0_RUN_CAL,
360 base + HSIO_RCOMP_CFG_CFG0);
362 while (readl(base + HSIO_RCOMP_STATUS) &
363 HSIO_RCOMP_STATUS_BUSY)
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);
400 * There are 4 serdes6g, configure all except serdes6g0, therefore
401 * the address is b1110
403 serdes6g_write(base, addr);
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);
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);
417 static void serdes_setup(struct luton_private *priv)
422 for (i = 0; i < MAX_PORT; ++i) {
423 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
426 mask = BIT(priv->ports[i].serdes_index);
427 serdes6g_setup(priv->regs[HSIO], mask, priv->ports[i].phy_mode);
431 static int luton_switch_init(struct luton_private *priv)
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));
436 /* Reset switch & memories */
437 writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
438 priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
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");
446 /* Enable switch core */
447 setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
448 SYS_SYSTEM_RST_CORE_ENA);
450 /* Setup the Serdes macros */
456 static int luton_initialize(struct luton_private *priv)
460 /* Initialize switch memories, enable core */
461 ret = luton_switch_init(priv);
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.
470 for (i = 0; i < MAX_PORT; i++)
471 writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
474 mscc_flush(priv->regs[QS], luton_regs_qs);
476 /* Setup frame ageing - "2 sec" - The unit is 4ns on Luton*/
477 writel(2000000000 / 4,
478 priv->regs[SYS] + SYS_FRM_AGING);
480 for (i = 0; i < MAX_PORT; i++) {
482 luton_gmii_port_init(priv, i);
484 if (i == PORT10 || i == PORT11)
485 luton_port_init(priv, i);
487 luton_ext_port_init(priv, i);
490 luton_cpu_capture_setup(priv);
495 static int luton_write_hwaddr(struct udevice *dev)
497 struct luton_private *priv = dev_get_priv(dev);
498 struct eth_pdata *pdata = dev_get_platdata(dev);
500 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
501 pdata->enetaddr, PGID_UNICAST);
503 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
508 static int luton_start(struct udevice *dev)
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,
516 ret = luton_initialize(priv);
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);
524 writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
525 priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
527 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
528 pdata->enetaddr, PGID_UNICAST);
530 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
535 static int luton_send(struct udevice *dev, void *packet, int length)
537 struct luton_private *priv = dev_get_priv(dev);
539 int port = BIT(0); /* use port 0 */
542 ifh[0] = IFH_INJ_BYPASS | port;
543 ifh[1] = (IFH_TAG_TYPE_C << 16);
545 return mscc_send(priv->regs[QS], luton_regs_qs,
546 ifh, IFH_LEN, buf, length);
549 static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
551 struct luton_private *priv = dev_get_priv(dev);
552 u32 *rxbuf = (u32 *)net_rx_packets[0];
555 byte_cnt = mscc_recv(priv->regs[QS], luton_regs_qs, rxbuf, IFH_LEN,
558 *packetp = net_rx_packets[0];
563 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
567 for (i = 0; i < LUTON_MIIM_BUS_COUNT; ++i)
568 if (miim[i].miim_base == base && miim[i].miim_size == size)
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)
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;
584 static int luton_probe(struct udevice *dev)
586 struct luton_private *priv = dev_get_priv(dev);
590 phys_addr_t addr_base;
591 unsigned long addr_size;
592 ofnode eth_node, node, mdio_node;
595 struct ofnode_phandle_args phandle;
596 struct phy_device *phy;
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]) {
606 ("Error can't get regs base addresses for %s\n",
612 /* Release reset in the CU-PHY */
613 writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
615 /* Ports with ext phy don't need to reset clk */
616 for (i = 0; i < MAX_INT_PORT; i++) {
618 clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
619 DEV_GMII_PORT_MODE_CLK_PHY_RST);
621 clrbits_le32(priv->regs[i] + DEV_PORT_MODE_CLK,
622 DEV_PORT_MODE_CLK_PHY_RST);
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))
631 /* Initialize miim buses */
632 memset(&miim, 0x0, sizeof(miim) * LUTON_MIIM_BUS_COUNT);
634 /* iterate all the ports and find out on which bus they are */
636 eth_node = dev_read_first_subnode(dev);
637 for (node = ofnode_first_subnode(eth_node);
639 node = ofnode_next_subnode(node)) {
640 if (ofnode_read_resource(node, 0, &res))
644 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
649 /* Get phy address on mdio bus */
650 if (ofnode_read_resource(phandle.node, 0, &res))
652 phy_addr = res.start;
655 mdio_node = ofnode_get_parent(phandle.node);
657 if (ofnode_read_resource(mdio_node, 0, &res))
659 faddr = cpu_to_fdt32(res.start);
661 addr_base = ofnode_translate_address(mdio_node, &faddr);
662 addr_size = res.end - res.start;
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,
670 /* Connect mdio bus with the port */
671 bus = get_mdiobus(addr_base, addr_size);
673 /* Get serdes info */
674 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
677 add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
679 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
683 for (i = 0; i < MAX_PORT; i++) {
684 if (!priv->ports[i].bus)
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);
695 * coma_mode is need on only one phy, because all the other phys
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);
705 static int luton_remove(struct udevice *dev)
707 struct luton_private *priv = dev_get_priv(dev);
710 for (i = 0; i < LUTON_MIIM_BUS_COUNT; i++) {
711 mdio_unregister(priv->bus[i]);
712 mdio_free(priv->bus[i]);
718 static const struct eth_ops luton_ops = {
719 .start = luton_start,
723 .write_hwaddr = luton_write_hwaddr,
726 static const struct udevice_id mscc_luton_ids[] = {
727 {.compatible = "mscc,vsc7527-switch", },
731 U_BOOT_DRIVER(luton) = {
732 .name = "luton-switch",
734 .of_match = mscc_luton_ids,
735 .probe = luton_probe,
736 .remove = luton_remove,
738 .priv_auto_alloc_size = sizeof(struct luton_private),
739 .platdata_auto_alloc_size = sizeof(struct eth_pdata),