From patchwork Tue Jan 27 16:51:11 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Glendinning X-Patchwork-Id: 20468 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.176.167]) by ozlabs.org (Postfix) with ESMTP id 3D0CF4F384 for ; Wed, 28 Jan 2009 03:51:30 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756137AbZA0QvV (ORCPT ); Tue, 27 Jan 2009 11:51:21 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756092AbZA0QvU (ORCPT ); Tue, 27 Jan 2009 11:51:20 -0500 Received: from [86.54.240.114] ([86.54.240.114]:53200 "EHLO kensington.shawell.net" rhost-flags-FAIL-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1755781AbZA0QvR (ORCPT ); Tue, 27 Jan 2009 11:51:17 -0500 Received: from localhost.localdomain (kensington.shawell.net [127.0.0.1]) by kensington.shawell.net (Postfix) with ESMTP id CCAA44A4113; Tue, 27 Jan 2009 16:51:17 +0000 (GMT) From: Steve Glendinning To: linux-arm-kernel@lists.arm.linux.org.uk, netdev@vger.kernel.org Cc: David Miller , Russell King , Stanley Miao , Ian Saturley , Mark Brown , Catalin Marinas , Steve Glendinning Subject: [PATCH 03/10] smsc911x: add external phy detection overrides Date: Tue, 27 Jan 2009 16:51:11 +0000 Message-Id: <1233075077-17205-4-git-send-email-steve.glendinning@smsc.com> X-Mailer: git-send-email 1.6.0.6 In-Reply-To: <1233075077-17205-3-git-send-email-steve.glendinning@smsc.com> References: <1233075077-17205-1-git-send-email-steve.glendinning@smsc.com> <1233075077-17205-2-git-send-email-steve.glendinning@smsc.com> <1233075077-17205-3-git-send-email-steve.glendinning@smsc.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On LAN9115/LAN9117/LAN9215/LAN9217, external phys are supported. These are usually indicated by a hardware strap which sets an "external PHY detected" bit in the HW_CFG register. In some cases it is desirable to override this hardware strap and force use of either the internal phy or an external PHY. This patch adds SMSC911X_FORCE_INTERNAL_PHY and SMSC911X_FORCE_EXTERNAL_PHY flags so a platform can indicate this preference via its platform_data. Signed-off-by: Steve Glendinning Acked-by: Sascha Hauer Tested-by: Sascha Hauer --- drivers/net/smsc911x.c | 75 +++++++++++++++++++++++---------------------- include/linux/smsc911x.h | 2 + 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index f882fd5..c7379f5 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -368,48 +368,53 @@ out: return reg; } -/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 flavors. - * If something goes wrong, returns -ENODEV to revert back to internal phy. - * Performed at initialisation only, so interrupts are enabled */ -static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata) +/* Switch to external phy. Assumes tx and rx are stopped. */ +static void smsc911x_phy_enable_external(struct smsc911x_data *pdata) { unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); - /* External phy is requested, supported, and detected */ - if (hwcfg & HW_CFG_EXT_PHY_DET_) { + /* Disable phy clocks to the MAC */ + hwcfg &= (~HW_CFG_PHY_CLK_SEL_); + hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); + udelay(10); /* Enough time for clocks to stop */ - /* Switch to external phy. Assuming tx and rx are stopped - * because smsc911x_phy_initialise is called before - * smsc911x_rx_initialise and tx_initialise. */ + /* Switch to external phy */ + hwcfg |= HW_CFG_EXT_PHY_EN_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); - /* Disable phy clocks to the MAC */ - hwcfg &= (~HW_CFG_PHY_CLK_SEL_); - hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); - udelay(10); /* Enough time for clocks to stop */ + /* Enable phy clocks to the MAC */ + hwcfg &= (~HW_CFG_PHY_CLK_SEL_); + hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); + udelay(10); /* Enough time for clocks to restart */ - /* Switch to external phy */ - hwcfg |= HW_CFG_EXT_PHY_EN_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); - - /* Enable phy clocks to the MAC */ - hwcfg &= (~HW_CFG_PHY_CLK_SEL_); - hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); - udelay(10); /* Enough time for clocks to restart */ + hwcfg |= HW_CFG_SMI_SEL_; + smsc911x_reg_write(pdata, HW_CFG, hwcfg); +} - hwcfg |= HW_CFG_SMI_SEL_; - smsc911x_reg_write(pdata, HW_CFG, hwcfg); +/* Autodetects and enables external phy if present on supported chips. + * autodetection can be overridden by specifying SMSC911X_FORCE_INTERNAL_PHY + * or SMSC911X_FORCE_EXTERNAL_PHY in the platform_data flags. */ +static void smsc911x_phy_initialise_external(struct smsc911x_data *pdata) +{ + unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); - SMSC_TRACE(HW, "Successfully switched to external PHY"); + if (pdata->config.flags & SMSC911X_FORCE_INTERNAL_PHY) { + SMSC_TRACE(HW, "Forcing internal PHY"); + pdata->using_extphy = 0; + } else if (pdata->config.flags & SMSC911X_FORCE_EXTERNAL_PHY) { + SMSC_TRACE(HW, "Forcing external PHY"); + smsc911x_phy_enable_external(pdata); + pdata->using_extphy = 1; + } else if (hwcfg & HW_CFG_EXT_PHY_DET_) { + SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET set, using external PHY"); + smsc911x_phy_enable_external(pdata); pdata->using_extphy = 1; } else { - SMSC_WARNING(HW, "No external PHY detected, " - "Using internal PHY instead."); - /* Use internal phy */ - return -ENODEV; + SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET clear, using internal PHY"); + pdata->using_extphy = 0; } - return 0; } /* Fetches a tx status out of the status fifo */ @@ -824,22 +829,18 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev, pdata->mii_bus->parent = &pdev->dev; - pdata->using_extphy = 0; - switch (pdata->idrev & 0xFFFF0000) { case 0x01170000: case 0x01150000: case 0x117A0000: case 0x115A0000: /* External PHY supported, try to autodetect */ - if (smsc911x_phy_initialise_external(pdata) < 0) { - SMSC_TRACE(HW, "No external PHY detected, " - "using internal PHY"); - } + smsc911x_phy_initialise_external(pdata); break; default: SMSC_TRACE(HW, "External PHY is not supported, " "using internal PHY"); + pdata->using_extphy = 0; break; } diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index 1cbf031..170c76b 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -43,5 +43,7 @@ struct smsc911x_platform_config { /* Constants for flags */ #define SMSC911X_USE_16BIT (BIT(0)) #define SMSC911X_USE_32BIT (BIT(1)) +#define SMSC911X_FORCE_INTERNAL_PHY (BIT(2)) +#define SMSC911X_FORCE_EXTERNAL_PHY (BIT(3)) #endif /* __LINUX_SMSC911X_H__ */