From patchwork Tue Dec 30 10:32:04 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: shaohui xie X-Patchwork-Id: 424619 X-Patchwork-Delegate: yorksun@freescale.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 06514140119 for ; Tue, 30 Dec 2014 22:08:46 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1DDDD4B61E; Tue, 30 Dec 2014 12:08:44 +0100 (CET) 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 gc+g+N+s11+m; Tue, 30 Dec 2014 12:08:43 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 918B74B610; Tue, 30 Dec 2014 12:08:43 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9AD194B610 for ; Tue, 30 Dec 2014 12:08:40 +0100 (CET) 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 SF98+ad7RXKJ for ; Tue, 30 Dec 2014 12:08:40 +0100 (CET) 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 na01-bn1-obe.outbound.protection.outlook.com (mail-bn1on0066.outbound.protection.outlook.com [157.56.110.66]) by theia.denx.de (Postfix) with ESMTPS id 242D84B606 for ; Tue, 30 Dec 2014 12:08:36 +0100 (CET) Received: from BN3PR0301CA0039.namprd03.prod.outlook.com (25.160.180.177) by BL2PR03MB1011.namprd03.prod.outlook.com (10.141.182.149) with Microsoft SMTP Server (TLS) id 15.1.26.15; Tue, 30 Dec 2014 10:34:08 +0000 Received: from BY2FFO11FD020.protection.gbl (2a01:111:f400:7c0c::165) by BN3PR0301CA0039.outlook.office365.com (2a01:111:e400:4000::49) with Microsoft SMTP Server (TLS) id 15.1.49.12 via Frontend Transport; Tue, 30 Dec 2014 10:34:08 +0000 Received: from az84smr01.freescale.net (192.88.158.2) by BY2FFO11FD020.mail.protection.outlook.com (10.1.14.137) with Microsoft SMTP Server (TLS) id 15.1.49.13 via Frontend Transport; Tue, 30 Dec 2014 10:34:07 +0000 Received: from titan.ap.freescale.net ([10.192.208.233]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id sBUAY4KW029229; Tue, 30 Dec 2014 03:34:05 -0700 From: To: Date: Tue, 30 Dec 2014 18:32:04 +0800 Message-ID: <1419935524-34134-1-git-send-email-shh.xie@gmail.com> X-Mailer: git-send-email 2.1.0.27.g96db324 X-EOPAttributedMessage: 0 X-Matching-Connectors: 130644092478435475; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () Received-SPF: SoftFail (protection.outlook.com: domain of transitioning gmail.com discourages use of 192.88.158.2 as permitted sender) Authentication-Results: spf=softfail (sender IP is 192.88.158.2) smtp.mailfrom=shh.xie@gmail.com; X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(189002)(199003)(97736003)(6806004)(83322999)(33646002)(47776003)(62966003)(73392002)(104016003)(120916001)(105596002)(89996001)(36756003)(229853001)(19580405001)(61266001)(87572001)(21056001)(99396003)(86152002)(55446002)(86362001)(48376002)(69596002)(2351001)(76482003)(20776003)(77096005)(82202001)(64706001)(107046002)(87936001)(110136001)(106466001)(50226001)(81156004)(68736005)(92566001)(31966008)(81442002)(77156002)(4396001)(50466002)(19580395003)(46102003)(84676001)(50986999)(73972006); DIR:OUT; SFP:1101; SCL:1; SRVR:BL2PR03MB1011; H:az84smr01.freescale.net; FPR:; SPF:SoftFail; MLV:sfv; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: UriScan:; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB1011; X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004); SRVR:BL2PR03MB1011; X-Forefront-PRVS: 04410E544A X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(400003)(401002)(402001); SRVR:BL2PR03MB1011; Cc: yorksun@freescale.com, Shaohui Xie Subject: [U-Boot] [PATCH] phylib: add support for aquantia PHYs X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Shaohui Xie This patch supports AQ1202, AQ2104, AQR105 PHY. Signed-off-by: Shaohui Xie Acked-by: Joe Hershberger --- drivers/net/phy/Makefile | 1 + drivers/net/phy/aquantia.c | 156 +++++++++++++++++++++++++++++++++++++++++++++ drivers/net/phy/phy.c | 3 + include/phy.h | 1 + 4 files changed, 161 insertions(+) create mode 100644 drivers/net/phy/aquantia.c diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 9556536..87d5c9c 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_MV88E6352_SWITCH) += mv88e6352.o obj-$(CONFIG_PHYLIB) += phy.o obj-$(CONFIG_PHYLIB_10G) += generic_10g.o +obj-$(CONFIG_PHY_AQUANTIA) += aquantia.o obj-$(CONFIG_PHY_ATHEROS) += atheros.o obj-$(CONFIG_PHY_BROADCOM) += broadcom.o obj-$(CONFIG_PHY_DAVICOM) += davicom.o diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c new file mode 100644 index 0000000..ef4da4e --- /dev/null +++ b/drivers/net/phy/aquantia.c @@ -0,0 +1,156 @@ +/* + * Aquantia PHY drivers + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Copyright 2014 Freescale Semiconductor, Inc. + */ +#include +#include +#include + +#ifndef CONFIG_PHYLIB_10G +#error The Aquantia PHY needs 10G support +#endif + +#define AQUNTIA_10G_CTL 0x20 +#define AQUNTIA_VENDOR_P1 0xc400 + +#define AQUNTIA_SPEED_LSB_MASK 0x2000 +#define AQUNTIA_SPEED_MSB_MASK 0x40 + +int aquantia_config(struct phy_device *phydev) +{ + u32 val = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR); + + if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { + /* 1000BASE-T mode */ + phydev->advertising = SUPPORTED_1000baseT_Full; + phydev->supported = phydev->advertising; + + val = (val & ~AQUNTIA_SPEED_LSB_MASK) | AQUNTIA_SPEED_MSB_MASK; + phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val); + } else if (phydev->interface == PHY_INTERFACE_MODE_XGMII) { + /* 10GBASE-T mode */ + phydev->advertising = SUPPORTED_10000baseT_Full; + phydev->supported = phydev->advertising; + + if (!(val & AQUNTIA_SPEED_LSB_MASK) || + !(val & AQUNTIA_SPEED_MSB_MASK)) + phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, + AQUNTIA_SPEED_LSB_MASK | + AQUNTIA_SPEED_MSB_MASK); + } else if (phydev->interface == PHY_INTERFACE_MODE_SGMII_2500) { + /* 2.5GBASE-T mode */ + phydev->advertising = SUPPORTED_1000baseT_Full; + phydev->supported = phydev->advertising; + + phy_write(phydev, MDIO_MMD_AN, AQUNTIA_10G_CTL, 1); + phy_write(phydev, MDIO_MMD_AN, AQUNTIA_VENDOR_P1, 0x9440); + } else if (phydev->interface == PHY_INTERFACE_MODE_MII) { + /* 100BASE-TX mode */ + phydev->advertising = SUPPORTED_100baseT_Full; + phydev->supported = phydev->advertising; + + val = (val & ~AQUNTIA_SPEED_MSB_MASK) | AQUNTIA_SPEED_LSB_MASK; + phy_write(phydev, MDIO_MMD_PMAPMD, MII_BMCR, val); + } + return 0; +} + +int aquantia_startup(struct phy_device *phydev) +{ + u32 reg, speed; + int i = 0; + + phydev->duplex = DUPLEX_FULL; + + /* if the AN is still in progress, wait till timeout. */ + phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); + reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); + if (!(reg & MDIO_AN_STAT1_COMPLETE)) { + printf("%s Waiting for PHY auto negotiation to complete", + phydev->dev->name); + do { + udelay(1000); + reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); + if ((i++ % 500) == 0) + printf("."); + } while (!(reg & MDIO_AN_STAT1_COMPLETE) && + i < (4 * PHY_ANEG_TIMEOUT)); + + if (i > PHY_ANEG_TIMEOUT) + printf(" TIMEOUT !\n"); + } + + /* Read twice because link state is latched and a + * read moves the current state into the register */ + phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); + reg = phy_read(phydev, MDIO_MMD_AN, MDIO_STAT1); + if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) + phydev->link = 0; + else + phydev->link = 1; + + speed = phy_read(phydev, MDIO_MMD_PMAPMD, MII_BMCR); + if (speed & AQUNTIA_SPEED_MSB_MASK) { + if (speed & AQUNTIA_SPEED_LSB_MASK) + phydev->speed = SPEED_10000; + else + phydev->speed = SPEED_1000; + } else { + if (speed & AQUNTIA_SPEED_LSB_MASK) + phydev->speed = SPEED_100; + else + phydev->speed = SPEED_10; + } + + return 0; +} + +struct phy_driver aq1202_driver = { + .name = "Aquantia AQ1202", + .uid = 0x3a1b445, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS| + MDIO_MMD_PHYXS | MDIO_MMD_AN | + MDIO_MMD_VEND1), + .config = &aquantia_config, + .startup = &aquantia_startup, + .shutdown = &gen10g_shutdown, +}; + +struct phy_driver aq2104_driver = { + .name = "Aquantia AQ2104", + .uid = 0x3a1b460, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS| + MDIO_MMD_PHYXS | MDIO_MMD_AN | + MDIO_MMD_VEND1), + .config = &aquantia_config, + .startup = &aquantia_startup, + .shutdown = &gen10g_shutdown, +}; + +struct phy_driver aqr105_driver = { + .name = "Aquantia AQR105", + .uid = 0x3a1b4a2, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS| + MDIO_MMD_PHYXS | MDIO_MMD_AN | + MDIO_MMD_VEND1), + .config = &aquantia_config, + .startup = &aquantia_startup, + .shutdown = &gen10g_shutdown, +}; +int phy_aquantia_init(void) +{ + phy_register(&aq1202_driver); + phy_register(&aq2104_driver); + phy_register(&aqr105_driver); + + return 0; +} diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1d6c14f..7b75f85 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -442,6 +442,9 @@ static LIST_HEAD(phy_drivers); int phy_init(void) { +#ifdef CONFIG_PHY_AQUANTIA + phy_aquantia_init(); +#endif #ifdef CONFIG_PHY_ATHEROS phy_atheros_init(); #endif diff --git a/include/phy.h b/include/phy.h index 2fcc328..c84a441 100644 --- a/include/phy.h +++ b/include/phy.h @@ -221,6 +221,7 @@ int gen10g_startup(struct phy_device *phydev); int gen10g_shutdown(struct phy_device *phydev); int gen10g_discover_mmds(struct phy_device *phydev); +int phy_aquantia_init(void); int phy_atheros_init(void); int phy_broadcom_init(void); int phy_davicom_init(void);