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 58static int 59mtkswitch_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 71static int 72mtkswitch_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 88static int 89mtkswitch_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 101static int 102mtkswitch_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 118static uint32_t 119mtkswitch_reg_read32(struct mtkswitch_softc *sc, int reg) 120{ 121 122 return (MTKSWITCH_READ(sc, reg)); 123} 124 125static uint32_t 126mtkswitch_reg_write32(struct mtkswitch_softc *sc, int reg, uint32_t val) 127{ 128 129 MTKSWITCH_WRITE(sc, reg, val); 130 return (0); 131} 132 133static uint32_t 134mtkswitch_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 147static uint32_t 148mtkswitch_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 160static int 161mtkswitch_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 172static int 173mtkswitch_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 191static int 192mtkswitch_reset(struct mtkswitch_softc *sc) 193{ 194 195 /* We don't reset the switch for now */ 196 return (0); 197} 198 199static int 200mtkswitch_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 212static int 213mtkswitch_hw_global_setup(struct mtkswitch_softc *sc) 214{ 215 /* Currently does nothing */ 216 217 /* Called early and hence unlocked */ 218 return (0); 219} 220 221static void 222mtkswitch_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 246static uint32_t 247mtkswitch_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 274static int 275mtkswitch_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 289static int 290mtkswitch_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 320static int 321mtkswitch_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 341static void 342mtkswitch_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 351static void 352mtkswitch_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 393static int 394mtkswitch_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 448static int 449mtkswitch_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 501static int 502mtkswitch_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 513static int 514mtkswitch_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 526extern void 527mtk_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} 565