From patchwork Thu Oct 22 04:45:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Appana Durga Kedareswara rao X-Patchwork-Id: 7462401 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 48409BEEA4 for ; Thu, 22 Oct 2015 04:49:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0D6E420980 for ; Thu, 22 Oct 2015 04:49:25 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C142F2097D for ; Thu, 22 Oct 2015 04:49:23 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zp7nA-0003E8-LF; Thu, 22 Oct 2015 04:47:56 +0000 Received: from mail-bn1bon0068.outbound.protection.outlook.com ([157.56.111.68] helo=na01-bn1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Zp7mr-0002zv-7n for linux-arm-kernel@lists.infradead.org; Thu, 22 Oct 2015 04:47:43 +0000 Received: from BL2FFO11FD016.protection.gbl (10.173.160.34) by BL2FFO11HUB041.protection.gbl (10.173.161.57) with Microsoft SMTP Server (TLS) id 15.1.300.4; Thu, 22 Oct 2015 04:47:15 +0000 Authentication-Results: spf=pass (sender IP is 149.199.60.83) smtp.mailfrom=xilinx.com; grandegger.com; dkim=none (message not signed) header.d=none;grandegger.com; dmarc=bestguesspass action=none header.from=xilinx.com; Received-SPF: Pass (protection.outlook.com: domain of xilinx.com designates 149.199.60.83 as permitted sender) receiver=protection.outlook.com; client-ip=149.199.60.83; helo=xsj-pvapsmtpgw01; Received: from xsj-pvapsmtpgw01 (149.199.60.83) by BL2FFO11FD016.mail.protection.outlook.com (10.173.160.224) with Microsoft SMTP Server (TLS) id 15.1.300.4 via Frontend Transport; Thu, 22 Oct 2015 04:47:13 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66] helo=xsj-pvapsmtp01) by xsj-pvapsmtpgw01 with esmtp (Exim 4.63) (envelope-from ) id 1Zp7mT-0003nR-3E; Wed, 21 Oct 2015 21:47:13 -0700 Received: from [127.0.0.1] (helo=localhost) by xsj-pvapsmtp01 with smtp (Exim 4.63) (envelope-from ) id 1Zp7mS-00068I-VF; Wed, 21 Oct 2015 21:47:13 -0700 Received: from [172.23.64.207] (helo=xhd-lin64re117.xilinx.com) by xsj-pvapsmtp01 with esmtp (Exim 4.63) (envelope-from ) id 1Zp7kh-0003n2-3D; Wed, 21 Oct 2015 21:45:23 -0700 Received: by xhd-lin64re117.xilinx.com (Postfix, from userid 13614) id 375652090A; Thu, 22 Oct 2015 10:15:22 +0530 (IST) From: Kedareswara rao Appana To: , , , , Subject: [PATCH v6] can: xilinx: Convert to runtime_pm Date: Thu, 22 Oct 2015 10:15:20 +0530 Message-ID: <1445489120-10933-1-git-send-email-appanad@xilinx.com> X-Mailer: git-send-email 2.1.2 X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.0.0.1202-21892.005 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11FD016; 1:tjF7ywkGWDxWm5mjUKlLA/OfDi5Njc5nVK8qvBPUjYu53+HE1EK/gCi80S8jnROuyAMz0UYlXPrKiWu8OGKuh/ZX/gwbSNUVl4/BdZd9HirW4QdFyzFnrjS3OwHNPRnm2j5qqrOl0vJmKvEDHvQhUtxGLnprOipXMguKY19PsP8XIe3lo6oPASJw7HXJl3N0egksD0LulLxh682kfsdbJpn4Iyd0/YD3bvGLaKVKtDPFCKTGAyC0vZZhwtx537nRG8tjFq5JKv5OfBFu9JU8UdlbZgvkkWsR33rQ1bgY6iwDbXZl/wACOhZOUG24FIL4JtYa4+yu/g8C01qt7T2UPeH7MQ/AS+knK7bo4sTKE3ZTLqcRnDOHdZ+xwp+Hg+QzQy4ZR0WfW75Tf1dWOwgGZQ== X-Forefront-Antispam-Report: CIP:149.199.60.83; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(2980300002)(438002)(189002)(199003)(229853001)(50986999)(86362001)(106466001)(64706001)(52956003)(50226001)(103686003)(189998001)(87936001)(48376002)(107886002)(47776003)(2201001)(33646002)(5001960100002)(19580405001)(36386004)(5001770100001)(46102003)(42186005)(19580395003)(63266004)(81156007)(50466002)(5890100001)(92566002)(45336002)(4001450100002)(5007970100001)(6806005)(11100500001)(36756003)(5003940100001)(46386002)(90966002)(5008740100001)(107986001)(2101003)(4001430100001); DIR:OUT; SFP:1101; SCL:1; SRVR:BL2FFO11HUB041; H:xsj-pvapsmtpgw01; FPR:; SPF:Pass; PTR:unknown-60-83.xilinx.com; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11HUB041; 2:rARlBSveckcBXa9zfkMH9T5U6EeK/JSWlVdb21oPnCYnf9K/MNp+kZBGDbwtH8NeWsgTwhVUgnoJOWcqztUs6DguCGzDgtkhOQktGx9RuqzbADyGjTLYiiG6SbtOj6U55rw/WENA2w1xGTN4OQx/vBy3eZeGaXjE8Srr6Ha2sVw=; 3:iKCdgOcqyjBjwi3Y60+bsfEJi6fUNueZxqZZaIxkmCHwHIFdevBeQ0jH69SPZxd9C2j5E3FcvSKdS+TFhf0bGge4ktb1zbkydp72K30GsVr/lGrjPfM7j9bSUXoL3rB4SY8IQY/0UaQ2Uzie3d1z7KZdRPb34zd73RH+RsCaA5xBgH+iGD9BnDgFaqFsp5eegRrK6MuZL2+UKqEp+bnjHj6d7/qK6lWY9o9XiDrDUnwCR2gSYgGI/UMClF41jLU7qzSwd+N3N4EC8xlaJCjVgQ==; 25:sUMutrDyMUSEn6+Lv6VrgDAzikPuSmZjBz8kLqnGF8k+MwseN9gE/PSGZOSHfnUKrdOTw2whN3okSHnaC/wnS8yYF+Ah4GpEVBcEEv16peu5sD3Ck0yxsZV4is9VmdWYuipm+7faeVG28hVkfICJKxdiA1pOUxxjTGjI6o9OlSpphWEHf0AN35F1kZTtaQ6Q5H6GReZH3B4nRCPbEP4P3lwSfh6e/d9VDwkQmCLVCd+lDTziaRP+79x2mvT4JgdY3sq8diRGWe9hmqx6odKlHw== X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(8251501001); SRVR:BL2FFO11HUB041; X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11HUB041; 20:aAt1ZfJ/tAoC9OUzj4RXO44mAip+MGqij3YQiKa8D3aOMqcxT8xe1GVWIirUoH8qHPLJ28S6clojnT41IcnKYhqs2dkF8VH5xT34Ut4zbWrnq0WLPzuslaUa5uYll+U5V/6lWlu75jf/b0nMXFihp8hPesytlBXHcHO68KEboPs9sbwyAPHCqWnTxVsp/VO7gQ/vYl0eYZ4uOxClyhBAiAOqn8xY2AE6CvDYVpbNcxJOAo/2c8y5yd2Oe81AIqe3zn1iD81efje0G5fUEHFKgSpF+DCDdQI6wrbjAtG5osDm+AtcyawKL5Gy01RMGSZf849o7fVK8rBQ4KENfnuXK5CF4e2NtF3nvwiIXEjAjCdNX94r2PKZpHz1nxwdg9o0DJ/0bwhBT1Yd68OhDPTFlGmM9WgB//VHt5hiQZQ3TaQHJfZZ3/1+WmZmQ0+OT3QqCyEvmE9MR0rtuFw2HEet7CZNAhaK49C8u/YtEbnPn9FeoF/LXx+OSuJ7zsP5Lhgo; 4:43EARYbxfSIaweSU/vBvAb6UKeT8KId7XLSe7Bdk8E2bf4Z3MTqXTd6HCXNX/o8Lyq6kTPc/dICNi7kXuWCQR8tH0665xXOU0Hs8/wH/cqtgoPDetHyChx4Ee+WDqV+ZU11HvyM7mjBTFFHLZhRAB/VdoGgrQzVqasag8n2TELb3GZ3kCrfi/5g1SnumUldJfufckBPIBTkux1m1bfMNAvWFIn6/AmF9kS//3GxSX6HxKrXxHvrd1PYsojw/40OHx3TiPcTalJD6+vP5W1HJTiK7BnsXudLPKp8snfue3+Nb82lTPmAbk/g8Hj911SFCpcRjaxC0wKUZb+YFzLU+973jXAeivvSYufhXpRwvX9lJGMNh+1IW4f4fUMZit1DFYObXohDtqqoNXegRkiS19Q== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(5005006)(520078)(8121501046)(3002001)(10115024)(102215023); SRVR:BL2FFO11HUB041; BCL:0; PCL:0; RULEID:; SRVR:BL2FFO11HUB041; X-Forefront-PRVS: 0737B96801 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BL2FFO11HUB041; 23:MWdBycHgj13l+TpaObNaJqecss8PYg8d6+DHZSxz?= =?us-ascii?Q?wK2oCNsLpY1Dh8K19eOn3HmqC6QxknRm8Wyi0LE/l67Fj6tvbZiVZPSbbAPP?= =?us-ascii?Q?D3QKhEQQY7Gpo4a3Z2oeYvTd8oaCSf6qrJ8rq6sWWwKzZesPuY0ZYT418kNG?= =?us-ascii?Q?rOtiqUVgfxv8a/aj937c67Uje7WgZ4W/MN3HbV34Qtd6FqLcx7pi57YPsQzR?= =?us-ascii?Q?5VxSwyujbSztGJmEHAWFQ8dAZAh5QHf9ItJkGBvG0c7tUe5gg93PUKDvW7AU?= =?us-ascii?Q?EjzrYPtH1WI+FnI/5cUHGNfwr9aJ2m/sQ4j2ATfKIfLOcURMCV2zfMUNckqD?= =?us-ascii?Q?gyeGxwsj4nPhkAtp04o8FuX1pBJsk4HaGEhjv0HEXUKtRwN8wgH5rIu3l1+S?= =?us-ascii?Q?9hxZjGrZvxFxbO9HfcOsIWgUEk8yVpOLQeYRYqQXgTXASdPULre53B/K5aCN?= =?us-ascii?Q?+A9yBQjILYW/LIcv3uqJVUyK6s4/hGTNLyV0+pSaYtVRmXmBxWNFDs4XC5f0?= =?us-ascii?Q?ASzAv49m7qt/vPvc3InSAzbxNtRa15R1wqAb3kqD1JlDPnUAo+TuyoIc8kms?= =?us-ascii?Q?70AoazGhbXitPVi5R91uJP6K+QsXPsoqRZcr7+M+39frU8V9wWQ2qKbVEP/p?= =?us-ascii?Q?GvTJNxQhSK+3Yt71PsEr2S/qyfCQISOQgGgrhuR5i34NxiHkwdHqH3ilwa6B?= =?us-ascii?Q?Py+sTa4/j5z/xJKhlaHDA9+PwcH2pIHKsNhWfxzeVJ3p7VUmmNb0YN0ZnIVf?= =?us-ascii?Q?+CeehAs9MhYfPGTBKC4eVCr3mMfkXnCSQlVJ8PwFdP4yrma0xZKL6TFf1dMl?= =?us-ascii?Q?H/5g2ct9mOKCXRnnYGz8X7UsYbL/V12BGttO3U/bvZBqQwKIbTXRrW4dIN7F?= =?us-ascii?Q?RMOymfznCNDxBvj8zPYdVDiRt5pNFyKgMTxO/uRdymRmdKBYl5TnsaI3/c/K?= =?us-ascii?Q?RQGVFuKM9jtE6bpODdn3a8TEYDJAXe65vRxdRwZkcfL6gU3BHHh50wvDBnLm?= =?us-ascii?Q?QG50ptLvYrFE7xaAG802vdQg9aCO1poq6tqgxVhMmIqQT6MN3qajPrPYna9D?= =?us-ascii?Q?NMR4tqxcAri9ThjIOStE4WeFMYzxt6mBwRQa19sYsD5Y+1HcjMwMfMgY6zqU?= =?us-ascii?Q?oYvkyrmow1BHDauRMfvUTcRZC2BEKkA0EY4SJB38LO8fCuB1lsWp0yQS4GlR?= =?us-ascii?Q?BNnP6a3rDhvX7v94PNF1Y9PMN9TGhJc+UThL?= X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11HUB041; 5:z3l+uvZBE+4EYPjp8+lc5mWTC1EnFozSKwAaLx684m4g1Beg23P0Ax/e5HdDn7wNDZAmFiUWKddvoZ4kGppu9no7CMRFcs98Sap/cnn5lO/67fUZgUNOYbLb4fFt1aodzjRCVQgCyjoChMaeaGm9IA==; 24:vlzOxCkb4iKdWfUXO/Oi5FvXrcNhrSpvxTdZNUOHowSepe+PlMHNWqDT8p5q+vHnTasnUc59abty27L3Hd0hAtet6PXTIKXrjEjIy/m4x+A= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Oct 2015 04:47:13.8238 (UTC) X-MS-Exchange-CrossTenant-Id: 657af505-d5df-48d0-8300-c31994686c5c X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=657af505-d5df-48d0-8300-c31994686c5c; Ip=[149.199.60.83]; Helo=[xsj-pvapsmtpgw01] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL2FFO11HUB041 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151021_214737_853292_6D5E42EC X-CRM114-Status: GOOD ( 17.37 ) X-Spam-Score: -1.9 (-) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: netdev@vger.kernel.org, Kedareswara rao Appana , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-can@vger.kernel.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 Instead of enabling/disabling clocks at several locations in the driver, Use the runtime_pm framework. This consolidates the actions for runtime PM In the appropriate callbacks and makes the driver more readable and mantainable. Signed-off-by: Kedareswara rao Appana --- Sorry for the long delay for sending this next version of the patch. somehow couldn't manage to send this next version of the patch. Changes for v6: - Updated the driver with review comments as suggested by Marc. Changes for v5: - Updated with the review comments. Updated the remove fuction to use runtime_pm. Chnages for v4: - Updated with the review comments. Changes for v3: - Converted the driver to use runtime_pm. Changes for v2: - Removed the struct platform_device* from suspend/resume as suggest by Lothar. drivers/net/can/xilinx_can.c | 176 +++++++++++++++++++++++++++---------------- 1 file changed, 110 insertions(+), 66 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index fc55e8e..6114214 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -32,6 +32,7 @@ #include #include #include +#include #define DRIVER_NAME "xilinx_can" @@ -138,7 +139,7 @@ struct xcan_priv { u32 (*read_reg)(const struct xcan_priv *priv, enum xcan_reg reg); void (*write_reg)(const struct xcan_priv *priv, enum xcan_reg reg, u32 val); - struct net_device *dev; + struct device *dev; void __iomem *reg_base; unsigned long irq_flags; struct clk *bus_clk; @@ -843,6 +844,13 @@ static int xcan_open(struct net_device *ndev) struct xcan_priv *priv = netdev_priv(ndev); int ret; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); + return ret; + } + ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags, ndev->name, ndev); if (ret < 0) { @@ -850,29 +858,17 @@ static int xcan_open(struct net_device *ndev) goto err; } - ret = clk_prepare_enable(priv->can_clk); - if (ret) { - netdev_err(ndev, "unable to enable device clock\n"); - goto err_irq; - } - - ret = clk_prepare_enable(priv->bus_clk); - if (ret) { - netdev_err(ndev, "unable to enable bus clock\n"); - goto err_can_clk; - } - /* Set chip into reset mode */ ret = set_reset_mode(ndev); if (ret < 0) { netdev_err(ndev, "mode resetting failed!\n"); - goto err_bus_clk; + goto err_irq; } /* Common open */ ret = open_candev(ndev); if (ret) - goto err_bus_clk; + goto err_irq; ret = xcan_chip_start(ndev); if (ret < 0) { @@ -888,13 +884,11 @@ static int xcan_open(struct net_device *ndev) err_candev: close_candev(ndev); -err_bus_clk: - clk_disable_unprepare(priv->bus_clk); -err_can_clk: - clk_disable_unprepare(priv->can_clk); err_irq: free_irq(ndev->irq, ndev); err: + pm_runtime_put(priv->dev); + return ret; } @@ -911,12 +905,11 @@ static int xcan_close(struct net_device *ndev) netif_stop_queue(ndev); napi_disable(&priv->napi); xcan_chip_stop(ndev); - clk_disable_unprepare(priv->bus_clk); - clk_disable_unprepare(priv->can_clk); free_irq(ndev->irq, ndev); close_candev(ndev); can_led_event(ndev, CAN_LED_EVENT_STOP); + pm_runtime_put(priv->dev); return 0; } @@ -935,27 +928,20 @@ static int xcan_get_berr_counter(const struct net_device *ndev, struct xcan_priv *priv = netdev_priv(ndev); int ret; - ret = clk_prepare_enable(priv->can_clk); - if (ret) - goto err; - - ret = clk_prepare_enable(priv->bus_clk); - if (ret) - goto err_clk; + ret = pm_runtime_get_sync(priv->dev); + if (ret < 0) { + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); + return ret; + } bec->txerr = priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_TEC_MASK; bec->rxerr = ((priv->read_reg(priv, XCAN_ECR_OFFSET) & XCAN_ECR_REC_MASK) >> XCAN_ESR_REC_SHIFT); - clk_disable_unprepare(priv->bus_clk); - clk_disable_unprepare(priv->can_clk); + pm_runtime_put(priv->dev); return 0; - -err_clk: - clk_disable_unprepare(priv->can_clk); -err: - return ret; } @@ -968,15 +954,45 @@ static const struct net_device_ops xcan_netdev_ops = { /** * xcan_suspend - Suspend method for the driver - * @dev: Address of the platform_device structure + * @dev: Address of the device structure * * Put the driver into low power mode. - * Return: 0 always + * Return: 0 on success and failure value on error */ static int __maybe_unused xcan_suspend(struct device *dev) { - struct platform_device *pdev = dev_get_drvdata(dev); - struct net_device *ndev = platform_get_drvdata(pdev); + if (!device_may_wakeup(dev)) + return pm_runtime_force_suspend(dev); + + return 0; +} + +/** + * xcan_resume - Resume from suspend + * @dev: Address of the device structure + * + * Resume operation after suspend. + * Return: 0 on success and failure value on error + */ +static int __maybe_unused xcan_resume(struct device *dev) +{ + if (!device_may_wakeup(dev)) + return pm_runtime_force_resume(dev); + + return 0; + +} + +/** + * xcan_runtime_suspend - Runtime suspend method for the driver + * @dev: Address of the device structure + * + * Put the driver into low power mode. + * Return: 0 always + */ +static int __maybe_unused xcan_runtime_suspend(struct device *dev) +{ + struct net_device *ndev = dev_get_drvdata(dev); struct xcan_priv *priv = netdev_priv(ndev); if (netif_running(ndev)) { @@ -987,43 +1003,55 @@ static int __maybe_unused xcan_suspend(struct device *dev) priv->write_reg(priv, XCAN_MSR_OFFSET, XCAN_MSR_SLEEP_MASK); priv->can.state = CAN_STATE_SLEEPING; - clk_disable(priv->bus_clk); - clk_disable(priv->can_clk); + clk_disable_unprepare(priv->bus_clk); + clk_disable_unprepare(priv->can_clk); return 0; } /** - * xcan_resume - Resume from suspend - * @dev: Address of the platformdevice structure + * xcan_runtime_resume - Runtime resume from suspend + * @dev: Address of the device structure * * Resume operation after suspend. * Return: 0 on success and failure value on error */ -static int __maybe_unused xcan_resume(struct device *dev) +static int __maybe_unused xcan_runtime_resume(struct device *dev) { - struct platform_device *pdev = dev_get_drvdata(dev); - struct net_device *ndev = platform_get_drvdata(pdev); + struct net_device *ndev = dev_get_drvdata(dev); struct xcan_priv *priv = netdev_priv(ndev); int ret; + u32 isr, status; - ret = clk_enable(priv->bus_clk); + ret = clk_prepare_enable(priv->bus_clk); if (ret) { dev_err(dev, "Cannot enable clock.\n"); return ret; } - ret = clk_enable(priv->can_clk); + ret = clk_prepare_enable(priv->can_clk); if (ret) { dev_err(dev, "Cannot enable clock.\n"); clk_disable_unprepare(priv->bus_clk); return ret; } - priv->write_reg(priv, XCAN_MSR_OFFSET, 0); - priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); - priv->can.state = CAN_STATE_ERROR_ACTIVE; + priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); + isr = priv->read_reg(priv, XCAN_ISR_OFFSET); + status = priv->read_reg(priv, XCAN_SR_OFFSET); if (netif_running(ndev)) { + if (isr & XCAN_IXR_BSOFF_MASK) { + priv->can.state = CAN_STATE_BUS_OFF; + priv->write_reg(priv, XCAN_SRR_OFFSET, + XCAN_SRR_RESET_MASK); + } else if ((status & XCAN_SR_ESTAT_MASK) == + XCAN_SR_ESTAT_MASK) { + priv->can.state = CAN_STATE_ERROR_PASSIVE; + } else if (status & XCAN_SR_ERRWRN_MASK) { + priv->can.state = CAN_STATE_ERROR_WARNING; + } else { + priv->can.state = CAN_STATE_ERROR_ACTIVE; + } netif_device_attach(ndev); netif_start_queue(ndev); } @@ -1031,7 +1059,10 @@ static int __maybe_unused xcan_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); +static const struct dev_pm_ops xcan_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(xcan_suspend, xcan_resume) + SET_RUNTIME_PM_OPS(xcan_runtime_suspend, xcan_runtime_resume, NULL) +}; /** * xcan_probe - Platform registration call @@ -1072,7 +1103,7 @@ static int xcan_probe(struct platform_device *pdev) return -ENOMEM; priv = netdev_priv(ndev); - priv->dev = ndev; + priv->dev = &pdev->dev; priv->can.bittiming_const = &xcan_bittiming_const; priv->can.do_set_mode = xcan_do_set_mode; priv->can.do_get_berr_counter = xcan_get_berr_counter; @@ -1114,21 +1145,30 @@ static int xcan_probe(struct platform_device *pdev) } } - ret = clk_prepare_enable(priv->can_clk); + ret = clk_prepare(priv->can_clk); if (ret) { dev_err(&pdev->dev, "unable to enable device clock\n"); goto err_free; } - ret = clk_prepare_enable(priv->bus_clk); + ret = clk_prepare(priv->bus_clk); if (ret) { dev_err(&pdev->dev, "unable to enable bus clock\n"); - goto err_unprepare_disable_dev; + goto err_unprepare_dev; } priv->write_reg = xcan_write_reg_le; priv->read_reg = xcan_read_reg_le; + pm_runtime_irq_safe(&pdev->dev); + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", + __func__, ret); + goto err_unprepare_busclk; + } + if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) { priv->write_reg = xcan_write_reg_be; priv->read_reg = xcan_read_reg_be; @@ -1141,22 +1181,26 @@ static int xcan_probe(struct platform_device *pdev) ret = register_candev(ndev); if (ret) { dev_err(&pdev->dev, "fail to register failed (err=%d)\n", ret); - goto err_unprepare_disable_busclk; + goto err_disableclks; } devm_can_led_init(ndev); - clk_disable_unprepare(priv->bus_clk); - clk_disable_unprepare(priv->can_clk); + + pm_runtime_put(&pdev->dev); + netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", priv->reg_base, ndev->irq, priv->can.clock.freq, priv->tx_max); return 0; -err_unprepare_disable_busclk: - clk_disable_unprepare(priv->bus_clk); -err_unprepare_disable_dev: - clk_disable_unprepare(priv->can_clk); +err_disableclks: + pm_runtime_put(priv->dev); +err_unprepare_busclk: + pm_runtime_disable(&pdev->dev); + clk_unprepare(priv->bus_clk); +err_unprepare_dev: + clk_unprepare(priv->can_clk); err_free: free_candev(ndev); err: @@ -1175,11 +1219,11 @@ static int xcan_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct xcan_priv *priv = netdev_priv(ndev); - if (set_reset_mode(ndev) < 0) - netdev_err(ndev, "mode resetting failed!\n"); - unregister_candev(ndev); + pm_runtime_disable(&pdev->dev); netif_napi_del(&priv->napi); + clk_unprepare(priv->bus_clk); + clk_unprepare(priv->can_clk); free_candev(ndev); return 0;