From patchwork Mon Sep 10 15:23:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Hunter, Jon" X-Patchwork-Id: 1432641 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 88B094025E for ; Mon, 10 Sep 2012 15:30:11 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TB5sh-0007hQ-6B; Mon, 10 Sep 2012 15:26:35 +0000 Received: from arroyo.ext.ti.com ([192.94.94.40]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TB5qF-0006NS-IP for linux-arm-kernel@lists.infradead.org; Mon, 10 Sep 2012 15:24:10 +0000 Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id q8AFNtjv021867; Mon, 10 Sep 2012 10:23:55 -0500 Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q8AFNthG005843; Mon, 10 Sep 2012 10:23:55 -0500 Received: from dlelxv24.itg.ti.com (172.17.1.199) by dfle73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.1.323.3; Mon, 10 Sep 2012 10:23:55 -0500 Received: from legion.dal.design.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dlelxv24.itg.ti.com (8.13.8/8.13.8) with ESMTP id q8AFNt4j001977; Mon, 10 Sep 2012 10:23:55 -0500 Received: from localhost (h56-53.vpn.ti.com [172.24.56.53]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id q8AFNsr00997; Mon, 10 Sep 2012 10:23:54 -0500 (CDT) From: Jon Hunter To: Tony Lindgren Subject: [PATCH V3 6/8] ARM: OMAP4: Route PMU IRQs to CTI IRQs Date: Mon, 10 Sep 2012 10:23:44 -0500 Message-ID: <1347290626-21164-7-git-send-email-jon-hunter@ti.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1347290626-21164-1-git-send-email-jon-hunter@ti.com> References: <1347290626-21164-1-git-send-email-jon-hunter@ti.com> MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -7.3 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [192.94.94.40 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -0.4 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Kevin Hilman , Paul Walmsley , Woodruff Richard , Benoit Cousson , Ming Lei , Will Deacon , Jon Hunter , linux-omap , linux-arm 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: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Ming Lei For OMAP4430 there are no dedicate PMU interrupts, however, PMU events can be routed to via the CTI IRQs. This allows tools such as PERF and OPROFILE to work on OMAP4430. The idea is from Woodruff Richard in the disscussion about "Oprofile on Pandaboard / Omap4" on pandaboard@googlegroups.com. Ming's original patch was called "arm: omap4: support pmu" [1] and has been renamed and modified by Jon Hunter. There main differences from the original patch are ... 1. Instead of only configuring the CTI interrupt once during boot, the interrupts are configured everytime the the PMU is used. The reason for this is because during power transitions the CTI logic state will be lost and so we will need to configure the interrupts everytime they are used. This is accomplished by using the PM runtime callbacks which will be called whenever the PMU is used. 2. Assign the PMU events to different cross triggering channels. This prevents a single PMU event generating interrupts to both CPUs and hence can cause spurious interrupts to occur. Reported by Ming [2]. [1] http://marc.info/?l=linux-arm-kernel&m=132227620816504&w=2 [2] http://permalink.gmane.org/gmane.linux.linaro.devel/10532 Acked-by: Jean Pihet Acked-by: Tony Lindgren Acked-by: Santosh Shilimkar Cc: Woodruff Richard Cc: Ming Lei Cc: Will Deacon Cc: Benoit Cousson Cc: Paul Walmsley Cc: Kevin Hilman Signed-off-by: Ming Lei Signed-off-by: Will Deacon Signed-off-by: Jon Hunter --- arch/arm/mach-omap2/pmu.c | 98 +++++++++++++++++++++++++++- arch/arm/plat-omap/include/plat/omap44xx.h | 3 + 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c index 03007b6..5918098 100644 --- a/arch/arm/mach-omap2/pmu.c +++ b/arch/arm/mach-omap2/pmu.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -24,6 +25,91 @@ static char *omap2_pmu_oh_names[] = {"mpu"}; static char *omap3_pmu_oh_names[] = {"mpu", "debugss"}; static char *omap4430_pmu_oh_names[] = {"l3_main_3", "l3_instr", "debugss"}; static struct platform_device *omap_pmu_dev; +static struct arm_pmu_platdata omap_pmu_data; +static struct cti omap4_cti[2]; + +/** + * omap4_pmu_runtime_resume - PMU runtime resume callback + * @dev OMAP PMU device + * + * Platform specific PMU runtime resume callback for OMAP4430 devices to + * configure the cross trigger interface for routing PMU interrupts. This + * is called by the PM runtime framework. + */ +static int omap4_pmu_runtime_resume(struct device *dev) +{ + /* configure CTI0 for PMU IRQ routing */ + cti_unlock(&omap4_cti[0]); + cti_map_trigger(&omap4_cti[0], 1, 6, 2); + cti_enable(&omap4_cti[0]); + + /* configure CTI1 for PMU IRQ routing */ + cti_unlock(&omap4_cti[1]); + cti_map_trigger(&omap4_cti[1], 1, 6, 3); + cti_enable(&omap4_cti[1]); + + return 0; +} + +/** + * omap4_pmu_runtime_suspend - PMU runtime suspend callback + * @dev OMAP PMU device + * + * Platform specific PMU runtime suspend callback for OMAP4430 devices to + * disable the cross trigger interface interrupts. This is called by the + * PM runtime framework. + */ +static int omap4_pmu_runtime_suspend(struct device *dev) +{ + cti_disable(&omap4_cti[0]); + cti_disable(&omap4_cti[1]); + + return 0; +} + +/** + * omap4_pmu_handle_irq - PMU IRQ Handler + * @irq OMAP CTI IRQ number + * @dev OMAP PMU device + * @handler ARM PMU interrupt handler + * + * Platform specific PMU IRQ handler for OMAP4430 devices that route PMU + * interrupts via cross trigger interface. This is called by the PMU driver. + */ +static irqreturn_t +omap4_pmu_handle_irq(int irq, void *dev, irq_handler_t handler) +{ + if (irq == OMAP44XX_IRQ_CTI0) + cti_irq_ack(&omap4_cti[0]); + else if (irq == OMAP44XX_IRQ_CTI1) + cti_irq_ack(&omap4_cti[1]); + + return handler(irq, dev); +} + +/** + * omap4_init_cti - initialise cross trigger interface instances + * + * Initialises two cross trigger interface (CTI) instances in preparation + * for routing PMU interrupts to the OMAP interrupt controller. Note that + * this does not configure the actual CTI hardware but just the CTI + * software structures to be used. + */ +static int __init omap4_init_cti(void) +{ + omap4_cti[0].base = ioremap(OMAP44XX_CTI0_BASE, SZ_4K); + omap4_cti[1].base = ioremap(OMAP44XX_CTI1_BASE, SZ_4K); + + if (!omap4_cti[0].base || !omap4_cti[1].base) { + pr_err("ioremap for OMAP4 CTI failed\n"); + return -ENOMEM; + } + + cti_init(&omap4_cti[0], omap4_cti[0].base, OMAP44XX_IRQ_CTI0, 6); + cti_init(&omap4_cti[1], omap4_cti[1].base, OMAP44XX_IRQ_CTI1, 6); + + return 0; +} /** * omap2_init_pmu - creates and registers PMU platform device @@ -51,8 +137,8 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[]) } } - omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0, - NULL, 0, 0); + omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, + &omap_pmu_data, sizeof(omap_pmu_data), NULL, 0, 0); WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n", dev_name); @@ -66,6 +152,7 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[]) static int __init omap_init_pmu(void) { + int r; unsigned oh_num; char **oh_names; @@ -84,6 +171,13 @@ static int __init omap_init_pmu(void) oh_num = ARRAY_SIZE(omap3_pmu_oh_names); oh_names = omap3_pmu_oh_names; } else if (cpu_is_omap443x()) { + r = omap4_init_cti(); + if (r) + return r; + + omap_pmu_data.handle_irq = omap4_pmu_handle_irq; + omap_pmu_data.runtime_resume = omap4_pmu_runtime_resume; + omap_pmu_data.runtime_suspend = omap4_pmu_runtime_suspend; oh_num = ARRAY_SIZE(omap4430_pmu_oh_names); oh_names = omap4430_pmu_oh_names; } else { diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h index c0d478e..1800a9b 100644 --- a/arch/arm/plat-omap/include/plat/omap44xx.h +++ b/arch/arm/plat-omap/include/plat/omap44xx.h @@ -58,5 +58,8 @@ #define OMAP44XX_HSUSB_OHCI_BASE (L4_44XX_BASE + 0x64800) #define OMAP44XX_HSUSB_EHCI_BASE (L4_44XX_BASE + 0x64C00) +#define OMAP44XX_CTI0_BASE (L4_EMU_44XX_BASE + 0x148000) +#define OMAP44XX_CTI1_BASE (L4_EMU_44XX_BASE + 0x149000) + #endif /* __ASM_ARCH_OMAP44XX_H */