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