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