1235288Sadrian/*- 2235288Sadrian * Copyright (c) 2011-2012 Stefan Bethke. 3235288Sadrian * Copyright (c) 2012 Adrian Chadd. 4235288Sadrian * All rights reserved. 5235288Sadrian * 6235288Sadrian * Redistribution and use in source and binary forms, with or without 7235288Sadrian * modification, are permitted provided that the following conditions 8235288Sadrian * are met: 9235288Sadrian * 1. Redistributions of source code must retain the above copyright 10235288Sadrian * notice, this list of conditions and the following disclaimer. 11235288Sadrian * 2. Redistributions in binary form must reproduce the above copyright 12235288Sadrian * notice, this list of conditions and the following disclaimer in the 13235288Sadrian * documentation and/or other materials provided with the distribution. 14235288Sadrian * 15235288Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16235288Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17235288Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18235288Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19235288Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20235288Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21235288Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22235288Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23235288Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24235288Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25235288Sadrian * SUCH DAMAGE. 26235288Sadrian * 27235288Sadrian * $FreeBSD$ 28235288Sadrian */ 29235288Sadrian 30235288Sadrian#include <sys/param.h> 31235288Sadrian#include <sys/bus.h> 32235288Sadrian#include <sys/errno.h> 33235288Sadrian#include <sys/kernel.h> 34235288Sadrian#include <sys/module.h> 35235288Sadrian#include <sys/socket.h> 36235288Sadrian#include <sys/sockio.h> 37235288Sadrian#include <sys/sysctl.h> 38235288Sadrian#include <sys/systm.h> 39235288Sadrian 40235288Sadrian#include <net/if.h> 41235288Sadrian#include <net/if_arp.h> 42235288Sadrian#include <net/ethernet.h> 43235288Sadrian#include <net/if_dl.h> 44235288Sadrian#include <net/if_media.h> 45235288Sadrian#include <net/if_types.h> 46235288Sadrian 47235288Sadrian#include <machine/bus.h> 48235288Sadrian#include <dev/iicbus/iic.h> 49235288Sadrian#include <dev/iicbus/iiconf.h> 50235288Sadrian#include <dev/iicbus/iicbus.h> 51235288Sadrian#include <dev/mii/mii.h> 52235288Sadrian#include <dev/mii/miivar.h> 53235288Sadrian#include <dev/etherswitch/mdio.h> 54235288Sadrian 55235288Sadrian#include <dev/etherswitch/etherswitch.h> 56235288Sadrian 57235288Sadrian#include <dev/etherswitch/arswitch/arswitchreg.h> 58235288Sadrian#include <dev/etherswitch/arswitch/arswitchvar.h> 59235288Sadrian 60235288Sadrian#include <dev/etherswitch/arswitch/arswitch_reg.h> 61235288Sadrian#include <dev/etherswitch/arswitch/arswitch_phy.h> 62235288Sadrian 63235288Sadrian#include "mdio_if.h" 64235288Sadrian#include "miibus_if.h" 65235288Sadrian#include "etherswitch_if.h" 66235288Sadrian 67235288Sadrian#if defined(DEBUG) 68235288Sadrianstatic SYSCTL_NODE(_debug, OID_AUTO, arswitch, CTLFLAG_RD, 0, "arswitch"); 69235288Sadrian#endif 70235288Sadrian 71235288Sadrian/* 72235288Sadrian * access PHYs integrated into the switch chip through the switch's MDIO 73235288Sadrian * control register. 74235288Sadrian */ 75235288Sadrianint 76235288Sadrianarswitch_readphy(device_t dev, int phy, int reg) 77235288Sadrian{ 78241578Sray struct arswitch_softc *sc; 79235288Sadrian uint32_t data = 0, ctrl; 80235288Sadrian int err, timeout; 81235288Sadrian 82241578Sray sc = device_get_softc(dev); 83241578Sray ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 84241578Sray 85235288Sadrian if (phy < 0 || phy >= 32) 86235288Sadrian return (ENXIO); 87235288Sadrian if (reg < 0 || reg >= 32) 88235288Sadrian return (ENXIO); 89241578Sray 90241578Sray ARSWITCH_LOCK(sc); 91235288Sadrian err = arswitch_writereg_msb(dev, AR8X16_REG_MDIO_CTRL, 92235288Sadrian AR8X16_MDIO_CTRL_BUSY | AR8X16_MDIO_CTRL_MASTER_EN | 93235288Sadrian AR8X16_MDIO_CTRL_CMD_READ | 94235288Sadrian (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) | 95235288Sadrian (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT)); 96235288Sadrian DEVERR(dev, err, "arswitch_readphy()=%d: phy=%d.%02x\n", phy, reg); 97235288Sadrian if (err != 0) 98241578Sray goto fail; 99235288Sadrian for (timeout = 100; timeout--; ) { 100235288Sadrian ctrl = arswitch_readreg_msb(dev, AR8X16_REG_MDIO_CTRL); 101235288Sadrian if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0) 102235288Sadrian break; 103235288Sadrian } 104235288Sadrian if (timeout < 0) 105241578Sray goto fail; 106235288Sadrian data = arswitch_readreg_lsb(dev, AR8X16_REG_MDIO_CTRL) & 107235288Sadrian AR8X16_MDIO_CTRL_DATA_MASK; 108241578Sray ARSWITCH_UNLOCK(sc); 109235288Sadrian return (data); 110241578Sray 111241578Srayfail: 112241578Sray ARSWITCH_UNLOCK(sc); 113241578Sray return (-1); 114235288Sadrian} 115235288Sadrian 116235288Sadrianint 117235288Sadrianarswitch_writephy(device_t dev, int phy, int reg, int data) 118235288Sadrian{ 119241578Sray struct arswitch_softc *sc; 120235288Sadrian uint32_t ctrl; 121235288Sadrian int err, timeout; 122241578Sray 123241578Sray sc = device_get_softc(dev); 124241578Sray ARSWITCH_LOCK_ASSERT(sc, MA_NOTOWNED); 125241578Sray 126235288Sadrian if (reg < 0 || reg >= 32) 127235288Sadrian return (ENXIO); 128241578Sray 129241578Sray ARSWITCH_LOCK(sc); 130253570Sloos err = arswitch_writereg(dev, AR8X16_REG_MDIO_CTRL, 131235288Sadrian AR8X16_MDIO_CTRL_BUSY | 132235288Sadrian AR8X16_MDIO_CTRL_MASTER_EN | 133235288Sadrian AR8X16_MDIO_CTRL_CMD_WRITE | 134235288Sadrian (phy << AR8X16_MDIO_CTRL_PHY_ADDR_SHIFT) | 135253570Sloos (reg << AR8X16_MDIO_CTRL_REG_ADDR_SHIFT) | 136253570Sloos (data & AR8X16_MDIO_CTRL_DATA_MASK)); 137235288Sadrian if (err != 0) 138241578Sray goto out; 139235288Sadrian for (timeout = 100; timeout--; ) { 140235288Sadrian ctrl = arswitch_readreg(dev, AR8X16_REG_MDIO_CTRL); 141235288Sadrian if ((ctrl & AR8X16_MDIO_CTRL_BUSY) == 0) 142235288Sadrian break; 143235288Sadrian } 144235288Sadrian if (timeout < 0) 145235288Sadrian err = EIO; 146241578Srayout: 147235288Sadrian DEVERR(dev, err, "arswitch_writephy()=%d: phy=%d.%02x\n", phy, reg); 148241578Sray ARSWITCH_UNLOCK(sc); 149235288Sadrian return (err); 150235288Sadrian} 151