From patchwork Thu Jul 31 21:23:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergei Shtylyov X-Patchwork-Id: 4658991 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id D43789F377 for ; Thu, 31 Jul 2014 21:23:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DB2942012E for ; Thu, 31 Jul 2014 21:23:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id BEBC520121 for ; Thu, 31 Jul 2014 21:23:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752781AbaGaVXf (ORCPT ); Thu, 31 Jul 2014 17:23:35 -0400 Received: from mail-lb0-f177.google.com ([209.85.217.177]:65508 "EHLO mail-lb0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751648AbaGaVXd (ORCPT ); Thu, 31 Jul 2014 17:23:33 -0400 Received: by mail-lb0-f177.google.com with SMTP id s7so2499570lbd.22 for ; Thu, 31 Jul 2014 14:23:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:to:subject:cc:from:organization:date :mime-version:content-type:content-transfer-encoding:message-id; bh=0qw1R0bXmLsdliwLzmb+k2j59ykgCehDSnO9u+Z2+WM=; b=M2EeFTj5iOWhhmYq89bZ1LZf6ycqszh5b3VTF7RvX4iwniWFqGf90qYbt6cQKubX7g y65qryEipMR6xjdPwHIsf8xiO0io26RxR4tR6/O1EPfUCRM8EQUN4+UFV3JJRmT4j3H2 HBMwhAKGLbJJXYvvZH8IpmGpgcyJ8fUrWpztiuS/FhGbjGoSTe8JbYtfoQ6FJ+RHHOUt Mieh3hm6O838FLfy+yhIXhNdUBViMVsXpgE/zX0yo8Yl4wa8G1ySunWB/EEm5NNC5tPc unQpsjb11ZfT1UiIL6wN6W+lmmFhAJ+olEvzqR1/KERhd9p4AkJfm67SXodXZqjHK69x hp8Q== X-Gm-Message-State: ALoCoQkxmDznpcJ3/fB1Fmhx37cdVlQqgfuTLwIWPgjSYPja8DiCfJQH8RM1TFRdRaN9XUL9MeYu X-Received: by 10.112.28.8 with SMTP id x8mr875351lbg.104.1406841812121; Thu, 31 Jul 2014 14:23:32 -0700 (PDT) Received: from wasted.cogentembedded.com (ppp19-216.pppoe.mtu-net.ru. [81.195.19.216]) by mx.google.com with ESMTPSA id l9sm9933619lbh.44.2014.07.31.14.23.30 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 31 Jul 2014 14:23:31 -0700 (PDT) To: netdev@vger.kernel.org, wg@grandegger.com, mkl@pengutronix.de, linux-can@vger.kernel.org Subject: [PATCH v2] rcar_can: support all input clocks Cc: linux-sh@vger.kernel.org, vksavl@gmail.com From: Sergei Shtylyov Organization: Cogent Embedded Date: Fri, 1 Aug 2014 01:23:32 +0400 MIME-Version: 1.0 Message-Id: <201408010123.33528.sergei.shtylyov@cogentembedded.com> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When writing the driver, I didn't give enough attention to the possible sources of the CAN clock: although the value of the CLKR register was specified by the platform data, the driver only handled one case, that is CAN clock being sourced from the clkp1 clock, the same that clocks the whole CAN module. In order to fix that overlook, we'll have to handle the CAN clock separately from the peripheral clock (however, clkp1 will be specified for a CAN device only once)... Signed-off-by: Sergei Shtylyov --- The patch is against the 'linux-can-next.git' repo, however it's a fix, not a new feature. Changes in version 2: - added 'clock_select' local variable in the probe() method; - used ARRAY_SIZE() in the 'clock_select' variable sanity check. drivers/net/can/rcar_can.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: linux-can-next/drivers/net/can/rcar_can.c =================================================================== --- linux-can-next.orig/drivers/net/can/rcar_can.c +++ linux-can-next/drivers/net/can/rcar_can.c @@ -87,6 +87,7 @@ struct rcar_can_priv { struct napi_struct napi; struct rcar_can_regs __iomem *regs; struct clk *clk; + struct clk *can_clk; u8 tx_dlc[RCAR_CAN_FIFO_DEPTH]; u32 tx_head; u32 tx_tail; @@ -505,14 +506,20 @@ static int rcar_can_open(struct net_devi err = clk_prepare_enable(priv->clk); if (err) { - netdev_err(ndev, "clk_prepare_enable() failed, error %d\n", + netdev_err(ndev, "failed to enable periperal clock, error %d\n", err); goto out; } + err = clk_prepare_enable(priv->can_clk); + if (err) { + netdev_err(ndev, "failed to enable CAN clock, error %d\n", + err); + goto out_clock; + } err = open_candev(ndev); if (err) { netdev_err(ndev, "open_candev() failed, error %d\n", err); - goto out_clock; + goto out_can_clock; } napi_enable(&priv->napi); err = request_irq(ndev->irq, rcar_can_interrupt, 0, ndev->name, ndev); @@ -527,6 +534,8 @@ static int rcar_can_open(struct net_devi out_close: napi_disable(&priv->napi); close_candev(ndev); +out_can_clock: + clk_disable_unprepare(priv->can_clk); out_clock: clk_disable_unprepare(priv->clk); out: @@ -565,6 +574,7 @@ static int rcar_can_close(struct net_dev rcar_can_stop(ndev); free_irq(ndev->irq, ndev); napi_disable(&priv->napi); + clk_disable_unprepare(priv->can_clk); clk_disable_unprepare(priv->clk); close_candev(ndev); can_led_event(ndev, CAN_LED_EVENT_STOP); @@ -715,6 +725,12 @@ static int rcar_can_get_berr_counter(con return 0; } +static const char * const clock_names[] = { + [CLKR_CLKP1] = "clkp1", + [CLKR_CLKP2] = "clkp2", + [CLKR_CLKEXT] = "can_clk", +}; + static int rcar_can_probe(struct platform_device *pdev) { struct rcar_can_platform_data *pdata; @@ -722,6 +738,7 @@ static int rcar_can_probe(struct platfor struct net_device *ndev; struct resource *mem; void __iomem *addr; + u32 clock_select; int err = -ENODEV; int irq; @@ -730,6 +747,7 @@ static int rcar_can_probe(struct platfor dev_err(&pdev->dev, "No platform data provided!\n"); goto fail; } + clock_select = pdata->clock_select; irq = platform_get_irq(pdev, 0); if (!irq) { @@ -753,10 +771,22 @@ static int rcar_can_probe(struct platfor priv = netdev_priv(ndev); - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get(&pdev->dev, "clkp1"); if (IS_ERR(priv->clk)) { err = PTR_ERR(priv->clk); - dev_err(&pdev->dev, "cannot get clock: %d\n", err); + dev_err(&pdev->dev, "cannot get peripheral clock: %d\n", err); + goto fail_clk; + } + + if (clock_select >= ARRAY_SIZE(clock_names)) { + err = -EINVAL; + dev_err(&pdev->dev, "invalid CAN clock selected\n"); + goto fail_clk; + } + priv->can_clk = devm_clk_get(&pdev->dev, clock_names[clock_select]); + if (IS_ERR(priv->can_clk)) { + err = PTR_ERR(priv->can_clk); + dev_err(&pdev->dev, "cannot get CAN clock: %d\n", err); goto fail_clk; } @@ -765,8 +795,8 @@ static int rcar_can_probe(struct platfor ndev->flags |= IFF_ECHO; priv->ndev = ndev; priv->regs = addr; - priv->clock_select = pdata->clock_select; - priv->can.clock.freq = clk_get_rate(priv->clk); + priv->clock_select = clock_select; + priv->can.clock.freq = clk_get_rate(priv->can_clk); priv->can.bittiming_const = &rcar_can_bittiming_const; priv->can.do_set_mode = rcar_can_do_set_mode; priv->can.do_get_berr_counter = rcar_can_get_berr_counter;