From patchwork Sat Jun 20 18:38:29 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Lunn X-Patchwork-Id: 487020 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 69FC41401AF for ; Sun, 21 Jun 2015 04:44:31 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932343AbbFTSo1 (ORCPT ); Sat, 20 Jun 2015 14:44:27 -0400 Received: from vps0.lunn.ch ([178.209.37.122]:60042 "EHLO vps0.lunn.ch" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753701AbbFTSo0 (ORCPT ); Sat, 20 Jun 2015 14:44:26 -0400 Received: from andrew by vps0.lunn.ch with local (Exim 4.80) (envelope-from ) id 1Z6Ney-0002vp-3j; Sat, 20 Jun 2015 20:38:32 +0200 From: Andrew Lunn To: David Miller Cc: Nimrod Andy , Duan Andy , Cory Tusar , netdev , Andrew Lunn Subject: [PATCHv3 net-next] net: fec: Ensure clocks are enabled while using mdio bus Date: Sat, 20 Jun 2015 20:38:29 +0200 Message-Id: <1434825509-11241-1-git-send-email-andrew@lunn.ch> X-Mailer: git-send-email 1.7.10.4 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When a switch is attached to the mdio bus, the mdio bus can be used while the interface is not open. If the IPG clock are not enabled, MDIO reads/writes will simply time out. So enable the clock before starting a transaction, and disable it afterwards. The CCF performs reference counting so the clock will only be disabled if there are no other users. Signed-off-by: Andrew Lunn --- v3: Return the error code from clk_prepare_enable() v2: Only enable the IGP clock. drivers/net/ethernet/freescale/fec_main.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index bf4cf3fbb5f2..8d9b1fd175f7 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -65,6 +65,7 @@ static void set_multicast_list(struct net_device *ndev); static void fec_enet_itr_coal_init(struct net_device *ndev); +static int fec_enet_clk_enable(struct net_device *ndev, bool enable); #define DRIVER_NAME "fec" @@ -1764,6 +1765,11 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { struct fec_enet_private *fep = bus->priv; unsigned long time_left; + int ret; + + ret = clk_prepare_enable(fep->clk_ipg); + if (ret) + return ret; fep->mii_timeout = 0; init_completion(&fep->mdio_done); @@ -1779,11 +1785,14 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) if (time_left == 0) { fep->mii_timeout = 1; netdev_err(fep->netdev, "MDIO read timeout\n"); + clk_disable_unprepare(fep->clk_ipg); return -ETIMEDOUT; } - /* return value */ - return FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); + ret = FEC_MMFR_DATA(readl(fep->hwp + FEC_MII_DATA)); + clk_disable_unprepare(fep->clk_ipg); + + return ret; } static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, @@ -1791,10 +1800,15 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, { struct fec_enet_private *fep = bus->priv; unsigned long time_left; + int ret; fep->mii_timeout = 0; init_completion(&fep->mdio_done); + ret = clk_prepare_enable(fep->clk_ipg); + if (ret) + return ret; + /* start a write op */ writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | @@ -1807,9 +1821,12 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, if (time_left == 0) { fep->mii_timeout = 1; netdev_err(fep->netdev, "MDIO write timeout\n"); + clk_disable_unprepare(fep->clk_ipg); return -ETIMEDOUT; } + clk_disable_unprepare(fep->clk_ipg); + return 0; }