From patchwork Mon Oct 14 23:59:00 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Soren Brinkmann X-Patchwork-Id: 283427 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 125222C032D for ; Tue, 15 Oct 2013 11:00:12 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758037Ab3JNX7n (ORCPT ); Mon, 14 Oct 2013 19:59:43 -0400 Received: from mail-pb0-f54.google.com ([209.85.160.54]:54467 "EHLO mail-pb0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757784Ab3JNX7d (ORCPT ); Mon, 14 Oct 2013 19:59:33 -0400 Received: by mail-pb0-f54.google.com with SMTP id ro12so8014494pbb.27 for ; Mon, 14 Oct 2013 16:59:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=VrSKKENFLwKIh6jkoRbP9fHKZBZe+Yh63TqVQR4UbsY=; b=QavDrcNrUTtpbbLjLhzC66U/irxbyd+qe0Ds3ETPTyoV24tYjbfwv73A2Eg6FTBZv+ h50Sr98QoM0xpWB4mVV39+4kMvpZT9xxcdpZbgtNtzlM+CqTfNo3UsYHmB0w4Hd9OQDb CIH8U1kUukTQgnhMoaIrBXBlza9jfg+rsikWtOhZYam9nH1HDZJ/n28U8dClVauyPZxo tPc8mz2wi4cNzUWPnmszJCXorYVscXBas+cn9VR2KiML0SkOSE+Dn94c3J7u7Rk1tT37 dCljvDESIBuNkda0f+VM8wlP31nogl2RpCbIZPoJBsEepYejkrDbedFkiADA5Ub+KtJF ypLA== X-Received: by 10.67.23.227 with SMTP id id3mr40625131pad.101.1381795172995; Mon, 14 Oct 2013 16:59:32 -0700 (PDT) Received: from localhost ([149.199.62.254]) by mx.google.com with ESMTPSA id yo2sm94317034pab.8.1969.12.31.16.00.00 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 14 Oct 2013 16:59:32 -0700 (PDT) From: Soren Brinkmann To: Nicolas Ferre Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Michal Simek , Soren Brinkmann Subject: [PATCH RFC 5/5] net: macb: Adjust tx_clk when link speed changes Date: Mon, 14 Oct 2013 16:59:00 -0700 Message-Id: <1381795140-10792-6-git-send-email-soren.brinkmann@xilinx.com> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1381795140-10792-1-git-send-email-soren.brinkmann@xilinx.com> References: <1381795140-10792-1-git-send-email-soren.brinkmann@xilinx.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Adjust the ethernet clock according to the negotiated link speed. Signed-off-by: Soren Brinkmann --- drivers/net/ethernet/cadence/macb.c | 66 +++++++++++++++++++++++++++++++++++++ drivers/net/ethernet/cadence/macb.h | 1 + 2 files changed, 67 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 603844b1d483..beb9fa863811 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -204,6 +204,49 @@ static int macb_mdio_reset(struct mii_bus *bus) return 0; } +/** + * macb_set_tx_clk() - Set a clock to a new frequency + * @clk Pointer to the clock to change + * @rate New frequency in Hz + * @dev Pointer to the struct net_device + */ +static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) +{ + long ferr; + long rate; + long rate_rounded; + + switch (speed) { + case SPEED_10: + rate = 2500000; + break; + case SPEED_100: + rate = 25000000; + break; + case SPEED_1000: + rate = 125000000; + break; + default: + break; + } + + rate_rounded = clk_round_rate(clk, rate); + if (rate_rounded < 0) + return; + + /* RGMII allows 50 ppm frequency error. Test and warn if this limit + * are not satisfied. + */ + ferr = abs(rate_rounded - rate); + ferr = DIV_ROUND_UP(ferr, rate / 100000); + if (ferr > 5) + netdev_warn(dev, "unable to generate target frequency: %ld Hz\n", + rate); + + if (clk_set_rate(clk, rate_rounded)) + netdev_err(dev, "adjusting tx_clk failed.\n"); +} + static void macb_handle_link_change(struct net_device *dev) { struct macb *bp = netdev_priv(dev); @@ -251,6 +294,9 @@ static void macb_handle_link_change(struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); + if (!IS_ERR(bp->tx_clk)) + macb_set_tx_clk(bp->tx_clk, phydev->speed, dev); + if (status_change) { if (phydev->link) { netif_carrier_on(dev); @@ -1805,6 +1851,8 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out_free_dev; } + bp->tx_clk = devm_clk_get(&pdev->dev, "tx_clk"); + err = clk_prepare_enable(bp->pclk); if (err) { dev_err(&pdev->dev, "failed to enable pclk (%u)\n", err); @@ -1817,6 +1865,15 @@ static int __init macb_probe(struct platform_device *pdev) goto err_out_disable_pclk; } + if (!IS_ERR(bp->tx_clk)) { + err = clk_prepare_enable(bp->tx_clk); + if (err) { + dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", + err); + goto err_out_disable_hclk; + } + } + bp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); if (!bp->regs) { dev_err(&pdev->dev, "failed to map registers, aborting.\n"); @@ -1917,6 +1974,9 @@ static int __init macb_probe(struct platform_device *pdev) err_out_unregister_netdev: unregister_netdev(dev); err_out_disable_clocks: + if (!IS_ERR(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); +err_out_disable_hclk: clk_disable_unprepare(bp->hclk); err_out_disable_pclk: clk_disable_unprepare(bp->pclk); @@ -1941,6 +2001,8 @@ static int __exit macb_remove(struct platform_device *pdev) kfree(bp->mii_bus->irq); mdiobus_free(bp->mii_bus); unregister_netdev(dev); + if (!IS_ERR(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); free_netdev(dev); @@ -1959,6 +2021,8 @@ static int macb_suspend(struct device *dev) netif_carrier_off(netdev); netif_device_detach(netdev); + if (!IS_ERR(bp->tx_clk)) + clk_disable_unprepare(bp->tx_clk); clk_disable_unprepare(bp->hclk); clk_disable_unprepare(bp->pclk); @@ -1973,6 +2037,8 @@ static int macb_resume(struct device *dev) clk_prepare_enable(bp->pclk); clk_prepare_enable(bp->hclk); + if (!IS_ERR(bp->tx_clk)) + clk_prepare_enable(bp->tx_clk); netif_device_attach(netdev); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index f4076155bed7..51c02442160a 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -572,6 +572,7 @@ struct macb { struct platform_device *pdev; struct clk *pclk; struct clk *hclk; + struct clk *tx_clk; struct net_device *dev; struct napi_struct napi; struct work_struct tx_error_task;