drivers: net: ls1088ardb: Fix EC1 and EC2 RCW offset
[oweals/u-boot.git] / drivers / net / mscc_eswitch / luton_switch.c
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_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
139 enum 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
180 enum luton_mdio_target {
181         MIIM,
182         TARGET_MDIO_MAX,
183 };
184
185 enum luton_phy_id {
186         INTERNAL,
187         EXTERNAL,
188         NUM_PHY,
189 };
190
191 struct luton_private {
192         void __iomem *regs[TARGET_MAX];
193         struct mii_dev *bus[NUM_PHY];
194 };
195
196 static 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
204 static 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
210 static struct mscc_miim_dev miim[NUM_PHY];
211
212 static 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
259 static 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
271 static 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
312 static 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
334 static 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
356 static 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
403 static 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
418 static 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
479 static 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
504 static 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
543 static 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
556 static 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
583 static 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
597 static 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
611 static 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
701 static 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
714 static 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
722 static const struct udevice_id mscc_luton_ids[] = {
723         {.compatible = "mscc,vsc7527-switch", },
724         { /* Sentinel */ }
725 };
726
727 U_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 };