Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752248AbdLGFoi (ORCPT ); Thu, 7 Dec 2017 00:44:38 -0500 Received: from mail-by2nam03on0058.outbound.protection.outlook.com ([104.47.42.58]:53558 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750744AbdLGFog (ORCPT ); Thu, 7 Dec 2017 00:44:36 -0500 Authentication-Results: spf=pass (sender IP is 149.199.60.100) smtp.mailfrom=xilinx.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=xilinx.com; From: Kedareswara rao Appana To: , , , , , , CC: , , Subject: [RESEND PATCH v2] dmaengine: zynqmp_dma: Add runtime pm support Date: Thu, 7 Dec 2017 10:59:57 +0530 Message-ID: <1512624597-14502-1-git-send-email-appanad@xilinx.com> X-Mailer: git-send-email 1.9.1 X-RCIS-Action: ALLOW X-TM-AS-Product-Ver: IMSS-7.1.0.1224-8.1.0.1062-23512.006 X-TM-AS-User-Approved-Sender: Yes;Yes X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:149.199.60.100;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(376002)(346002)(39860400002)(2980300002)(438002)(199004)(189003)(6666003)(36756003)(5660300001)(47776003)(36386004)(33646002)(8936002)(54906003)(316002)(16586007)(106002)(77096006)(63266004)(110136005)(2201001)(50226002)(106466001)(81166006)(81156014)(305945005)(4326008)(8676002)(39060400002)(9786002)(50466002)(478600001)(51416003)(2906002)(7696005)(48376002)(356003)(107986001)(217873001)(5001870100001);DIR:OUT;SFP:1101;SCL:1;SRVR:MWHPR02MB3279;H:xsj-pvapsmtpgw02;FPR:;SPF:Pass;PTR:unknown-60-100.xilinx.com,xapps1.xilinx.com;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;CY1NAM02FT060;1:LX/CFSMnqcGHMUj5DtUJEXtkvbgSFCR+omHpZz2BKCrCON6J04l4oTkL37WmomGsomv57QoMswE/Xy9zfDvzEeJlCDbrURTwxJDJmfaeEjz9m3pPW6SvBoRbAcYQu+e9 MIME-Version: 1.0 Content-Type: text/plain X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 42c17f8c-a2b5-4cb4-f269-08d53d35980b X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(5600026)(4604075)(4608076)(2017052603286);SRVR:MWHPR02MB3279; X-Microsoft-Exchange-Diagnostics: 1;MWHPR02MB3279;3:+qRjv/KmjeYczJGeES1Efez3PYjFgsiHN/hqVxeJENnly/tKaMBcaRMfVex5HefxFzxmq3xyb8lwOxX5M5e0RrQ7Jhvk/botOAFjkceX2Cwm4nUDlgXWON9z2AFL5wd6+JPi18OR/8LSgzCA9iRkIKdCjYSGJA7KPgqMYeeiWs8k8waDba5g/THvo0YfcT280EkSGoYdBMniitrhF+iPOJNakDmt3+I8GYRaTg2KfRMHkYeZdqKtaa+9szyxmC9hMnxL8UsdA+3FwQKkqlkIoTFoD4e+QL7VOZCREV8zQkQU5qKo4u+r1qoXnxdpMVrF4sSo0VdrF5s1FAqi1HzhJZuCoqbmJCmQXAhop9MoOV8=;25:Q29FJspF2wM4B+HYPNHfPwQMKV/kxhtjO7UPn3e6SpTLvt3d/TQSDXvqd7r0tNyytgplPCQ5ak6QBg3GAFziRlDmT4+ctCp3NYRBnbYYkBxE0f7cD6GU8AYK+2djElFYNOEcyArnd48PZToxdHIns0bh/M2aJx9Y76LxD75Qt8UDbiP3CbPPnb6vepJFYqn486AW5QHCVw2BNLYZ2vv1xeeMXDvTfdbZdgsgc1QXnOMWe2Of8JySzTldaDMolmBGeKhUG5a5yqljE5OPFk7St+Y4GYYs21ZlPo/HUVkUYepnPw8eO50FDHveq7gqv4C3xe1EtFWIDtaPKSg+CcaiAA== X-MS-TrafficTypeDiagnostic: MWHPR02MB3279: X-Microsoft-Exchange-Diagnostics: 1;MWHPR02MB3279;31:+z//Hk9cThunBoSv+26fXpjHhOw9+L1ucbtG8s+cz1h68YHveAOO3rbqqO6p4wpe2ps3dzvYssIPsUlT+aKH5xyJiGLVP6vziRoFw0P+VyI3FWOz0AlOXeOVd4fESID9VeSwy8wlQwfwCi901BaPXNN6UdY6Nbbt4016bxFEncnXVBp7hpx2fNBKyW9cvGmT88Zj5dpA8NDSXmZDheh4OVsexBIulYtMyL+YxnQoK1Y=;20:iDgXpUltutnQU0hgVh3WVYlvR9yGosKQjXi2cLjvv6i78yhgUTPwzmh2RIHZL+VbkdAHg+/0hKsRau5knAhlbL8914rZ/IMlDIX4k5lO/BKc4HcdMOHwPsiHGatVr9vy35J6WnUWqYDl6o/O4oSbBJStJaqbV5UuZYO1EjEqcLQQYKY9ak9gFl7hfMajCZD5ekUQEts3RnVccCCzgjX9BULJ69CmwUxw1xWJRYca1doSy5Chwr4z3SZEgokNJWPI9RVgxrW8xA6MzqftUeIU841phU1+mQRFqPcnt6Zagng/trWrhbAfLuS+eNGhbMMvISQe5YYBF7lii0ZW9IuCdMyrBZ3h5XQzE9o8JtwQKSpkgqcr7873hH5uxJXJ2PuXHqUCtIMFIOHT73fnZPDUqpegr/zVOx+zSZ81ojR5zKQGN2c34Sq0diOPE65NTuDGZ2kD3y+ASIcapQ+WkKQu5l3xtO546kBC9FrTFm+nb9mJyDTdokf9BwmoI3PLCxLG X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192813158149592); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040450)(2401047)(5005006)(8121501046)(3231022)(3002001)(10201501046)(93006095)(93004095)(6055026)(6041248)(20161123560025)(20161123564025)(20161123555025)(20161123562025)(20161123558100)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(6072148)(201708071742011);SRVR:MWHPR02MB3279;BCL:0;PCL:0;RULEID:(100000803101)(100110400095);SRVR:MWHPR02MB3279; X-Microsoft-Exchange-Diagnostics: 1;MWHPR02MB3279;4:kceHJHoJ/YHvyUpw+JRt9VN1v+JODeh0tr0Rt5RNiKXkkoLwBsC80NvFiWO19GnxaO+thmqr6WuOwx9llxed6SUwcUf1CR1c7HMEgHG/bp2U5VoLOiE059MwPJn9YLsXF7RT3SZvnunR4XzMkihVyEt52N4nXf5c+3bS6d07vDf6ukMAilZnEL3xEs8JETW/NdeuvU2spYoJcdgSSF+50DYN+GtDpa0lRczXSdVXUgvM2lB52oenLc+gEstDkY0SJ/t8B5DSq0PdvBq6R3R0aN2I4YaOx8ZQrW+0WvHUbnDcZxnsthhafAjnePYpncIz X-Forefront-PRVS: 05143A8241 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;MWHPR02MB3279;23:C7Cp7Hudr5v9OViGSKfuUv7bn8s3RItFHkPo8KV/Q?= =?us-ascii?Q?x2dLdQeVXg4tse1dJ9SUNacppUNWqufa7mR9U3PuR4Zg3J4ziyJ8Sp4yhZrf?= =?us-ascii?Q?tKv8Vsxa8m4fejtyaA9A6fdb8lxPXxYAYp4VpwEeqQeaDxTj2JnKpuZjcYmn?= =?us-ascii?Q?k8Jajnm1a3261lfeyOS0LKIO/ZQSJnzXjjJCjDSdij9GBoOYiM8JEUDn/q4e?= =?us-ascii?Q?0no67yKHOnXVpI4cBUXoYh8WjVw9/6HU8SYLwGKA4rTBus5fGoLnlJLYh/wW?= =?us-ascii?Q?hxr6UaAx/S2lE7tsbXb4SyG4Z1qyo+FIrRa213hxpe915oO9MP9TD4SGdDZr?= =?us-ascii?Q?++vcSmOTqJCFkY97RCiatdkANyvBgs4OCtlPwHgh9xofqLem+Cn285IX9b5G?= =?us-ascii?Q?3QCUW5AYkS5B2IqgMTn8XqNbDWVrX3tnUxEBfrDwaZe+BCDBMewvFNVc06TW?= =?us-ascii?Q?+EyUZDjkwSEGtcsmdOr9lbqxO8+pzcmMzaqjNjcyCqFdCN2V59xg/gkrAnCC?= =?us-ascii?Q?0hbOr6Gr4ve2pUp8krffdCYvnE6+K/2St3qREJtqRpafLLPOsB+mQNGkNUYD?= =?us-ascii?Q?+NqzsCfsXI59u65Yl1YcHmNbayErp8qCG+SWB6zdDPYdyPC53p3ciro37voN?= =?us-ascii?Q?qt+LEzw0PzRqUBWJfTPtHnBNhr8dDc/3n2yurgoOwaalQhK5WnnwlxixnVL9?= =?us-ascii?Q?lL0fC4HsqYzIeKepEgImqXsAFEz93XftrlMPru/H+ImknYqBCsY0T52lfIAY?= =?us-ascii?Q?ZXlXBZt2Bhqm1AX+SLMDtQWT6mUKcFlX9RuIFmddaTE4NxOzo2ukcko+dtzN?= =?us-ascii?Q?ez9yFAlq6Qz2+VMcrJkVOwXJrQ70K4twh2XnCxUmwHBF9xopGHjLlk7YZPhv?= =?us-ascii?Q?dfZ/eOm7mGCAb/kOrIj9uI6982Jzse+iP6vu+hL4Fy7+vbF84Cs0hSYZWVP7?= =?us-ascii?Q?TGZcE6NNoZ9SW72DrlOx5MqY6lQ3MMLPbYK/eP+48vxtRakyf7T5x2441XcW?= =?us-ascii?Q?VA=3D?= X-Microsoft-Exchange-Diagnostics: 1;MWHPR02MB3279;6:EMnAWC05yZifyIXUzaxHJU1g/W/BAv3Ka48elmpxq+lAwqoxKfGn/14Nrg9YAC7+bHNhcDRQJuXyHEaOrfA1IMNYQeEODy6Wlnq39nhSKFlhjSIZfnCpDBxY/8ILHGl6cwk2BUQTaAF4a8tOaG+Vu6oMjLAD8B3OPXhJAO2f1hEfMjMNv4sj3MNdev/vk7AdIbhr3WvoUafg15zD5m2GYR4Jg9gJjayK5nq8152+/vc0BErx3rkv/qR1uw2flb5ePC0K8Jtf9objXCJBSWYxO4M5KUBQ1niXKL1Z6v5/0oGpMZEIwap5aj2j5D1LWIaqIOPhbCn7/n36yGFC0smQtdAY6p8j9R7gWacAi2Rmmt8=;5:yD2xauihWa8iRWlOyMRlkIlvMOsOiQs6MnSa8miVDrX3wPc8N9R5ledQYM6qgbWZMz5+aQ6ogZWYuEjlIXpg7fVE61ijhf1oi0eFw3ytKgqXNDq3gUhaHa7e/I0sL4rxLVBUJy3OynmPaUeLbP2XGgspGBeUX8SwzEQ04vSvEYQ=;24:ihfUuDJH/cD5UbfnAWTKyi82jHzf7raYJgI3I/OMFtX7YGg8S3VVmYYREftRsIGJV3fyRL4K8mTX901emgAHPwQJXrbcniwqFOelSzfJytg=;7:s2P/wHCRG+DqsJHBaXW/6ka42ACVA3xFoSZJx4rl+pZVPPVQMO6fyKmpsGkrKOJFbo8hNVmTKAsvYG56oo2Q1TPVmvlu0XRRbINblFYrdKV+gemdTZu4m6JHnBxwCVf6VkiGaUALRt0soXgHaaGXTUuLDywdO1ONynYQ13/nLfyTsJkMERQuhUHsfwDqUaUMRoIPquhpACsROzj9w4r0bSmUjETNJGibosnSiPAHID6eE9kkvsYLcQ9qt+DDuYVk SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: xilinx.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Dec 2017 05:44:30.5801 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 42c17f8c-a2b5-4cb4-f269-08d53d35980b 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.100];Helo=[xsj-pvapsmtpgw02] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR02MB3279 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8133 Lines: 292 This patch adds runtime pm support in the driver. Signed-off-by: Kedareswara rao Appana --- Resending the patch as there are some issues with my git send-email, patch is not showing in the dmeengine mailing list. Changes for v2: --> Fixed error path in the probe. drivers/dma/xilinx/zynqmp_dma.c | 160 ++++++++++++++++++++++++++++++++-------- 1 file changed, 128 insertions(+), 32 deletions(-) diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 1ee1241..4fa14bf 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "../dmaengine.h" @@ -138,6 +139,8 @@ #define ZYNQMP_DMA_BUS_WIDTH_64 64 #define ZYNQMP_DMA_BUS_WIDTH_128 128 +#define ZDMA_PM_TIMEOUT 100 + #define ZYNQMP_DMA_DESC_SIZE(chan) (chan->desc_size) #define to_chan(chan) container_of(chan, struct zynqmp_dma_chan, \ @@ -211,8 +214,6 @@ struct zynqmp_dma_desc_sw { * @bus_width: Bus width * @src_burst_len: Source burst length * @dst_burst_len: Dest burst length - * @clk_main: Pointer to main clock - * @clk_apb: Pointer to apb clock */ struct zynqmp_dma_chan { struct zynqmp_dma_device *zdev; @@ -237,8 +238,6 @@ struct zynqmp_dma_chan { u32 bus_width; u32 src_burst_len; u32 dst_burst_len; - struct clk *clk_main; - struct clk *clk_apb; }; /** @@ -246,11 +245,15 @@ struct zynqmp_dma_chan { * @dev: Device Structure * @common: DMA device structure * @chan: Driver specific DMA channel + * @clk_main: Pointer to main clock + * @clk_apb: Pointer to apb clock */ struct zynqmp_dma_device { struct device *dev; struct dma_device common; struct zynqmp_dma_chan *chan; + struct clk *clk_main; + struct clk *clk_apb; }; static inline void zynqmp_dma_writeq(struct zynqmp_dma_chan *chan, u32 reg, @@ -461,7 +464,11 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) { struct zynqmp_dma_chan *chan = to_chan(dchan); struct zynqmp_dma_desc_sw *desc; - int i; + int i, ret; + + ret = pm_runtime_get_sync(chan->dev); + if (ret < 0) + return ret; chan->sw_desc_pool = kzalloc(sizeof(*desc) * ZYNQMP_DMA_NUM_DESCS, GFP_KERNEL); @@ -664,6 +671,8 @@ static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan) (2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS), chan->desc_pool_v, chan->desc_pool_p); kfree(chan->sw_desc_pool); + pm_runtime_mark_last_busy(chan->dev); + pm_runtime_put_autosuspend(chan->dev); } /** @@ -841,8 +850,6 @@ static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan) devm_free_irq(chan->zdev->dev, chan->irq, chan); tasklet_kill(&chan->tasklet); list_del(&chan->common.device_node); - clk_disable_unprepare(chan->clk_apb); - clk_disable_unprepare(chan->clk_main); } /** @@ -907,30 +914,6 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, "zynqmp-dma", chan); if (err) return err; - chan->clk_main = devm_clk_get(&pdev->dev, "clk_main"); - if (IS_ERR(chan->clk_main)) { - dev_err(&pdev->dev, "main clock not found.\n"); - return PTR_ERR(chan->clk_main); - } - - chan->clk_apb = devm_clk_get(&pdev->dev, "clk_apb"); - if (IS_ERR(chan->clk_apb)) { - dev_err(&pdev->dev, "apb clock not found.\n"); - return PTR_ERR(chan->clk_apb); - } - - err = clk_prepare_enable(chan->clk_main); - if (err) { - dev_err(&pdev->dev, "Unable to enable main clock.\n"); - return err; - } - - err = clk_prepare_enable(chan->clk_apb); - if (err) { - clk_disable_unprepare(chan->clk_main); - dev_err(&pdev->dev, "Unable to enable apb clock.\n"); - return err; - } chan->desc_size = sizeof(struct zynqmp_dma_desc_ll); chan->idle = true; @@ -953,6 +936,87 @@ static struct dma_chan *of_zynqmp_dma_xlate(struct of_phandle_args *dma_spec, } /** + * zynqmp_dma_suspend - Suspend method for the driver + * @dev: Address of the device structure + * + * Put the driver into low power mode. + * Return: 0 on success and failure value on error + */ +static int __maybe_unused zynqmp_dma_suspend(struct device *dev) +{ + if (!device_may_wakeup(dev)) + return pm_runtime_force_suspend(dev); + + return 0; +} + +/** + * zynqmp_dma_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 zynqmp_dma_resume(struct device *dev) +{ + if (!device_may_wakeup(dev)) + return pm_runtime_force_resume(dev); + + return 0; +} + +/** + * zynqmp_dma_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 zynqmp_dma_runtime_suspend(struct device *dev) +{ + struct zynqmp_dma_device *zdev = dev_get_drvdata(dev); + + clk_disable_unprepare(zdev->clk_main); + clk_disable_unprepare(zdev->clk_apb); + + return 0; +} + +/** + * zynqmp_dma_runtime_resume - 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 zynqmp_dma_runtime_resume(struct device *dev) +{ + struct zynqmp_dma_device *zdev = dev_get_drvdata(dev); + int err; + + err = clk_prepare_enable(zdev->clk_main); + if (err) { + dev_err(dev, "Unable to enable main clock.\n"); + return err; + } + + err = clk_prepare_enable(zdev->clk_apb); + if (err) { + dev_err(dev, "Unable to enable apb clock.\n"); + clk_disable_unprepare(zdev->clk_main); + return err; + } + + return 0; +} + +static const struct dev_pm_ops zynqmp_dma_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(zynqmp_dma_suspend, zynqmp_dma_resume) + SET_RUNTIME_PM_OPS(zynqmp_dma_runtime_suspend, + zynqmp_dma_runtime_resume, NULL) +}; + +/** * zynqmp_dma_probe - Driver probe function * @pdev: Pointer to the platform_device structure * @@ -984,12 +1048,33 @@ static int zynqmp_dma_probe(struct platform_device *pdev) p->device_config = zynqmp_dma_device_config; p->dev = &pdev->dev; + zdev->clk_main = devm_clk_get(&pdev->dev, "clk_main"); + if (IS_ERR(zdev->clk_main)) { + dev_err(&pdev->dev, "main clock not found.\n"); + return PTR_ERR(zdev->clk_main); + } + + zdev->clk_apb = devm_clk_get(&pdev->dev, "clk_apb"); + if (IS_ERR(zdev->clk_apb)) { + dev_err(&pdev->dev, "apb clock not found.\n"); + return PTR_ERR(zdev->clk_apb); + } + platform_set_drvdata(pdev, zdev); + pm_runtime_set_autosuspend_delay(zdev->dev, ZDMA_PM_TIMEOUT); + pm_runtime_use_autosuspend(zdev->dev); + pm_runtime_enable(zdev->dev); + pm_runtime_get_sync(zdev->dev); + if (!pm_runtime_enabled(zdev->dev)) { + ret = zynqmp_dma_runtime_resume(zdev->dev); + if (ret) + return ret; + } ret = zynqmp_dma_chan_probe(zdev, pdev); if (ret) { dev_err(&pdev->dev, "Probing channel failed\n"); - goto free_chan_resources; + goto err_disable_pm; } p->dst_addr_widths = BIT(zdev->chan->bus_width / 8); @@ -1005,12 +1090,19 @@ static int zynqmp_dma_probe(struct platform_device *pdev) goto free_chan_resources; } + pm_runtime_mark_last_busy(zdev->dev); + pm_runtime_put_sync_autosuspend(zdev->dev); + dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n"); return 0; free_chan_resources: zynqmp_dma_chan_remove(zdev->chan); +err_disable_pm: + if (!pm_runtime_enabled(zdev->dev)) + zynqmp_dma_runtime_suspend(zdev->dev); + pm_runtime_disable(zdev->dev); return ret; } @@ -1028,6 +1120,9 @@ static int zynqmp_dma_remove(struct platform_device *pdev) dma_async_device_unregister(&zdev->common); zynqmp_dma_chan_remove(zdev->chan); + pm_runtime_disable(zdev->dev); + if (!pm_runtime_enabled(zdev->dev)) + zynqmp_dma_runtime_suspend(zdev->dev); return 0; } @@ -1042,6 +1137,7 @@ static struct platform_driver zynqmp_dma_driver = { .driver = { .name = "xilinx-zynqmp-dma", .of_match_table = zynqmp_dma_of_match, + .pm = &zynqmp_dma_dev_pm_ops, }, .probe = zynqmp_dma_probe, .remove = zynqmp_dma_remove, -- 2.7.4