1
2
3
4
5
6#include <common.h>
7#include <config.h>
8#include <dm.h>
9#include <malloc.h>
10#include <dm/of_access.h>
11#include <dm/of_addr.h>
12#include <fdt_support.h>
13#include <linux/bitops.h>
14#include <linux/io.h>
15#include <linux/ioport.h>
16#include <miiphy.h>
17#include <net.h>
18#include <wait_bit.h>
19
20#include "mscc_xfer.h"
21#include "mscc_mac_table.h"
22#include "mscc_miim.h"
23
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))
32
33#define SYS_FRM_AGING 0x8300
34
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
45
46#define REW_PORT_CFG(x) (0x8 + 0x80 * (x))
47#define REW_PORT_CFG_IFH_INSERT_ENA BIT(7)
48
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)
53
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)
57
58#define HSIO_PLL5G_CFG_PLL5G_CFG2 0x8
59
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)
106
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)
112
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)
129
130#define IFH_INJ_BYPASS BIT(31)
131#define IFH_TAG_TYPE_C 0
132#define MAC_VID 1
133#define CPU_PORT 26
134#define INTERNAL_PORT_MSK 0xFFFFFF
135#define IFH_LEN 2
136#define ETH_ALEN 6
137#define PGID_BROADCAST 28
138#define PGID_UNICAST 29
139#define PGID_SRC 80
140
141static 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",
145 "port22", "port23",
146 "sys", "ana", "rew", "gcb", "qs", "hsio",
147};
148
149#define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
150#define MAX_PORT 24
151
152enum luton_ctrl_regs {
153 SYS = MAX_PORT,
154 ANA,
155 REW,
156 GCB,
157 QS,
158 HSIO
159};
160
161#define MIN_INT_PORT 0
162#define PORT10 10
163#define PORT11 11
164#define MAX_INT_PORT 12
165#define MIN_EXT_PORT MAX_INT_PORT
166#define MAX_EXT_PORT MAX_PORT
167
168#define LUTON_MIIM_BUS_COUNT 2
169
170struct luton_phy_port_t {
171 size_t phy_addr;
172 struct mii_dev *bus;
173 u8 serdes_index;
174 u8 phy_mode;
175};
176
177struct 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];
181};
182
183static 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,
189};
190
191static 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,
195};
196
197static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
198static int miim_count = -1;
199
200static void luton_stop(struct udevice *dev)
201{
202 struct luton_private *priv = dev_get_priv(dev);
203
204
205
206
207
208
209 writel(GENMASK(9, 2), priv->regs[SYS] + SYS_SCH_CPU);
210}
211
212static void luton_cpu_capture_setup(struct luton_private *priv)
213{
214 int i;
215
216
217 writel(0x0, priv->regs[SYS] + SYS_SCH_CPU);
218
219 for (i = 0; i <= 1; i++) {
220
221
222
223
224 writel(QS_XTR_MAP_ENA | (QS_XTR_MAP_GRP * i),
225 priv->regs[QS] + QS_XTR_MAP(i));
226
227
228 setbits_le32(priv->regs[REW] + REW_PORT_CFG(CPU_PORT + i),
229 REW_PORT_CFG_IFH_INSERT_ENA);
230
231
232 setbits_le32(priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i),
233 SYS_PORT_MODE_INCL_INJ_HDR);
234 }
235
236
237 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
238 ANA_PORT_VLAN_CFG_POP_CNT(1) |
239 MAC_VID,
240 priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
241
242
243 writel(ANA_PORT_PORT_CFG_RECV_ENA,
244 priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
245
246
247 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(CPU_PORT),
248 SYS_SWITCH_PORT_MODE_PORT_ENA);
249
250 setbits_le32(priv->regs[SYS] + SYS_EGR_NO_SHARING, BIT(CPU_PORT));
251}
252
253static void luton_gmii_port_init(struct luton_private *priv, int port)
254{
255 void __iomem *regs = priv->regs[port];
256
257 writel(0, regs + DEV_GMII_PORT_MODE_CLK);
258
259
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);
263
264
265 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
266 ANA_PORT_VLAN_CFG_POP_CNT(1) |
267 MAC_VID,
268 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
269
270
271 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
272 SYS_SWITCH_PORT_MODE_PORT_ENA);
273}
274
275static void luton_port_init(struct luton_private *priv, int port)
276{
277 void __iomem *regs = priv->regs[port];
278
279 writel(0, regs + DEV_PORT_MODE_CLK);
280
281
282 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
283 DEV_MAC_CFG_MAC_ENA_TX_ENA,
284 regs + DEV_MAC_CFG_MAC_ENA);
285
286
287 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
288 ANA_PORT_VLAN_CFG_POP_CNT(1) |
289 MAC_VID,
290 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
291
292
293 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
294 SYS_SWITCH_PORT_MODE_PORT_ENA);
295}
296
297static void luton_ext_port_init(struct luton_private *priv, int port)
298{
299 void __iomem *regs = priv->regs[port];
300
301
302 writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
303 regs + DEV_PCS1G_CFG_PCS1G_CFG);
304
305
306 writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
307
308
309 writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
310 DEV_MAC_CFG_MAC_ENA_TX_ENA,
311 regs + DEV_MAC_CFG_MAC_ENA);
312
313
314 writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
315
316
317
318
319
320 writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
321 regs + DEV_PCS1G_CFG_PCS1G_ANEG);
322
323
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);
328
329
330 writel(DEV_PORT_MODE_CLK_LINK_SPEED_1000,
331 regs + DEV_PORT_MODE_CLK);
332
333
334 writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
335 ANA_PORT_VLAN_CFG_POP_CNT(1) |
336 MAC_VID,
337 priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
338
339
340 setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
341 SYS_SWITCH_PORT_MODE_PORT_ENA);
342}
343
344static void serdes6g_write(void __iomem *base, u32 addr)
345{
346 u32 data;
347
348 writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
349 HSIO_MCB_SERDES6G_CFG_ADDR(addr),
350 base + HSIO_MCB_SERDES6G_CFG);
351
352 do {
353 data = readl(base + HSIO_MCB_SERDES6G_CFG);
354 } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
355}
356
357static void serdes6g_setup(void __iomem *base, uint32_t addr,
358 phy_interface_t interface)
359{
360 writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
361 HSIO_RCOMP_CFG_CFG0_RUN_CAL,
362 base + HSIO_RCOMP_CFG_CFG0);
363
364 while (readl(base + HSIO_RCOMP_STATUS) &
365 HSIO_RCOMP_STATUS_BUSY)
366 ;
367
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);
401
402
403
404
405 serdes6g_write(base, addr);
406
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);
411
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);
417}
418
419static void serdes_setup(struct luton_private *priv)
420{
421 size_t mask;
422 int i = 0;
423
424 for (i = 0; i < MAX_PORT; ++i) {
425 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
426 continue;
427
428 mask = BIT(priv->ports[i].serdes_index);
429 serdes6g_setup(priv->regs[HSIO], mask, priv->ports[i].phy_mode);
430 }
431}
432
433static int luton_switch_init(struct luton_private *priv)
434{
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));
437
438
439 writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
440 priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
441
442
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");
446 }
447
448
449 setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
450 SYS_SYSTEM_RST_CORE_ENA);
451
452
453 serdes_setup(priv);
454
455 return 0;
456}
457
458static int luton_initialize(struct luton_private *priv)
459{
460 int ret, i;
461
462
463 ret = luton_switch_init(priv);
464 if (ret)
465 return ret;
466
467
468
469
470
471
472 for (i = 0; i < MAX_PORT; i++)
473 writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
474
475
476 mscc_flush(priv->regs[QS], luton_regs_qs);
477
478
479 writel(2000000000 / 4,
480 priv->regs[SYS] + SYS_FRM_AGING);
481
482 for (i = 0; i < MAX_PORT; i++) {
483 if (i < PORT10)
484 luton_gmii_port_init(priv, i);
485 else
486 if (i == PORT10 || i == PORT11)
487 luton_port_init(priv, i);
488 else
489 luton_ext_port_init(priv, i);
490 }
491
492 luton_cpu_capture_setup(priv);
493
494 return 0;
495}
496
497static int luton_write_hwaddr(struct udevice *dev)
498{
499 struct luton_private *priv = dev_get_priv(dev);
500 struct eth_pdata *pdata = dev_get_plat(dev);
501
502 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
503 pdata->enetaddr, PGID_UNICAST);
504
505 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
506
507 return 0;
508}
509
510static int luton_start(struct udevice *dev)
511{
512 struct luton_private *priv = dev_get_priv(dev);
513 struct eth_pdata *pdata = dev_get_plat(dev);
514 const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
515 0xff };
516 int ret;
517
518 ret = luton_initialize(priv);
519 if (ret)
520 return ret;
521
522
523 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
524 mac, PGID_BROADCAST);
525
526 writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
527 priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
528
529 mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
530 pdata->enetaddr, PGID_UNICAST);
531
532 writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
533
534 return 0;
535}
536
537static int luton_send(struct udevice *dev, void *packet, int length)
538{
539 struct luton_private *priv = dev_get_priv(dev);
540 u32 ifh[IFH_LEN];
541 int port = BIT(0);
542 u32 *buf = packet;
543
544 ifh[0] = IFH_INJ_BYPASS | port;
545 ifh[1] = (IFH_TAG_TYPE_C << 16);
546
547 return mscc_send(priv->regs[QS], luton_regs_qs,
548 ifh, IFH_LEN, buf, length);
549}
550
551static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
552{
553 struct luton_private *priv = dev_get_priv(dev);
554 u32 *rxbuf = (u32 *)net_rx_packets[0];
555 int byte_cnt = 0;
556
557 byte_cnt = mscc_recv(priv->regs[QS], luton_regs_qs, rxbuf, IFH_LEN,
558 true);
559
560 *packetp = net_rx_packets[0];
561
562 return byte_cnt;
563}
564
565static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
566{
567 int i = 0;
568
569 for (i = 0; i < LUTON_MIIM_BUS_COUNT; ++i)
570 if (miim[i].miim_base == base && miim[i].miim_size == size)
571 return miim[i].bus;
572
573 return NULL;
574}
575
576static 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)
579{
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;
584}
585
586static int luton_probe(struct udevice *dev)
587{
588 struct luton_private *priv = dev_get_priv(dev);
589 int i, ret;
590 struct resource res;
591 phys_addr_t addr_base;
592 unsigned long addr_size;
593 ofnode eth_node, node, mdio_node;
594 size_t phy_addr;
595 struct mii_dev *bus;
596 struct ofnode_phandle_args phandle;
597 struct phy_device *phy;
598
599 if (!priv)
600 return -EINVAL;
601
602
603 for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
604 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
605 if (!priv->regs[i]) {
606 debug
607 ("Error can't get regs base addresses for %s\n",
608 regs_names[i]);
609 return -ENOMEM;
610 }
611 }
612
613
614 writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
615
616
617 for (i = 0; i < MAX_INT_PORT; i++) {
618 if (i < PORT10)
619 clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
620 DEV_GMII_PORT_MODE_CLK_PHY_RST);
621 else
622 clrbits_le32(priv->regs[i] + DEV_PORT_MODE_CLK,
623 DEV_PORT_MODE_CLK_PHY_RST);
624 }
625
626
627 if (wait_for_bit_le32(priv->regs[GCB] + GCB_MISC_STAT,
628 GCB_MISC_STAT_PHY_READY, true, 500, false))
629 return -EACCES;
630
631
632
633 memset(&miim, 0x0, sizeof(miim) * LUTON_MIIM_BUS_COUNT);
634
635
636 i = 0;
637 eth_node = dev_read_first_subnode(dev);
638 for (node = ofnode_first_subnode(eth_node);
639 ofnode_valid(node);
640 node = ofnode_next_subnode(node)) {
641 if (ofnode_read_resource(node, 0, &res))
642 return -ENOMEM;
643 i = res.start;
644
645 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
646 0, 0, &phandle);
647 if (ret)
648 continue;
649
650
651 if (ofnode_read_resource(phandle.node, 0, &res))
652 return -ENOMEM;
653 phy_addr = res.start;
654
655
656 mdio_node = ofnode_get_parent(phandle.node);
657
658 if (ofnode_read_resource(mdio_node, 0, &res))
659 return -ENOMEM;
660 addr_base = res.start;
661 addr_size = res.end - res.start;
662
663
664 if (!get_mdiobus(addr_base, addr_size))
665 priv->bus[miim_count] =
666 mscc_mdiobus_init(miim, &miim_count, addr_base,
667 addr_size);
668
669
670 bus = get_mdiobus(addr_base, addr_size);
671
672
673 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
674 3, 0, &phandle);
675 if (ret)
676 add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
677 else
678 add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
679 phandle.args[2]);
680 }
681
682 for (i = 0; i < MAX_PORT; i++) {
683 if (!priv->ports[i].bus)
684 continue;
685
686 phy = phy_connect(priv->ports[i].bus,
687 priv->ports[i].phy_addr, dev,
688 PHY_INTERFACE_MODE_NONE);
689 if (phy && i >= MAX_INT_PORT)
690 board_phy_config(phy);
691 }
692
693
694
695
696
697 mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0x10);
698 mscc_miim_write(priv->ports[0].bus, 0, 0, 14, 0x800);
699 mscc_miim_write(priv->ports[0].bus, 0, 0, 31, 0);
700
701 return 0;
702}
703
704static int luton_remove(struct udevice *dev)
705{
706 struct luton_private *priv = dev_get_priv(dev);
707 int i;
708
709 for (i = 0; i < LUTON_MIIM_BUS_COUNT; i++) {
710 mdio_unregister(priv->bus[i]);
711 mdio_free(priv->bus[i]);
712 }
713
714 return 0;
715}
716
717static const struct eth_ops luton_ops = {
718 .start = luton_start,
719 .stop = luton_stop,
720 .send = luton_send,
721 .recv = luton_recv,
722 .write_hwaddr = luton_write_hwaddr,
723};
724
725static const struct udevice_id mscc_luton_ids[] = {
726 {.compatible = "mscc,vsc7527-switch", },
727 { }
728};
729
730U_BOOT_DRIVER(luton) = {
731 .name = "luton-switch",
732 .id = UCLASS_ETH,
733 .of_match = mscc_luton_ids,
734 .probe = luton_probe,
735 .remove = luton_remove,
736 .ops = &luton_ops,
737 .priv_auto = sizeof(struct luton_private),
738 .plat_auto = sizeof(struct eth_pdata),
739};
740