From patchwork Tue Aug 2 11:31:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 654690 X-Patchwork-Delegate: joe.hershberger@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3s3YxN227Rz9t49 for ; Tue, 2 Aug 2016 21:33:44 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=bTRIY1Ha; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 41325A75CC; Tue, 2 Aug 2016 13:32:59 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Xjeq4M-qEEi4; Tue, 2 Aug 2016 13:32:59 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BE6ECA764C; Tue, 2 Aug 2016 13:32:37 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A3017A7599 for ; Tue, 2 Aug 2016 13:32:25 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id anmowRk2aqR1 for ; Tue, 2 Aug 2016 13:32:25 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-lf0-f68.google.com (mail-lf0-f68.google.com [209.85.215.68]) by theia.denx.de (Postfix) with ESMTPS id 715B7A75CA for ; Tue, 2 Aug 2016 13:32:18 +0200 (CEST) Received: by mail-lf0-f68.google.com with SMTP id l69so9777279lfg.1 for ; Tue, 02 Aug 2016 04:32:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5dQcIEfD39koD5NW/4fo2Bb0P6VsGnbPsSkcNeN3eCo=; b=bTRIY1HaszolT7FZ+XxFa4PgjigtSRqpTbi1LDd0dEE7Fn1pF46EWJHF/tboN4c0vE sRmZX71qcOkP/vz1X7koAaSMENeEByXMD6E5U0UIyOVuEqU0hsM0Je4Ow+B5r1hqTxT+ v2FIdfMwyzSxZg0kYKdTyG33az7u1eWwN3eZkgkvKR3WGC9yiCJ+/e7rrcwsQCNbYjJG O11EaoLxBlG7QlLR8ZR4+YckzPYOogFm2b4xyhArlxlFQvwpa3O351yDUBbemvM47vis EenGMu64uQdEv/iDzvLJTBje3S/4a4+KKNs0I5lcu/Xpd/1KrmPGkz0hp1OJJNpkA0AD KfkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5dQcIEfD39koD5NW/4fo2Bb0P6VsGnbPsSkcNeN3eCo=; b=bBYmHbqksxYGGofPR0jw2TX/eJ3DWLTaOyg58mz1+PfjYaDMmAME7HZGGgJIrK18Ke 5gdiYPkzCK0LsA6ZI1/yXFXrJxvvLv0QXchYaA/d2mwZhTuqcHr9P7VoAt0HPPDggwh5 TXTLWYj2o3KsCztdd8wF7scuiW+M/Q+VHBsLYZ3Vpq34vwgfEEsUhvH8STPIplmYkM9j ENzFmF8heS1yiUj0+SvYDVeOQfDcyvCjLJFvTBToaN/RpkwvcWV94JPN4mxb/9nxlud7 +MxVGPpd1Q1P/7lO2A3w1kGN+4Ysavcpp9+F3ch0ARATq+VB2A6Q2qnDrBPX/7d4DDT6 8t6Q== X-Gm-Message-State: AEkoousaHKZKyOltOm4cE00kVa2uVoGnKbOGcDFJn/n1KcFqVVudX8oDd+HGiqLXOo88iA== X-Received: by 10.25.22.152 with SMTP id 24mr20616919lfw.180.1470137537731; Tue, 02 Aug 2016 04:32:17 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by smtp.gmail.com with ESMTPSA id f69sm417906lji.19.2016.08.02.04.32.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 02 Aug 2016 04:32:16 -0700 (PDT) From: Max Filippov To: u-boot@lists.denx.de Date: Tue, 2 Aug 2016 14:31:10 +0300 Message-Id: <1470137470-6051-8-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1470137470-6051-1-git-send-email-jcmvbkbc@gmail.com> References: <1470137470-6051-1-git-send-email-jcmvbkbc@gmail.com> Cc: Joe Hershberger Subject: [U-Boot] [PATCH 7/7] net/ethoc: implement MDIO bus and support phylib X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Implement MDIO bus read/write functions, initialize the bus and scan for the PHY when phylib is enabled. Limit PHY speeds to 10/100 Mbps. Cc: Michal Simek Signed-off-by: Max Filippov --- drivers/net/ethoc.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 146 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index fa623d5..fe04396 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -181,6 +181,11 @@ struct ethoc { void __iomem *iobase; void __iomem *packet; phys_addr_t packet_phys; + +#ifdef CONFIG_PHYLIB + struct mii_dev *bus; + struct phy_device *phydev; +#endif }; /** @@ -319,13 +324,31 @@ static int ethoc_reset(struct ethoc *priv) static int ethoc_init_common(struct ethoc *priv) { + int ret = 0; + priv->num_tx = 1; priv->num_rx = PKTBUFSRX; ethoc_write(priv, TX_BD_NUM, priv->num_tx); ethoc_init_ring(priv); ethoc_reset(priv); - return 0; +#ifdef CONFIG_PHYLIB + ret = phy_startup(priv->phydev); + if (ret) { + printf("Could not initialize PHY %s\n", + priv->phydev->dev->name); + return ret; + } +#endif + return ret; +} + +static void ethoc_stop_common(struct ethoc *priv) +{ + ethoc_disable_rx_and_tx(priv); +#ifdef CONFIG_PHYLIB + phy_shutdown(priv->phydev); +#endif } static int ethoc_update_rx_stats(struct ethoc_bd *bd) @@ -509,13 +532,119 @@ static int ethoc_free_pkt_common(struct ethoc *priv) return 0; } +#ifdef CONFIG_PHYLIB + +static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct ethoc *priv = bus->priv; + ulong tmo = get_timer(0); + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg)); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ); + + while (get_timer(tmo) < CONFIG_SYS_HZ) { + u32 status = ethoc_read(priv, MIISTATUS); + + if (!(status & MIISTATUS_BUSY)) { + u32 data = ethoc_read(priv, MIIRX_DATA); + + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + return data; + } + } + return -ETIMEDOUT; +} + +static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct ethoc *priv = bus->priv; + ulong tmo = get_timer(0); + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg)); + ethoc_write(priv, MIITX_DATA, val); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE); + + while (get_timer(tmo) < CONFIG_SYS_HZ) { + u32 stat = ethoc_read(priv, MIISTATUS); + + if (!(stat & MIISTATUS_BUSY)) { + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + return 0; + } + } + return -ETIMEDOUT; +} + +static int ethoc_mdio_init(const char *name, struct ethoc *priv) +{ + struct mii_dev *bus = mdio_alloc(); + int ret; + + if (!bus) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->read = ethoc_mdio_read; + bus->write = ethoc_mdio_write; + snprintf(bus->name, sizeof(bus->name), "%s", name); + bus->priv = priv; + + ret = mdio_register(bus); + if (ret < 0) + return ret; + + priv->bus = miiphy_get_dev_by_name(name); + return 0; +} + +static int ethoc_phy_init(struct ethoc *priv, void *dev) +{ + struct phy_device *phydev; + int mask = 0xffffffff; + +#ifdef CONFIG_PHY_ADDR + mask = 1 << CONFIG_PHY_ADDR; +#endif + + phydev = phy_find_by_mask(priv->bus, mask, PHY_INTERFACE_MODE_MII); + if (!phydev) + return -ENODEV; + + phy_connect_dev(phydev, dev); + + phydev->supported &= PHY_BASIC_FEATURES; + phydev->advertising = phydev->supported; + + priv->phydev = phydev; + phy_config(phydev); + + return 0; +} + +#else + +static inline int ethoc_mdio_init(const char *name, struct ethoc *priv) +{ + return 0; +} + +static inline int ethoc_phy_init(struct ethoc *priv, void *dev) +{ + return 0; +} + +#endif + #ifndef CONFIG_DM_ETH static int ethoc_init(struct eth_device *dev, bd_t *bd) { struct ethoc *priv = (struct ethoc *)dev->priv; - priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE); return ethoc_init_common(priv); } @@ -534,7 +663,7 @@ static int ethoc_send(struct eth_device *dev, void *packet, int length) static void ethoc_halt(struct eth_device *dev) { - ethoc_disable_rx_and_tx(dev->priv); + ethoc_stop_common(dev->priv); } static int ethoc_recv(struct eth_device *dev) @@ -584,6 +713,10 @@ int ethoc_initialize(u8 dev_num, int base_addr) priv->iobase = ioremap(dev->iobase, ETHOC_IOSIZE); eth_register(dev); + + ethoc_mdio_init(dev->name, priv); + ethoc_phy_init(priv, dev); + return 1; } @@ -625,9 +758,7 @@ static int ethoc_start(struct udevice *dev) static void ethoc_stop(struct udevice *dev) { - struct ethoc *priv = dev_get_priv(dev); - - ethoc_disable_rx_and_tx(priv); + ethoc_stop_common(dev_get_priv(dev)); } static int ethoc_ofdata_to_platdata(struct udevice *dev) @@ -653,6 +784,10 @@ static int ethoc_probe(struct udevice *dev) priv->packet = ioremap(pdata->packet_base, (1 + PKTBUFSRX) * PKTSIZE_ALIGN); } + + ethoc_mdio_init(dev->name, priv); + ethoc_phy_init(priv, dev); + return 0; } @@ -660,6 +795,11 @@ static int ethoc_remove(struct udevice *dev) { struct ethoc *priv = dev_get_priv(dev); +#ifdef CONFIG_PHYLIB + free(priv->phydev); + mdio_unregister(priv->bus); + mdio_free(priv->bus); +#endif iounmap(priv->iobase); return 0; }