blob: 6667614966daf38b77edb5be3b27891f8be10984 [file] [log] [blame]
Horatiu Vultura4097192019-01-31 15:30:39 +01001// 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
139enum 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
180enum luton_mdio_target {
181 MIIM,
182 TARGET_MDIO_MAX,
183};
184
185enum luton_phy_id {
186 INTERNAL,
187 EXTERNAL,
188 NUM_PHY,
189};
190
191struct luton_private {
192 void __iomem *regs[TARGET_MAX];
193 struct mii_dev *bus[NUM_PHY];
194};
195
196static 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
204static 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
210static struct mscc_miim_dev miim[NUM_PHY];
211
212static 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
259static 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
271static 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
312static 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
334static 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
356static 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
403static 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
418static 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
479static 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
504static 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
543static 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
556static 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
583static 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
597static 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
611static 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
701static 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
714static 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
722static const struct udevice_id mscc_luton_ids[] = {
723 {.compatible = "mscc,vsc7527-switch", },
724 { /* Sentinel */ }
725};
726
727U_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};