bf95a38354d6b8f933f03f33ca5bbbe78bc0aec9
[oweals/u-boot.git] / drivers / net / mscc_eswitch / servalt_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 <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_miim.h"
21
22 #define PHY_CFG                         0x0
23 #define PHY_CFG_ENA                             0x3
24 #define PHY_CFG_COMMON_RST                      BIT(2)
25 #define PHY_CFG_RST                             (0x3 << 3)
26 #define PHY_STAT                        0x4
27 #define PHY_STAT_SUPERVISOR_COMPLETE            BIT(0)
28
29 #define ANA_AC_RAM_CTRL_RAM_INIT                0x14fdc
30 #define ANA_AC_STAT_GLOBAL_CFG_PORT_RESET       0x15474
31
32 #define ANA_CL_PORT_VLAN_CFG(x)                 (0xa018 + 0xc8 * (x))
33 #define         ANA_CL_PORT_VLAN_CFG_AWARE_ENA                  BIT(19)
34 #define         ANA_CL_PORT_VLAN_CFG_POP_CNT(x)                 ((x) << 17)
35
36 #define ANA_L2_COMMON_FWD_CFG                   0x18498
37 #define         ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA BIT(6)
38
39 #define ASM_CFG_STAT_CFG                        0xb08
40 #define ASM_CFG_PORT(x)                         (0xb74 + 0x4 * (x))
41 #define         ASM_CFG_PORT_NO_PREAMBLE_ENA            BIT(8)
42 #define         ASM_CFG_PORT_INJ_FORMAT_CFG(x)          ((x) << 1)
43 #define ASM_RAM_CTRL_RAM_INIT                   0xbfc
44
45 #define DEV_DEV_CFG_DEV_RST_CTRL        0x0
46 #define         DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(x)   ((x) << 20)
47 #define DEV_MAC_CFG_MAC_ENA             0x24
48 #define         DEV_MAC_CFG_MAC_ENA_RX_ENA              BIT(4)
49 #define         DEV_MAC_CFG_MAC_ENA_TX_ENA              BIT(0)
50 #define DEV_MAC_CFG_MAC_IFG             0x3c
51 #define         DEV_MAC_CFG_MAC_IFG_TX_IFG(x)           ((x) << 8)
52 #define         DEV_MAC_CFG_MAC_IFG_RX_IFG2(x)          ((x) << 4)
53 #define         DEV_MAC_CFG_MAC_IFG_RX_IFG1(x)          (x)
54 #define DEV_PCS1G_CFG_PCS1G_CFG         0x48
55 #define         DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA         BIT(0)
56 #define DEV_PCS1G_CFG_PCS1G_MODE        0x4c
57 #define DEV_PCS1G_CFG_PCS1G_SD          0x50
58 #define DEV_PCS1G_CFG_PCS1G_ANEG        0x54
59 #define         DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(x) ((x) << 16)
60
61 #define LRN_COMMON_ACCESS_CTRL                  0x0
62 #define         LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT    BIT(0)
63 #define LRN_COMMON_MAC_ACCESS_CFG0              0x4
64 #define LRN_COMMON_MAC_ACCESS_CFG1              0x8
65 #define LRN_COMMON_MAC_ACCESS_CFG2              0xc
66 #define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(x)    (x)
67 #define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(x)    ((x) << 12)
68 #define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD        BIT(15)
69 #define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED     BIT(16)
70 #define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY   BIT(23)
71 #define         LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(x)  ((x) << 24)
72
73 #define QFWD_SYSTEM_SWITCH_PORT_MODE(x)         (0x4400 + 0x4 * (x))
74 #define         QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA           BIT(17)
75
76 #define QS_XTR_GRP_CFG(x)               (4 * (x))
77 #define QS_INJ_GRP_CFG(x)               (0x24 + (x) * 4)
78
79 #define QSYS_SYSTEM_RESET_CFG                   0x1048
80 #define QSYS_CALCFG_CAL_AUTO                    0x1134
81 #define QSYS_CALCFG_CAL_CTRL                    0x113c
82 #define         QSYS_CALCFG_CAL_CTRL_CAL_MODE(x)                ((x) << 11)
83 #define QSYS_RAM_CTRL_RAM_INIT                  0x1140
84
85 #define REW_RAM_CTRL_RAM_INIT                   0xFFF4
86
87 #define MAC_VID                 0
88 #define CPU_PORT                11
89 #define IFH_LEN                 7
90 #define ETH_ALEN                6
91 #define PGID_BROADCAST          50
92 #define PGID_UNICAST            51
93
94 static const char * const regs_names[] = {
95         "port0", "port1",
96         "ana_ac", "ana_cl", "ana_l2", "asm", "lrn", "qfwd", "qs", "qsys", "rew",
97 };
98
99 #define REGS_NAMES_COUNT ARRAY_SIZE(regs_names) + 1
100 #define MAX_PORT 2
101
102 enum servalt_ctrl_regs {
103         ANA_AC = MAX_PORT,
104         ANA_CL,
105         ANA_L2,
106         ASM,
107         LRN,
108         QFWD,
109         QS,
110         QSYS,
111         REW,
112 };
113
114 #define SERVALT_MIIM_BUS_COUNT 2
115
116 struct servalt_phy_port_t {
117         size_t phy_addr;
118         struct mii_dev *bus;
119 };
120
121 struct servalt_private {
122         void __iomem *regs[REGS_NAMES_COUNT];
123         struct mii_dev *bus[SERVALT_MIIM_BUS_COUNT];
124         struct servalt_phy_port_t ports[MAX_PORT];
125 };
126
127 static const unsigned long servalt_regs_qs[] = {
128         [MSCC_QS_XTR_RD] = 0x8,
129         [MSCC_QS_XTR_FLUSH] = 0x18,
130         [MSCC_QS_XTR_DATA_PRESENT] = 0x1c,
131         [MSCC_QS_INJ_WR] = 0x2c,
132         [MSCC_QS_INJ_CTRL] = 0x34,
133 };
134
135 static struct mscc_miim_dev miim[SERVALT_MIIM_BUS_COUNT];
136 static int miim_count = -1;
137
138 static void mscc_phy_reset(void)
139 {
140         writel(0, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
141         writel(PHY_CFG_RST | PHY_CFG_COMMON_RST
142                | PHY_CFG_ENA, BASE_DEVCPU_GCB + GCB_PHY_CFG + PHY_CFG);
143         if (wait_for_bit_le32((const void *)(BASE_DEVCPU_GCB + GCB_PHY_CFG) +
144                               PHY_STAT, PHY_STAT_SUPERVISOR_COMPLETE,
145                               true, 2000, false)) {
146                 pr_err("Timeout in phy reset\n");
147         }
148 }
149
150 static void servalt_cpu_capture_setup(struct servalt_private *priv)
151 {
152         /* ASM: No preamble and IFH prefix on CPU injected frames */
153         writel(ASM_CFG_PORT_NO_PREAMBLE_ENA |
154                ASM_CFG_PORT_INJ_FORMAT_CFG(1),
155                priv->regs[ASM] + ASM_CFG_PORT(CPU_PORT));
156
157         /* Set Manual injection via DEVCPU_QS registers for CPU queue 0 */
158         writel(0x5, priv->regs[QS] + QS_INJ_GRP_CFG(0));
159
160         /* Set Manual extraction via DEVCPU_QS registers for CPU queue 0 */
161         writel(0x7, priv->regs[QS] + QS_XTR_GRP_CFG(0));
162
163         /* Enable CPU port for any frame transfer */
164         setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(CPU_PORT),
165                      QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
166
167         /* Send a copy to CPU when found as forwarding entry */
168         setbits_le32(priv->regs[ANA_L2] + ANA_L2_COMMON_FWD_CFG,
169                      ANA_L2_COMMON_FWD_CFG_CPU_DMAC_COPY_ENA);
170 }
171
172 static void servalt_port_init(struct servalt_private *priv, int port)
173 {
174         void __iomem *regs = priv->regs[port];
175
176         /* Enable PCS */
177         writel(DEV_PCS1G_CFG_PCS1G_CFG_PCS_ENA,
178                regs + DEV_PCS1G_CFG_PCS1G_CFG);
179
180         /* Disable Signal Detect */
181         writel(0, regs + DEV_PCS1G_CFG_PCS1G_SD);
182
183         /* Enable MAC RX and TX */
184         writel(DEV_MAC_CFG_MAC_ENA_RX_ENA |
185                DEV_MAC_CFG_MAC_ENA_TX_ENA,
186                regs + DEV_MAC_CFG_MAC_ENA);
187
188         /* Clear sgmii_mode_ena */
189         writel(0, regs + DEV_PCS1G_CFG_PCS1G_MODE);
190
191         /*
192          * Clear sw_resolve_ena(bit 0) and set adv_ability to
193          * something meaningful just in case
194          */
195         writel(DEV_PCS1G_CFG_PCS1G_ANEG_ADV_ABILITY(0x20),
196                regs + DEV_PCS1G_CFG_PCS1G_ANEG);
197
198         /* Set MAC IFG Gaps */
199         writel(DEV_MAC_CFG_MAC_IFG_TX_IFG(4) |
200                DEV_MAC_CFG_MAC_IFG_RX_IFG1(5) |
201                DEV_MAC_CFG_MAC_IFG_RX_IFG2(1),
202                regs + DEV_MAC_CFG_MAC_IFG);
203
204         /* Set link speed and release all resets */
205         writel(DEV_DEV_CFG_DEV_RST_CTRL_SPEED_SEL(2),
206                regs + DEV_DEV_CFG_DEV_RST_CTRL);
207
208         /* Make VLAN aware for CPU traffic */
209         writel(ANA_CL_PORT_VLAN_CFG_AWARE_ENA |
210                ANA_CL_PORT_VLAN_CFG_POP_CNT(1) |
211                MAC_VID,
212                priv->regs[ANA_CL] + ANA_CL_PORT_VLAN_CFG(port));
213
214         /* Enable CPU port for any frame transfer */
215         setbits_le32(priv->regs[QFWD] + QFWD_SYSTEM_SWITCH_PORT_MODE(port),
216                      QFWD_SYSTEM_SWITCH_PORT_MODE_PORT_ENA);
217 }
218
219 static int ram_init(u32 val, void __iomem *addr)
220 {
221         writel(val, addr);
222
223         if (wait_for_bit_le32(addr, BIT(1), false, 2000, false)) {
224                 printf("Timeout in memory reset, reg = 0x%08x\n", val);
225                 return 1;
226         }
227
228         return 0;
229 }
230
231 static int servalt_switch_init(struct servalt_private *priv)
232 {
233         /* Initialize memories */
234         ram_init(0x3, priv->regs[QSYS] + QSYS_RAM_CTRL_RAM_INIT);
235         ram_init(0x3, priv->regs[ASM] + ASM_RAM_CTRL_RAM_INIT);
236         ram_init(0x3, priv->regs[ANA_AC] + ANA_AC_RAM_CTRL_RAM_INIT);
237         ram_init(0x3, priv->regs[REW] + REW_RAM_CTRL_RAM_INIT);
238
239         /* Reset counters */
240         writel(0x1, priv->regs[ANA_AC] + ANA_AC_STAT_GLOBAL_CFG_PORT_RESET);
241         writel(0x1, priv->regs[ASM] + ASM_CFG_STAT_CFG);
242
243         /* Enable switch-core and queue system */
244         writel(0x1, priv->regs[QSYS] + QSYS_SYSTEM_RESET_CFG);
245
246         return 0;
247 }
248
249 static void servalt_switch_config(struct servalt_private *priv)
250 {
251         writel(0x55555555, priv->regs[QSYS] + QSYS_CALCFG_CAL_AUTO);
252
253         writel(readl(priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL) |
254                QSYS_CALCFG_CAL_CTRL_CAL_MODE(8),
255                priv->regs[QSYS] + QSYS_CALCFG_CAL_CTRL);
256 }
257
258 static int servalt_initialize(struct servalt_private *priv)
259 {
260         int ret, i;
261
262         /* Initialize switch memories, enable core */
263         ret = servalt_switch_init(priv);
264         if (ret)
265                 return ret;
266
267         servalt_switch_config(priv);
268
269         for (i = 0; i < MAX_PORT; i++)
270                 servalt_port_init(priv, i);
271
272         servalt_cpu_capture_setup(priv);
273
274         return 0;
275 }
276
277 static inline
278 int servalt_vlant_wait_for_completion(struct servalt_private *priv)
279 {
280         if (wait_for_bit_le32(priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL,
281                               LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
282                               false, 2000, false))
283                 return -ETIMEDOUT;
284
285         return 0;
286 }
287
288 static int servalt_mac_table_add(struct servalt_private *priv,
289                                  const unsigned char mac[ETH_ALEN], int pgid)
290 {
291         u32 macl = 0, mach = 0;
292
293         /*
294          * Set the MAC address to handle and the vlan associated in a format
295          * understood by the hardware.
296          */
297         mach |= MAC_VID << 16;
298         mach |= ((u32)mac[0]) << 8;
299         mach |= ((u32)mac[1]) << 0;
300         macl |= ((u32)mac[2]) << 24;
301         macl |= ((u32)mac[3]) << 16;
302         macl |= ((u32)mac[4]) << 8;
303         macl |= ((u32)mac[5]) << 0;
304
305         writel(mach, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG0);
306         writel(macl, priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG1);
307
308         writel(LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_ADDR(pgid) |
309                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_TYPE(0x3) |
310                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_COPY |
311                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_CPU_QU(0) |
312                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_VLD |
313                LRN_COMMON_MAC_ACCESS_CFG2_MAC_ENTRY_LOCKED,
314                priv->regs[LRN] + LRN_COMMON_MAC_ACCESS_CFG2);
315
316         writel(LRN_COMMON_ACCESS_CTRL_MAC_TABLE_ACCESS_SHOT,
317                priv->regs[LRN] + LRN_COMMON_ACCESS_CTRL);
318
319         return servalt_vlant_wait_for_completion(priv);
320 }
321
322 static int servalt_write_hwaddr(struct udevice *dev)
323 {
324         struct servalt_private *priv = dev_get_priv(dev);
325         struct eth_pdata *pdata = dev_get_platdata(dev);
326
327         return servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
328 }
329
330 static int servalt_start(struct udevice *dev)
331 {
332         struct servalt_private *priv = dev_get_priv(dev);
333         struct eth_pdata *pdata = dev_get_platdata(dev);
334         const unsigned char mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff,
335                 0xff };
336         int ret;
337
338         ret = servalt_initialize(priv);
339         if (ret)
340                 return ret;
341
342         /* Set MAC address tables entries for CPU redirection */
343         ret = servalt_mac_table_add(priv, mac, PGID_BROADCAST);
344         if (ret)
345                 return ret;
346
347         ret = servalt_mac_table_add(priv, pdata->enetaddr, PGID_UNICAST);
348         if (ret)
349                 return ret;
350
351         return 0;
352 }
353
354 static void servalt_stop(struct udevice *dev)
355 {
356 }
357
358 static int servalt_send(struct udevice *dev, void *packet, int length)
359 {
360         struct servalt_private *priv = dev_get_priv(dev);
361         u32 ifh[IFH_LEN];
362         u32 *buf = packet;
363
364         memset(ifh, '\0', IFH_LEN * 4);
365
366         /* Set DST PORT_MASK */
367         ifh[0] = htonl(0);
368         ifh[1] = htonl(0x1FFFFF);
369         ifh[2] = htonl(~0);
370         /* Set DST_MODE to INJECT and UPDATE_FCS */
371         ifh[5] = htonl(0x4c0);
372
373         return mscc_send(priv->regs[QS], servalt_regs_qs,
374                          ifh, IFH_LEN, buf, length);
375 }
376
377 static int servalt_recv(struct udevice *dev, int flags, uchar **packetp)
378 {
379         struct servalt_private *priv = dev_get_priv(dev);
380         u32 *rxbuf = (u32 *)net_rx_packets[0];
381         int byte_cnt = 0;
382
383         byte_cnt = mscc_recv(priv->regs[QS], servalt_regs_qs, rxbuf, IFH_LEN,
384                              false);
385
386         *packetp = net_rx_packets[0];
387
388         return byte_cnt;
389 }
390
391 static struct mii_dev *get_mdiobus(phys_addr_t base, unsigned long size)
392 {
393         int i = 0;
394
395         for (i = 0; i < SERVALT_MIIM_BUS_COUNT; ++i)
396                 if (miim[i].miim_base == base && miim[i].miim_size == size)
397                         return miim[i].bus;
398
399         return NULL;
400 }
401
402 static void add_port_entry(struct servalt_private *priv, size_t index,
403                            size_t phy_addr, struct mii_dev *bus)
404 {
405         priv->ports[index].phy_addr = phy_addr;
406         priv->ports[index].bus = bus;
407 }
408
409 static int servalt_probe(struct udevice *dev)
410 {
411         struct servalt_private *priv = dev_get_priv(dev);
412         int i;
413         struct resource res;
414         fdt32_t faddr;
415         phys_addr_t addr_base;
416         unsigned long addr_size;
417         ofnode eth_node, node, mdio_node;
418         size_t phy_addr;
419         struct mii_dev *bus;
420         struct ofnode_phandle_args phandle;
421
422         if (!priv)
423                 return -EINVAL;
424
425         /* Get registers and map them to the private structure */
426         for (i = 0; i < ARRAY_SIZE(regs_names); i++) {
427                 priv->regs[i] = dev_remap_addr_name(dev, regs_names[i]);
428                 if (!priv->regs[i]) {
429                         debug
430                             ("Error can't get regs base addresses for %s\n",
431                              regs_names[i]);
432                         return -ENOMEM;
433                 }
434         }
435
436         /* Initialize miim buses */
437         memset(&miim, 0x0, sizeof(struct mscc_miim_dev) *
438                SERVALT_MIIM_BUS_COUNT);
439
440         /* iterate all the ports and find out on which bus they are */
441         i = 0;
442         eth_node = dev_read_first_subnode(dev);
443         for (node = ofnode_first_subnode(eth_node);
444              ofnode_valid(node);
445              node = ofnode_next_subnode(node)) {
446                 if (ofnode_read_resource(node, 0, &res))
447                         return -ENOMEM;
448                 i = res.start;
449
450                 ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
451                                                &phandle);
452
453                 /* Get phy address on mdio bus */
454                 if (ofnode_read_resource(phandle.node, 0, &res))
455                         return -ENOMEM;
456                 phy_addr = res.start;
457
458                 /* Get mdio node */
459                 mdio_node = ofnode_get_parent(phandle.node);
460
461                 if (ofnode_read_resource(mdio_node, 0, &res))
462                         return -ENOMEM;
463                 faddr = cpu_to_fdt32(res.start);
464
465                 addr_base = ofnode_translate_address(mdio_node, &faddr);
466                 addr_size = res.end - res.start;
467
468                 /* If the bus is new then create a new bus */
469                 if (!get_mdiobus(addr_base, addr_size))
470                         priv->bus[miim_count] =
471                                 mscc_mdiobus_init(miim, &miim_count, addr_base,
472                                                   addr_size);
473
474                 /* Connect mdio bus with the port */
475                 bus = get_mdiobus(addr_base, addr_size);
476                 add_port_entry(priv, i, phy_addr, bus);
477         }
478
479         mscc_phy_reset();
480
481         for (i = 0; i < MAX_PORT; i++) {
482                 if (!priv->ports[i].bus)
483                         continue;
484
485                 phy_connect(priv->ports[i].bus, priv->ports[i].phy_addr, dev,
486                             PHY_INTERFACE_MODE_NONE);
487         }
488
489         return 0;
490 }
491
492 static int servalt_remove(struct udevice *dev)
493 {
494         struct servalt_private *priv = dev_get_priv(dev);
495         int i;
496
497         for (i = 0; i < SERVALT_MIIM_BUS_COUNT; i++) {
498                 mdio_unregister(priv->bus[i]);
499                 mdio_free(priv->bus[i]);
500         }
501
502         return 0;
503 }
504
505 static const struct eth_ops servalt_ops = {
506         .start        = servalt_start,
507         .stop         = servalt_stop,
508         .send         = servalt_send,
509         .recv         = servalt_recv,
510         .write_hwaddr = servalt_write_hwaddr,
511 };
512
513 static const struct udevice_id mscc_servalt_ids[] = {
514         {.compatible = "mscc,vsc7437-switch" },
515         { /* Sentinel */ }
516 };
517
518 U_BOOT_DRIVER(servalt) = {
519         .name                           = "servalt-switch",
520         .id                             = UCLASS_ETH,
521         .of_match                       = mscc_servalt_ids,
522         .probe                          = servalt_probe,
523         .remove                         = servalt_remove,
524         .ops                            = &servalt_ops,
525         .priv_auto_alloc_size           = sizeof(struct servalt_private),
526         .platdata_auto_alloc_size       = sizeof(struct eth_pdata),
527 };