drivers/net/vsc9953: Add default configuration for VSC9953 L2 Switch
[oweals/u-boot.git] / drivers / net / vsc9953.c
1 /*
2  *  Copyright 2014 Freescale Semiconductor, Inc.
3  *
4  *  SPDX-License-Identifier:      GPL-2.0+
5  *
6  *  Driver for the Vitesse VSC9953 L2 Switch
7  */
8
9 #include <asm/io.h>
10 #include <asm/fsl_serdes.h>
11 #include <fm_eth.h>
12 #include <fsl_memac.h>
13 #include <bitfield.h>
14 #include <errno.h>
15 #include <malloc.h>
16 #include <vsc9953.h>
17
18 static struct vsc9953_info vsc9953_l2sw = {
19                 .port[0] = VSC9953_PORT_INFO_INITIALIZER(0),
20                 .port[1] = VSC9953_PORT_INFO_INITIALIZER(1),
21                 .port[2] = VSC9953_PORT_INFO_INITIALIZER(2),
22                 .port[3] = VSC9953_PORT_INFO_INITIALIZER(3),
23                 .port[4] = VSC9953_PORT_INFO_INITIALIZER(4),
24                 .port[5] = VSC9953_PORT_INFO_INITIALIZER(5),
25                 .port[6] = VSC9953_PORT_INFO_INITIALIZER(6),
26                 .port[7] = VSC9953_PORT_INFO_INITIALIZER(7),
27                 .port[8] = VSC9953_PORT_INFO_INITIALIZER(8),
28                 .port[9] = VSC9953_PORT_INFO_INITIALIZER(9),
29 };
30
31 void vsc9953_port_info_set_mdio(int port_no, struct mii_dev *bus)
32 {
33         if (!VSC9953_PORT_CHECK(port_no))
34                 return;
35
36         vsc9953_l2sw.port[port_no].bus = bus;
37 }
38
39 void vsc9953_port_info_set_phy_address(int port_no, int address)
40 {
41         if (!VSC9953_PORT_CHECK(port_no))
42                 return;
43
44         vsc9953_l2sw.port[port_no].phyaddr = address;
45 }
46
47 void vsc9953_port_info_set_phy_int(int port_no, phy_interface_t phy_int)
48 {
49         if (!VSC9953_PORT_CHECK(port_no))
50                 return;
51
52         vsc9953_l2sw.port[port_no].enet_if = phy_int;
53 }
54
55 void vsc9953_port_enable(int port_no)
56 {
57         if (!VSC9953_PORT_CHECK(port_no))
58                 return;
59
60         vsc9953_l2sw.port[port_no].enabled = 1;
61 }
62
63 void vsc9953_port_disable(int port_no)
64 {
65         if (!VSC9953_PORT_CHECK(port_no))
66                 return;
67
68         vsc9953_l2sw.port[port_no].enabled = 0;
69 }
70
71 static void vsc9953_mdio_write(struct vsc9953_mii_mng *phyregs, int port_addr,
72                 int regnum, int value)
73 {
74         int timeout = 50000;
75
76         out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
77                         ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
78                         (0x1 << 1));
79         asm("sync");
80
81         while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
82                 udelay(1);
83
84         if (timeout == 0)
85                 debug("Timeout waiting for MDIO write\n");
86 }
87
88 static int vsc9953_mdio_read(struct vsc9953_mii_mng *phyregs, int port_addr,
89                 int regnum)
90 {
91         int value = 0xFFFF;
92         int timeout = 50000;
93
94         while ((in_le32(&phyregs->miimstatus) & MIIMIND_OPR_PEND) && --timeout)
95                 udelay(1);
96         if (timeout == 0) {
97                 debug("Timeout waiting for MDIO operation to finish\n");
98                 return value;
99         }
100
101         /* Put the address of the phy, and the register
102          * number into MIICMD
103          */
104         out_le32(&phyregs->miimcmd, (0x1 << 31) | ((port_addr & 0x1f) << 25) |
105                         ((regnum & 0x1f) << 20) | ((value & 0xffff) << 4) |
106                         (0x2 << 1));
107
108         timeout = 50000;
109         /* Wait for the the indication that the read is done */
110         while ((in_le32(&phyregs->miimstatus) & 0x8) && --timeout)
111                 udelay(1);
112         if (timeout == 0)
113                 debug("Timeout waiting for MDIO read\n");
114
115         /* Grab the value read from the PHY */
116         value = in_le32(&phyregs->miimdata);
117
118         if ((value & 0x00030000) == 0)
119                 return value & 0x0000ffff;
120
121         return value;
122 }
123
124 static int init_phy(struct eth_device *dev)
125 {
126         struct vsc9953_port_info *l2sw_port = dev->priv;
127         struct phy_device *phydev = NULL;
128
129 #ifdef CONFIG_PHYLIB
130         if (!l2sw_port->bus)
131                 return 0;
132         phydev = phy_connect(l2sw_port->bus, l2sw_port->phyaddr, dev,
133                         l2sw_port->enet_if);
134         if (!phydev) {
135                 printf("Failed to connect\n");
136                 return -1;
137         }
138
139         phydev->supported &= SUPPORTED_10baseT_Half |
140                         SUPPORTED_10baseT_Full |
141                         SUPPORTED_100baseT_Half |
142                         SUPPORTED_100baseT_Full |
143                         SUPPORTED_1000baseT_Full;
144         phydev->advertising = phydev->supported;
145
146         l2sw_port->phydev = phydev;
147
148         phy_config(phydev);
149 #endif
150
151         return 0;
152 }
153
154 static int vsc9953_port_init(int port_no)
155 {
156         struct eth_device *dev;
157
158         /* Internal ports never have a PHY */
159         if (VSC9953_INTERNAL_PORT_CHECK(port_no))
160                 return 0;
161
162         /* alloc eth device */
163         dev = (struct eth_device *)calloc(1, sizeof(struct eth_device));
164         if (!dev)
165                 return -ENOMEM;
166
167         sprintf(dev->name, "SW@PORT%d", port_no);
168         dev->priv = &vsc9953_l2sw.port[port_no];
169         dev->init = NULL;
170         dev->halt = NULL;
171         dev->send = NULL;
172         dev->recv = NULL;
173
174         if (init_phy(dev)) {
175                 free(dev);
176                 return -ENODEV;
177         }
178
179         return 0;
180 }
181
182 static int vsc9953_vlan_table_poll_idle(void)
183 {
184         struct vsc9953_analyzer *l2ana_reg;
185         int timeout;
186
187         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
188                         VSC9953_ANA_OFFSET);
189
190         timeout = 50000;
191         while (((in_le32(&l2ana_reg->ana_tables.vlan_access) &
192                  VSC9953_VLAN_CMD_MASK) != VSC9953_VLAN_CMD_IDLE) && --timeout)
193                 udelay(1);
194
195         return timeout ? 0 : -EBUSY;
196 }
197
198 /* vlan table set/clear all membership of vid */
199 static void vsc9953_vlan_table_membership_all_set(int vid, int set_member)
200 {
201         uint val;
202         struct vsc9953_analyzer *l2ana_reg;
203
204         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
205                         VSC9953_ANA_OFFSET);
206
207         if (vsc9953_vlan_table_poll_idle() < 0) {
208                 debug("VLAN table timeout\n");
209                 return;
210         }
211
212         /* read current vlan configuration */
213         val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
214         out_le32(&l2ana_reg->ana_tables.vlan_tidx,
215                  bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
216
217         clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
218                         VSC9953_VLAN_CMD_MASK, VSC9953_VLAN_CMD_READ);
219
220         if (vsc9953_vlan_table_poll_idle() < 0) {
221                 debug("VLAN table timeout\n");
222                 return;
223         }
224
225         val = in_le32(&l2ana_reg->ana_tables.vlan_tidx);
226         out_le32(&l2ana_reg->ana_tables.vlan_tidx,
227                  bitfield_replace_by_mask(val, VSC9953_ANA_TBL_VID_MASK, vid));
228
229         clrsetbits_le32(&l2ana_reg->ana_tables.vlan_access,
230                         VSC9953_VLAN_PORT_MASK | VSC9953_VLAN_CMD_MASK,
231                         VSC9953_VLAN_CMD_WRITE |
232                         (set_member ? VSC9953_VLAN_PORT_MASK : 0));
233 }
234
235 /* Set PVID for a VSC9953 port */
236 static void vsc9953_port_vlan_pvid_set(int port_no, int pvid)
237 {
238         uint val;
239         struct vsc9953_analyzer *l2ana_reg;
240         struct vsc9953_rew_reg *l2rew_reg;
241
242         /* Administrative down */
243         if (!vsc9953_l2sw.port[port_no].enabled) {
244                 printf("Port %d is administrative down\n", port_no);
245                 return;
246         }
247
248         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
249                         VSC9953_ANA_OFFSET);
250         l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
251                         VSC9953_REW_OFFSET);
252
253         /* Set PVID on ingress */
254         val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
255         val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_VID_MASK, pvid);
256         out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
257
258         /* Set PVID on egress */
259         val = in_le32(&l2rew_reg->port[port_no].port_vlan_cfg);
260         val = bitfield_replace_by_mask(val, VSC9953_PORT_VLAN_CFG_VID_MASK,
261                                        pvid);
262         out_le32(&l2rew_reg->port[port_no].port_vlan_cfg, val);
263 }
264
265 static void vsc9953_port_all_vlan_pvid_set(int pvid)
266 {
267         int i;
268
269         for (i = 0; i < VSC9953_MAX_PORTS; i++)
270                 vsc9953_port_vlan_pvid_set(i, pvid);
271 }
272
273 /* Enable/disable vlan aware of a VSC9953 port */
274 static void vsc9953_port_vlan_aware_set(int port_no, int enabled)
275 {
276         struct vsc9953_analyzer *l2ana_reg;
277
278         /* Administrative down */
279         if (!vsc9953_l2sw.port[port_no].enabled) {
280                 printf("Port %d is administrative down\n", port_no);
281                 return;
282         }
283
284         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
285                         VSC9953_ANA_OFFSET);
286
287         if (enabled)
288                 setbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
289                              VSC9953_VLAN_CFG_AWARE_ENA);
290         else
291                 clrbits_le32(&l2ana_reg->port[port_no].vlan_cfg,
292                              VSC9953_VLAN_CFG_AWARE_ENA);
293 }
294
295 /* Set all VSC9953 ports' vlan aware  */
296 static void vsc9953_port_all_vlan_aware_set(int enabled)
297 {
298         int i;
299
300         for (i = 0; i < VSC9953_MAX_PORTS; i++)
301                 vsc9953_port_vlan_aware_set(i, enabled);
302 }
303
304 /* Enable/disable vlan pop count of a VSC9953 port */
305 static void vsc9953_port_vlan_popcnt_set(int port_no, int popcnt)
306 {
307         uint val;
308         struct vsc9953_analyzer *l2ana_reg;
309
310         /* Administrative down */
311         if (!vsc9953_l2sw.port[port_no].enabled) {
312                 printf("Port %d is administrative down\n", port_no);
313                 return;
314         }
315
316         if (popcnt > 3 || popcnt < 0) {
317                 printf("Invalid pop count value: %d\n", port_no);
318                 return;
319         }
320
321         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
322                         VSC9953_ANA_OFFSET);
323
324         val = in_le32(&l2ana_reg->port[port_no].vlan_cfg);
325         val = bitfield_replace_by_mask(val, VSC9953_VLAN_CFG_POP_CNT_MASK,
326                                        popcnt);
327         out_le32(&l2ana_reg->port[port_no].vlan_cfg, val);
328 }
329
330 /* Set all VSC9953 ports' pop count  */
331 static void vsc9953_port_all_vlan_poncnt_set(int popcnt)
332 {
333         int i;
334
335         for (i = 0; i < VSC9953_MAX_PORTS; i++)
336                 vsc9953_port_vlan_popcnt_set(i, popcnt);
337 }
338
339 /* Enable/disable learning for frames dropped due to ingress filtering */
340 static void vsc9953_vlan_ingr_fltr_learn_drop(int enable)
341 {
342         struct vsc9953_analyzer *l2ana_reg;
343
344         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
345                         VSC9953_ANA_OFFSET);
346
347         if (enable)
348                 setbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
349         else
350                 clrbits_le32(&l2ana_reg->ana.adv_learn, VSC9953_VLAN_CHK);
351 }
352
353 /* Egress untag modes of a VSC9953 port */
354 enum egress_untag_mode {
355         EGRESS_UNTAG_ALL = 0,
356         EGRESS_UNTAG_PVID_AND_ZERO,
357         EGRESS_UNTAG_ZERO,
358         EGRESS_UNTAG_NONE,
359 };
360
361 static void vsc9953_port_vlan_egr_untag_set(int port_no,
362                                             enum egress_untag_mode mode)
363 {
364         struct vsc9953_rew_reg *l2rew_reg;
365
366         /* Administrative down */
367         if (!vsc9953_l2sw.port[port_no].enabled) {
368                 printf("Port %d is administrative down\n", port_no);
369                 return;
370         }
371
372         l2rew_reg = (struct vsc9953_rew_reg *)(VSC9953_OFFSET +
373                         VSC9953_REW_OFFSET);
374
375         switch (mode) {
376         case EGRESS_UNTAG_ALL:
377                 clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
378                                 VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_NONE);
379                 break;
380         case EGRESS_UNTAG_PVID_AND_ZERO:
381                 clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
382                                 VSC9953_TAG_CFG_MASK,
383                                 VSC9953_TAG_CFG_ALL_BUT_PVID_ZERO);
384                 break;
385         case EGRESS_UNTAG_ZERO:
386                 clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
387                                 VSC9953_TAG_CFG_MASK,
388                                 VSC9953_TAG_CFG_ALL_BUT_ZERO);
389                 break;
390         case EGRESS_UNTAG_NONE:
391                 clrsetbits_le32(&l2rew_reg->port[port_no].port_tag_cfg,
392                                 VSC9953_TAG_CFG_MASK, VSC9953_TAG_CFG_ALL);
393                 break;
394         default:
395                 printf("Unknown untag mode for port %d\n", port_no);
396         }
397 }
398
399 static void vsc9953_port_all_vlan_egress_untagged_set(
400                 enum egress_untag_mode mode)
401 {
402         int i;
403
404         for (i = 0; i < VSC9953_MAX_PORTS; i++)
405                 vsc9953_port_vlan_egr_untag_set(i, mode);
406 }
407
408 /*****************************************************************************
409 At startup, the default configuration would be:
410         - HW learning enabled on all ports; (HW default)
411         - All ports are in VLAN 1;
412         - All ports are VLAN aware;
413         - All ports have POP_COUNT 1;
414         - All ports have PVID 1;
415         - All ports have TPID 0x8100; (HW default)
416         - All ports tag frames classified to all VLANs that are not PVID;
417 *****************************************************************************/
418 void vsc9953_default_configuration(void)
419 {
420         int i;
421
422         for (i = 0; i < VSC9953_MAX_VLAN; i++)
423                 vsc9953_vlan_table_membership_all_set(i, 0);
424         vsc9953_port_all_vlan_aware_set(1);
425         vsc9953_port_all_vlan_pvid_set(1);
426         vsc9953_port_all_vlan_poncnt_set(1);
427         vsc9953_vlan_table_membership_all_set(1, 1);
428         vsc9953_vlan_ingr_fltr_learn_drop(1);
429         vsc9953_port_all_vlan_egress_untagged_set(EGRESS_UNTAG_PVID_AND_ZERO);
430 }
431
432 void vsc9953_init(bd_t *bis)
433 {
434         u32 i;
435         u32 hdx_cfg = 0;
436         u32 phy_addr = 0;
437         int timeout;
438         struct vsc9953_system_reg *l2sys_reg;
439         struct vsc9953_qsys_reg *l2qsys_reg;
440         struct vsc9953_dev_gmii *l2dev_gmii_reg;
441         struct vsc9953_analyzer *l2ana_reg;
442         struct vsc9953_devcpu_gcb *l2dev_gcb;
443
444         l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(VSC9953_OFFSET +
445                         VSC9953_DEV_GMII_OFFSET);
446
447         l2ana_reg = (struct vsc9953_analyzer *)(VSC9953_OFFSET +
448                         VSC9953_ANA_OFFSET);
449
450         l2sys_reg = (struct vsc9953_system_reg *)(VSC9953_OFFSET +
451                         VSC9953_SYS_OFFSET);
452
453         l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
454                         VSC9953_QSYS_OFFSET);
455
456         l2dev_gcb = (struct vsc9953_devcpu_gcb *)(VSC9953_OFFSET +
457                         VSC9953_DEVCPU_GCB);
458
459         out_le32(&l2dev_gcb->chip_regs.soft_rst,
460                  VSC9953_SOFT_SWC_RST_ENA);
461         timeout = 50000;
462         while ((in_le32(&l2dev_gcb->chip_regs.soft_rst) &
463                         VSC9953_SOFT_SWC_RST_ENA) && --timeout)
464                 udelay(1); /* busy wait for vsc9953 soft reset */
465         if (timeout == 0)
466                 debug("Timeout waiting for VSC9953 to reset\n");
467
468         out_le32(&l2sys_reg->sys.reset_cfg, VSC9953_MEM_ENABLE |
469                  VSC9953_MEM_INIT);
470
471         timeout = 50000;
472         while ((in_le32(&l2sys_reg->sys.reset_cfg) &
473                 VSC9953_MEM_INIT) && --timeout)
474                 udelay(1); /* busy wait for vsc9953 memory init */
475         if (timeout == 0)
476                 debug("Timeout waiting for VSC9953 memory to initialize\n");
477
478         out_le32(&l2sys_reg->sys.reset_cfg, (in_le32(&l2sys_reg->sys.reset_cfg)
479                         | VSC9953_CORE_ENABLE));
480
481         /* VSC9953 Setting to be done once only */
482         out_le32(&l2qsys_reg->sys.ext_cpu_cfg, 0x00000b00);
483
484         for (i = 0; i < VSC9953_MAX_PORTS; i++) {
485                 if (vsc9953_port_init(i))
486                         printf("Failed to initialize l2switch port %d\n", i);
487
488                 /* Enable VSC9953 GMII Ports Port ID 0 - 7 */
489                 if (VSC9953_INTERNAL_PORT_CHECK(i)) {
490                         out_le32(&l2ana_reg->pfc[i].pfc_cfg,
491                                  VSC9953_PFC_FC_QSGMII);
492                         out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
493                                  VSC9953_MAC_FC_CFG_QSGMII);
494                 } else {
495                         out_le32(&l2ana_reg->pfc[i].pfc_cfg,
496                                  VSC9953_PFC_FC);
497                         out_le32(&l2sys_reg->pause_cfg.mac_fc_cfg[i],
498                                  VSC9953_MAC_FC_CFG);
499                 }
500                 out_le32(&l2dev_gmii_reg->port_mode.clock_cfg,
501                          VSC9953_CLOCK_CFG);
502                 out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ena_cfg,
503                          VSC9953_MAC_ENA_CFG);
504                 out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_mode_cfg,
505                          VSC9953_MAC_MODE_CFG);
506                 out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_ifg_cfg,
507                          VSC9953_MAC_IFG_CFG);
508                 /* mac_hdx_cfg varies with port id*/
509                 hdx_cfg = VSC9953_MAC_HDX_CFG | (i << 16);
510                 out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_hdx_cfg, hdx_cfg);
511                 out_le32(&l2sys_reg->sys.front_port_mode[i],
512                          VSC9953_FRONT_PORT_MODE);
513                 setbits_le32(&l2qsys_reg->sys.switch_port_mode[i],
514                              VSC9953_PORT_ENA);
515                 out_le32(&l2dev_gmii_reg->mac_cfg_status.mac_maxlen_cfg,
516                          VSC9953_MAC_MAX_LEN);
517                 out_le32(&l2sys_reg->pause_cfg.pause_cfg[i],
518                          VSC9953_PAUSE_CFG);
519                 /* WAIT FOR 2 us*/
520                 udelay(2);
521
522                 l2dev_gmii_reg = (struct vsc9953_dev_gmii *)(
523                                 (char *)l2dev_gmii_reg
524                                 + T1040_SWITCH_GMII_DEV_OFFSET);
525
526                 /* Initialize Lynx PHY Wrappers */
527                 phy_addr = 0;
528                 if (vsc9953_l2sw.port[i].enet_if ==
529                                 PHY_INTERFACE_MODE_QSGMII)
530                         phy_addr = (i + 0x4) & 0x1F;
531                 else if (vsc9953_l2sw.port[i].enet_if ==
532                                 PHY_INTERFACE_MODE_SGMII)
533                         phy_addr = (i + 1) & 0x1F;
534
535                 if (phy_addr) {
536                         /* SGMII IF mode + AN enable */
537                         vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
538                                            0x14, PHY_SGMII_IF_MODE_AN |
539                                            PHY_SGMII_IF_MODE_SGMII);
540                         /* Dev ability according to SGMII specification */
541                         vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
542                                            0x4, PHY_SGMII_DEV_ABILITY_SGMII);
543                         /* Adjust link timer for SGMII
544                          * 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40
545                          */
546                         vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
547                                            0x13, 0x0003);
548                         vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
549                                            0x12, 0x0d40);
550                         /* Restart AN */
551                         vsc9953_mdio_write(&l2dev_gcb->mii_mng[0], phy_addr,
552                                            0x0, PHY_SGMII_CR_DEF_VAL |
553                                            PHY_SGMII_CR_RESET_AN);
554
555                         timeout = 50000;
556                         while ((vsc9953_mdio_read(&l2dev_gcb->mii_mng[0],
557                                         phy_addr, 0x01) & 0x0020) && --timeout)
558                                 udelay(1); /* wait for AN to complete */
559                         if (timeout == 0)
560                                 debug("Timeout waiting for AN to complete\n");
561                 }
562         }
563
564         vsc9953_default_configuration();
565
566         printf("VSC9953 L2 switch initialized\n");
567         return;
568 }
569
570 #ifdef CONFIG_VSC9953_CMD
571 /* Enable/disable status of a VSC9953 port */
572 static void vsc9953_port_status_set(int port_no, u8 enabled)
573 {
574         struct vsc9953_qsys_reg *l2qsys_reg;
575
576         /* Administrative down */
577         if (!vsc9953_l2sw.port[port_no].enabled)
578                 return;
579
580         l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
581                         VSC9953_QSYS_OFFSET);
582
583         if (enabled)
584                 setbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
585                              VSC9953_PORT_ENA);
586         else
587                 clrbits_le32(&l2qsys_reg->sys.switch_port_mode[port_no],
588                              VSC9953_PORT_ENA);
589 }
590
591 /* Set all VSC9953 ports' status */
592 static void vsc9953_port_all_status_set(u8 enabled)
593 {
594         int i;
595
596         for (i = 0; i < VSC9953_MAX_PORTS; i++)
597                 vsc9953_port_status_set(i, enabled);
598 }
599
600 /* Start autonegotiation for a VSC9953 PHY */
601 static void vsc9953_phy_autoneg(int port_no)
602 {
603         if (!vsc9953_l2sw.port[port_no].phydev)
604                 return;
605
606         if (vsc9953_l2sw.port[port_no].phydev->drv->startup(
607                         vsc9953_l2sw.port[port_no].phydev))
608                 printf("Failed to start PHY for port %d\n", port_no);
609 }
610
611 /* Start autonegotiation for all VSC9953 PHYs */
612 static void vsc9953_phy_all_autoneg(void)
613 {
614         int i;
615
616         for (i = 0; i < VSC9953_MAX_PORTS; i++)
617                 vsc9953_phy_autoneg(i);
618 }
619
620 /* Print a VSC9953 port's configuration */
621 static void vsc9953_port_config_show(int port_no)
622 {
623         int speed;
624         int duplex;
625         int link;
626         u8 enabled;
627         u32 val;
628         struct vsc9953_qsys_reg *l2qsys_reg;
629
630         l2qsys_reg = (struct vsc9953_qsys_reg *)(VSC9953_OFFSET +
631                         VSC9953_QSYS_OFFSET);
632
633         val = in_le32(&l2qsys_reg->sys.switch_port_mode[port_no]);
634         enabled = vsc9953_l2sw.port[port_no].enabled &&
635                   (val & VSC9953_PORT_ENA);
636
637         /* internal ports (8 and 9) are fixed */
638         if (VSC9953_INTERNAL_PORT_CHECK(port_no)) {
639                 link = 1;
640                 speed = SPEED_2500;
641                 duplex = DUPLEX_FULL;
642         } else {
643                 if (vsc9953_l2sw.port[port_no].phydev) {
644                         link = vsc9953_l2sw.port[port_no].phydev->link;
645                         speed = vsc9953_l2sw.port[port_no].phydev->speed;
646                         duplex = vsc9953_l2sw.port[port_no].phydev->duplex;
647                 } else {
648                         link = -1;
649                         speed = -1;
650                         duplex = -1;
651                 }
652         }
653
654         printf("%8d ", port_no);
655         printf("%8s ", enabled == 1 ? "enabled" : "disabled");
656         printf("%8s ", link == 1 ? "up" : "down");
657
658         switch (speed) {
659         case SPEED_10:
660                 printf("%8d ", 10);
661                 break;
662         case SPEED_100:
663                 printf("%8d ", 100);
664                 break;
665         case SPEED_1000:
666                 printf("%8d ", 1000);
667                 break;
668         case SPEED_2500:
669                 printf("%8d ", 2500);
670                 break;
671         case SPEED_10000:
672                 printf("%8d ", 10000);
673                 break;
674         default:
675                 printf("%8s ", "-");
676         }
677
678         printf("%8s\n", duplex == DUPLEX_FULL ? "full" : "half");
679 }
680
681 /* Print VSC9953 ports' configuration */
682 static void vsc9953_port_all_config_show(void)
683 {
684         int i;
685
686         for (i = 0; i < VSC9953_MAX_PORTS; i++)
687                 vsc9953_port_config_show(i);
688 }
689
690 /* function to interpret commands starting with "ethsw " */
691 static int do_ethsw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
692 {
693         u8 enable;
694         u32 port;
695
696         if (argc < 4)
697                 return -1;
698
699         if (strcmp(argv[1], "port"))
700                 return -1;
701
702         if (!strcmp(argv[3], "show")) {
703                 if (!strcmp(argv[2], "all")) {
704                         vsc9953_phy_all_autoneg();
705                         printf("%8s %8s %8s %8s %8s\n",
706                                "Port", "Status", "Link", "Speed",
707                                "Duplex");
708                         vsc9953_port_all_config_show();
709                         return 0;
710                 } else {
711                         port = simple_strtoul(argv[2], NULL, 10);
712                         if (!VSC9953_PORT_CHECK(port))
713                                 return -1;
714                         vsc9953_phy_autoneg(port);
715                         printf("%8s %8s %8s %8s %8s\n",
716                                "Port", "Status", "Link", "Speed",
717                                "Duplex");
718                         vsc9953_port_config_show(port);
719                         return 0;
720                 }
721         } else if (!strcmp(argv[3], "enable")) {
722                 enable = 1;
723         } else if (!strcmp(argv[3], "disable")) {
724                 enable = 0;
725         } else {
726                 return -1;
727         }
728
729         if (!strcmp(argv[2], "all")) {
730                 vsc9953_port_all_status_set(enable);
731                 return 0;
732         } else {
733                 port = simple_strtoul(argv[2], NULL, 10);
734                 if (!VSC9953_PORT_CHECK(port))
735                         return -1;
736                 vsc9953_port_status_set(port, enable);
737                 return 0;
738         }
739
740         return -1;
741 }
742
743 U_BOOT_CMD(ethsw, 5, 0, do_ethsw,
744            "vsc9953 l2 switch commands",
745            "port <port_no> enable|disable\n"
746            "    - enable/disable an l2 switch port\n"
747            "      port_no=0..9; use \"all\" for all ports\n"
748            "ethsw port <port_no> show\n"
749            "    - show an l2 switch port's configuration\n"
750            "      port_no=0..9; use \"all\" for all ports\n"
751 );
752 #endif /* CONFIG_VSC9953_CMD */