From patchwork Mon May 2 12:17:54 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pramod Gurav X-Patchwork-Id: 67011 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp8544qge; Mon, 2 May 2016 05:18:34 -0700 (PDT) X-Received: by 10.98.7.153 with SMTP id 25mr51504371pfh.38.1462191514330; Mon, 02 May 2016 05:18:34 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y7si12127903par.183.2016.05.02.05.18.34; Mon, 02 May 2016 05:18:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-arm-msm-owner@vger.kernel.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753265AbcEBMSQ (ORCPT + 8 others); Mon, 2 May 2016 08:18:16 -0400 Received: from mail-pf0-f181.google.com ([209.85.192.181]:33902 "EHLO mail-pf0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753136AbcEBMSK (ORCPT ); Mon, 2 May 2016 08:18:10 -0400 Received: by mail-pf0-f181.google.com with SMTP id y69so77573831pfb.1 for ; Mon, 02 May 2016 05:18:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=72TolxI2gjfALO8p4dIfkehoT38F6/dv8RKR4E0YD0Q=; b=bB7XdeZCQMuOvM4BYNnYcKF40jkZpO3EOB7B1yvfG2u8to1I9tjlJBcGvJ8h7fMYr5 EJXsBnc3srGAfozo9wnbomxJq7MbkYqUebu8YHx5VfgEUlUVuNxmAD0LN/g9REGZkRVb 1irB9kRHWTqlk2VNYPjLGfmnujw1zBWO901PU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=72TolxI2gjfALO8p4dIfkehoT38F6/dv8RKR4E0YD0Q=; b=N+K9bknxoQ4zcIFn/TmjkeF+b3SjtPQLHZ+eM4uiwLSMZy7G7qVEOskcakVs6VK5yE SF5Qb3cB1+WKPvkzUWVezfFjZ1UHBhF3X0lEBBVM9WLGzr38P6VAacS8WladRqY3QpG9 mD62doveVZ9IHA+eL0I5gaJqXV9i534nlChDJhRj0a4Ylcv0K6PEzZa5H7XmJEvJr//L z7PLrjPBdcG2RXRcWtd+/arRbwN2XZG9POUMWmCkJm06zqC7aeS0P9oL2ITZAKMAA/xo EGmecssYvitew9hp0s1o8+pKSHc0vf0xrzrH04K3Bl+DtVkKZ+Qpi7Jtz9AhdbnuLDMp ljbQ== X-Gm-Message-State: AOPr4FVLbRI1Dk9ixVIhJbqgz8cEy/H+e6JStPEOoHqJArnSnyAnkBNwql54lKCjIUgb+1Qt X-Received: by 10.98.38.66 with SMTP id m63mr50744631pfm.57.1462191489264; Mon, 02 May 2016 05:18:09 -0700 (PDT) Received: from blr-ubuntu-56.ap.qualcomm.com ([202.46.23.61]) by smtp.gmail.com with ESMTPSA id m190sm44990103pfm.29.2016.05.02.05.18.04 (version=TLS1_1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 02 May 2016 05:18:07 -0700 (PDT) From: Pramod Gurav To: vinod.koul@intel.com, andy.gross@linaro.org, ulf.hansson@linaro.org, rjw@rjwysocki.net, linux-arm-msm@vger.kernel.org Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org, stanimir.varbanov@linaro.org, okaya@codeaurora.org, Pramod Gurav Subject: [PATCH 1/2] dmaengine: qcom-bam-dma: Add pm_runtime support Date: Mon, 2 May 2016 17:47:54 +0530 Message-Id: <1462191475-30904-1-git-send-email-pramod.gurav@linaro.org> X-Mailer: git-send-email 1.8.2.1 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Adds pm_runtime support for BAM DMA so that clock is enabled only when there is a transaction going on to help save power. Signed-off-by: Pramod Gurav --- drivers/dma/qcom/bam_dma.c | 88 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 5b427c4..577f323 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "../dmaengine.h" #include "../virt-dma.h" @@ -58,6 +59,8 @@ struct bam_desc_hw { u16 flags; }; +#define BAM_DMA_AUTOSUSPEND_DELAY 100 + #define DESC_FLAG_INT BIT(15) #define DESC_FLAG_EOT BIT(14) #define DESC_FLAG_EOB BIT(13) @@ -535,6 +538,7 @@ static void bam_free_chan(struct dma_chan *chan) return; } + pm_runtime_get_sync(bdev->dev); spin_lock_irqsave(&bchan->vc.lock, flags); bam_reset_channel(bchan); spin_unlock_irqrestore(&bchan->vc.lock, flags); @@ -550,6 +554,8 @@ static void bam_free_chan(struct dma_chan *chan) /* disable irq */ writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_IRQ_EN)); + pm_runtime_mark_last_busy(bdev->dev); + pm_runtime_put_autosuspend(bdev->dev); } /** @@ -696,10 +702,13 @@ static int bam_pause(struct dma_chan *chan) struct bam_device *bdev = bchan->bdev; unsigned long flag; + pm_runtime_get_sync(bdev->dev); spin_lock_irqsave(&bchan->vc.lock, flag); writel_relaxed(1, bam_addr(bdev, bchan->id, BAM_P_HALT)); bchan->paused = 1; spin_unlock_irqrestore(&bchan->vc.lock, flag); + pm_runtime_mark_last_busy(bdev->dev); + pm_runtime_put_autosuspend(bdev->dev); return 0; } @@ -715,10 +724,13 @@ static int bam_resume(struct dma_chan *chan) struct bam_device *bdev = bchan->bdev; unsigned long flag; + pm_runtime_get_sync(bdev->dev); spin_lock_irqsave(&bchan->vc.lock, flag); writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_HALT)); bchan->paused = 0; spin_unlock_irqrestore(&bchan->vc.lock, flag); + pm_runtime_mark_last_busy(bdev->dev); + pm_runtime_put_autosuspend(bdev->dev); return 0; } @@ -943,6 +955,7 @@ static void bam_start_dma(struct bam_chan *bchan) wmb(); writel_relaxed(bchan->tail * sizeof(struct bam_desc_hw), bam_addr(bdev, bchan->id, BAM_P_EVNT_REG)); + } /** @@ -967,6 +980,9 @@ static void dma_tasklet(unsigned long data) bam_start_dma(bchan); spin_unlock_irqrestore(&bchan->vc.lock, flags); } + + pm_runtime_mark_last_busy(bdev->dev); + pm_runtime_put_autosuspend(bdev->dev); } /** @@ -978,8 +994,12 @@ static void dma_tasklet(unsigned long data) static void bam_issue_pending(struct dma_chan *chan) { struct bam_chan *bchan = to_bam_chan(chan); + struct bam_device *bdev = bchan->bdev; unsigned long flags; + if (pm_runtime_status_suspended(bdev->dev)) + pm_runtime_get_sync(bdev->dev); + spin_lock_irqsave(&bchan->vc.lock, flags); /* if work pending and idle, start a transaction */ @@ -1210,6 +1230,13 @@ static int bam_dma_probe(struct platform_device *pdev) if (ret) goto err_unregister_dma; + pm_runtime_irq_safe(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, BAM_DMA_AUTOSUSPEND_DELAY); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; err_unregister_dma: @@ -1221,7 +1248,6 @@ err_tasklet_kill: tasklet_kill(&bdev->task); err_disable_clk: clk_disable_unprepare(bdev->bamclk); - return ret; } @@ -1252,16 +1278,76 @@ static int bam_dma_remove(struct platform_device *pdev) tasklet_kill(&bdev->task); + pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(bdev->bamclk); + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + + return 0; +} + +static int bam_dma_runtime_suspend(struct device *dev) +{ + struct bam_device *bdev = dev_get_drvdata(dev); + + clk_disable(bdev->bamclk); + + return 0; +} + +static int bam_dma_runtime_resume(struct device *dev) +{ + struct bam_device *bdev = dev_get_drvdata(dev); + int ret; + + ret = clk_enable(bdev->bamclk); + if (ret < 0) { + dev_err(dev, "clk_enable failed: %d\n", ret); + return ret; + } + + return 0; +} +#ifdef CONFIG_PM_SLEEP +static int bam_dma_suspend(struct device *dev) +{ + struct bam_device *bdev = dev_get_drvdata(dev); + + pm_runtime_force_suspend(dev); + + clk_unprepare(bdev->bamclk); + + return 0; +} + +static int bam_dma_resume(struct device *dev) +{ + struct bam_device *bdev = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare(bdev->bamclk); + if (ret) + return ret; + + pm_runtime_force_resume(dev); return 0; } +#endif + +static const struct dev_pm_ops bam_dma_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(bam_dma_suspend, bam_dma_resume) + SET_RUNTIME_PM_OPS(bam_dma_runtime_suspend, bam_dma_runtime_resume, + NULL) +}; static struct platform_driver bam_dma_driver = { .probe = bam_dma_probe, .remove = bam_dma_remove, .driver = { .name = "bam-dma-engine", + .pm = &bam_dma_pm_ops, .of_match_table = bam_of_match, }, };