From patchwork Fri Aug 5 15:26:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 656239 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 3s5W065z5Jz9t0F for ; Sat, 6 Aug 2016 01:27:50 +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=Zheq6XK5; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 3A330A7577; Fri, 5 Aug 2016 17:27:32 +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 vXumcGSknjm9; Fri, 5 Aug 2016 17:27:32 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5A669A751C; Fri, 5 Aug 2016 17:27:13 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9D6B84BF90 for ; Fri, 5 Aug 2016 17:27:06 +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 k10eb5GCmUAI for ; Fri, 5 Aug 2016 17:27:06 +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-f66.google.com (mail-lf0-f66.google.com [209.85.215.66]) by theia.denx.de (Postfix) with ESMTPS id 1BDAE4BB1A for ; Fri, 5 Aug 2016 17:27:05 +0200 (CEST) Received: by mail-lf0-f66.google.com with SMTP id f93so17028119lfi.0 for ; Fri, 05 Aug 2016 08:27:05 -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=pz3IDttCr5+V8UfNBEd1AVzuGDKQEFTLhK/kk7f7wCE=; b=Zheq6XK5e50Pmkp6o4eJazf+Ph+PuTMxXk6rNWpUYglxqaH6/R8ZVhJW020T00XMn0 1526M5bPgNjt4xO5vnppiRCQQefnoBz3GMjz0ODrcsnXpnk1fQadSbJNTc7eodlFZXmD fPFvPWUufZaNiVbN5jkvarZbNua88G/QcMOw6X3SCi4yDZp0alAgomPhtixqvszl6T5o JBcmLlZYbeBoDwGeuNlzSKgCZXOSpg/ikGlfmiKccHC/0XgAu0/Y/py7mOjy0G/yPuli 8u94mQ+7cm/fc2CAXiX/fFUo0iEi5e7rXsiokiODmZS2BA7RlVW5zye+/e/5coqVYRKY AJMQ== 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=pz3IDttCr5+V8UfNBEd1AVzuGDKQEFTLhK/kk7f7wCE=; b=GbBidwkV9qdhioGD73uWhigfy/WYdfHWmX0B0Gh37QVFuYLP+QeUcYg7gA5pQMhEU4 2HvQE46vEy/yYlPC860WUQnH0eaBsuzo34Y7MWfxogm0WXOQro2N1VE+UZvX/2BahS5B enaZj2zw4zQ5+pT6rzuBTeS4Iuxi27oFOpxf0G0ulAovAE4M/TTqkSv/lus75XblFCsB L6/bnydPObFPu3HyyrCT2TyBODS5X7PJkbdgO+jKEizzDqKAqgFflRY7B009wscrXEhV 0JMZ8gyqo1djqA3u6/EgOLGyptMeeGnY1oQB1/rK2twjnve7L3QW5/lqRUzuOfFNMrAF iWpg== X-Gm-Message-State: AEkoouvolOPugXZnWd5jTGOOvgf+7504NUUG0Wpp5OS0nhTmadVpaQII3SybcumZXBfaZA== X-Received: by 10.25.142.204 with SMTP id q195mr21673773lfd.220.1470410824420; Fri, 05 Aug 2016 08:27:04 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by smtp.gmail.com with ESMTPSA id u11sm3211980lja.12.2016.08.05.08.27.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 05 Aug 2016 08:27:03 -0700 (PDT) From: Max Filippov To: u-boot@lists.denx.de Date: Fri, 5 Aug 2016 18:26:21 +0300 Message-Id: <1470410781-7944-8-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1470410781-7944-1-git-send-email-jcmvbkbc@gmail.com> References: <1470410781-7944-1-git-send-email-jcmvbkbc@gmail.com> Cc: Joe Hershberger Subject: [U-Boot] [PATCH v2 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 Acked-by: Joe Hershberger --- Changes v1->v2: - use wait_for_bit in ethoc_mdio_read/ethoc_mdio_write; - remove stray ioremap removal. drivers/net/ethoc.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 150 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index d825aaa..ad8c462 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -18,6 +18,7 @@ #include #include #include +#include /* register offsets */ #define MODER 0x00 @@ -181,6 +182,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 }; /** @@ -193,14 +199,19 @@ struct ethoc_bd { u32 addr; }; +static inline u32 *ethoc_reg(struct ethoc *priv, size_t offset) +{ + return priv->iobase + offset; +} + static inline u32 ethoc_read(struct ethoc *priv, size_t offset) { - return readl(priv->iobase + offset); + return readl(ethoc_reg(priv, offset)); } static inline void ethoc_write(struct ethoc *priv, size_t offset, u32 data) { - writel(data, priv->iobase + offset); + writel(data, ethoc_reg(priv, offset)); } static inline void ethoc_read_bd(struct ethoc *priv, int index, @@ -319,13 +330,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,6 +538,110 @@ 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; + int rc; + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg)); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ); + + rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS), + MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false); + + if (rc == 0) { + u32 data = ethoc_read(priv, MIIRX_DATA); + + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + return data; + } + return rc; +} + +static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct ethoc *priv = bus->priv; + int rc; + + ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg)); + ethoc_write(priv, MIITX_DATA, val); + ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE); + + rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS), + MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false); + + if (rc == 0) { + /* reset MII command register */ + ethoc_write(priv, MIICOMMAND, 0); + } + return rc; +} + +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 + #ifdef CONFIG_DM_ETH static int ethoc_write_hwaddr(struct udevice *dev) @@ -548,9 +681,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) @@ -576,6 +707,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; } @@ -583,6 +718,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; } @@ -687,6 +827,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; }