ARM: omapl138_lcdk: Remove dead code
[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_xfer.h"
19 #include "mscc_mac_table.h"
20 #include "mscc_miim.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 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",
143         "port22", "port23",
144         "sys", "ana", "rew", "gcb", "qs", "hsio",
145 };
146
147 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
148 #define MAX_PORT 24
149
150 enum luton_ctrl_regs {
151         SYS = MAX_PORT,
152         ANA,
153         REW,
154         GCB,
155         QS,
156         HSIO
157 };
158
159 #define MIN_INT_PORT    0
160 #define PORT10          10
161 #define PORT11          11
162 #define MAX_INT_PORT    12
163 #define MIN_EXT_PORT    MAX_INT_PORT
164 #define MAX_EXT_PORT    MAX_PORT
165
166 #define LUTON_MIIM_BUS_COUNT 2
167
168 struct luton_phy_port_t {
169         size_t phy_addr;
170         struct mii_dev *bus;
171         u8 serdes_index;
172         u8 phy_mode;
173 };
174
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];
179 };
180
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,
187 };
188
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,
193 };
194
195 static struct mscc_miim_dev miim[LUTON_MIIM_BUS_COUNT];
196 static int miim_count = -1;
197
198 static void luton_stop(struct udevice *dev)
199 {
200         struct luton_private *priv = dev_get_priv(dev);
201
202         /*
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.
206          */
207         writel(GENMASK(9, 2), priv->regs[SYS] + SYS_SCH_CPU);
208 }
209
210 static void luton_cpu_capture_setup(struct luton_private *priv)
211 {
212         int i;
213
214         /* map the 8 CPU extraction queues to CPU port 26 */
215         writel(0x0, priv->regs[SYS] + SYS_SCH_CPU);
216
217         for (i = 0; i <= 1; i++) {
218                 /*
219                  * One to one mapping from CPU Queue number to Group extraction
220                  * number
221                  */
222                 writel(QS_XTR_MAP_ENA | (QS_XTR_MAP_GRP * i),
223                        priv->regs[QS] + QS_XTR_MAP(i));
224
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);
228
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);
232         }
233
234         /* Make VLAN aware for CPU traffic */
235         writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
236                ANA_PORT_VLAN_CFG_POP_CNT(1) |
237                MAC_VID,
238                priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
239
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));
243
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);
247
248         setbits_le32(priv->regs[SYS] + SYS_EGR_NO_SHARING, BIT(CPU_PORT));
249 }
250
251 static void luton_gmii_port_init(struct luton_private *priv, int port)
252 {
253         void __iomem *regs = priv->regs[port];
254
255         writel(0, regs + DEV_GMII_PORT_MODE_CLK);
256
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);
261
262         /* Make VLAN aware for CPU traffic */
263         writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
264                ANA_PORT_VLAN_CFG_POP_CNT(1) |
265                MAC_VID,
266                priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
267
268         /* Enable switching to/from port */
269         setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
270                      SYS_SWITCH_PORT_MODE_PORT_ENA);
271 }
272
273 static void luton_port_init(struct luton_private *priv, int port)
274 {
275         void __iomem *regs = priv->regs[port];
276
277         writel(0, regs + DEV_PORT_MODE_CLK);
278
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);
283
284         /* Make VLAN aware for CPU traffic */
285         writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
286                ANA_PORT_VLAN_CFG_POP_CNT(1) |
287                MAC_VID,
288                priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
289
290         /* Enable switching to/from port */
291         setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
292                      SYS_SWITCH_PORT_MODE_PORT_ENA);
293 }
294
295 static void luton_ext_port_init(struct luton_private *priv, int port)
296 {
297         void __iomem *regs = priv->regs[port];
298
299         /* Enable PCS */
300         writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
301                regs + DEV_PCS1G_CFG_PCS1G_CFG);
302
303         /* Disable Signal Detect */
304         writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
305
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);
310
311         /* Clear sgmii_mode_ena */
312         writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
313
314         /*
315          * Clear sw_resolve_ena(bit 0) and set adv_ability to
316          * something meaningful just in case
317          */
318         writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
319                regs + DEV_PCS1G_CFG_PCS1G_ANEG);
320
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);
326
327         /* Set link speed and release all resets */
328         writel(DEV_PORT_MODE_CLK_LINK_SPEED_1000,
329                regs + DEV_PORT_MODE_CLK);
330
331         /* Make VLAN aware for CPU traffic */
332         writel(ANA_PORT_VLAN_CFG_AWARE_ENA |
333                ANA_PORT_VLAN_CFG_POP_CNT(1) |
334                MAC_VID,
335                priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
336
337         /* Enable switching to/from port */
338         setbits_le32(priv->regs[SYS] + SYS_SWITCH_PORT_MODE(port),
339                      SYS_SWITCH_PORT_MODE_PORT_ENA);
340 }
341
342 static void serdes6g_write(void __iomem *base, u32 addr)
343 {
344         u32 data;
345
346         writel(HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT |
347                HSIO_MCB_SERDES6G_CFG_ADDR(addr),
348                base + HSIO_MCB_SERDES6G_CFG);
349
350         do {
351                 data = readl(base + HSIO_MCB_SERDES6G_CFG);
352         } while (data & HSIO_MCB_SERDES6G_CFG_WR_ONE_SHOT);
353 }
354
355 static void serdes6g_setup(void __iomem *base, uint32_t addr,
356                            phy_interface_t interface)
357 {
358         writel(HSIO_RCOMP_CFG_CFG0_MODE_SEL(0x3) |
359                HSIO_RCOMP_CFG_CFG0_RUN_CAL,
360                base + HSIO_RCOMP_CFG_CFG0);
361
362         while (readl(base + HSIO_RCOMP_STATUS) &
363                HSIO_RCOMP_STATUS_BUSY)
364                 ;
365
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);
399         /*
400          * There are 4 serdes6g, configure all except serdes6g0, therefore
401          * the address is b1110
402          */
403         serdes6g_write(base, addr);
404
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);
409
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);
415 }
416
417 static void serdes_setup(struct luton_private *priv)
418 {
419         size_t mask;
420         int i = 0;
421
422         for (i = 0; i < MAX_PORT; ++i) {
423                 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
424                         continue;
425
426                 mask = BIT(priv->ports[i].serdes_index);
427                 serdes6g_setup(priv->regs[HSIO], mask, priv->ports[i].phy_mode);
428         }
429 }
430
431 static int luton_switch_init(struct luton_private *priv)
432 {
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));
435
436         /* Reset switch & memories */
437         writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
438                priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
439
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");
444         }
445
446         /* Enable switch core */
447         setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
448                      SYS_SYSTEM_RST_CORE_ENA);
449
450         /* Setup the Serdes macros */
451         serdes_setup(priv);
452
453         return 0;
454 }
455
456 static int luton_initialize(struct luton_private *priv)
457 {
458         int ret, i;
459
460         /* Initialize switch memories, enable core */
461         ret = luton_switch_init(priv);
462         if (ret)
463                 return ret;
464
465         /*
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.
469          */
470         for (i = 0; i < MAX_PORT; i++)
471                 writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
472
473         /* Flush queues */
474         mscc_flush(priv->regs[QS], luton_regs_qs);
475
476         /* Setup frame ageing - "2 sec" - The unit is 4ns on Luton*/
477         writel(2000000000 / 4,
478                priv->regs[SYS] + SYS_FRM_AGING);
479
480         for (i = 0; i < MAX_PORT; i++) {
481                 if (i < PORT10)
482                         luton_gmii_port_init(priv, i);
483                 else
484                         if (i == PORT10 || i == PORT11)
485                                 luton_port_init(priv, i);
486                         else
487                                 luton_ext_port_init(priv, i);
488         }
489
490         luton_cpu_capture_setup(priv);
491
492         return 0;
493 }
494
495 static int luton_write_hwaddr(struct udevice *dev)
496 {
497         struct luton_private *priv = dev_get_priv(dev);
498         struct eth_pdata *pdata = dev_get_platdata(dev);
499
500         mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
501                            pdata->enetaddr, PGID_UNICAST);
502
503         writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
504
505         return 0;
506 }
507
508 static int luton_start(struct udevice *dev)
509 {
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,
513                                               0xff };
514         int ret;
515
516         ret = luton_initialize(priv);
517         if (ret)
518                 return ret;
519
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);
523
524         writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
525                priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
526
527         mscc_mac_table_add(priv->regs[ANA], luton_regs_ana_table,
528                            pdata->enetaddr, PGID_UNICAST);
529
530         writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
531
532         return 0;
533 }
534
535 static int luton_send(struct udevice *dev, void *packet, int length)
536 {
537         struct luton_private *priv = dev_get_priv(dev);
538         u32 ifh[IFH_LEN];
539         int port = BIT(0);      /* use port 0 */
540         u32 *buf = packet;
541
542         ifh[0] = IFH_INJ_BYPASS | port;
543         ifh[1] = (IFH_TAG_TYPE_C << 16);
544
545         return mscc_send(priv->regs[QS], luton_regs_qs,
546                          ifh, IFH_LEN, buf, length);
547 }
548
549 static int luton_recv(struct udevice *dev, int flags, uchar **packetp)
550 {
551         struct luton_private *priv = dev_get_priv(dev);
552         u32 *rxbuf = (u32 *)net_rx_packets[0];
553         int byte_cnt = 0;
554
555         byte_cnt = mscc_recv(priv->regs[QS], luton_regs_qs, rxbuf, IFH_LEN,
556                              true);
557
558         *packetp = net_rx_packets[0];
559
560         return byte_cnt;
561 }
562
563 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
564 {
565         int i = 0;
566
567         for (i = 0; i < LUTON_MIIM_BUS_COUNT; ++i)
568                 if (miim[i].miim_base == base && miim[i].miim_size == size)
569                         return miim[i].bus;
570
571         return NULL;
572 }
573
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)
577 {
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;
582 }
583
584 static int luton_probe(struct udevice *dev)
585 {
586         struct luton_private *priv = dev_get_priv(dev);
587         int i, ret;
588         struct resource res;
589         fdt32_t faddr;
590         phys_addr_t addr_base;
591         unsigned long addr_size;
592         ofnode eth_node, node, mdio_node;
593         size_t phy_addr;
594         struct mii_dev *bus;
595         struct ofnode_phandle_args phandle;
596         struct phy_device *phy;
597
598         if (!priv)
599                 return -EINVAL;
600
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]) {
605                         debug
606                             ("Error can't get regs base addresses for %s\n",
607                              regs_names[i]);
608                         return -ENOMEM;
609                 }
610         }
611
612         /* Release reset in the CU-PHY */
613         writel(0, priv->regs[GCB] + GCB_DEVCPU_RST_SOFT_CHIP_RST);
614
615         /* Ports with ext phy don't need to reset clk */
616         for (i = 0; i < MAX_INT_PORT; i++) {
617                 if (i < PORT10)
618                         clrbits_le32(priv->regs[i] + DEV_GMII_PORT_MODE_CLK,
619                                      DEV_GMII_PORT_MODE_CLK_PHY_RST);
620                 else
621                         clrbits_le32(priv->regs[i] + DEV_PORT_MODE_CLK,
622                                      DEV_PORT_MODE_CLK_PHY_RST);
623         }
624
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))
628                 return -EACCES;
629
630
631         /* Initialize miim buses */
632         memset(&miim, 0x0, sizeof(miim) * LUTON_MIIM_BUS_COUNT);
633
634         /* iterate all the ports and find out on which bus they are */
635         i = 0;
636         eth_node = dev_read_first_subnode(dev);
637         for (node = ofnode_first_subnode(eth_node);
638              ofnode_valid(node);
639              node = ofnode_next_subnode(node)) {
640                 if (ofnode_read_resource(node, 0, &res))
641                         return -ENOMEM;
642                 i = res.start;
643
644                 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL,
645                                                      0, 0, &phandle);
646                 if (ret)
647                         continue;
648
649                 /* Get phy address on mdio bus */
650                 if (ofnode_read_resource(phandle.node, 0, &res))
651                         return -ENOMEM;
652                 phy_addr = res.start;
653
654                 /* Get mdio node */
655                 mdio_node = ofnode_get_parent(phandle.node);
656
657                 if (ofnode_read_resource(mdio_node, 0, &res))
658                         return -ENOMEM;
659                 faddr = cpu_to_fdt32(res.start);
660
661                 addr_base = ofnode_translate_address(mdio_node, &faddr);
662                 addr_size = res.end - res.start;
663
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,
668                                                   addr_size);
669
670                 /* Connect mdio bus with the port */
671                 bus = get_mdiobus(addr_base, addr_size);
672
673                 /* Get serdes info */
674                 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
675                                                      3, 0, &phandle);
676                 if (ret)
677                         add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
678                 else
679                         add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
680                                        phandle.args[2]);
681         }
682
683         for (i = 0; i < MAX_PORT; i++) {
684                 if (!priv->ports[i].bus)
685                         continue;
686
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);
692         }
693
694         /*
695          * coma_mode is need on only one phy, because all the other phys
696          * will be affected.
697          */
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);
701
702         return 0;
703 }
704
705 static int luton_remove(struct udevice *dev)
706 {
707         struct luton_private *priv = dev_get_priv(dev);
708         int i;
709
710         for (i = 0; i < LUTON_MIIM_BUS_COUNT; i++) {
711                 mdio_unregister(priv->bus[i]);
712                 mdio_free(priv->bus[i]);
713         }
714
715         return 0;
716 }
717
718 static const struct eth_ops luton_ops = {
719         .start        = luton_start,
720         .stop         = luton_stop,
721         .send         = luton_send,
722         .recv         = luton_recv,
723         .write_hwaddr = luton_write_hwaddr,
724 };
725
726 static const struct udevice_id mscc_luton_ids[] = {
727         {.compatible = "mscc,vsc7527-switch", },
728         { /* Sentinel */ }
729 };
730
731 U_BOOT_DRIVER(luton) = {
732         .name     = "luton-switch",
733         .id       = UCLASS_ETH,
734         .of_match = mscc_luton_ids,
735         .probe    = luton_probe,
736         .remove   = luton_remove,
737         .ops      = &luton_ops,
738         .priv_auto_alloc_size = sizeof(struct luton_private),
739         .platdata_auto_alloc_size = sizeof(struct eth_pdata),
740 };