Date: Sun, 25 Oct 2015 22:00:57 +0000 (UTC) From: Zbigniew Bodek <zbb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r289945 - in head/sys: arm/conf conf dev/mge Message-ID: <201510252200.t9PM0v0D005329@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: zbb Date: Sun Oct 25 22:00:56 2015 New Revision: 289945 URL: https://svnweb.freebsd.org/changeset/base/289945 Log: Add etherswitch support to mge This commit introduces support for etherswitch devices that utilize SMI as a way of accessing its registers. SMI register is located in address space of mge -- access to it was exported through MDIO interface. Attachment functions were enhanced so as to ensure proper initialisation in both cases: 1) PHYs attached directly to mge, 2) PHYs attached to switch device and switch attached to mge. Attachment of etherswitch device depends on dts entry with compatible="mrvl,sw" property. If none is found, typical PHY attachment procedure follows. In case of switch attached, PHYs' status and configuration is accessible via etherswitchcfg, and ifconfig shows always-up, non-configurable mge interfaces. Due to the fact that there may be simultaneous accessess to SMI registers (e.g. from PHY attached to one of mge instances and switch to the other), SMI access interlock was added. It is SX lock, because sleep ability is necessary -- busy-waiting would result in poor performance due to long delays required by hardware. Underlying switch driver is obliged to use sleepable locks as well. Reviewed by: adrian Obtained from: Semihalf Submitted by: Bartosz Szczepanek <bsz@semihalf.com> Differential revision: https://reviews.freebsd.org/D3900 Modified: head/sys/arm/conf/ARMADAXP head/sys/arm/conf/DB-78XXX head/sys/arm/conf/DB-88F5XXX head/sys/arm/conf/DB-88F6XXX head/sys/arm/conf/DOCKSTAR head/sys/arm/conf/DREAMPLUG-1001 head/sys/arm/conf/SHEEVAPLUG head/sys/arm/conf/TS7800 head/sys/conf/files head/sys/dev/mge/if_mge.c head/sys/dev/mge/if_mgevar.h Modified: head/sys/arm/conf/ARMADAXP ============================================================================== --- head/sys/arm/conf/ARMADAXP Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/ARMADAXP Sun Oct 25 22:00:56 2015 (r289945) @@ -95,6 +95,7 @@ device iicbus device ether device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy device bpf options DEVICE_POLLING Modified: head/sys/arm/conf/DB-78XXX ============================================================================== --- head/sys/arm/conf/DB-78XXX Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/DB-78XXX Sun Oct 25 22:00:56 2015 (r289945) @@ -66,6 +66,7 @@ device uart device ether device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy device bpf Modified: head/sys/arm/conf/DB-88F5XXX ============================================================================== --- head/sys/arm/conf/DB-88F5XXX Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/DB-88F5XXX Sun Oct 25 22:00:56 2015 (r289945) @@ -65,6 +65,7 @@ device uart device ether device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy device bpf options DEVICE_POLLING Modified: head/sys/arm/conf/DB-88F6XXX ============================================================================== --- head/sys/arm/conf/DB-88F6XXX Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/DB-88F6XXX Sun Oct 25 22:00:56 2015 (r289945) @@ -67,6 +67,7 @@ device uart device ether device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy device bpf Modified: head/sys/arm/conf/DOCKSTAR ============================================================================== --- head/sys/arm/conf/DOCKSTAR Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/DOCKSTAR Sun Oct 25 22:00:56 2015 (r289945) @@ -96,6 +96,7 @@ device uart # Networking device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy # USB Modified: head/sys/arm/conf/DREAMPLUG-1001 ============================================================================== --- head/sys/arm/conf/DREAMPLUG-1001 Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/DREAMPLUG-1001 Sun Oct 25 22:00:56 2015 (r289945) @@ -100,6 +100,7 @@ device uart # Networking device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy # USB Modified: head/sys/arm/conf/SHEEVAPLUG ============================================================================== --- head/sys/arm/conf/SHEEVAPLUG Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/SHEEVAPLUG Sun Oct 25 22:00:56 2015 (r289945) @@ -60,6 +60,7 @@ device uart device ether device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy device bpf options DEVICE_POLLING Modified: head/sys/arm/conf/TS7800 ============================================================================== --- head/sys/arm/conf/TS7800 Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/arm/conf/TS7800 Sun Oct 25 22:00:56 2015 (r289945) @@ -60,6 +60,7 @@ device uart device ether device mge # Marvell Gigabit Ethernet controller device mii +device mdio device e1000phy device bpf options HZ=1000 Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/conf/files Sun Oct 25 22:00:56 2015 (r289945) @@ -1398,8 +1398,8 @@ dev/etherswitch/ip17x/ip175c.c optional dev/etherswitch/ip17x/ip175d.c optional ip17x dev/etherswitch/ip17x/ip17x_phy.c optional ip17x dev/etherswitch/ip17x/ip17x_vlans.c optional ip17x -dev/etherswitch/mdio_if.m optional miiproxy -dev/etherswitch/mdio.c optional miiproxy +dev/etherswitch/mdio_if.m optional miiproxy | mdio +dev/etherswitch/mdio.c optional miiproxy | mdio dev/etherswitch/miiproxy.c optional miiproxy dev/etherswitch/rtl8366/rtl8366rb.c optional rtl8366rb dev/etherswitch/ukswitch/ukswitch.c optional ukswitch Modified: head/sys/dev/mge/if_mge.c ============================================================================== --- head/sys/dev/mge/if_mge.c Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/dev/mge/if_mge.c Sun Oct 25 22:00:56 2015 (r289945) @@ -1,5 +1,7 @@ /*- * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. + * Copyright (C) 2009-2015 Semihalf + * Copyright (C) 2015 Stormshield * All rights reserved. * * Developed by Semihalf. @@ -50,7 +52,6 @@ __FBSDID("$FreeBSD$"); #include <net/ethernet.h> #include <net/bpf.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_arp.h> #include <net/if_dl.h> #include <net/if_media.h> @@ -73,12 +74,16 @@ __FBSDID("$FreeBSD$"); #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <dev/etherswitch/mdio.h> #include <dev/mge/if_mgevar.h> #include <arm/mv/mvreg.h> #include <arm/mv/mvvar.h> #include "miibus_if.h" +#include "mdio_if.h" + +#define MGE_DELAY(x) pause("SMI access sleep", (x) / tick_sbt) static int mge_probe(device_t dev); static int mge_attach(device_t dev); @@ -90,6 +95,9 @@ static int mge_resume(device_t dev); static int mge_miibus_readreg(device_t dev, int phy, int reg); static int mge_miibus_writereg(device_t dev, int phy, int reg, int value); +static int mge_mdio_readreg(device_t dev, int phy, int reg); +static int mge_mdio_writereg(device_t dev, int phy, int reg, int value); + static int mge_ifmedia_upd(struct ifnet *ifp); static void mge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr); @@ -154,21 +162,23 @@ static device_method_t mge_methods[] = { /* MII interface */ DEVMETHOD(miibus_readreg, mge_miibus_readreg), DEVMETHOD(miibus_writereg, mge_miibus_writereg), + /* MDIO interface */ + DEVMETHOD(mdio_readreg, mge_mdio_readreg), + DEVMETHOD(mdio_writereg, mge_mdio_writereg), { 0, 0 } }; -static driver_t mge_driver = { - "mge", - mge_methods, - sizeof(struct mge_softc), -}; +DEFINE_CLASS_0(mge, mge_driver, mge_methods, sizeof(struct mge_softc)); static devclass_t mge_devclass; +static int switch_attached = 0; DRIVER_MODULE(mge, simplebus, mge_driver, mge_devclass, 0, 0); DRIVER_MODULE(miibus, mge, miibus_driver, miibus_devclass, 0, 0); +DRIVER_MODULE(mdio, mge, mdio_driver, mdio_devclass, 0, 0); MODULE_DEPEND(mge, ether, 1, 1, 1); MODULE_DEPEND(mge, miibus, 1, 1, 1); +MODULE_DEPEND(mge, mdio, 1, 1, 1); static struct resource_spec res_spec[] = { { SYS_RES_MEMORY, 0, RF_ACTIVE }, @@ -190,6 +200,133 @@ static struct { { mge_intr_err, "GbE error interrupt" }, }; +/* SMI access interlock */ +static struct sx sx_smi; + +static uint32_t +mv_read_ge_smi(device_t dev, int phy, int reg) +{ + uint32_t timeout; + uint32_t ret; + struct mge_softc *sc; + + sc = device_get_softc(dev); + KASSERT(sc != NULL, ("NULL softc ptr!")); + timeout = MGE_SMI_WRITE_RETRIES; + + MGE_SMI_LOCK(); + while (--timeout && + (MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_BUSY)) + MGE_DELAY(MGE_SMI_WRITE_DELAY); + + if (timeout == 0) { + device_printf(dev, "SMI write timeout.\n"); + ret = ~0U; + goto out; + } + + MGE_WRITE(sc, MGE_REG_SMI, MGE_SMI_MASK & + (MGE_SMI_READ | (reg << 21) | (phy << 16))); + + /* Wait till finished. */ + timeout = MGE_SMI_WRITE_RETRIES; + while (--timeout && + !((MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_READVALID))) + MGE_DELAY(MGE_SMI_WRITE_DELAY); + + if (timeout == 0) { + device_printf(dev, "SMI write validation timeout.\n"); + ret = ~0U; + goto out; + } + + /* Wait for the data to update in the SMI register */ + MGE_DELAY(MGE_SMI_DELAY); + ret = MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_DATA_MASK; + +out: + MGE_SMI_UNLOCK(); + return (ret); + +} + +static void +mv_write_ge_smi(device_t dev, int phy, int reg, uint32_t value) +{ + uint32_t timeout; + struct mge_softc *sc; + + sc = device_get_softc(dev); + KASSERT(sc != NULL, ("NULL softc ptr!")); + + MGE_SMI_LOCK(); + timeout = MGE_SMI_READ_RETRIES; + while (--timeout && + (MGE_READ(sc, MGE_REG_SMI) & MGE_SMI_BUSY)) + MGE_DELAY(MGE_SMI_READ_DELAY); + + if (timeout == 0) { + device_printf(dev, "SMI read timeout.\n"); + goto out; + } + + MGE_WRITE(sc, MGE_REG_SMI, MGE_SMI_MASK & + (MGE_SMI_WRITE | (reg << 21) | (phy << 16) | + (value & MGE_SMI_DATA_MASK))); + +out: + MGE_SMI_UNLOCK(); +} + +static int +mv_read_ext_phy(device_t dev, int phy, int reg) +{ + uint32_t retries; + struct mge_softc *sc; + uint32_t ret; + + sc = device_get_softc(dev); + + MGE_SMI_LOCK(); + MGE_WRITE(sc->phy_sc, MGE_REG_SMI, MGE_SMI_MASK & + (MGE_SMI_READ | (reg << 21) | (phy << 16))); + + retries = MGE_SMI_READ_RETRIES; + while (--retries && + !(MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_READVALID)) + DELAY(MGE_SMI_READ_DELAY); + + if (retries == 0) + device_printf(dev, "Timeout while reading from PHY\n"); + + ret = MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_DATA_MASK; + MGE_SMI_UNLOCK(); + + return (ret); +} + +static void +mv_write_ext_phy(device_t dev, int phy, int reg, int value) +{ + uint32_t retries; + struct mge_softc *sc; + + sc = device_get_softc(dev); + + MGE_SMI_LOCK(); + MGE_WRITE(sc->phy_sc, MGE_REG_SMI, MGE_SMI_MASK & + (MGE_SMI_WRITE | (reg << 21) | (phy << 16) | + (value & MGE_SMI_DATA_MASK))); + + retries = MGE_SMI_WRITE_RETRIES; + while (--retries && MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_BUSY) + DELAY(MGE_SMI_WRITE_DELAY); + + if (retries == 0) + device_printf(dev, "Timeout while writing to PHY\n"); + MGE_SMI_UNLOCK(); +} + static void mge_get_mac_address(struct mge_softc *sc, uint8_t *addr) { @@ -605,10 +742,10 @@ mge_poll(struct ifnet *ifp, enum poll_cm uint32_t int_cause, int_cause_ext; int rx_npkts = 0; - MGE_GLOBAL_LOCK(sc); + MGE_RECEIVE_LOCK(sc); if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - MGE_GLOBAL_UNLOCK(sc); + MGE_RECEIVE_UNLOCK(sc); return (rx_npkts); } @@ -626,10 +763,13 @@ mge_poll(struct ifnet *ifp, enum poll_cm } } - mge_intr_tx_locked(sc); + rx_npkts = mge_intr_rx_locked(sc, count); - MGE_GLOBAL_UNLOCK(sc); + MGE_RECEIVE_UNLOCK(sc); + MGE_TRANSMIT_LOCK(sc); + mge_intr_tx_locked(sc); + MGE_TRANSMIT_UNLOCK(sc); return (rx_npkts); } #endif /* DEVICE_POLLING */ @@ -646,14 +786,34 @@ mge_attach(device_t dev) sc = device_get_softc(dev); sc->dev = dev; sc->node = ofw_bus_get_node(dev); + phy = 0; + + if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) == 0) { + device_printf(dev, "PHY%i attached, phy_sc points to %s\n", phy, + device_get_nameunit(sc->phy_sc->dev)); + sc->phy_attached = 1; + } else { + device_printf(dev, "PHY not attached.\n"); + sc->phy_attached = 0; + sc->phy_sc = sc; + } + + if (fdt_find_compatible(sc->node, "mrvl,sw", 1) != 0) { + device_printf(dev, "Switch attached.\n"); + sc->switch_attached = 1; + /* additional variable available across instances */ + switch_attached = 1; + } else { + sc->switch_attached = 0; + } + + if (device_get_unit(dev) == 0) { + sx_init(&sx_smi, "mge_tick() SMI access threads interlock"); + } /* Set chip version-dependent parameters */ mge_ver_params(sc); - /* Get phy address and used softc from fdt */ - if (fdt_get_phyaddr(sc->node, sc->dev, &phy, (void **)&sc->phy_sc) != 0) - return (ENXIO); - /* Initialize mutexes */ mtx_init(&sc->transmit_lock, device_get_nameunit(dev), "mge TX lock", MTX_DEF); mtx_init(&sc->receive_lock, device_get_nameunit(dev), "mge RX lock", MTX_DEF); @@ -719,18 +879,32 @@ mge_attach(device_t dev) callout_init(&sc->wd_callout, 0); /* Attach PHY(s) */ - error = mii_attach(dev, &sc->miibus, ifp, mge_ifmedia_upd, - mge_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); - if (error) { - device_printf(dev, "attaching PHYs failed\n"); - mge_detach(dev); - return (error); - } - sc->mii = device_get_softc(sc->miibus); + if (sc->phy_attached) { + error = mii_attach(dev, &sc->miibus, ifp, mge_ifmedia_upd, + mge_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0); + if (error) { + device_printf(dev, "MII failed to find PHY\n"); + if_free(ifp); + sc->ifp = NULL; + mge_detach(dev); + return (error); + } + sc->mii = device_get_softc(sc->miibus); - /* Tell the MAC where to find the PHY so autoneg works */ - miisc = LIST_FIRST(&sc->mii->mii_phys); - MGE_WRITE(sc, MGE_REG_PHYDEV, miisc->mii_phy); + /* Tell the MAC where to find the PHY so autoneg works */ + miisc = LIST_FIRST(&sc->mii->mii_phys); + MGE_WRITE(sc, MGE_REG_PHYDEV, miisc->mii_phy); + } else { + /* no PHY, so use hard-coded values */ + ifmedia_init(&sc->mge_ifmedia, 0, + mge_ifmedia_upd, + mge_ifmedia_sts); + ifmedia_add(&sc->mge_ifmedia, + IFM_ETHER | IFM_1000_T | IFM_FDX, + 0, NULL); + ifmedia_set(&sc->mge_ifmedia, + IFM_ETHER | IFM_1000_T | IFM_FDX); + } /* Attach interrupt handlers */ /* TODO: review flags, in part. mark RX as INTR_ENTROPY ? */ @@ -747,6 +921,13 @@ mge_attach(device_t dev) } } + if (sc->switch_attached) { + device_t child; + MGE_WRITE(sc, MGE_REG_PHYDEV, MGE_SWITCH_PHYDEV); + child = device_add_child(dev, "mdio", -1); + bus_generic_attach(dev); + } + return (0); } @@ -792,6 +973,9 @@ mge_detach(device_t dev) mtx_destroy(&sc->receive_lock); mtx_destroy(&sc->transmit_lock); + if (device_get_unit(dev) == 0) + sx_destroy(&sx_smi); + return (0); } @@ -801,7 +985,13 @@ mge_ifmedia_sts(struct ifnet *ifp, struc struct mge_softc *sc = ifp->if_softc; struct mii_data *mii; - MGE_TRANSMIT_LOCK(sc); + MGE_GLOBAL_LOCK(sc); + + if (!sc->phy_attached) { + ifmr->ifm_active = IFM_1000_T | IFM_FDX | IFM_ETHER; + ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE; + goto out_unlock; + } mii = sc->mii; mii_pollstat(mii); @@ -809,7 +999,8 @@ mge_ifmedia_sts(struct ifnet *ifp, struc ifmr->ifm_active = mii->mii_media_active; ifmr->ifm_status = mii->mii_media_status; - MGE_TRANSMIT_UNLOCK(sc); +out_unlock: + MGE_GLOBAL_UNLOCK(sc); } static uint32_t @@ -826,13 +1017,13 @@ mge_set_port_serial_control(uint32_t med break; case IFM_1000_T: port_config |= (PORT_SERIAL_GMII_SPEED_1000 | - PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC | - PORT_SERIAL_SPEED_AUTONEG); + PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC + | PORT_SERIAL_SPEED_AUTONEG); break; case IFM_100_TX: port_config |= (PORT_SERIAL_MII_SPEED_100 | - PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC | - PORT_SERIAL_SPEED_AUTONEG); + PORT_SERIAL_AUTONEG | PORT_SERIAL_AUTONEG_FC + | PORT_SERIAL_SPEED_AUTONEG); break; case IFM_10_T: port_config |= (PORT_SERIAL_AUTONEG | @@ -851,13 +1042,21 @@ mge_ifmedia_upd(struct ifnet *ifp) { struct mge_softc *sc = ifp->if_softc; - if (ifp->if_flags & IFF_UP) { + /* + * Do not do anything for switch here, as updating media between + * MGE MAC and switch MAC is hardcoded in PCB. Changing it here would + * break the link. + */ + if (sc->phy_attached) { MGE_GLOBAL_LOCK(sc); + if (ifp->if_flags & IFF_UP) { + sc->mge_media_status = sc->mii->mii_media.ifm_media; + mii_mediachg(sc->mii); - sc->mge_media_status = sc->mii->mii_media.ifm_media; - mii_mediachg(sc->mii); - mge_init_locked(sc); + /* MGE MAC needs to be reinitialized. */ + mge_init_locked(sc); + } MGE_GLOBAL_UNLOCK(sc); } @@ -883,6 +1082,7 @@ mge_init_locked(void *arg) struct mge_desc_wrapper *dw; volatile uint32_t reg_val; int i, count; + uint32_t media_status; MGE_GLOBAL_LOCK_ASSERT(sc); @@ -925,8 +1125,17 @@ mge_init_locked(void *arg) PORT_CONFIG_ARO_RXQ(0)); MGE_WRITE(sc, MGE_PORT_EXT_CONFIG , 0x0); + /* Configure promisc mode */ + mge_set_prom_mode(sc, MGE_RX_DEFAULT_QUEUE); + + media_status = sc->mge_media_status; + if (sc->switch_attached) { + media_status &= ~IFM_TMASK; + media_status |= IFM_1000_T; + } + /* Setup port configuration */ - reg_val = mge_set_port_serial_control(sc->mge_media_status); + reg_val = mge_set_port_serial_control(media_status); MGE_WRITE(sc, MGE_PORT_SERIAL_CTRL, reg_val); /* Setup SDMA configuration */ @@ -997,7 +1206,8 @@ mge_init_locked(void *arg) sc->wd_timer = 0; /* Schedule watchdog timeout */ - callout_reset(&sc->wd_callout, hz, mge_tick, sc); + if (sc->phy_attached) + callout_reset(&sc->wd_callout, hz, mge_tick, sc); } static void @@ -1331,6 +1541,18 @@ mge_ioctl(struct ifnet *ifp, u_long comm break; case SIOCGIFMEDIA: /* fall through */ case SIOCSIFMEDIA: + /* + * Setting up media type via ioctls is *not* supported for MAC + * which is connected to switch. Use etherswitchcfg. + */ + if (!sc->phy_attached && (command == SIOCSIFMEDIA)) + return (0); + else if (!sc->phy_attached) { + error = ifmedia_ioctl(ifp, ifr, &sc->mge_ifmedia, + command); + break; + } + if (IFM_SUBTYPE(ifr->ifr_media) == IFM_1000_T && !(ifr->ifr_media & IFM_FDX)) { device_printf(sc->dev, @@ -1349,41 +1571,23 @@ static int mge_miibus_readreg(device_t dev, int phy, int reg) { struct mge_softc *sc; - uint32_t retries; - sc = device_get_softc(dev); - MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff & - (MGE_SMI_READ | (reg << 21) | (phy << 16))); - - retries = MGE_SMI_READ_RETRIES; - while (--retries && - !(MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_READVALID)) - DELAY(MGE_SMI_READ_DELAY); + KASSERT(!switch_attached, ("miibus used with switch attached")); - if (retries == 0) - device_printf(dev, "Timeout while reading from PHY\n"); - - return (MGE_READ(sc->phy_sc, MGE_REG_SMI) & 0xffff); + return (mv_read_ext_phy(dev, phy, reg)); } static int mge_miibus_writereg(device_t dev, int phy, int reg, int value) { struct mge_softc *sc; - uint32_t retries; - sc = device_get_softc(dev); - MGE_WRITE(sc->phy_sc, MGE_REG_SMI, 0x1fffffff & - (MGE_SMI_WRITE | (reg << 21) | (phy << 16) | (value & 0xffff))); + KASSERT(!switch_attached, ("miibus used with switch attached")); - retries = MGE_SMI_WRITE_RETRIES; - while (--retries && MGE_READ(sc->phy_sc, MGE_REG_SMI) & MGE_SMI_BUSY) - DELAY(MGE_SMI_WRITE_DELAY); + mv_write_ext_phy(dev, phy, reg, value); - if (retries == 0) - device_printf(dev, "Timeout while writing to PHY\n"); return (0); } @@ -1489,6 +1693,10 @@ mge_tick(void *msc) { struct mge_softc *sc = msc; + KASSERT(sc->phy_attached == 1, ("mge_tick while PHY not attached")); + + MGE_GLOBAL_LOCK(sc); + /* Check for TX timeout */ mge_watchdog(sc); @@ -1498,8 +1706,12 @@ mge_tick(void *msc) if(sc->mge_media_status != sc->mii->mii_media.ifm_media) mge_ifmedia_upd(sc->ifp); + MGE_GLOBAL_UNLOCK(sc); + /* Schedule another timeout one second from now */ callout_reset(&sc->wd_callout, hz, mge_tick, sc); + + return; } static void @@ -1509,10 +1721,7 @@ mge_watchdog(struct mge_softc *sc) ifp = sc->ifp; - MGE_GLOBAL_LOCK(sc); - if (sc->wd_timer == 0 || --sc->wd_timer) { - MGE_GLOBAL_UNLOCK(sc); return; } @@ -1521,8 +1730,6 @@ mge_watchdog(struct mge_softc *sc) mge_stop(sc); mge_init_locked(sc); - - MGE_GLOBAL_UNLOCK(sc); } static void @@ -1927,3 +2134,23 @@ mge_add_sysctls(struct mge_softc *sc) CTLTYPE_UINT | CTLFLAG_RW, sc, MGE_IC_TX, mge_sysctl_ic, "I", "IC TX time threshold"); } + +static int +mge_mdio_writereg(device_t dev, int phy, int reg, int value) +{ + + mv_write_ge_smi(dev, phy, reg, value); + + return (0); +} + + +static int +mge_mdio_readreg(device_t dev, int phy, int reg) +{ + int ret; + + ret = mv_read_ge_smi(dev, phy, reg); + + return (ret); +} Modified: head/sys/dev/mge/if_mgevar.h ============================================================================== --- head/sys/dev/mge/if_mgevar.h Sun Oct 25 21:48:45 2015 (r289944) +++ head/sys/dev/mge/if_mgevar.h Sun Oct 25 22:00:56 2015 (r289945) @@ -34,6 +34,8 @@ #ifndef __IF_MGE_H__ #define __IF_MGE_H__ +#include <arm/mv/mvvar.h> + #define MGE_INTR_COUNT 5 /* ETH controller occupies 5 IRQ lines */ #define MGE_TX_DESC_NUM 256 #define MGE_RX_DESC_NUM 256 @@ -71,6 +73,7 @@ struct mge_softc { device_t miibus; struct mii_data *mii; + struct ifmedia mge_ifmedia; struct resource *res[1 + MGE_INTR_COUNT]; /* resources */ void *ih_cookie[MGE_INTR_COUNT]; /* interrupt handlers cookies */ struct mtx transmit_lock; /* transmitter lock */ @@ -106,6 +109,8 @@ struct mge_softc { int mge_intr_cnt; uint8_t mge_hw_csum; + int phy_attached; + int switch_attached; struct mge_softc *phy_sc; }; @@ -150,6 +155,14 @@ struct mge_softc { MGE_RECEIVE_LOCK_ASSERT(sc); \ } while (0) +#define MGE_SMI_LOCK() do { \ + sx_assert(&sx_smi, SA_UNLOCKED); \ + sx_xlock(&sx_smi); \ +} while (0) + +#define MGE_SMI_UNLOCK() sx_unlock(&sx_smi) +#define MGE_SMI_LOCK_ASSERT() sx_assert(&sx_smi, SA_XLOCKED) + /* SMI-related macros */ #define MGE_REG_PHYDEV 0x000 #define MGE_REG_SMI 0x004 @@ -158,6 +171,17 @@ struct mge_softc { #define MGE_SMI_READVALID (1 << 27) #define MGE_SMI_BUSY (1 << 28) +#define MGE_SMI_MASK 0x1fffffff +#define MGE_SMI_DATA_MASK 0xffff +#define MGE_SMI_DELAY 1000 + +#define MGE_SWITCH_PHYDEV 6 + +/* Internal Switch SMI Command */ + +#define SW_SMI_READ_CMD(phy, reg) ((1 << 15) | (1 << 12) | (1 << 11) | (phy << 5) | reg) +#define SW_SMI_WRITE_CMD(phy, reg) ((1 << 15) | (1 << 12) | (1 << 10) | (phy << 5) | reg) + /* TODO verify the timings and retries count w/specs */ #define MGE_SMI_READ_RETRIES 1000 #define MGE_SMI_READ_DELAY 100
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201510252200.t9PM0v0D005329>