From patchwork Thu Oct 13 14:37:40 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Fleming X-Patchwork-Id: 119543 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 7A043B7255 for ; Fri, 14 Oct 2011 01:37:55 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755864Ab1JMOht (ORCPT ); Thu, 13 Oct 2011 10:37:49 -0400 Received: from am1ehsobe004.messaging.microsoft.com ([213.199.154.207]:15379 "EHLO AM1EHSOBE004.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755543Ab1JMOhr (ORCPT ); Thu, 13 Oct 2011 10:37:47 -0400 Received: from mail21-am1-R.bigfish.com (10.3.201.245) by AM1EHSOBE004.bigfish.com (10.3.204.24) with Microsoft SMTP Server id 14.1.225.22; Thu, 13 Oct 2011 14:37:45 +0000 Received: from mail21-am1 (localhost.localdomain [127.0.0.1]) by mail21-am1-R.bigfish.com (Postfix) with ESMTP id BE1442B00DE; Thu, 13 Oct 2011 14:37:45 +0000 (UTC) X-SpamScore: 8 X-BigFish: VS8(z1039oz1fa4Jc8kzz1202hzz8275bhz2dh2a8h668h839h) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPVD:NLI; H:mail.freescale.net; RD:none; EFVD:NLI Received: from mail21-am1 (localhost.localdomain [127.0.0.1]) by mail21-am1 (MessageSwitch) id 1318516665469557_3941; Thu, 13 Oct 2011 14:37:45 +0000 (UTC) Received: from AM1EHSMHS008.bigfish.com (unknown [10.3.201.248]) by mail21-am1.bigfish.com (Postfix) with ESMTP id 628A417D8054; Thu, 13 Oct 2011 14:37:45 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by AM1EHSMHS008.bigfish.com (10.3.207.108) with Microsoft SMTP Server (TLS) id 14.1.225.22; Thu, 13 Oct 2011 14:37:44 +0000 Received: from az33smr01.freescale.net (10.64.34.199) by 039-SN1MMR1-002.039d.mgd.msft.net (10.84.1.15) with Microsoft SMTP Server id 14.1.339.2; Thu, 13 Oct 2011 09:37:42 -0500 Received: from localhost (right.am.freescale.net [10.82.193.13]) by az33smr01.freescale.net (8.13.1/8.13.0) with ESMTP id p9DEbgIS009898; Thu, 13 Oct 2011 09:37:42 -0500 (CDT) From: Andy Fleming To: CC: Subject: [PATCH v3 3/3] phylib: Add rudimentary Generic 10G support Date: Thu, 13 Oct 2011 09:37:40 -0500 Message-ID: <1318516660-25452-4-git-send-email-afleming@freescale.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1318516660-25452-1-git-send-email-afleming@freescale.com> References: <1318516660-25452-1-git-send-email-afleming@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This is mostly taken from mdio.c, and modified to work under phylib. However, the support is skewed toward 10GBaseT, as that is the only PHY available to me at this time. Signed-off-by: Andy Fleming --- v2: split off from 10G API changes v3: Make patch series more coherent drivers/net/phy/phy_device.c | 118 ++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 118 insertions(+), 0 deletions(-) diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 22281d4..e2ee8dd 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -10,6 +10,7 @@ * * Copyright (c) 2004-2006, 2008-2011 Freescale Semiconductor, Inc. * + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your @@ -54,6 +55,7 @@ static void phy_device_release(struct device *dev) } static struct phy_driver genphy_driver; +static struct phy_driver gen10g_driver; extern int mdio_bus_init(void); extern void mdio_bus_exit(void); @@ -439,6 +441,9 @@ int phy_init_hw(struct phy_device *phydev) static struct phy_driver *generic_for_interface(phy_interface_t interface) { + if (is_10g_interface(interface)) + return &gen10g_driver; + return &genphy_driver; } @@ -632,6 +637,12 @@ static int genphy_config_advert(struct phy_device *phydev) return changed; } +int gen10g_config_advert(struct phy_device *dev) +{ + return 0; +} +EXPORT_SYMBOL(gen10g_config_advert); + /** * genphy_setup_forced - configures/forces speed/duplex from @phydev * @phydev: target phy_device struct @@ -660,6 +671,11 @@ static int genphy_setup_forced(struct phy_device *phydev) return err; } +int gen10g_setup_forced(struct phy_device *phydev) +{ + return 0; +} + /** * genphy_restart_aneg - Enable and Restart Autonegotiation * @phydev: target phy_device struct @@ -684,6 +700,13 @@ int genphy_restart_aneg(struct phy_device *phydev) } EXPORT_SYMBOL(genphy_restart_aneg); +int gen10g_restart_aneg(struct phy_device *phydev) +{ + return 0; +} +EXPORT_SYMBOL(gen10g_restart_aneg); + + /** * genphy_config_aneg - restart auto-negotiation or write BMCR * @phydev: target phy_device struct @@ -725,6 +748,12 @@ int genphy_config_aneg(struct phy_device *phydev) } EXPORT_SYMBOL(genphy_config_aneg); +int gen10g_config_aneg(struct phy_device *phydev) +{ + return 0; +} +EXPORT_SYMBOL(gen10g_config_aneg); + /** * genphy_update_link - update link status in @phydev * @phydev: target phy_device struct @@ -854,6 +883,33 @@ int genphy_read_status(struct phy_device *phydev) } EXPORT_SYMBOL(genphy_read_status); +int gen10g_read_status(struct phy_device *phydev) +{ + int devad, reg; + u32 mmd_mask = phydev->mmds; + + phydev->link = 1; + + /* For now just lie and say it's 10G all the time */ + phydev->speed = 10000; + phydev->duplex = DUPLEX_FULL; + + for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) { + if (!mmd_mask & 1) + continue; + + /* Read twice because link state is latched and a + * read moves the current state into the register */ + phy45_read(phydev, devad, MDIO_STAT1); + reg = phy45_read(phydev, devad, MDIO_STAT1); + if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS)) + phydev->link = 0; + } + + return 0; +} +EXPORT_SYMBOL(gen10g_read_status); + static int genphy_config_init(struct phy_device *phydev) { int val; @@ -901,6 +957,35 @@ static int genphy_config_init(struct phy_device *phydev) return 0; } +/* Replicate mdio45_probe */ +int gen10g_config_init(struct phy_device *phydev) +{ + int mmd, stat2, devs1, devs2; + + phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full; + + /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY + * XS or DTE XS; give up if none is present. */ + for (mmd = 1; mmd <= 5; mmd++) { + /* Is this MMD present? */ + stat2 = phy45_read(phydev, mmd, MDIO_STAT2); + if (stat2 < 0 || + (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) + continue; + + /* It should tell us about all the other MMDs */ + devs1 = phy45_read(phydev, mmd, MDIO_DEVS1); + devs2 = phy45_read(phydev, mmd, MDIO_DEVS2); + if (devs1 < 0 || devs2 < 0) + continue; + + phydev->mmds = devs1 | (devs2 << 16); + return 0; + } + + return -ENODEV; +} + int genphy_suspend(struct phy_device *phydev) { int value; @@ -916,6 +1001,12 @@ int genphy_suspend(struct phy_device *phydev) } EXPORT_SYMBOL(genphy_suspend); +int gen10g_suspend(struct phy_device *phydev) +{ + return 0; +} +EXPORT_SYMBOL(gen10g_suspend); + int genphy_resume(struct phy_device *phydev) { int value; @@ -931,6 +1022,13 @@ int genphy_resume(struct phy_device *phydev) } EXPORT_SYMBOL(genphy_resume); +int gen10g_resume(struct phy_device *phydev) +{ + return 0; +} +EXPORT_SYMBOL(gen10g_resume); + + /** * phy_probe - probe and init a PHY device * @dev: device to probe and init @@ -1044,6 +1142,19 @@ static struct phy_driver genphy_driver = { .driver = {.owner = THIS_MODULE, }, }; +static struct phy_driver gen10g_driver = { + .phy_id = 0xffffffff, + .phy_id_mask = 0xffffffff, + .name = "Generic 10G PHY", + .config_init = gen10g_config_init, + .features = 0, + .config_aneg = gen10g_config_aneg, + .read_status = gen10g_read_status, + .suspend = gen10g_suspend, + .resume = gen10g_resume, + .driver = {.owner = THIS_MODULE, }, +}; + static int __init phy_init(void) { int rc; @@ -1056,8 +1167,14 @@ static int __init phy_init(void) if (rc) goto genphy_register_failed; + rc = phy_driver_register(&gen10g_driver); + if (rc) + goto gen10g_register_failed; + return rc; +gen10g_register_failed: + phy_driver_unregister(&genphy_driver); genphy_register_failed: mdio_bus_exit(); @@ -1066,6 +1183,7 @@ genphy_register_failed: static void __exit phy_exit(void) { + phy_driver_unregister(&gen10g_driver); phy_driver_unregister(&genphy_driver); mdio_bus_exit(); }