]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/etherswitch/mtkswitch/mtkswitch_mt7620.c
MFV r330102: ntp 4.2.8p11
[FreeBSD/FreeBSD.git] / sys / dev / etherswitch / mtkswitch / mtkswitch_mt7620.c
1 /*-
2  * Copyright (c) 2016 Stanislav Galabov.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #include <sys/param.h>
30 #include <sys/bus.h>
31 #include <sys/errno.h>
32 #include <sys/kernel.h>
33 #include <sys/lock.h>
34 #include <sys/malloc.h>
35 #include <sys/module.h>
36 #include <sys/mutex.h>
37 #include <sys/rman.h>
38 #include <sys/socket.h>
39 #include <sys/sockio.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
42
43 #include <net/if.h>
44 #include <net/if_var.h>
45 #include <net/ethernet.h>
46 #include <net/if_media.h>
47 #include <net/if_types.h>
48
49 #include <machine/bus.h>
50 #include <dev/mii/mii.h>
51 #include <dev/mii/miivar.h>
52 #include <dev/mdio/mdio.h>
53
54 #include <dev/etherswitch/etherswitch.h>
55 #include <dev/etherswitch/mtkswitch/mtkswitchvar.h>
56 #include <dev/etherswitch/mtkswitch/mtkswitch_mt7620.h>
57
58 static int
59 mtkswitch_phy_read_locked(struct mtkswitch_softc *sc, int phy, int reg)
60 {
61         uint32_t data;
62         
63         MTKSWITCH_WRITE(sc, MTKSWITCH_PIAC, PIAC_PHY_ACS_ST | PIAC_MDIO_ST |
64             (reg << PIAC_MDIO_REG_ADDR_OFF) | (phy << PIAC_MDIO_PHY_ADDR_OFF) |
65             PIAC_MDIO_CMD_READ);
66         while ((data = MTKSWITCH_READ(sc, MTKSWITCH_PIAC)) & PIAC_PHY_ACS_ST);
67         
68         return ((int)(data & PIAC_MDIO_RW_DATA_MASK));
69 }
70
71 static int
72 mtkswitch_phy_read(device_t dev, int phy, int reg)
73 {
74         struct mtkswitch_softc *sc = device_get_softc(dev);
75         int data;
76
77         if ((phy < 0 || phy >= 32) || (reg < 0 || reg >= 32))
78                 return (ENXIO);
79
80         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
81         MTKSWITCH_LOCK(sc);
82         data = mtkswitch_phy_read_locked(sc, phy, reg);
83         MTKSWITCH_UNLOCK(sc);
84
85         return (data);
86 }
87
88 static int
89 mtkswitch_phy_write_locked(struct mtkswitch_softc *sc, int phy, int reg,
90     int val)
91 {
92
93         MTKSWITCH_WRITE(sc, MTKSWITCH_PIAC, PIAC_PHY_ACS_ST | PIAC_MDIO_ST |
94             (reg << PIAC_MDIO_REG_ADDR_OFF) | (phy << PIAC_MDIO_PHY_ADDR_OFF) |
95             (val & PIAC_MDIO_RW_DATA_MASK) | PIAC_MDIO_CMD_WRITE);
96         while (MTKSWITCH_READ(sc, MTKSWITCH_PIAC) & PIAC_PHY_ACS_ST);
97
98         return (0);
99 }
100
101 static int
102 mtkswitch_phy_write(device_t dev, int phy, int reg, int val)
103 {
104         struct mtkswitch_softc *sc = device_get_softc(dev);
105         int res;
106
107         if ((phy < 0 || phy >= 32) || (reg < 0 || reg >= 32))
108                 return (ENXIO);
109
110         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
111         MTKSWITCH_LOCK(sc);
112         res = mtkswitch_phy_write_locked(sc, phy, reg, val);
113         MTKSWITCH_UNLOCK(sc);
114
115         return (res);
116 }
117
118 static uint32_t
119 mtkswitch_reg_read32(struct mtkswitch_softc *sc, int reg)
120 {
121
122         return (MTKSWITCH_READ(sc, reg));
123 }
124
125 static uint32_t
126 mtkswitch_reg_write32(struct mtkswitch_softc *sc, int reg, uint32_t val)
127 {
128
129         MTKSWITCH_WRITE(sc, reg, val);
130         return (0);
131 }
132
133 static uint32_t
134 mtkswitch_reg_read32_mt7621(struct mtkswitch_softc *sc, int reg)
135 {
136         uint32_t low, hi;
137
138         mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
139             MTKSWITCH_GLOBAL_REG, MTKSWITCH_REG_ADDR(reg));
140         low = mtkswitch_phy_read_locked(sc, MTKSWITCH_GLOBAL_PHY,
141             MTKSWITCH_REG_LO(reg));
142         hi = mtkswitch_phy_read_locked(sc, MTKSWITCH_GLOBAL_PHY,
143             MTKSWITCH_REG_HI(reg));;
144         return (low | (hi << 16));
145 }
146
147 static uint32_t
148 mtkswitch_reg_write32_mt7621(struct mtkswitch_softc *sc, int reg, uint32_t val)
149 {
150
151         mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
152             MTKSWITCH_GLOBAL_REG, MTKSWITCH_REG_ADDR(reg));
153         mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
154             MTKSWITCH_REG_LO(reg), MTKSWITCH_VAL_LO(val));
155         mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY,
156             MTKSWITCH_REG_HI(reg), MTKSWITCH_VAL_HI(val));
157         return (0);
158 }
159
160 static int
161 mtkswitch_reg_read(device_t dev, int reg)
162 {
163         struct mtkswitch_softc *sc = device_get_softc(dev);
164         uint32_t val;
165
166         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_REG32(reg));
167         if (MTKSWITCH_IS_HI16(reg))
168                 return (MTKSWITCH_HI16(val));
169         return (MTKSWITCH_LO16(val));
170 }
171
172 static int
173 mtkswitch_reg_write(device_t dev, int reg, int val)
174 {
175         struct mtkswitch_softc *sc = device_get_softc(dev);
176         uint32_t tmp;
177
178         tmp = sc->hal.mtkswitch_read(sc, MTKSWITCH_REG32(reg));
179         if (MTKSWITCH_IS_HI16(reg)) {
180                 tmp &= MTKSWITCH_LO16_MSK;
181                 tmp |= MTKSWITCH_TO_HI16(val);
182         } else {
183                 tmp &= MTKSWITCH_HI16_MSK;
184                 tmp |= MTKSWITCH_TO_LO16(val);
185         }
186         sc->hal.mtkswitch_write(sc, MTKSWITCH_REG32(reg), tmp);
187
188         return (0);
189 }
190
191 static int
192 mtkswitch_reset(struct mtkswitch_softc *sc)
193 {
194
195         /* We don't reset the switch for now */
196         return (0);
197 }
198
199 static int
200 mtkswitch_hw_setup(struct mtkswitch_softc *sc)
201 {
202
203         /*
204          * TODO: parse the device tree and see if we need to configure
205          *       ports, etc. differently. For now we fallback to defaults.
206          */
207
208         /* Called early and hence unlocked */
209         return (0);
210 }
211
212 static int
213 mtkswitch_hw_global_setup(struct mtkswitch_softc *sc)
214 {
215         /* Currently does nothing */
216
217         /* Called early and hence unlocked */
218         return (0);
219 }
220
221 static void
222 mtkswitch_port_init(struct mtkswitch_softc *sc, int port)
223 {
224         uint32_t val;
225
226         /* Called early and hence unlocked */
227
228         /* Set the port to secure mode */
229         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PCR(port));
230         val |= PCR_PORT_VLAN_SECURE;
231         sc->hal.mtkswitch_write(sc, MTKSWITCH_PCR(port), val);
232
233         /* Set port's vlan_attr to user port */
234         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PVC(port));
235         val &= ~PVC_VLAN_ATTR_MASK;
236         sc->hal.mtkswitch_write(sc, MTKSWITCH_PVC(port), val);
237
238         val = PMCR_CFG_DEFAULT;
239         if (port == sc->cpuport)
240                 val |= PMCR_FORCE_LINK | PMCR_FORCE_DPX | PMCR_FORCE_SPD_1000 |
241                     PMCR_FORCE_MODE;
242         /* Set port's MAC to default settings */
243         sc->hal.mtkswitch_write(sc, MTKSWITCH_PMCR(port), val);
244 }
245
246 static uint32_t
247 mtkswitch_get_port_status(struct mtkswitch_softc *sc, int port)
248 {
249         uint32_t val, res, tmp;
250
251         MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
252         res = 0;
253         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PMSR(port));
254
255         if (val & PMSR_MAC_LINK_STS)
256                 res |= MTKSWITCH_LINK_UP;
257         if (val & PMSR_MAC_DPX_STS)
258                 res |= MTKSWITCH_DUPLEX;
259         tmp = PMSR_MAC_SPD(val);
260         if (tmp == 0)
261                 res |= MTKSWITCH_SPEED_10;
262         else if (tmp == 1)
263                 res |= MTKSWITCH_SPEED_100;
264         else if (tmp == 2)
265                 res |= MTKSWITCH_SPEED_1000;
266         if (val & PMSR_TX_FC_STS)
267                 res |= MTKSWITCH_TXFLOW;
268         if (val & PMSR_RX_FC_STS)
269                 res |= MTKSWITCH_RXFLOW;
270
271         return (res);
272 }
273
274 static int
275 mtkswitch_atu_flush(struct mtkswitch_softc *sc)
276 {
277
278         MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
279
280         /* Flush all non-static MAC addresses */
281         while (sc->hal.mtkswitch_read(sc, MTKSWITCH_ATC) & ATC_BUSY);
282         sc->hal.mtkswitch_write(sc, MTKSWITCH_ATC, ATC_BUSY |
283             ATC_AC_MAT_NON_STATIC_MACS | ATC_AC_CMD_CLEAN);
284         while (sc->hal.mtkswitch_read(sc, MTKSWITCH_ATC) & ATC_BUSY);
285
286         return (0);
287 }
288
289 static int
290 mtkswitch_port_vlan_setup(struct mtkswitch_softc *sc, etherswitch_port_t *p)
291 {
292         int err;
293
294         /*
295          * Port behaviour wrt tag/untag/stack is currently defined per-VLAN.
296          * So we say we don't support it here.
297          */
298         if ((p->es_flags & (ETHERSWITCH_PORT_DOUBLE_TAG |
299             ETHERSWITCH_PORT_ADDTAG | ETHERSWITCH_PORT_STRIPTAG)) != 0)
300                 return (ENOTSUP);
301
302         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
303         MTKSWITCH_LOCK(sc);
304
305         /* Set the PVID */
306         if (p->es_pvid != 0) {
307                 err = sc->hal.mtkswitch_vlan_set_pvid(sc, p->es_port,
308                     p->es_pvid);
309                 if (err != 0) {
310                         MTKSWITCH_UNLOCK(sc);
311                         return (err);
312                 }
313         }
314
315         MTKSWITCH_UNLOCK(sc);
316
317         return (0);
318 }
319
320 static int
321 mtkswitch_port_vlan_get(struct mtkswitch_softc *sc, etherswitch_port_t *p)
322 {
323
324         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
325         MTKSWITCH_LOCK(sc);
326
327         /* Retrieve the PVID */
328         sc->hal.mtkswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid);
329
330         /*
331          * Port flags are not supported at the moment.
332          * Port's tag/untag/stack behaviour is defined per-VLAN.
333          */
334         p->es_flags = 0;
335
336         MTKSWITCH_UNLOCK(sc);
337
338         return (0);
339 }
340
341 static void
342 mtkswitch_invalidate_vlan(struct mtkswitch_softc *sc, uint32_t vid)
343 {
344
345         while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
346         sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY |
347             VTCR_FUNC_VID_INVALID | (vid & VTCR_VID_MASK));
348         while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
349 }
350
351 static void
352 mtkswitch_vlan_init_hw(struct mtkswitch_softc *sc)
353 {
354         uint32_t val, vid, i;
355
356         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
357         MTKSWITCH_LOCK(sc);
358         /* Reset all VLANs to defaults first */
359         for (i = 0; i < sc->info.es_nvlangroups; i++) {
360                 mtkswitch_invalidate_vlan(sc, i);
361                 if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
362                         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTIM(i));
363                         val &= ~(VTIM_MASK << VTIM_OFF(i));
364                         val |= ((i + 1) << VTIM_OFF(i));
365                         sc->hal.mtkswitch_write(sc, MTKSWITCH_VTIM(i), val);
366                 }
367         }
368
369         /* Now, add all ports as untagged members of VLAN 1 */
370         if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
371                 /* MT7620 uses vid index instead of actual vid */
372                 vid = 0;
373         } else {
374                 /* MT7621 uses the vid itself */
375                 vid = 1;
376         }
377         val = VAWD1_IVL_MAC | VAWD1_VTAG_EN | VAWD1_VALID;
378         for (i = 0; i < sc->info.es_nports; i++)
379                 val |= VAWD1_PORT_MEMBER(i);
380         sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD1, val);
381         sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD2, 0);
382         val = VTCR_BUSY | VTCR_FUNC_VID_WRITE | vid;
383         sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, val);
384
385         /* Set all port PVIDs to 1 */
386         for (i = 0; i < sc->info.es_nports; i++) {
387                 sc->hal.mtkswitch_vlan_set_pvid(sc, i, 1);
388         }
389
390         MTKSWITCH_UNLOCK(sc);
391 }
392
393 static int
394 mtkswitch_vlan_getvgroup(struct mtkswitch_softc *sc, etherswitch_vlangroup_t *v)
395 {
396         uint32_t val, i;
397
398         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
399
400         if ((sc->vlan_mode != ETHERSWITCH_VLAN_DOT1Q) ||
401             (v->es_vlangroup > sc->info.es_nvlangroups))
402                 return (EINVAL);
403
404         /* Reset the member ports. */
405         v->es_untagged_ports = 0;
406         v->es_member_ports = 0;
407
408         /* Not supported for now */
409         v->es_fid = 0;
410
411         MTKSWITCH_LOCK(sc);
412         if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
413                 v->es_vid = (sc->hal.mtkswitch_read(sc,
414                     MTKSWITCH_VTIM(v->es_vlangroup)) >>
415                     VTIM_OFF(v->es_vlangroup)) & VTIM_MASK;
416         } else {
417                 v->es_vid = v->es_vlangroup;
418         }
419
420         while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
421         sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY |
422             VTCR_FUNC_VID_READ | (v->es_vlangroup & VTCR_VID_MASK));
423         while ((val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR)) & VTCR_BUSY);
424         if (val & VTCR_IDX_INVALID) {
425                 MTKSWITCH_UNLOCK(sc);
426                 return (0);
427         }
428
429         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VAWD1);
430         if (val & VAWD1_VALID)
431                 v->es_vid |= ETHERSWITCH_VID_VALID;
432         else {
433                 MTKSWITCH_UNLOCK(sc);
434                 return (0);
435         }
436         v->es_member_ports = (val >> VAWD1_MEMBER_OFF) & VAWD1_MEMBER_MASK;
437
438         val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VAWD2);
439         for (i = 0; i < sc->info.es_nports; i++) {
440                 if ((val & VAWD2_PORT_MASK(i)) == VAWD2_PORT_UNTAGGED(i))
441                         v->es_untagged_ports |= (1<<i);
442         }
443
444         MTKSWITCH_UNLOCK(sc);
445         return (0);
446 }
447
448 static int
449 mtkswitch_vlan_setvgroup(struct mtkswitch_softc *sc, etherswitch_vlangroup_t *v)
450 {
451         uint32_t val, i, vid;
452
453         MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED);
454
455         if ((sc->vlan_mode != ETHERSWITCH_VLAN_DOT1Q) ||
456             (v->es_vlangroup > sc->info.es_nvlangroups))
457                 return (EINVAL);
458
459         /* We currently don't support FID */
460         if (v->es_fid != 0)
461                 return (EINVAL);
462
463         MTKSWITCH_LOCK(sc);
464         while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY);
465         if (sc->sc_switchtype == MTK_SWITCH_MT7620) {
466                 val = sc->hal.mtkswitch_read(sc,
467                     MTKSWITCH_VTIM(v->es_vlangroup));
468                 val &= ~(VTIM_MASK << VTIM_OFF(v->es_vlangroup));
469                 val |= ((v->es_vid & VTIM_MASK) << VTIM_OFF(v->es_vlangroup));
470                 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTIM(v->es_vlangroup),
471                     val);
472                 vid = v->es_vlangroup;
473         } else
474                 vid = v->es_vid;
475
476         /* We use FID 0 */
477         val = VAWD1_IVL_MAC | VAWD1_VTAG_EN | VAWD1_VALID;
478         val |= ((v->es_member_ports & VAWD1_MEMBER_MASK) << VAWD1_MEMBER_OFF);
479         sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD1, val);
480
481         /* Set tagged ports */
482         val = 0;
483         for (i = 0; i < sc->info.es_nports; i++)
484                 if (((1<<i) & v->es_untagged_ports) == 0)
485                         val |= VAWD2_PORT_TAGGED(i);
486         sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD2, val);
487
488         /* Write the VLAN entry */
489         sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY |
490             VTCR_FUNC_VID_WRITE | (vid & VTCR_VID_MASK));
491         while ((val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR)) & VTCR_BUSY);
492
493         MTKSWITCH_UNLOCK(sc);
494
495         if (val & VTCR_IDX_INVALID)
496                 return (EINVAL);
497
498         return (0);
499 }
500
501 static int
502 mtkswitch_vlan_get_pvid(struct mtkswitch_softc *sc, int port, int *pvid)
503 {
504
505         MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
506
507         *pvid = sc->hal.mtkswitch_read(sc, MTKSWITCH_PPBV1(port));
508         *pvid = PPBV_VID_FROM_REG(*pvid);
509
510         return (0); 
511 }
512
513 static int
514 mtkswitch_vlan_set_pvid(struct mtkswitch_softc *sc, int port, int pvid)
515 {
516         uint32_t val;
517
518         MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED);
519         val = PPBV_VID(pvid & PPBV_VID_MASK);
520         sc->hal.mtkswitch_write(sc, MTKSWITCH_PPBV1(port), val);
521         sc->hal.mtkswitch_write(sc, MTKSWITCH_PPBV2(port), val);
522
523         return (0);
524 }
525
526 extern void
527 mtk_attach_switch_mt7620(struct mtkswitch_softc *sc)
528 {
529
530         sc->portmap = 0x7f;
531         sc->phymap = 0x1f;
532
533         sc->info.es_nports = 7;
534         sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q;
535         sc->info.es_nvlangroups = 16;
536         sprintf(sc->info.es_name, "Mediatek GSW");
537
538         if (sc->sc_switchtype == MTK_SWITCH_MT7621) {
539                 sc->hal.mtkswitch_read = mtkswitch_reg_read32_mt7621;
540                 sc->hal.mtkswitch_write = mtkswitch_reg_write32_mt7621;
541                 sc->info.es_nvlangroups = 4096;
542         } else {
543                 sc->hal.mtkswitch_read = mtkswitch_reg_read32;
544                 sc->hal.mtkswitch_write = mtkswitch_reg_write32;
545         }
546
547         sc->hal.mtkswitch_reset = mtkswitch_reset;
548         sc->hal.mtkswitch_hw_setup = mtkswitch_hw_setup;
549         sc->hal.mtkswitch_hw_global_setup = mtkswitch_hw_global_setup;
550         sc->hal.mtkswitch_port_init = mtkswitch_port_init;
551         sc->hal.mtkswitch_get_port_status = mtkswitch_get_port_status;
552         sc->hal.mtkswitch_atu_flush = mtkswitch_atu_flush;
553         sc->hal.mtkswitch_port_vlan_setup = mtkswitch_port_vlan_setup;
554         sc->hal.mtkswitch_port_vlan_get = mtkswitch_port_vlan_get;
555         sc->hal.mtkswitch_vlan_init_hw = mtkswitch_vlan_init_hw;
556         sc->hal.mtkswitch_vlan_getvgroup = mtkswitch_vlan_getvgroup;
557         sc->hal.mtkswitch_vlan_setvgroup = mtkswitch_vlan_setvgroup;
558         sc->hal.mtkswitch_vlan_get_pvid = mtkswitch_vlan_get_pvid;
559         sc->hal.mtkswitch_vlan_set_pvid = mtkswitch_vlan_set_pvid;
560         sc->hal.mtkswitch_phy_read = mtkswitch_phy_read;
561         sc->hal.mtkswitch_phy_write = mtkswitch_phy_write;
562         sc->hal.mtkswitch_reg_read = mtkswitch_reg_read;
563         sc->hal.mtkswitch_reg_write = mtkswitch_reg_write;
564 }