From patchwork Wed Aug 15 20:40:16 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Troy Kisky X-Patchwork-Id: 177806 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 EDED52C0085 for ; Thu, 16 Aug 2012 06:40:47 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B56A12815E; Wed, 15 Aug 2012 22:40:38 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 L6LIKOPYOeJc; Wed, 15 Aug 2012 22:40:38 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 849662813F; Wed, 15 Aug 2012 22:40:25 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6366D28122 for ; Wed, 15 Aug 2012 22:40:22 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de 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 ilqc6fptSyg7 for ; Wed, 15 Aug 2012 22:40:21 +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-pb0-f44.google.com (mail-pb0-f44.google.com [209.85.160.44]) by theia.denx.de (Postfix) with ESMTPS id 18A5E28126 for ; Wed, 15 Aug 2012 22:40:19 +0200 (CEST) Received: by pbbrr4 with SMTP id rr4so400922pbb.3 for ; Wed, 15 Aug 2012 13:40:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:x-gm-message-state; bh=cvqfJvo1n+4YJG2Ue+Xp3HBDkDDhsffuCZf/mM0A644=; b=aYWJyuMvpBiZ2CCB5y0IMx9mOMGCXAdYZcQ0RGFEGLvC+K6+tXWl1TVELNB0950AL5 EzGv2ZyT9cWBUUr9XJ4/c1YYMD+EG1mxRvfNOOCdnG7l7Q6zN745hl0rRe3l1TY2L7Gr 5ZhKRSiphJSEVuAlhPmvzgh/8WEZGN2CZ3AtPAsqB/MbUpV6V9l7cN5x9lDX7w8qjKIz nTM4Pos2vwX8j5J1kmkMC0XEgWvTiNKGKNR8fk+fq8DVgwgHgvOMpHgo1ATtvj7y9JDv pI6itWotf0jHUhNWjn1/TtLx0jCSySXIWG5VYayiE7jjV691JQg+NepnRrI7NxT/sdgM G41w== Received: by 10.68.141.80 with SMTP id rm16mr9575848pbb.23.1345063217631; Wed, 15 Aug 2012 13:40:17 -0700 (PDT) Received: from officeserver-2 ([70.96.116.236]) by mx.google.com with ESMTPS id vd4sm1072751pbc.41.2012.08.15.13.40.15 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 15 Aug 2012 13:40:16 -0700 (PDT) Received: from tkisky by officeserver-2 with local (Exim 4.76) (envelope-from ) id 1T1kO4-00050i-2T; Wed, 15 Aug 2012 13:40:20 -0700 From: Troy Kisky To: u-boot@lists.denx.de, Joe Hershberger , sbabic@denx.de, dirk.behme@googlemail.com Date: Wed, 15 Aug 2012 13:40:16 -0700 Message-Id: <1345063218-19228-1-git-send-email-troy.kisky@boundarydevices.com> X-Mailer: git-send-email 1.7.9.5 X-Gm-Message-State: ALoCoQm0Cg7c5JYBfcogbrQdj8pTM93cjWuOxSXvPFu8Vz8qoj4JlkTezV/9I52J4U1U5vzu2Qzi Cc: r49496@freescale.com, afleming@gmail.com Subject: [U-Boot] [PATCH 1/3] phy: add phy_connect_by_mask X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de It is useful to be able to try a range of possible phy addresses to connect. Signed-off-by: Troy Kisky --- drivers/net/phy/phy.c | 108 +++++++++++++++++++++++++++++++------------------ include/phy.h | 2 + 2 files changed, 71 insertions(+), 39 deletions(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index baef60f..a22d2e0 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -31,6 +31,7 @@ #include #include #include +#include /* Generic PHY support and helper functions */ @@ -573,6 +574,61 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) return 0; } +static struct phy_device *create_phy_by_mask(struct mii_dev *bus, + unsigned phy_mask, int devad, phy_interface_t interface) +{ + u32 phy_id = 0xffffffff; + while (phy_mask) { + int addr = ffs(phy_mask) - 1; + int r = get_phy_id(bus, addr, devad, &phy_id); + if (r < 0) + return ERR_PTR(r); + /* If the PHY ID is mostly f's, we didn't find anything */ + if ((phy_id & 0x1fffffff) != 0x1fffffff) + return phy_device_create(bus, addr, phy_id, interface); + phy_mask &= ~(1 << addr); + } + return NULL; +} + +static struct phy_device *search_for_existing_phy(struct mii_dev *bus, + unsigned phy_mask, phy_interface_t interface) +{ + /* If we have one, return the existing device, with new interface */ + while (phy_mask) { + int addr = ffs(phy_mask) - 1; + if (bus->phymap[addr]) { + bus->phymap[addr]->interface = interface; + return bus->phymap[addr]; + } + phy_mask &= ~(1 << addr); + } + return NULL; +} + +static struct phy_device *get_phy_device_by_mask(struct mii_dev *bus, + unsigned phy_mask, phy_interface_t interface) +{ + int i; + struct phy_device *phydev; + + phydev = search_for_existing_phy(bus, phy_mask, interface); + if (phydev) + return phydev; + /* Try Standard (ie Clause 22) access */ + /* Otherwise we have to try Clause 45 */ + for (i = 0; i < 5; i++) { + phydev = create_phy_by_mask(bus, phy_mask, + i ? i : MDIO_DEVAD_NONE, interface); + if (IS_ERR(phydev)) + return NULL; + if (phydev) + return phydev; + } + printf("Phy not found\n"); + return phy_device_create(bus, ffs(phy_mask) - 1, 0xffffffff, interface); +} + /** * get_phy_device - reads the specified PHY device and returns its @phy_device struct * @bus: the target MII bus @@ -584,38 +640,7 @@ int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id) struct phy_device *get_phy_device(struct mii_dev *bus, int addr, phy_interface_t interface) { - u32 phy_id = 0x1fffffff; - int i; - int r; - - /* If we have one, return the existing device, with new interface */ - if (bus->phymap[addr]) { - bus->phymap[addr]->interface = interface; - - return bus->phymap[addr]; - } - - /* Try Standard (ie Clause 22) access */ - r = get_phy_id(bus, addr, MDIO_DEVAD_NONE, &phy_id); - if (r) - return NULL; - - /* If the PHY ID is mostly f's, we didn't find anything */ - if ((phy_id & 0x1fffffff) != 0x1fffffff) - return phy_device_create(bus, addr, phy_id, interface); - - /* Otherwise we have to try Clause 45 */ - for (i = 1; i < 5; i++) { - r = get_phy_id(bus, addr, i, &phy_id); - if (r) - return NULL; - - /* If the phy_id is mostly Fs, there is no device there */ - if ((phy_id & 0x1fffffff) != 0x1fffffff) - break; - } - - return phy_device_create(bus, addr, phy_id, interface); + return get_phy_device_by_mask(bus, 1 << addr, interface); } int phy_reset(struct phy_device *phydev) @@ -688,9 +713,8 @@ int miiphy_reset(const char *devname, unsigned char addr) return phy_reset(phydev); } -struct phy_device *phy_connect(struct mii_dev *bus, int addr, - struct eth_device *dev, - phy_interface_t interface) +struct phy_device *phy_connect_by_mask(struct mii_dev *bus, unsigned phy_mask, + struct eth_device *dev, phy_interface_t interface) { struct phy_device *phydev; @@ -701,11 +725,11 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr, /* Wait 15ms to make sure the PHY has come out of hard reset */ udelay(15000); - phydev = get_phy_device(bus, addr, interface); + phydev = get_phy_device_by_mask(bus, phy_mask, interface); if (!phydev) { - printf("Could not get PHY for %s:%d\n", bus->name, addr); - + printf("Could not get PHY for %s: phy mask %x\n", + bus->name, phy_mask); return NULL; } @@ -714,7 +738,7 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr, if (phydev->dev) printf("%s:%d is connected to %s. Reconnecting to %s\n", - bus->name, addr, phydev->dev->name, dev->name); + bus->name, phydev->addr, phydev->dev->name, dev->name); phydev->dev = dev; @@ -723,6 +747,12 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr, return phydev; } +struct phy_device *phy_connect(struct mii_dev *bus, int addr, + struct eth_device *dev, phy_interface_t interface) +{ + return phy_connect_by_mask(bus, 1 << addr, dev, interface); +} + /* * Start the PHY. Returns 0 on success, or a negative error code. */ diff --git a/include/phy.h b/include/phy.h index 3c30f11..aea462f 100644 --- a/include/phy.h +++ b/include/phy.h @@ -202,6 +202,8 @@ int phy_reset(struct phy_device *phydev); struct phy_device *phy_connect(struct mii_dev *bus, int addr, struct eth_device *dev, phy_interface_t interface); +struct phy_device *phy_connect_by_mask(struct mii_dev *bus, unsigned phy_mask, + struct eth_device *dev, phy_interface_t interface); int phy_startup(struct phy_device *phydev); int phy_config(struct phy_device *phydev); int phy_shutdown(struct phy_device *phydev);