From patchwork Fri Aug 10 17:36:27 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Will Deacon X-Patchwork-Id: 1306191 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 4D4333FC66 for ; Fri, 10 Aug 2012 17:40:38 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Szt9V-0006FR-7R; Fri, 10 Aug 2012 17:37:37 +0000 Received: from cam-admin0.cambridge.arm.com ([217.140.96.50]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Szt8j-00068R-OU for linux-arm-kernel@lists.infradead.org; Fri, 10 Aug 2012 17:36:55 +0000 Received: from mudshark.cambridge.arm.com (mudshark.cambridge.arm.com [10.1.79.58]) by cam-admin0.cambridge.arm.com (8.12.6/8.12.6) with ESMTP id q7AHaeOK011205; Fri, 10 Aug 2012 18:36:40 +0100 (BST) Received: by mudshark.cambridge.arm.com (Postfix, from userid 1000) id C73BAC02E7; Fri, 10 Aug 2012 18:36:38 +0100 (BST) From: Will Deacon To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 1/9] ARM: PMU: Add runtime PM Support Date: Fri, 10 Aug 2012 18:36:27 +0100 Message-Id: <1344620195-22372-2-git-send-email-will.deacon@arm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1344620195-22372-1-git-send-email-will.deacon@arm.com> References: <1344620195-22372-1-git-send-email-will.deacon@arm.com> X-Spam-Note: CRM114 invocation failed X-Spam-Score: -6.9 (------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-6.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [217.140.96.50 listed in list.dnswl.org] -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Kevin Hilman , Paul Walmsley , Benoit Cousson , Ming Lei , Will Deacon , jon-hunter@ti.com, chris.smith@st.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Jon Hunter Add runtime PM support to the ARM PMU driver so that devices such as OMAP supporting dynamic PM can use the platform->runtime_* hooks to initialise hardware at runtime. Without having these runtime PM hooks in place any configuration of the PMU hardware would be lost when low power states are entered and hence would prevent PMU from working. This change also replaces the PMU platform functions enable_irq and disable_irq added by Ming Lei with runtime_resume and runtime_suspend funtions. Ming had added the enable_irq and disable_irq functions as a method to configure the cross trigger interface on OMAP4 for routing the PMU interrupts. By adding runtime PM support, we can move the code called by enable_irq and disable_irq into the runtime PM callbacks runtime_resume and runtime_suspend. Cc: Ming Lei Cc: Benoit Cousson Cc: Paul Walmsley Cc: Kevin Hilman Signed-off-by: Jon Hunter Signed-off-by: Will Deacon --- arch/arm/include/asm/pmu.h | 20 ++++++++++++-------- arch/arm/kernel/perf_event.c | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 4432305..40d7dff 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -31,18 +31,22 @@ enum arm_pmu_type { * interrupt and passed the address of the low level handler, * and can be used to implement any platform specific handling * before or after calling it. - * @enable_irq: an optional handler which will be called after - * request_irq and be used to handle some platform specific - * irq enablement - * @disable_irq: an optional handler which will be called before - * free_irq and be used to handle some platform specific - * irq disablement + * @runtime_resume: an optional handler which will be called by the + * runtime PM framework following a call to pm_runtime_get(). + * Note that if pm_runtime_get() is called more than once in + * succession this handler will only be called once. + * @runtime_suspend: an optional handler which will be called by the + * runtime PM framework following a call to pm_runtime_put(). + * Note that if pm_runtime_get() is called more than once in + * succession this handler will only be called following the + * final call to pm_runtime_put() that actually disables the + * hardware. */ struct arm_pmu_platdata { irqreturn_t (*handle_irq)(int irq, void *dev, irq_handler_t pmu_handler); - void (*enable_irq)(int irq); - void (*disable_irq)(int irq); + int (*runtime_resume)(struct device *dev); + int (*runtime_suspend)(struct device *dev); }; #ifdef CONFIG_CPU_HAS_PMU diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index ab243b8..c44647e 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -364,8 +365,6 @@ armpmu_release_hardware(struct arm_pmu *armpmu) { int i, irq, irqs; struct platform_device *pmu_device = armpmu->plat_device; - struct arm_pmu_platdata *plat = - dev_get_platdata(&pmu_device->dev); irqs = min(pmu_device->num_resources, num_possible_cpus()); @@ -373,13 +372,11 @@ armpmu_release_hardware(struct arm_pmu *armpmu) if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) continue; irq = platform_get_irq(pmu_device, i); - if (irq >= 0) { - if (plat && plat->disable_irq) - plat->disable_irq(irq); + if (irq >= 0) free_irq(irq, armpmu); - } } + pm_runtime_put_sync(&pmu_device->dev); release_pmu(armpmu->type); } @@ -412,6 +409,8 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) return -ENODEV; } + pm_runtime_get_sync(&pmu_device->dev); + for (i = 0; i < irqs; ++i) { err = 0; irq = platform_get_irq(pmu_device, i); @@ -437,8 +436,7 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) irq); armpmu_release_hardware(armpmu); return err; - } else if (plat && plat->enable_irq) - plat->enable_irq(irq); + } cpumask_set_cpu(i, &armpmu->active_irqs); } @@ -581,6 +579,28 @@ static void armpmu_disable(struct pmu *pmu) armpmu->stop(); } +#ifdef CONFIG_PM_RUNTIME +static int armpmu_runtime_resume(struct device *dev) +{ + struct arm_pmu_platdata *plat = dev_get_platdata(dev); + + if (plat && plat->runtime_resume) + return plat->runtime_resume(dev); + + return 0; +} + +static int armpmu_runtime_suspend(struct device *dev) +{ + struct arm_pmu_platdata *plat = dev_get_platdata(dev); + + if (plat && plat->runtime_suspend) + return plat->runtime_suspend(dev); + + return 0; +} +#endif + static void __init armpmu_init(struct arm_pmu *armpmu) { atomic_set(&armpmu->active_events, 0); @@ -647,9 +667,14 @@ static int __devinit armpmu_device_probe(struct platform_device *pdev) return 0; } +static const struct dev_pm_ops armpmu_dev_pm_ops = { + SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL) +}; + static struct platform_driver armpmu_driver = { .driver = { .name = "arm-pmu", + .pm = &armpmu_dev_pm_ops, .of_match_table = armpmu_of_device_ids, }, .probe = armpmu_device_probe,