rtl8366rb.c revision 268093
1/*- 2 * Copyright (c) 2011-2012 Stefan Bethke. 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: head/sys/dev/etherswitch/rtl8366/rtl8366rb.c 268093 2014-07-01 14:33:48Z loos $ 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/socket.h> 38#include <sys/sockio.h> 39#include <sys/sysctl.h> 40#include <sys/systm.h> 41 42#include <net/if.h> 43#include <net/if_var.h> 44#include <net/ethernet.h> 45#include <net/if_media.h> 46#include <net/if_types.h> 47 48#include <machine/bus.h> 49#include <dev/iicbus/iic.h> 50#include <dev/iicbus/iiconf.h> 51#include <dev/iicbus/iicbus.h> 52#include <dev/mii/mii.h> 53#include <dev/mii/miivar.h> 54 55#include <dev/etherswitch/etherswitch.h> 56#include <dev/etherswitch/rtl8366/rtl8366rbvar.h> 57 58#include "iicbus_if.h" 59#include "miibus_if.h" 60#include "etherswitch_if.h" 61 62 63struct rtl8366rb_softc { 64 struct mtx sc_mtx; /* serialize access to softc */ 65 int smi_acquired; /* serialize access to SMI/I2C bus */ 66 struct mtx callout_mtx; /* serialize callout */ 67 device_t dev; 68 int vid[RTL8366RB_NUM_VLANS]; 69 char *ifname[RTL8366RB_NUM_PHYS]; 70 device_t miibus[RTL8366RB_NUM_PHYS]; 71 struct ifnet *ifp[RTL8366RB_NUM_PHYS]; 72 struct callout callout_tick; 73}; 74 75static etherswitch_info_t etherswitch_info = { 76 .es_nports = RTL8366RB_NUM_PORTS, 77 .es_nvlangroups = RTL8366RB_NUM_VLANS, 78 .es_name = "Realtek RTL8366RB" 79}; 80 81#define RTL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 82#define RTL_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 83#define RTL_LOCK_ASSERT(_sc, _what) mtx_assert(&(_s)c->sc_mtx, (_what)) 84#define RTL_TRYLOCK(_sc) mtx_trylock(&(_sc)->sc_mtx) 85 86#define RTL_WAITOK 0 87#define RTL_NOWAIT 1 88 89#define RTL_SMI_ACQUIRED 1 90#define RTL_SMI_ACQUIRED_ASSERT(_sc) \ 91 KASSERT((_sc)->smi_acquired == RTL_SMI_ACQUIRED, ("smi must be acquired @%s", __FUNCTION__)) 92 93#if defined(DEBUG) 94#define DPRINTF(dev, args...) device_printf(dev, args) 95#define DEVERR(dev, err, fmt, args...) do { \ 96 if (err != 0) device_printf(dev, fmt, err, args); \ 97 } while (0) 98#define DEBUG_INCRVAR(var) do { \ 99 var++; \ 100 } while (0) 101 102static int callout_blocked = 0; 103static int iic_select_retries = 0; 104static int phy_access_retries = 0; 105static SYSCTL_NODE(_debug, OID_AUTO, rtl8366rb, CTLFLAG_RD, 0, "rtl8366rb"); 106SYSCTL_INT(_debug_rtl8366rb, OID_AUTO, callout_blocked, CTLFLAG_RW, &callout_blocked, 0, 107 "number of times the callout couldn't acquire the bus"); 108SYSCTL_INT(_debug_rtl8366rb, OID_AUTO, iic_select_retries, CTLFLAG_RW, &iic_select_retries, 0, 109 "number of times the I2C bus selection had to be retried"); 110SYSCTL_INT(_debug_rtl8366rb, OID_AUTO, phy_access_retries, CTLFLAG_RW, &phy_access_retries, 0, 111 "number of times PHY register access had to be retried"); 112#else 113#define DPRINTF(dev, args...) 114#define DEVERR(dev, err, fmt, args...) 115#define DEBUG_INCRVAR(var) 116#endif 117 118static int smi_probe(device_t dev); 119static int smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep); 120static int smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep); 121static int smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep); 122static void rtl8366rb_tick(void *arg); 123static int rtl8366rb_ifmedia_upd(struct ifnet *); 124static void rtl8366rb_ifmedia_sts(struct ifnet *, struct ifmediareq *); 125 126static void 127rtl8366rb_identify(driver_t *driver, device_t parent) 128{ 129 device_t child; 130 struct iicbus_ivar *devi; 131 132 if (device_find_child(parent, "rtl8366rb", -1) == NULL) { 133 child = BUS_ADD_CHILD(parent, 0, "rtl8366rb", -1); 134 devi = IICBUS_IVAR(child); 135 devi->addr = RTL8366RB_IIC_ADDR; 136 } 137} 138 139static int 140rtl8366rb_probe(device_t dev) 141{ 142 if (smi_probe(dev) != 0) 143 return (ENXIO); 144 device_set_desc(dev, "RTL8366RB Ethernet Switch Controller"); 145 return (BUS_PROBE_DEFAULT); 146} 147 148static void 149rtl8366rb_init(device_t dev) 150{ 151 /* Initialisation for TL-WR1043ND */ 152 smi_rmw(dev, RTL8366RB_RCR, 153 RTL8366RB_RCR_HARD_RESET, 154 RTL8366RB_RCR_HARD_RESET, RTL_WAITOK); 155 DELAY(100000); 156 /* Enable 16 VLAN mode */ 157 smi_rmw(dev, RTL8366RB_SGCR, 158 RTL8366RB_SGCR_EN_VLAN | RTL8366RB_SGCR_EN_VLAN_4KTB, 159 RTL8366RB_SGCR_EN_VLAN, RTL_WAITOK); 160 /* remove port 0 form VLAN 0 */ 161 smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 0), 162 (1 << 0), 0, RTL_WAITOK); 163 /* add port 0 untagged and port 5 tagged to VLAN 1 */ 164 smi_rmw(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, 1), 165 ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT) 166 | ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT), 167 ((1 << 5 | 1 << 0) << RTL8366RB_VMCR_MU_MEMBER_SHIFT 168 | ((1 << 0) << RTL8366RB_VMCR_MU_UNTAG_SHIFT)), 169 RTL_WAITOK); 170 /* set PVLAN 1 for port 0 */ 171 smi_rmw(dev, RTL8366RB_PVCR_REG(0), 172 RTL8366RB_PVCR_VAL(0, RTL8366RB_PVCR_PORT_MASK), 173 RTL8366RB_PVCR_VAL(0, 1), RTL_WAITOK); 174} 175 176static int 177rtl8366rb_attach(device_t dev) 178{ 179 uint16_t rev = 0; 180 struct rtl8366rb_softc *sc; 181 char name[IFNAMSIZ]; 182 int err = 0; 183 int i; 184 185 sc = device_get_softc(dev); 186 bzero(sc, sizeof(*sc)); 187 sc->dev = dev; 188 mtx_init(&sc->sc_mtx, "rtl8366rb", NULL, MTX_DEF); 189 sc->smi_acquired = 0; 190 mtx_init(&sc->callout_mtx, "rtl8366rbcallout", NULL, MTX_DEF); 191 192 rtl8366rb_init(dev); 193 smi_read(dev, RTL8366RB_CVCR, &rev, RTL_WAITOK); 194 device_printf(dev, "rev. %d\n", rev & 0x000f); 195 196 /* attach miibus and phys */ 197 /* PHYs need an interface, so we generate a dummy one */ 198 for (i = 0; i < RTL8366RB_NUM_PHYS; i++) { 199 sc->ifp[i] = if_alloc(IFT_ETHER); 200 sc->ifp[i]->if_softc = sc; 201 sc->ifp[i]->if_flags |= IFF_UP | IFF_BROADCAST | IFF_DRV_RUNNING 202 | IFF_SIMPLEX; 203 snprintf(name, IFNAMSIZ, "%sport", device_get_nameunit(dev)); 204 sc->ifname[i] = malloc(strlen(name)+1, M_DEVBUF, M_WAITOK); 205 bcopy(name, sc->ifname[i], strlen(name)+1); 206 if_initname(sc->ifp[i], sc->ifname[i], i); 207 err = mii_attach(dev, &sc->miibus[i], sc->ifp[i], rtl8366rb_ifmedia_upd, \ 208 rtl8366rb_ifmedia_sts, BMSR_DEFCAPMASK, \ 209 i, MII_OFFSET_ANY, 0); 210 if (err != 0) { 211 device_printf(dev, "attaching PHY %d failed\n", i); 212 return (err); 213 } 214 } 215 216 bus_generic_probe(dev); 217 bus_enumerate_hinted_children(dev); 218 err = bus_generic_attach(dev); 219 if (err != 0) 220 return (err); 221 222 callout_init_mtx(&sc->callout_tick, &sc->callout_mtx, 0); 223 rtl8366rb_tick(sc); 224 225 return (err); 226} 227 228static int 229rtl8366rb_detach(device_t dev) 230{ 231 struct rtl8366rb_softc *sc = device_get_softc(dev); 232 int i; 233 234 for (i=0; i < RTL8366RB_NUM_PHYS; i++) { 235 if (sc->miibus[i]) 236 device_delete_child(dev, sc->miibus[i]); 237 if (sc->ifp[i] != NULL) 238 if_free(sc->ifp[i]); 239 free(sc->ifname[i], M_DEVBUF); 240 } 241 bus_generic_detach(dev); 242 callout_drain(&sc->callout_tick); 243 mtx_destroy(&sc->callout_mtx); 244 mtx_destroy(&sc->sc_mtx); 245 246 return (0); 247} 248 249static void 250rtl8366rb_update_ifmedia(int portstatus, u_int *media_status, u_int *media_active) 251{ 252 *media_active = IFM_ETHER; 253 *media_status = IFM_AVALID; 254 if ((portstatus & RTL8366RB_PLSR_LINK) != 0) 255 *media_status |= IFM_ACTIVE; 256 else { 257 *media_active |= IFM_NONE; 258 return; 259 } 260 switch (portstatus & RTL8366RB_PLSR_SPEED_MASK) { 261 case RTL8366RB_PLSR_SPEED_10: 262 *media_active |= IFM_10_T; 263 break; 264 case RTL8366RB_PLSR_SPEED_100: 265 *media_active |= IFM_100_TX; 266 break; 267 case RTL8366RB_PLSR_SPEED_1000: 268 *media_active |= IFM_1000_T; 269 break; 270 } 271 if ((portstatus & RTL8366RB_PLSR_FULLDUPLEX) == 0) 272 *media_active |= IFM_FDX; 273 else 274 *media_active |= IFM_HDX; 275 if ((portstatus & RTL8366RB_PLSR_TXPAUSE) != 0) 276 *media_active |= IFM_ETH_TXPAUSE; 277 if ((portstatus & RTL8366RB_PLSR_RXPAUSE) != 0) 278 *media_active |= IFM_ETH_RXPAUSE; 279} 280 281static void 282rtl833rb_miipollstat(struct rtl8366rb_softc *sc) 283{ 284 int i; 285 struct mii_data *mii; 286 struct mii_softc *miisc; 287 uint16_t value; 288 int portstatus; 289 290 for (i = 0; i < RTL8366RB_NUM_PHYS; i++) { 291 mii = device_get_softc(sc->miibus[i]); 292 if ((i % 2) == 0) { 293 if (smi_read(sc->dev, RTL8366RB_PLSR_BASE + i/2, &value, RTL_NOWAIT) != 0) { 294 DEBUG_INCRVAR(callout_blocked); 295 return; 296 } 297 portstatus = value & 0xff; 298 } else { 299 portstatus = (value >> 8) & 0xff; 300 } 301 rtl8366rb_update_ifmedia(portstatus, &mii->mii_media_status, &mii->mii_media_active); 302 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) { 303 if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != miisc->mii_inst) 304 continue; 305 mii_phy_update(miisc, MII_POLLSTAT); 306 } 307 } 308} 309 310static void 311rtl8366rb_tick(void *arg) 312{ 313 struct rtl8366rb_softc *sc = arg; 314 315 rtl833rb_miipollstat(sc); 316 callout_reset(&sc->callout_tick, hz, rtl8366rb_tick, sc); 317} 318 319static int 320smi_probe(device_t dev) 321{ 322 device_t iicbus, iicha; 323 int err, i; 324 uint16_t chipid; 325 char bytes[2]; 326 int xferd; 327 328 bytes[0] = RTL8366RB_CIR & 0xff; 329 bytes[1] = (RTL8366RB_CIR >> 8) & 0xff; 330 iicbus = device_get_parent(dev); 331 iicha = device_get_parent(iicbus); 332 iicbus_reset(iicbus, IIC_FASTEST, RTL8366RB_IIC_ADDR, NULL); 333 for (i=3; i--; ) { 334 IICBUS_STOP(iicha); 335 /* 336 * we go directly to the host adapter because iicbus.c 337 * only issues a stop on a bus that was successfully started. 338 */ 339 } 340 err = iicbus_request_bus(iicbus, dev, IIC_WAIT); 341 if (err != 0) 342 goto out; 343 err = iicbus_start(iicbus, RTL8366RB_IIC_ADDR | RTL_IICBUS_READ, RTL_IICBUS_TIMEOUT); 344 if (err != 0) 345 goto out; 346 err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT); 347 if (err != 0) 348 goto out; 349 err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0); 350 if (err != 0) 351 goto out; 352 chipid = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); 353 DPRINTF(dev, "chip id 0x%04x\n", chipid); 354 if (chipid != RTL8366RB_CIR_ID8366RB) 355 err = ENXIO; 356out: 357 iicbus_stop(iicbus); 358 iicbus_release_bus(iicbus, dev); 359 return (err == 0 ? 0 : ENXIO); 360} 361 362static int 363smi_acquire(struct rtl8366rb_softc *sc, int sleep) 364{ 365 int r = 0; 366 if (sleep == RTL_WAITOK) 367 RTL_LOCK(sc); 368 else 369 if (RTL_TRYLOCK(sc) == 0) 370 return (EWOULDBLOCK); 371 if (sc->smi_acquired == RTL_SMI_ACQUIRED) 372 r = EBUSY; 373 else { 374 r = iicbus_request_bus(device_get_parent(sc->dev), sc->dev, \ 375 sleep == RTL_WAITOK ? IIC_WAIT : IIC_DONTWAIT); 376 if (r == 0) 377 sc->smi_acquired = RTL_SMI_ACQUIRED; 378 } 379 RTL_UNLOCK(sc); 380 return (r); 381} 382 383static int 384smi_release(struct rtl8366rb_softc *sc, int sleep) 385{ 386 if (sleep == RTL_WAITOK) 387 RTL_LOCK(sc); 388 else 389 if (RTL_TRYLOCK(sc) == 0) 390 return (EWOULDBLOCK); 391 RTL_SMI_ACQUIRED_ASSERT(sc); 392 iicbus_release_bus(device_get_parent(sc->dev), sc->dev); 393 sc->smi_acquired = 0; 394 RTL_UNLOCK(sc); 395 return (0); 396} 397 398static int 399smi_select(device_t dev, int op, int sleep) 400{ 401 int err, i; 402 device_t iicbus = device_get_parent(dev); 403 struct iicbus_ivar *devi = IICBUS_IVAR(dev); 404 int slave = devi->addr; 405 406 RTL_SMI_ACQUIRED_ASSERT((struct rtl8366rb_softc *)device_get_softc(dev)); 407 /* 408 * The chip does not use clock stretching when it is busy, 409 * instead ignoring the command. Retry a few times. 410 */ 411 for (i = RTL_IICBUS_RETRIES; i--; ) { 412 err = iicbus_start(iicbus, slave | op, RTL_IICBUS_TIMEOUT); 413 if (err != IIC_ENOACK) 414 break; 415 if (sleep == RTL_WAITOK) { 416 DEBUG_INCRVAR(iic_select_retries); 417 pause("smi_select", RTL_IICBUS_RETRY_SLEEP); 418 } else 419 break; 420 } 421 return (err); 422} 423 424static int 425smi_read_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t *data, int sleep) 426{ 427 int err; 428 device_t iicbus = device_get_parent(sc->dev); 429 char bytes[2]; 430 int xferd; 431 432 RTL_SMI_ACQUIRED_ASSERT(sc); 433 bytes[0] = addr & 0xff; 434 bytes[1] = (addr >> 8) & 0xff; 435 err = smi_select(sc->dev, RTL_IICBUS_READ, sleep); 436 if (err != 0) 437 goto out; 438 err = iicbus_write(iicbus, bytes, 2, &xferd, RTL_IICBUS_TIMEOUT); 439 if (err != 0) 440 goto out; 441 err = iicbus_read(iicbus, bytes, 2, &xferd, IIC_LAST_READ, 0); 442 if (err != 0) 443 goto out; 444 *data = ((bytes[1] & 0xff) << 8) | (bytes[0] & 0xff); 445 446out: 447 iicbus_stop(iicbus); 448 return (err); 449} 450 451static int 452smi_write_locked(struct rtl8366rb_softc *sc, uint16_t addr, uint16_t data, int sleep) 453{ 454 int err; 455 device_t iicbus = device_get_parent(sc->dev); 456 char bytes[4]; 457 int xferd; 458 459 RTL_SMI_ACQUIRED_ASSERT(sc); 460 bytes[0] = addr & 0xff; 461 bytes[1] = (addr >> 8) & 0xff; 462 bytes[2] = data & 0xff; 463 bytes[3] = (data >> 8) & 0xff; 464 465 err = smi_select(sc->dev, RTL_IICBUS_WRITE, sleep); 466 if (err == 0) 467 err = iicbus_write(iicbus, bytes, 4, &xferd, RTL_IICBUS_TIMEOUT); 468 iicbus_stop(iicbus); 469 470 return (err); 471} 472 473static int 474smi_read(device_t dev, uint16_t addr, uint16_t *data, int sleep) 475{ 476 struct rtl8366rb_softc *sc = device_get_softc(dev); 477 int err; 478 479 err = smi_acquire(sc, sleep); 480 if (err != 0) 481 return (EBUSY); 482 err = smi_read_locked(sc, addr, data, sleep); 483 smi_release(sc, sleep); 484 DEVERR(dev, err, "smi_read()=%d: addr=%04x\n", addr); 485 return (err == 0 ? 0 : EIO); 486} 487 488static int 489smi_write(device_t dev, uint16_t addr, uint16_t data, int sleep) 490{ 491 struct rtl8366rb_softc *sc = device_get_softc(dev); 492 int err; 493 494 err = smi_acquire(sc, sleep); 495 if (err != 0) 496 return (EBUSY); 497 err = smi_write_locked(sc, addr, data, sleep); 498 smi_release(sc, sleep); 499 DEVERR(dev, err, "smi_write()=%d: addr=%04x\n", addr); 500 return (err == 0 ? 0 : EIO); 501} 502 503static int 504smi_rmw(device_t dev, uint16_t addr, uint16_t mask, uint16_t data, int sleep) 505{ 506 struct rtl8366rb_softc *sc = device_get_softc(dev); 507 int err; 508 uint16_t oldv, newv; 509 510 err = smi_acquire(sc, sleep); 511 if (err != 0) 512 return (EBUSY); 513 if (err == 0) { 514 err = smi_read_locked(sc, addr, &oldv, sleep); 515 if (err == 0) { 516 newv = oldv & ~mask; 517 newv |= data & mask; 518 if (newv != oldv) 519 err = smi_write_locked(sc, addr, newv, sleep); 520 } 521 } 522 smi_release(sc, sleep); 523 DEVERR(dev, err, "smi_rmw()=%d: addr=%04x\n", addr); 524 return (err == 0 ? 0 : EIO); 525} 526 527static etherswitch_info_t * 528rtl_getinfo(device_t dev) 529{ 530 return (ðerswitch_info); 531} 532 533static int 534rtl_readreg(device_t dev, int reg) 535{ 536 uint16_t data = 0; 537 538 smi_read(dev, reg, &data, RTL_WAITOK); 539 return (data); 540} 541 542static int 543rtl_writereg(device_t dev, int reg, int value) 544{ 545 return (smi_write(dev, reg, value, RTL_WAITOK)); 546} 547 548static int 549rtl_getport(device_t dev, etherswitch_port_t *p) 550{ 551 struct rtl8366rb_softc *sc; 552 struct ifmedia *ifm; 553 struct mii_data *mii; 554 struct ifmediareq *ifmr = &p->es_ifmr; 555 uint16_t v; 556 int err, vlangroup; 557 558 if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PORTS) 559 return (ENXIO); 560 sc = device_get_softc(dev); 561 vlangroup = RTL8366RB_PVCR_GET(p->es_port, 562 rtl_readreg(dev, RTL8366RB_PVCR_REG(p->es_port))); 563 p->es_pvid = sc->vid[vlangroup]; 564 565 if (p->es_port < RTL8366RB_NUM_PHYS) { 566 mii = device_get_softc(sc->miibus[p->es_port]); 567 ifm = &mii->mii_media; 568 err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCGIFMEDIA); 569 if (err) 570 return (err); 571 } else { 572 /* fill in fixed values for CPU port */ 573 p->es_flags |= ETHERSWITCH_PORT_CPU; 574 ifmr->ifm_count = 0; 575 smi_read(dev, RTL8366RB_PLSR_BASE + (RTL8366RB_NUM_PHYS)/2, &v, RTL_WAITOK); 576 v = v >> (8 * ((RTL8366RB_NUM_PHYS) % 2)); 577 rtl8366rb_update_ifmedia(v, &ifmr->ifm_status, &ifmr->ifm_active); 578 ifmr->ifm_current = ifmr->ifm_active; 579 ifmr->ifm_mask = 0; 580 ifmr->ifm_status = IFM_ACTIVE | IFM_AVALID; 581 } 582 return (0); 583} 584 585static int 586rtl_setport(device_t dev, etherswitch_port_t *p) 587{ 588 int i, err, vlangroup; 589 struct rtl8366rb_softc *sc; 590 struct ifmedia *ifm; 591 struct mii_data *mii; 592 593 if (p->es_port < 0 || p->es_port >= RTL8366RB_NUM_PHYS) 594 return (ENXIO); 595 sc = device_get_softc(dev); 596 vlangroup = -1; 597 for (i = 0; i < RTL8366RB_NUM_VLANS; i++) { 598 if (sc->vid[i] == p->es_pvid) { 599 vlangroup = i; 600 break; 601 } 602 } 603 if (vlangroup == -1) 604 return (ENXIO); 605 err = smi_rmw(dev, RTL8366RB_PVCR_REG(p->es_port), 606 RTL8366RB_PVCR_VAL(p->es_port, RTL8366RB_PVCR_PORT_MASK), 607 RTL8366RB_PVCR_VAL(p->es_port, vlangroup), RTL_WAITOK); 608 if (err) 609 return (err); 610 if (p->es_port == RTL8366RB_CPU_PORT) 611 return (0); 612 mii = device_get_softc(sc->miibus[p->es_port]); 613 ifm = &mii->mii_media; 614 err = ifmedia_ioctl(sc->ifp[p->es_port], &p->es_ifr, ifm, SIOCSIFMEDIA); 615 return (err); 616} 617 618static int 619rtl_getvgroup(device_t dev, etherswitch_vlangroup_t *vg) 620{ 621 uint16_t vmcr[3]; 622 int i; 623 624 for (i=0; i<3; i++) 625 vmcr[i] = rtl_readreg(dev, RTL8366RB_VMCR(i, vg->es_vlangroup)); 626 627 vg->es_vid = RTL8366RB_VMCR_VID(vmcr) | ETHERSWITCH_VID_VALID; 628 vg->es_member_ports = RTL8366RB_VMCR_MEMBER(vmcr); 629 vg->es_untagged_ports = RTL8366RB_VMCR_UNTAG(vmcr); 630 vg->es_fid = RTL8366RB_VMCR_FID(vmcr); 631 return (0); 632} 633 634static int 635rtl_setvgroup(device_t dev, etherswitch_vlangroup_t *vg) 636{ 637 struct rtl8366rb_softc *sc; 638 int g = vg->es_vlangroup; 639 640 sc = device_get_softc(dev); 641 sc->vid[g] = vg->es_vid; 642 rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_DOT1Q_REG, g), 643 (vg->es_vid << RTL8366RB_VMCR_DOT1Q_VID_SHIFT) & RTL8366RB_VMCR_DOT1Q_VID_MASK); 644 rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_MU_REG, g), 645 ((vg->es_member_ports << RTL8366RB_VMCR_MU_MEMBER_SHIFT) & RTL8366RB_VMCR_MU_MEMBER_MASK) | 646 ((vg->es_untagged_ports << RTL8366RB_VMCR_MU_UNTAG_SHIFT) & RTL8366RB_VMCR_MU_UNTAG_MASK)); 647 rtl_writereg(dev, RTL8366RB_VMCR(RTL8366RB_VMCR_FID_REG, g), 648 vg->es_fid); 649 return (0); 650} 651 652static int 653rtl_readphy(device_t dev, int phy, int reg) 654{ 655 struct rtl8366rb_softc *sc = device_get_softc(dev); 656 uint16_t data = 0; 657 int err, i, sleep; 658 659 if (phy < 0 || phy >= RTL8366RB_NUM_PHYS) 660 return (ENXIO); 661 if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG) 662 return (ENXIO); 663 sleep = RTL_WAITOK; 664 err = smi_acquire(sc, sleep); 665 if (err != 0) 666 return (EBUSY); 667 for (i = RTL_IICBUS_RETRIES; i--; ) { 668 err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_READ, sleep); 669 if (err == 0) 670 err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), 0, sleep); 671 if (err == 0) { 672 err = smi_read_locked(sc, RTL8366RB_PADR, &data, sleep); 673 break; 674 } 675 DEBUG_INCRVAR(phy_access_retries); 676 DPRINTF(dev, "rtl_readphy(): chip not responsive, retrying %d more times\n", i); 677 pause("rtl_readphy", RTL_IICBUS_RETRY_SLEEP); 678 } 679 smi_release(sc, sleep); 680 DEVERR(dev, err, "rtl_readphy()=%d: phy=%d.%02x\n", phy, reg); 681 return (data); 682} 683 684static int 685rtl_writephy(device_t dev, int phy, int reg, int data) 686{ 687 struct rtl8366rb_softc *sc = device_get_softc(dev); 688 int err, i, sleep; 689 690 if (phy < 0 || phy >= RTL8366RB_NUM_PHYS) 691 return (ENXIO); 692 if (reg < 0 || reg >= RTL8366RB_NUM_PHY_REG) 693 return (ENXIO); 694 sleep = RTL_WAITOK; 695 err = smi_acquire(sc, sleep); 696 if (err != 0) 697 return (EBUSY); 698 for (i = RTL_IICBUS_RETRIES; i--; ) { 699 err = smi_write_locked(sc, RTL8366RB_PACR, RTL8366RB_PACR_WRITE, sleep); 700 if (err == 0) 701 err = smi_write_locked(sc, RTL8366RB_PHYREG(phy, 0, reg), data, sleep); 702 if (err == 0) { 703 break; 704 } 705 DEBUG_INCRVAR(phy_access_retries); 706 DPRINTF(dev, "rtl_writephy(): chip not responsive, retrying %d more tiems\n", i); 707 pause("rtl_writephy", RTL_IICBUS_RETRY_SLEEP); 708 } 709 smi_release(sc, sleep); 710 DEVERR(dev, err, "rtl_writephy()=%d: phy=%d.%02x\n", phy, reg); 711 return (err == 0 ? 0 : EIO); 712} 713 714static int 715rtl8366rb_ifmedia_upd(struct ifnet *ifp) 716{ 717 struct rtl8366rb_softc *sc = ifp->if_softc; 718 struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]); 719 720 mii_mediachg(mii); 721 return (0); 722} 723 724static void 725rtl8366rb_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 726{ 727 struct rtl8366rb_softc *sc = ifp->if_softc; 728 struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]); 729 730 mii_pollstat(mii); 731 ifmr->ifm_active = mii->mii_media_active; 732 ifmr->ifm_status = mii->mii_media_status; 733} 734 735 736static device_method_t rtl8366rb_methods[] = { 737 /* Device interface */ 738 DEVMETHOD(device_identify, rtl8366rb_identify), 739 DEVMETHOD(device_probe, rtl8366rb_probe), 740 DEVMETHOD(device_attach, rtl8366rb_attach), 741 DEVMETHOD(device_detach, rtl8366rb_detach), 742 743 /* bus interface */ 744 DEVMETHOD(bus_add_child, device_add_child_ordered), 745 746 /* MII interface */ 747 DEVMETHOD(miibus_readreg, rtl_readphy), 748 DEVMETHOD(miibus_writereg, rtl_writephy), 749 750 /* etherswitch interface */ 751 DEVMETHOD(etherswitch_getinfo, rtl_getinfo), 752 DEVMETHOD(etherswitch_readreg, rtl_readreg), 753 DEVMETHOD(etherswitch_writereg, rtl_writereg), 754 DEVMETHOD(etherswitch_readphyreg, rtl_readphy), 755 DEVMETHOD(etherswitch_writephyreg, rtl_writephy), 756 DEVMETHOD(etherswitch_getport, rtl_getport), 757 DEVMETHOD(etherswitch_setport, rtl_setport), 758 DEVMETHOD(etherswitch_getvgroup, rtl_getvgroup), 759 DEVMETHOD(etherswitch_setvgroup, rtl_setvgroup), 760 761 DEVMETHOD_END 762}; 763 764DEFINE_CLASS_0(rtl8366rb, rtl8366rb_driver, rtl8366rb_methods, 765 sizeof(struct rtl8366rb_softc)); 766static devclass_t rtl8366rb_devclass; 767 768DRIVER_MODULE(rtl8366rb, iicbus, rtl8366rb_driver, rtl8366rb_devclass, 0, 0); 769DRIVER_MODULE(miibus, rtl8366rb, miibus_driver, miibus_devclass, 0, 0); 770DRIVER_MODULE(etherswitch, rtl8366rb, etherswitch_driver, etherswitch_devclass, 0, 0); 771MODULE_VERSION(rtl8366rb, 1); 772MODULE_DEPEND(rtl8366rb, iicbus, 1, 1, 1); /* XXX which versions? */ 773MODULE_DEPEND(rtl8366rb, miibus, 1, 1, 1); /* XXX which versions? */ 774MODULE_DEPEND(rtl8366rb, etherswitch, 1, 1, 1); /* XXX which versions? */ 775