dm: core: Create a new header file for 'compat' features
[platform/kernel/u-boot.git] / drivers / net / mscc_eswitch / ocelot_switch.c
1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2 /*
3  * Copyright (c) 2018 Microsemi Corporation
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/io.h>
14 #include <linux/ioport.h>
15 #include <miiphy.h>
16 #include <net.h>
17 #include <wait_bit.h>
18
19 #include "mscc_xfer.h"
20 #include "mscc_mac_table.h"
21 #include "mscc_miim.h"
22
23 #define PHY_CFG                         0x0
24 #define PHY_CFG_ENA                             0xF
25 #define PHY_CFG_COMMON_RST                      BIT(4)
26 #define PHY_CFG_RST                             (0xF << 5)
27 #define PHY_STAT                        0x4
28 #define PHY_STAT_SUPERVISOR_COMPLETE            BIT(0)
29
30 #define ANA_PORT_VLAN_CFG(x)            (0x7000 + 0x100 * (x))
31 #define         ANA_PORT_VLAN_CFG_AWARE_ENA     BIT(20)
32 #define         ANA_PORT_VLAN_CFG_POP_CNT(x)    ((x) << 18)
33 #define ANA_PORT_PORT_CFG(x)            (0x7070 + 0x100 * (x))
34 #define         ANA_PORT_PORT_CFG_RECV_ENA      BIT(6)
35 #define ANA_PGID(x)                     (0x8c00 + 4 * (x))
36
37 #define HSIO_ANA_SERDES1G_DES_CFG               0x4c
38 #define         HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(x)            ((x) << 1)
39 #define         HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(x)             ((x) << 5)
40 #define         HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(x)          ((x) << 8)
41 #define         HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(x)           ((x) << 13)
42 #define HSIO_ANA_SERDES1G_IB_CFG                0x50
43 #define         HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(x)       (x)
44 #define         HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(x)             ((x) << 6)
45 #define         HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP        BIT(9)
46 #define         HSIO_ANA_SERDES1G_IB_CFG_ENA_DETLEV             BIT(11)
47 #define         HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM           BIT(13)
48 #define         HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(x)         ((x) << 24)
49 #define HSIO_ANA_SERDES1G_OB_CFG                0x54
50 #define         HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(x)       (x)
51 #define         HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(x)            ((x) << 4)
52 #define         HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(x)       ((x) << 10)
53 #define         HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(x)            ((x) << 13)
54 #define         HSIO_ANA_SERDES1G_OB_CFG_SLP(x)                 ((x) << 17)
55 #define HSIO_ANA_SERDES1G_SER_CFG               0x58
56 #define HSIO_ANA_SERDES1G_COMMON_CFG            0x5c
57 #define         HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE            BIT(0)
58 #define         HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE           BIT(18)
59 #define         HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST            BIT(31)
60 #define HSIO_ANA_SERDES1G_PLL_CFG               0x60
61 #define         HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA               BIT(7)
62 #define         HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(x)      ((x) << 8)
63 #define         HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2           BIT(21)
64 #define HSIO_DIG_SERDES1G_DFT_CFG0              0x68
65 #define HSIO_DIG_SERDES1G_MISC_CFG              0x7c
66 #define         HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST             BIT(0)
67 #define HSIO_MCB_SERDES1G_CFG                   0x88
68 #define         HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT               BIT(31)
69 #define         HSIO_MCB_SERDES1G_CFG_ADDR(x)                   (x)
70 #define HSIO_HW_CFGSTAT_HW_CFG                  0x10c
71
72 #define SYS_FRM_AGING                   0x574
73 #define         SYS_FRM_AGING_ENA               BIT(20)
74
75 #define SYS_SYSTEM_RST_CFG              0x508
76 #define         SYS_SYSTEM_RST_MEM_INIT         BIT(0)
77 #define         SYS_SYSTEM_RST_MEM_ENA          BIT(1)
78 #define         SYS_SYSTEM_RST_CORE_ENA         BIT(2)
79 #define SYS_PORT_MODE(x)                (0x514 + 0x4 * (x))
80 #define         SYS_PORT_MODE_INCL_INJ_HDR(x)   ((x) << 3)
81 #define         SYS_PORT_MODE_INCL_INJ_HDR_M    GENMASK(4, 3)
82 #define         SYS_PORT_MODE_INCL_XTR_HDR(x)   ((x) << 1)
83 #define         SYS_PORT_MODE_INCL_XTR_HDR_M    GENMASK(2, 1)
84 #define SYS_PAUSE_CFG(x)                (0x608 + 0x4 * (x))
85 #define         SYS_PAUSE_CFG_PAUSE_ENA         BIT(0)
86
87 #define QSYS_SWITCH_PORT_MODE(x)        (0x11234 + 0x4 * (x))
88 #define         QSYS_SWITCH_PORT_MODE_PORT_ENA  BIT(14)
89 #define QSYS_QMAP                       0x112d8
90 #define QSYS_EGR_NO_SHARING             0x1129c
91
92 /* Port registers */
93 #define DEV_CLOCK_CFG                   0x0
94 #define DEV_CLOCK_CFG_LINK_SPEED_1000           1
95 #define DEV_MAC_ENA_CFG                 0x1c
96 #define         DEV_MAC_ENA_CFG_RX_ENA          BIT(4)
97 #define         DEV_MAC_ENA_CFG_TX_ENA          BIT(0)
98
99 #define DEV_MAC_IFG_CFG                 0x30
100 #define         DEV_MAC_IFG_CFG_TX_IFG(x)       ((x) << 8)
101 #define         DEV_MAC_IFG_CFG_RX_IFG2(x)      ((x) << 4)
102 #define         DEV_MAC_IFG_CFG_RX_IFG1(x)      (x)
103
104 #define PCS1G_CFG                       0x48
105 #define         PCS1G_MODE_CFG_SGMII_MODE_ENA   BIT(0)
106 #define PCS1G_MODE_CFG                  0x4c
107 #define         PCS1G_MODE_CFG_UNIDIR_MODE_ENA  BIT(4)
108 #define         PCS1G_MODE_CFG_SGMII_MODE_ENA   BIT(0)
109 #define PCS1G_SD_CFG                    0x50
110 #define PCS1G_ANEG_CFG                  0x54
111 #define         PCS1G_ANEG_CFG_ADV_ABILITY(x)   ((x) << 16)
112
113 #define QS_XTR_GRP_CFG(x)               (4 * (x))
114 #define QS_XTR_GRP_CFG_MODE(x)                  ((x) << 2)
115 #define         QS_XTR_GRP_CFG_STATUS_WORD_POS  BIT(1)
116 #define         QS_XTR_GRP_CFG_BYTE_SWAP        BIT(0)
117 #define QS_INJ_GRP_CFG(x)               (0x24 + (x) * 4)
118 #define         QS_INJ_GRP_CFG_MODE(x)          ((x) << 2)
119 #define         QS_INJ_GRP_CFG_BYTE_SWAP        BIT(0)
120
121 #define IFH_INJ_BYPASS          BIT(31)
122 #define IFH_TAG_TYPE_C          0
123 #define MAC_VID                 1
124 #define CPU_PORT                11
125 #define INTERNAL_PORT_MSK       0x2FF
126 #define IFH_LEN                 4
127 #define ETH_ALEN                6
128 #define PGID_BROADCAST          13
129 #define PGID_UNICAST            14
130 #define PGID_SRC                80
131
132 static const char * const regs_names[] = {
133         "port0", "port1", "port2", "port3", "port4", "port5", "port6", "port7",
134         "port8", "port9", "port10", "sys", "rew", "qs", "hsio", "qsys", "ana",
135 };
136
137 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
138 #define MAX_PORT 11
139
140 enum ocelot_ctrl_regs {
141         SYS = MAX_PORT,
142         REW,
143         QS,
144         HSIO,
145         QSYS,
146         ANA,
147 };
148
149 #define OCELOT_MIIM_BUS_COUNT 2
150
151 struct ocelot_phy_port_t {
152         size_t phy_addr;
153         struct mii_dev *bus;
154         u8 serdes_index;
155         u8 phy_mode;
156 };
157
158 struct ocelot_private {
159         void __iomem *regs[REGS_NAMES_COUNT];
160         struct mii_dev *bus[OCELOT_MIIM_BUS_COUNT];
161         struct ocelot_phy_port_t ports[MAX_PORT];
162 };
163
164 static struct mscc_miim_dev miim[OCELOT_MIIM_BUS_COUNT];
165 static int miim_count = -1;
166
167 static const unsigned long ocelot_regs_qs[] = {
168         [MSCC_QS_XTR_RD] = 0x8,
169         [MSCC_QS_XTR_FLUSH] = 0x18,
170         [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
171         [MSCC_QS_INJ_WR] = 0x2c,
172         [MSCC_QS_INJ_CTRL] = 0x34,
173 };
174
175 static const unsigned long ocelot_regs_ana_table[] = {
176         [MSCC_ANA_TABLES_MACHDATA] = 0x8b34,
177         [MSCC_ANA_TABLES_MACLDATA] = 0x8b38,
178         [MSCC_ANA_TABLES_MACACCESS] = 0x8b3c,
179 };
180
181 static void mscc_phy_reset(void)
182 {
183         writel(0, BASE_DEVCPU_GCB + PERF_PHY_CFG + PHY_CFG);
184         writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
185                | PHY_CFG_ENA, BASE_DEVCPU_GCB + PERF_PHY_CFG + PHY_CFG);
186         if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + PERF_PHY_CFG) +
187                               PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
188                               true, 2000, false)) {
189                 pr_err("Timeout in phy reset\n");
190         }
191 }
192
193 __weak void mscc_switch_reset(void)
194 {
195 }
196
197 static void ocelot_stop(struct udevice *dev)
198 {
199         mscc_switch_reset();
200         mscc_phy_reset();
201 }
202
203 static void ocelot_cpu_capture_setup(struct ocelot_private *priv)
204 {
205         int i;
206
207         /* map the 8 CPU extraction queues to CPU port 11 */
208         writel(0, priv->regs[QSYS] + QSYS_QMAP);
209
210         for (i = 0; i <= 1; i++) {
211                 /*
212                  * Do byte-swap and expect status after last data word
213                  * Extraction: Mode: manual extraction) | Byte_swap
214                  */
215                 writel(QS_XTR_GRP_CFG_MODE(1) | QS_XTR_GRP_CFG_BYTE_SWAP,
216                        priv->regs[QS] + QS_XTR_GRP_CFG(i));
217                 /*
218                  * Injection: Mode: manual extraction | Byte_swap
219                  */
220                 writel(QS_INJ_GRP_CFG_MODE(1) | QS_INJ_GRP_CFG_BYTE_SWAP,
221                        priv->regs[QS] + QS_INJ_GRP_CFG(i));
222         }
223
224         for (i = 0; i <= 1; i++)
225                 /* Enable IFH insertion/parsing on CPU ports */
226                 writel(SYS_PORT_MODE_INCL_INJ_HDR(1) |
227                        SYS_PORT_MODE_INCL_XTR_HDR(1),
228                        priv->regs[SYS] + SYS_PORT_MODE(CPU_PORT + i));
229         /*
230          * Setup the CPU port as VLAN aware to support switching frames
231          * based on tags
232          */
233         writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
234                MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(CPU_PORT));
235
236         /* Disable learning (only RECV_ENA must be set) */
237         writel(ANA_PORT_PORT_CFG_RECV_ENA,
238                priv->regs[ANA] + ANA_PORT_PORT_CFG(CPU_PORT));
239
240         /* Enable switching to/from cpu port */
241         setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(CPU_PORT),
242                      QSYS_SWITCH_PORT_MODE_PORT_ENA);
243
244         /* No pause on CPU port - not needed (off by default) */
245         clrbits_le32(priv->regs[SYS] + SYS_PAUSE_CFG(CPU_PORT),
246                      SYS_PAUSE_CFG_PAUSE_ENA);
247
248         setbits_le32(priv->regs[QSYS] + QSYS_EGR_NO_SHARING, BIT(CPU_PORT));
249 }
250
251 static void ocelot_port_init(struct ocelot_private *priv, int port)
252 {
253         void __iomem *regs = priv->regs[port];
254
255         /* Enable PCS */
256         writel(PCS1G_MODE_CFG_SGMII_MODE_ENA, regs + PCS1G_CFG);
257
258         /* Disable Signal Detect */
259         writel(0, regs + PCS1G_SD_CFG);
260
261         /* Enable MAC RX and TX */
262         writel(DEV_MAC_ENA_CFG_RX_ENA | DEV_MAC_ENA_CFG_TX_ENA,
263                regs + DEV_MAC_ENA_CFG);
264
265         /* Clear sgmii_mode_ena */
266         writel(0, regs + PCS1G_MODE_CFG);
267
268         /*
269          * Clear sw_resolve_ena(bit 0) and set adv_ability to
270          * something meaningful just in case
271          */
272         writel(PCS1G_ANEG_CFG_ADV_ABILITY(0x20), regs + PCS1G_ANEG_CFG);
273
274         /* Set MAC IFG Gaps */
275         writel(DEV_MAC_IFG_CFG_TX_IFG(5) | DEV_MAC_IFG_CFG_RX_IFG1(5) |
276                DEV_MAC_IFG_CFG_RX_IFG2(1), regs + DEV_MAC_IFG_CFG);
277
278         /* Set link speed and release all resets */
279         writel(DEV_CLOCK_CFG_LINK_SPEED_1000, regs + DEV_CLOCK_CFG);
280
281         /* Make VLAN aware for CPU traffic */
282         writel(ANA_PORT_VLAN_CFG_AWARE_ENA | ANA_PORT_VLAN_CFG_POP_CNT(1) |
283                MAC_VID, priv->regs[ANA] + ANA_PORT_VLAN_CFG(port));
284
285         /* Enable the port in the core */
286         setbits_le32(priv->regs[QSYS] + QSYS_SWITCH_PORT_MODE(port),
287                      QSYS_SWITCH_PORT_MODE_PORT_ENA);
288 }
289
290 static void serdes1g_write(void __iomem *base, u32 addr)
291 {
292         u32 data;
293
294         writel(HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT |
295                HSIO_MCB_SERDES1G_CFG_ADDR(addr),
296                base + HSIO_MCB_SERDES1G_CFG);
297
298         do {
299                 data = readl(base + HSIO_MCB_SERDES1G_CFG);
300         } while (data & HSIO_MCB_SERDES1G_CFG_WR_ONE_SHOT);
301 }
302
303 static void serdes1g_setup(void __iomem *base, uint32_t addr,
304                            phy_interface_t interface)
305 {
306         writel(0x34, base + HSIO_HW_CFGSTAT_HW_CFG);
307
308         writel(0x0, base + HSIO_ANA_SERDES1G_SER_CFG);
309         writel(0x0, base + HSIO_DIG_SERDES1G_DFT_CFG0);
310         writel(HSIO_ANA_SERDES1G_IB_CFG_RESISTOR_CTRL(11) |
311                HSIO_ANA_SERDES1G_IB_CFG_EQ_GAIN(0) |
312                HSIO_ANA_SERDES1G_IB_CFG_ENA_OFFSET_COMP |
313                HSIO_ANA_SERDES1G_IB_CFG_ENA_CMV_TERM |
314                HSIO_ANA_SERDES1G_IB_CFG_ACJTAG_HYST(1),
315                base + HSIO_ANA_SERDES1G_IB_CFG);
316         writel(HSIO_ANA_SERDES1G_DES_CFG_BW_HYST(7) |
317                HSIO_ANA_SERDES1G_DES_CFG_BW_ANA(6) |
318                HSIO_ANA_SERDES1G_DES_CFG_MBTR_CTRL(2) |
319                HSIO_ANA_SERDES1G_DES_CFG_PHS_CTRL(6),
320                base + HSIO_ANA_SERDES1G_DES_CFG);
321         writel(HSIO_ANA_SERDES1G_OB_CFG_RESISTOR_CTRL(1) |
322                HSIO_ANA_SERDES1G_OB_CFG_VCM_CTRL(4) |
323                HSIO_ANA_SERDES1G_OB_CFG_CMM_BIAS_CTRL(2) |
324                HSIO_ANA_SERDES1G_OB_CFG_AMP_CTRL(12) |
325                HSIO_ANA_SERDES1G_OB_CFG_SLP(3),
326                base + HSIO_ANA_SERDES1G_OB_CFG);
327         writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
328                HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE,
329                base + HSIO_ANA_SERDES1G_COMMON_CFG);
330         writel(HSIO_ANA_SERDES1G_PLL_CFG_FSM_ENA |
331                HSIO_ANA_SERDES1G_PLL_CFG_FSM_CTRL_DATA(200) |
332                HSIO_ANA_SERDES1G_PLL_CFG_ENA_RC_DIV2,
333                base + HSIO_ANA_SERDES1G_PLL_CFG);
334         writel(HSIO_DIG_SERDES1G_MISC_CFG_LANE_RST,
335                base + HSIO_DIG_SERDES1G_MISC_CFG);
336
337         serdes1g_write(base, addr);
338
339         writel(HSIO_ANA_SERDES1G_COMMON_CFG_IF_MODE |
340                HSIO_ANA_SERDES1G_COMMON_CFG_ENA_LANE |
341                HSIO_ANA_SERDES1G_COMMON_CFG_SYS_RST,
342                base + HSIO_ANA_SERDES1G_COMMON_CFG);
343         serdes1g_write(base, addr);
344
345         writel(0x0, base + HSIO_DIG_SERDES1G_MISC_CFG);
346         serdes1g_write(base, addr);
347 }
348
349 static void serdes_setup(struct ocelot_private *priv)
350 {
351         size_t mask;
352         int i = 0;
353
354         for (i = 0; i < MAX_PORT; ++i) {
355                 if (!priv->ports[i].bus || priv->ports[i].serdes_index == 0xff)
356                         continue;
357
358                 mask = BIT(priv->ports[i].serdes_index);
359                 serdes1g_setup(priv->regs[HSIO], mask,
360                                priv->ports[i].phy_mode);
361         }
362 }
363
364 static int ocelot_switch_init(struct ocelot_private *priv)
365 {
366         /* Reset switch & memories */
367         writel(SYS_SYSTEM_RST_MEM_ENA | SYS_SYSTEM_RST_MEM_INIT,
368                priv->regs[SYS] + SYS_SYSTEM_RST_CFG);
369
370         /* Wait to complete */
371         if (wait_for_bit_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
372                               SYS_SYSTEM_RST_MEM_INIT, false, 2000, false)) {
373                 pr_err("Timeout in memory reset\n");
374                 return -EIO;
375         }
376
377         /* Enable switch core */
378         setbits_le32(priv->regs[SYS] + SYS_SYSTEM_RST_CFG,
379                      SYS_SYSTEM_RST_CORE_ENA);
380
381         serdes_setup(priv);
382         return 0;
383 }
384
385 static int ocelot_initialize(struct ocelot_private *priv)
386 {
387         int ret, i;
388
389         /* Initialize switch memories, enable core */
390         ret = ocelot_switch_init(priv);
391         if (ret)
392                 return ret;
393         /*
394          * Disable port-to-port by switching
395          * Put fron ports in "port isolation modes" - i.e. they cant send
396          * to other ports - via the PGID sorce masks.
397          */
398         for (i = 0; i < MAX_PORT; i++)
399                 writel(0, priv->regs[ANA] + ANA_PGID(PGID_SRC + i));
400
401         /* Flush queues */
402         mscc_flush(priv->regs[QS], ocelot_regs_qs);
403
404         /* Setup frame ageing - "2 sec" - The unit is 6.5us on Ocelot */
405         writel(SYS_FRM_AGING_ENA | (20000000 / 65),
406                priv->regs[SYS] + SYS_FRM_AGING);
407
408         for (i = 0; i < MAX_PORT; i++)
409                 ocelot_port_init(priv, i);
410
411         ocelot_cpu_capture_setup(priv);
412
413         debug("Ports enabled\n");
414
415         return 0;
416 }
417
418 static int ocelot_write_hwaddr(struct udevice *dev)
419 {
420         struct ocelot_private *priv = dev_get_priv(dev);
421         struct eth_pdata *pdata = dev_get_platdata(dev);
422
423         mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table,
424                            pdata->enetaddr, PGID_UNICAST);
425
426         writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
427
428         return 0;
429 }
430
431 static int ocelot_start(struct udevice *dev)
432 {
433         struct ocelot_private *priv = dev_get_priv(dev);
434         struct eth_pdata *pdata = dev_get_platdata(dev);
435         const unsigned char mac[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff,
436                                               0xff };
437         int ret;
438
439         ret = ocelot_initialize(priv);
440         if (ret)
441                 return ret;
442
443         /* Set MAC address tables entries for CPU redirection */
444         mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table, mac,
445                            PGID_BROADCAST);
446
447         writel(BIT(CPU_PORT) | INTERNAL_PORT_MSK,
448                priv->regs[ANA] + ANA_PGID(PGID_BROADCAST));
449
450         /* It should be setup latter in ocelot_write_hwaddr */
451         mscc_mac_table_add(priv->regs[ANA], ocelot_regs_ana_table,
452                            pdata->enetaddr, PGID_UNICAST);
453
454         writel(BIT(CPU_PORT), priv->regs[ANA] + ANA_PGID(PGID_UNICAST));
455
456         return 0;
457 }
458
459 static int ocelot_send(struct udevice *dev, void *packet, int length)
460 {
461         struct ocelot_private *priv = dev_get_priv(dev);
462         u32 ifh[IFH_LEN];
463         int port = BIT(0);      /* use port 0 */
464         u32 *buf = packet;
465
466         /*
467          * Generate the IFH for frame injection
468          *
469          * The IFH is a 128bit-value
470          * bit 127: bypass the analyzer processing
471          * bit 56-67: destination mask
472          * bit 28-29: pop_cnt: 3 disables all rewriting of the frame
473          * bit 20-27: cpu extraction queue mask
474          * bit 16: tag type 0: C-tag, 1: S-tag
475          * bit 0-11: VID
476          */
477         ifh[0] = IFH_INJ_BYPASS;
478         ifh[1] = (0xf00 & port) >> 8;
479         ifh[2] = (0xff & port) << 24;
480         ifh[3] = (IFH_TAG_TYPE_C << 16);
481
482         return mscc_send(priv->regs[QS], ocelot_regs_qs,
483                          ifh, IFH_LEN, buf, length);
484 }
485
486 static int ocelot_recv(struct udevice *dev, int flags, uchar **packetp)
487 {
488         struct ocelot_private *priv = dev_get_priv(dev);
489         u32 *rxbuf = (u32 *)net_rx_packets[0];
490         int byte_cnt;
491
492         byte_cnt = mscc_recv(priv->regs[QS], ocelot_regs_qs, rxbuf, IFH_LEN,
493                              false);
494
495         *packetp = net_rx_packets[0];
496
497         return byte_cnt;
498 }
499
500 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
501 {
502         int i = 0;
503
504         for (i = 0; i < OCELOT_MIIM_BUS_COUNT; ++i)
505                 if (miim[i].miim_base == base && miim[i].miim_size == size)
506                         return miim[i].bus;
507
508         return NULL;
509 }
510
511 static void add_port_entry(struct ocelot_private *priv, size_t index,
512                            size_t phy_addr, struct mii_dev *bus,
513                            u8 serdes_index, u8 phy_mode)
514 {
515         priv->ports[index].phy_addr = phy_addr;
516         priv->ports[index].bus = bus;
517         priv->ports[index].serdes_index = serdes_index;
518         priv->ports[index].phy_mode = phy_mode;
519 }
520
521 static int external_bus(struct ocelot_private *priv, size_t port_index)
522 {
523         return priv->ports[port_index].serdes_index != 0xff;
524 }
525
526 static int ocelot_probe(struct udevice *dev)
527 {
528         struct ocelot_private *priv = dev_get_priv(dev);
529         int i, ret;
530         struct resource res;
531         fdt32_t faddr;
532         phys_addr_t addr_base;
533         unsigned long addr_size;
534         ofnode eth_node, node, mdio_node;
535         size_t phy_addr;
536         struct mii_dev *bus;
537         struct ofnode_phandle_args phandle;
538         struct phy_device *phy;
539
540         if (!priv)
541                 return -EINVAL;
542
543         for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
544                 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
545                 if (!priv->regs[i]) {
546                         debug
547                             ("Error can't get regs base addresses for %s\n",
548                              regs_names[i]);
549                         return -ENOMEM;
550                 }
551         }
552
553         /* Initialize miim buses */
554         memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
555                OCELOT_MIIM_BUS_COUNT);
556
557         /* iterate all the ports and find out on which bus they are */
558         i = 0;
559         eth_node = dev_read_first_subnode(dev);
560         for (node = ofnode_first_subnode(eth_node); ofnode_valid(node);
561              node = ofnode_next_subnode(node)) {
562                 if (ofnode_read_resource(node, 0, &res))
563                         return -ENOMEM;
564                 i = res.start;
565
566                 ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
567                                                &phandle);
568
569                 /* Get phy address on mdio bus */
570                 if (ofnode_read_resource(phandle.node, 0, &res))
571                         return -ENOMEM;
572                 phy_addr = res.start;
573
574                 /* Get mdio node */
575                 mdio_node = ofnode_get_parent(phandle.node);
576
577                 if (ofnode_read_resource(mdio_node, 0, &res))
578                         return -ENOMEM;
579                 faddr = cpu_to_fdt32(res.start);
580
581                 addr_base = ofnode_translate_address(mdio_node, &faddr);
582                 addr_size = res.end - res.start;
583
584                 /* If the bus is new then create a new bus */
585                 if (!get_mdiobus(addr_base, addr_size))
586                         priv->bus[miim_count] =
587                                 mscc_mdiobus_init(miim, &miim_count, addr_base,
588                                                   addr_size);
589
590                 /* Connect mdio bus with the port */
591                 bus = get_mdiobus(addr_base, addr_size);
592
593                 /* Get serdes info */
594                 ret = ofnode_parse_phandle_with_args(node, "phys", NULL,
595                                                      3, 0, &phandle);
596                 if (ret)
597                         add_port_entry(priv, i, phy_addr, bus, 0xff, 0xff);
598                 else
599                         add_port_entry(priv, i, phy_addr, bus, phandle.args[1],
600                                        phandle.args[2]);
601         }
602
603         mscc_phy_reset();
604
605         for (i = 0; i < MAX_PORT; i++) {
606                 if (!priv->ports[i].bus)
607                         continue;
608
609                 phy = phy_connect(priv->ports[i].bus,
610                                   priv->ports[i].phy_addr, dev,
611                                   PHY_INTERFACE_MODE_NONE);
612                 if (phy && external_bus(priv, i))
613                         board_phy_config(phy);
614         }
615
616         return 0;
617 }
618
619 static int ocelot_remove(struct udevice *dev)
620 {
621         struct ocelot_private *priv = dev_get_priv(dev);
622         int i;
623
624         for (i = 0; i < OCELOT_MIIM_BUS_COUNT; i++) {
625                 mdio_unregister(priv->bus[i]);
626                 mdio_free(priv->bus[i]);
627         }
628
629         return 0;
630 }
631
632 static const struct eth_ops ocelot_ops = {
633         .start        = ocelot_start,
634         .stop         = ocelot_stop,
635         .send         = ocelot_send,
636         .recv         = ocelot_recv,
637         .write_hwaddr = ocelot_write_hwaddr,
638 };
639
640 static const struct udevice_id mscc_ocelot_ids[] = {
641         {.compatible = "mscc,vsc7514-switch"},
642         { /* Sentinel */ }
643 };
644
645 U_BOOT_DRIVER(ocelot) = {
646         .name     = "ocelot-switch",
647         .id       = UCLASS_ETH,
648         .of_match = mscc_ocelot_ids,
649         .probe    = ocelot_probe,
650         .remove   = ocelot_remove,
651         .ops      = &ocelot_ops,
652         .priv_auto_alloc_size = sizeof(struct ocelot_private),
653         .platdata_auto_alloc_size = sizeof(struct eth_pdata),
654 };