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_LOCK_ASSERT(sc, MA_OWNED); 139 mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY, 140 MTKSWITCH_GLOBAL_REG, MTKSWITCH_REG_ADDR(reg)); 141 low = mtkswitch_phy_read_locked(sc, MTKSWITCH_GLOBAL_PHY, 142 MTKSWITCH_REG_LO(reg)); 143 hi = mtkswitch_phy_read_locked(sc, MTKSWITCH_GLOBAL_PHY, 144 MTKSWITCH_REG_HI(reg));; 145 return (low | (hi << 16)); 146 } 147 148 static uint32_t 149 mtkswitch_reg_write32_mt7621(struct mtkswitch_softc *sc, int reg, uint32_t val) 150 { 151 152 MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED); 153 mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY, 154 MTKSWITCH_GLOBAL_REG, MTKSWITCH_REG_ADDR(reg)); 155 mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY, 156 MTKSWITCH_REG_LO(reg), MTKSWITCH_VAL_LO(val)); 157 mtkswitch_phy_write_locked(sc, MTKSWITCH_GLOBAL_PHY, 158 MTKSWITCH_REG_HI(reg), MTKSWITCH_VAL_HI(val)); 159 return (0); 160 } 161 162 static int 163 mtkswitch_reg_read(device_t dev, int reg) 164 { 165 struct mtkswitch_softc *sc = device_get_softc(dev); 166 uint32_t val; 167 168 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_REG32(reg)); 169 if (MTKSWITCH_IS_HI16(reg)) 170 return (MTKSWITCH_HI16(val)); 171 return (MTKSWITCH_LO16(val)); 172 } 173 174 static int 175 mtkswitch_reg_write(device_t dev, int reg, int val) 176 { 177 struct mtkswitch_softc *sc = device_get_softc(dev); 178 uint32_t tmp; 179 180 tmp = sc->hal.mtkswitch_read(sc, MTKSWITCH_REG32(reg)); 181 if (MTKSWITCH_IS_HI16(reg)) { 182 tmp &= MTKSWITCH_LO16_MSK; 183 tmp |= MTKSWITCH_TO_HI16(val); 184 } else { 185 tmp &= MTKSWITCH_HI16_MSK; 186 tmp |= MTKSWITCH_TO_LO16(val); 187 } 188 sc->hal.mtkswitch_write(sc, MTKSWITCH_REG32(reg), tmp); 189 190 return (0); 191 } 192 193 static int 194 mtkswitch_reset(struct mtkswitch_softc *sc) 195 { 196 197 /* We don't reset the switch for now */ 198 return (0); 199 } 200 201 static int 202 mtkswitch_hw_setup(struct mtkswitch_softc *sc) 203 { 204 205 /* 206 * TODO: parse the device tree and see if we need to configure 207 * ports, etc. differently. For now we fallback to defaults. 208 */ 209 210 /* Called early and hence unlocked */ 211 return (0); 212 } 213 214 static int 215 mtkswitch_hw_global_setup(struct mtkswitch_softc *sc) 216 { 217 /* Currently does nothing */ 218 219 /* Called early and hence unlocked */ 220 return (0); 221 } 222 223 static void 224 mtkswitch_port_init(struct mtkswitch_softc *sc, int port) 225 { 226 uint32_t val; 227 228 /* Called early and hence unlocked */ 229 230 /* Set the port to secure mode */ 231 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PCR(port)); 232 val |= PCR_PORT_VLAN_SECURE; 233 sc->hal.mtkswitch_write(sc, MTKSWITCH_PCR(port), val); 234 235 /* Set port's vlan_attr to user port */ 236 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PVC(port)); 237 val &= ~PVC_VLAN_ATTR_MASK; 238 sc->hal.mtkswitch_write(sc, MTKSWITCH_PVC(port), val); 239 240 val = PMCR_CFG_DEFAULT; 241 if (port == sc->cpuport) 242 val |= PMCR_FORCE_LINK | PMCR_FORCE_DPX | PMCR_FORCE_SPD_1000 | 243 PMCR_FORCE_MODE; 244 /* Set port's MAC to default settings */ 245 sc->hal.mtkswitch_write(sc, MTKSWITCH_PMCR(port), val); 246 } 247 248 static uint32_t 249 mtkswitch_get_port_status(struct mtkswitch_softc *sc, int port) 250 { 251 uint32_t val, res, tmp; 252 253 MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED); 254 res = 0; 255 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_PMSR(port)); 256 257 if (val & PMSR_MAC_LINK_STS) 258 res |= MTKSWITCH_LINK_UP; 259 if (val & PMSR_MAC_DPX_STS) 260 res |= MTKSWITCH_DUPLEX; 261 tmp = PMSR_MAC_SPD(val); 262 if (tmp == 0) 263 res |= MTKSWITCH_SPEED_10; 264 else if (tmp == 1) 265 res |= MTKSWITCH_SPEED_100; 266 else if (tmp == 2) 267 res |= MTKSWITCH_SPEED_1000; 268 if (val & PMSR_TX_FC_STS) 269 res |= MTKSWITCH_TXFLOW; 270 if (val & PMSR_RX_FC_STS) 271 res |= MTKSWITCH_RXFLOW; 272 273 return (res); 274 } 275 276 static int 277 mtkswitch_atu_flush(struct mtkswitch_softc *sc) 278 { 279 280 MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED); 281 282 /* Flush all non-static MAC addresses */ 283 while (sc->hal.mtkswitch_read(sc, MTKSWITCH_ATC) & ATC_BUSY); 284 sc->hal.mtkswitch_write(sc, MTKSWITCH_ATC, ATC_BUSY | 285 ATC_AC_MAT_NON_STATIC_MACS | ATC_AC_CMD_CLEAN); 286 while (sc->hal.mtkswitch_read(sc, MTKSWITCH_ATC) & ATC_BUSY); 287 288 return (0); 289 } 290 291 static int 292 mtkswitch_port_vlan_setup(struct mtkswitch_softc *sc, etherswitch_port_t *p) 293 { 294 int err; 295 296 /* 297 * Port behaviour wrt tag/untag/stack is currently defined per-VLAN. 298 * So we say we don't support it here. 299 */ 300 if ((p->es_flags & (ETHERSWITCH_PORT_DOUBLE_TAG | 301 ETHERSWITCH_PORT_ADDTAG | ETHERSWITCH_PORT_STRIPTAG)) != 0) 302 return (ENOTSUP); 303 304 MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 305 MTKSWITCH_LOCK(sc); 306 307 /* Set the PVID */ 308 if (p->es_pvid != 0) { 309 err = sc->hal.mtkswitch_vlan_set_pvid(sc, p->es_port, 310 p->es_pvid); 311 if (err != 0) { 312 MTKSWITCH_UNLOCK(sc); 313 return (err); 314 } 315 } 316 317 MTKSWITCH_UNLOCK(sc); 318 319 return (0); 320 } 321 322 static int 323 mtkswitch_port_vlan_get(struct mtkswitch_softc *sc, etherswitch_port_t *p) 324 { 325 326 MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 327 MTKSWITCH_LOCK(sc); 328 329 /* Retrieve the PVID */ 330 sc->hal.mtkswitch_vlan_get_pvid(sc, p->es_port, &p->es_pvid); 331 332 /* 333 * Port flags are not supported at the moment. 334 * Port's tag/untag/stack behaviour is defined per-VLAN. 335 */ 336 p->es_flags = 0; 337 338 MTKSWITCH_UNLOCK(sc); 339 340 return (0); 341 } 342 343 static void 344 mtkswitch_invalidate_vlan(struct mtkswitch_softc *sc, uint32_t vid) 345 { 346 347 while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY); 348 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY | 349 VTCR_FUNC_VID_INVALID | (vid & VTCR_VID_MASK)); 350 while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY); 351 } 352 353 static void 354 mtkswitch_vlan_init_hw(struct mtkswitch_softc *sc) 355 { 356 uint32_t val, vid, i; 357 358 MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 359 MTKSWITCH_LOCK(sc); 360 /* Reset all VLANs to defaults first */ 361 for (i = 0; i < sc->info.es_nvlangroups; i++) { 362 mtkswitch_invalidate_vlan(sc, i); 363 if (sc->sc_switchtype == MTK_SWITCH_MT7620) { 364 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTIM(i)); 365 val &= ~(VTIM_MASK << VTIM_OFF(i)); 366 val |= ((i + 1) << VTIM_OFF(i)); 367 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTIM(i), val); 368 } 369 } 370 371 /* Now, add all ports as untagged members of VLAN 1 */ 372 if (sc->sc_switchtype == MTK_SWITCH_MT7620) { 373 /* MT7620 uses vid index instead of actual vid */ 374 vid = 0; 375 } else { 376 /* MT7621 uses the vid itself */ 377 vid = 1; 378 } 379 val = VAWD1_IVL_MAC | VAWD1_VTAG_EN | VAWD1_VALID; 380 for (i = 0; i < sc->info.es_nports; i++) 381 val |= VAWD1_PORT_MEMBER(i); 382 sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD1, val); 383 sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD2, 0); 384 val = VTCR_BUSY | VTCR_FUNC_VID_WRITE | vid; 385 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, val); 386 387 /* Set all port PVIDs to 1 */ 388 for (i = 0; i < sc->info.es_nports; i++) { 389 sc->hal.mtkswitch_vlan_set_pvid(sc, i, 1); 390 } 391 392 MTKSWITCH_UNLOCK(sc); 393 } 394 395 static int 396 mtkswitch_vlan_getvgroup(struct mtkswitch_softc *sc, etherswitch_vlangroup_t *v) 397 { 398 uint32_t val, i; 399 400 MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 401 402 if ((sc->vlan_mode != ETHERSWITCH_VLAN_DOT1Q) || 403 (v->es_vlangroup > sc->info.es_nvlangroups)) 404 return (EINVAL); 405 406 /* Reset the member ports. */ 407 v->es_untagged_ports = 0; 408 v->es_member_ports = 0; 409 410 /* Not supported for now */ 411 v->es_fid = 0; 412 413 MTKSWITCH_LOCK(sc); 414 if (sc->sc_switchtype == MTK_SWITCH_MT7620) { 415 v->es_vid = (sc->hal.mtkswitch_read(sc, 416 MTKSWITCH_VTIM(v->es_vlangroup)) >> 417 VTIM_OFF(v->es_vlangroup)) & VTIM_MASK; 418 } else { 419 v->es_vid = v->es_vlangroup; 420 } 421 422 while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY); 423 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY | 424 VTCR_FUNC_VID_READ | (v->es_vlangroup & VTCR_VID_MASK)); 425 while ((val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR)) & VTCR_BUSY); 426 if (val & VTCR_IDX_INVALID) { 427 MTKSWITCH_UNLOCK(sc); 428 return (0); 429 } 430 431 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VAWD1); 432 if (val & VAWD1_VALID) 433 v->es_vid |= ETHERSWITCH_VID_VALID; 434 else { 435 MTKSWITCH_UNLOCK(sc); 436 return (0); 437 } 438 v->es_member_ports = (val >> VAWD1_MEMBER_OFF) & VAWD1_MEMBER_MASK; 439 440 val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VAWD2); 441 for (i = 0; i < sc->info.es_nports; i++) { 442 if ((val & VAWD2_PORT_MASK(i)) == VAWD2_PORT_UNTAGGED(i)) 443 v->es_untagged_ports |= (1<<i); 444 } 445 446 MTKSWITCH_UNLOCK(sc); 447 return (0); 448 } 449 450 static int 451 mtkswitch_vlan_setvgroup(struct mtkswitch_softc *sc, etherswitch_vlangroup_t *v) 452 { 453 uint32_t val, i, vid; 454 455 MTKSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 456 457 if ((sc->vlan_mode != ETHERSWITCH_VLAN_DOT1Q) || 458 (v->es_vlangroup > sc->info.es_nvlangroups)) 459 return (EINVAL); 460 461 /* We currently don't support FID */ 462 if (v->es_fid != 0) 463 return (EINVAL); 464 465 MTKSWITCH_LOCK(sc); 466 while (sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR) & VTCR_BUSY); 467 if (sc->sc_switchtype == MTK_SWITCH_MT7620) { 468 val = sc->hal.mtkswitch_read(sc, 469 MTKSWITCH_VTIM(v->es_vlangroup)); 470 val &= ~(VTIM_MASK << VTIM_OFF(v->es_vlangroup)); 471 val |= ((v->es_vid & VTIM_MASK) << VTIM_OFF(v->es_vlangroup)); 472 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTIM(v->es_vlangroup), 473 val); 474 vid = v->es_vlangroup; 475 } else 476 vid = v->es_vid; 477 478 /* We use FID 0 */ 479 val = VAWD1_IVL_MAC | VAWD1_VTAG_EN | VAWD1_VALID; 480 val |= ((v->es_member_ports & VAWD1_MEMBER_MASK) << VAWD1_MEMBER_OFF); 481 sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD1, val); 482 483 /* Set tagged ports */ 484 val = 0; 485 for (i = 0; i < sc->info.es_nports; i++) 486 if (((1<<i) & v->es_untagged_ports) == 0) 487 val |= VAWD2_PORT_TAGGED(i); 488 sc->hal.mtkswitch_write(sc, MTKSWITCH_VAWD2, val); 489 490 /* Write the VLAN entry */ 491 sc->hal.mtkswitch_write(sc, MTKSWITCH_VTCR, VTCR_BUSY | 492 VTCR_FUNC_VID_WRITE | (vid & VTCR_VID_MASK)); 493 while ((val = sc->hal.mtkswitch_read(sc, MTKSWITCH_VTCR)) & VTCR_BUSY); 494 495 MTKSWITCH_UNLOCK(sc); 496 497 if (val & VTCR_IDX_INVALID) 498 return (EINVAL); 499 500 return (0); 501 } 502 503 static int 504 mtkswitch_vlan_get_pvid(struct mtkswitch_softc *sc, int port, int *pvid) 505 { 506 507 MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED); 508 509 *pvid = sc->hal.mtkswitch_read(sc, MTKSWITCH_PPBV1(port)); 510 *pvid = PPBV_VID_FROM_REG(*pvid); 511 512 return (0); 513 } 514 515 static int 516 mtkswitch_vlan_set_pvid(struct mtkswitch_softc *sc, int port, int pvid) 517 { 518 uint32_t val; 519 520 MTKSWITCH_LOCK_ASSERT(sc, MA_OWNED); 521 val = PPBV_VID(pvid & PPBV_VID_MASK); 522 sc->hal.mtkswitch_write(sc, MTKSWITCH_PPBV1(port), val); 523 sc->hal.mtkswitch_write(sc, MTKSWITCH_PPBV2(port), val); 524 525 return (0); 526 } 527 528 extern void 529 mtk_attach_switch_mt7620(struct mtkswitch_softc *sc) 530 { 531 532 sc->portmap = 0x7f; 533 sc->phymap = 0x1f; 534 535 sc->info.es_nports = 7; 536 sc->info.es_vlan_caps = ETHERSWITCH_VLAN_DOT1Q; 537 sc->info.es_nvlangroups = 16; 538 sprintf(sc->info.es_name, "Mediatek GSW"); 539 540 if (sc->sc_switchtype == MTK_SWITCH_MT7621) { 541 sc->hal.mtkswitch_read = mtkswitch_reg_read32_mt7621; 542 sc->hal.mtkswitch_write = mtkswitch_reg_write32_mt7621; 543 sc->info.es_nvlangroups = 4096; 544 } else { 545 sc->hal.mtkswitch_read = mtkswitch_reg_read32; 546 sc->hal.mtkswitch_write = mtkswitch_reg_write32; 547 } 548 549 sc->hal.mtkswitch_reset = mtkswitch_reset; 550 sc->hal.mtkswitch_hw_setup = mtkswitch_hw_setup; 551 sc->hal.mtkswitch_hw_global_setup = mtkswitch_hw_global_setup; 552 sc->hal.mtkswitch_port_init = mtkswitch_port_init; 553 sc->hal.mtkswitch_get_port_status = mtkswitch_get_port_status; 554 sc->hal.mtkswitch_atu_flush = mtkswitch_atu_flush; 555 sc->hal.mtkswitch_port_vlan_setup = mtkswitch_port_vlan_setup; 556 sc->hal.mtkswitch_port_vlan_get = mtkswitch_port_vlan_get; 557 sc->hal.mtkswitch_vlan_init_hw = mtkswitch_vlan_init_hw; 558 sc->hal.mtkswitch_vlan_getvgroup = mtkswitch_vlan_getvgroup; 559 sc->hal.mtkswitch_vlan_setvgroup = mtkswitch_vlan_setvgroup; 560 sc->hal.mtkswitch_vlan_get_pvid = mtkswitch_vlan_get_pvid; 561 sc->hal.mtkswitch_vlan_set_pvid = mtkswitch_vlan_set_pvid; 562 sc->hal.mtkswitch_phy_read = mtkswitch_phy_read; 563 sc->hal.mtkswitch_phy_write = mtkswitch_phy_write; 564 sc->hal.mtkswitch_reg_read = mtkswitch_reg_read; 565 sc->hal.mtkswitch_reg_write = mtkswitch_reg_write; 566 } 567