msm: Perf: Add PL310 support for the 8625 and 7627A

Enable perf events support for the PL310 L2CC. Include
single kernel image support for both targets.

Change-Id: Iaad714b538782638a6a299e11dbb1d989b38a563
Signed-off-by: Ashwin Chaugule <ashwinc@codeaurora.org>
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 989d80e..5b0ac52 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -346,6 +346,7 @@
 	select MSM_RUN_QUEUE_STATS
 	select MIGHT_HAVE_CACHE_L2X0
 	select ARM_HAS_SG_CHAIN
+	select CPU_HAS_L2_PMU
 
 config ARCH_MSM9625
 	bool "MSM9625"
@@ -482,6 +483,7 @@
 	select ARCH_MSM_CORTEXMP
 	select MIGHT_HAVE_CACHE_L2X0
 	select ARM_HAS_SG_CHAIN
+	select CPU_HAS_L2_PMU
 
 config  MSM_VIC
 	bool
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9d9550e..8d75008 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -33,8 +33,9 @@
 obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
-obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o
+obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o perf_event_msm_pl310.o
 obj-$(CONFIG_ARCH_MSM9625) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM8625) += pmu.o perf_event_msm_pl310.o
 
 ifndef CONFIG_MSM_SMP
 obj-$(CONFIG_ARCH_MSM_SCORPION) += msm_fault_handlers.o
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index cf456f7..3c60fa6 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1667,7 +1667,7 @@
 	},
 	{
 		.name   = "l2_irq",
-		.start  = MSM8625_INT_L2CC_INTR,
+		.start  = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
 		.flags  = IORESOURCE_IRQ,
 	},
 };
@@ -2096,7 +2096,7 @@
 		msm_cpr_init();
 
 	if (!cpu_is_msm8625() && !cpu_is_msm8625q())
-		pl310_resources[1].start = INT_L2CC_INTR;
+		pl310_resources[1].start = SC_SICL2PERFMONIRPTREQ;
 
 	platform_device_register(&pl310_erp_device);
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-7xxx.h b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
index c90b4ee..97ca682 100644
--- a/arch/arm/mach-msm/include/mach/irqs-7xxx.h
+++ b/arch/arm/mach-msm/include/mach/irqs-7xxx.h
@@ -75,7 +75,7 @@
 /* 22-31 are reserved except 7x27a*/
 #if defined(CONFIG_ARCH_MSM7X27A)
 #define INT_L2CC_EM          (32 + 22)
-#define INT_L2CC_INTR        (32 + 23)
+#define SC_SICL2PERFMONIRPTREQ (32 + 23)
 #define INT_CE_IRQ           (32 + 24)
 #endif
 
diff --git a/arch/arm/mach-msm/include/mach/irqs-8625.h b/arch/arm/mach-msm/include/mach/irqs-8625.h
index a83dd2e..7083390 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8625.h
@@ -83,7 +83,7 @@
 #define MSM8625_INT_UART2DM_IRQ		(GIC_SPI_START + 32 + 20)
 #define MSM8625_INT_UART2DM_RX		(GIC_SPI_START + 32 + 21)
 #define MSM8625_INT_L2CC_EM		(GIC_SPI_START + 32 + 22)
-#define MSM8625_INT_L2CC_INTR		(GIC_SPI_START + 32 + 23)
+#define MSM8625_INT_SC_SICL2PERFMONIRPTREQ	(GIC_SPI_START + 32 + 23)
 #define MSM8625_INT_CE_IRQ		(GIC_SPI_START + 32 + 24)
 #define MSM8625_INT_CPR_IRQ0		(GIC_SPI_START + 32 + 25)
 #define MSM8625_INT_CPR_IRQ1		(GIC_SPI_START + 32 + 26)
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index aaac476..06c0606 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -101,7 +101,7 @@
 
 static uint16_t msm_bypassed_apps_irqs[] = {
 	MSM8625_INT_CPR_IRQ0,
-	MSM8625_INT_L2CC_INTR,
+	MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
 };
 
 /* Check IRQ falls into bypassed list are not */
diff --git a/arch/arm/mach-msm/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
index 40a2f98..e2a580f 100644
--- a/arch/arm/mach-msm/perf_event_msm_pl310.c
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -22,6 +22,9 @@
 
 #include <asm/pmu.h>
 #include <asm/hardware/cache-l2x0.h>
+#include <mach/socinfo.h>
+
+static u32 rev1;
 
 /*
  * Store dynamic PMU type after registration,
@@ -110,6 +113,30 @@
 
 #define COUNTER_ADDR(idx)	(l2x0_base + L2X0_EVENT_CNT0_VAL - 4*idx)
 
+static u32 l2x0_read_intr_mask(void)
+{
+	return readl_relaxed(l2x0_base + L2X0_INTR_MASK);
+}
+
+static void l2x0_write_intr_mask(u32 val)
+{
+	writel_relaxed(val, l2x0_base + L2X0_INTR_MASK);
+}
+
+static void l2x0_enable_counter_interrupt(void)
+{
+	u32 intr_mask = l2x0_read_intr_mask();
+	intr_mask |= L2X0_INTR_MASK_ECNTR;
+	l2x0_write_intr_mask(intr_mask);
+}
+
+static void l2x0_disable_counter_interrupt(void)
+{
+	u32 intr_mask = l2x0_read_intr_mask();
+	intr_mask &= ~L2X0_INTR_MASK_ECNTR;
+	l2x0_write_intr_mask(intr_mask);
+}
+
 static void l2x0_clear_interrupts(u32 flags)
 {
 	writel_relaxed(flags, l2x0_base + L2X0_INTR_CLEAR);
@@ -190,10 +217,8 @@
 
 	raw_spin_lock_irqsave(&l2x0pmu_hw_events.pmu_lock, flags);
 
-	/*
-	 * TODO: Enable counter interrupt,
-	 * once we know it works on this chip.
-	 */
+	if (!rev1)
+		l2x0_enable_counter_interrupt();
 
 	val = l2x0pmu_read_ctrl();
 
@@ -214,10 +239,8 @@
 	val &= ~L2X0_EVENT_CNT_ENABLE_MASK;
 	l2x0pmu_write_ctrl(val);
 
-	/*
-	 * TODO: Disable counter interrupt,
-	 * once we know it works on this chip.
-	 */
+	if (!rev1)
+		l2x0_disable_counter_interrupt();
 
 	raw_spin_unlock_irqrestore(&l2x0pmu_hw_events.pmu_lock, flags);
 }
@@ -401,6 +424,9 @@
 
 static int __init register_pmu_driver(void)
 {
+	if (machine_is_msm9625())
+		rev1 = 1;
+
 	return platform_driver_register(&l2x0pmu_driver);
 }
 device_initcall(register_pmu_driver);
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index f0b83f9..cb191fc 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -137,6 +137,21 @@
 	.resource	= msm8625_cpu_pmu_resource,
 	.num_resources	= ARRAY_SIZE(msm8625_cpu_pmu_resource),
 };
+
+static struct resource msm8625_l2_pmu_resource[] = {
+	{
+		.start = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
+		.end = MSM8625_INT_SC_SICL2PERFMONIRPTREQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm8625_l2_pmu_device = {
+	.name		= "l2-arm-pmu",
+	.id		= ARM_PMU_DEVICE_L2CC,
+	.resource	= msm8625_l2_pmu_resource,
+	.num_resources	= ARRAY_SIZE(msm8625_l2_pmu_resource),
+};
 #endif
 
 static struct platform_device *pmu_devices[] = {
@@ -168,6 +183,7 @@
 #ifdef CONFIG_ARCH_MSM8625
 	if (cpu_is_msm8625()) {
 		pmu_devices[0] = &msm8625_cpu_pmu_device;
+		pmu_devices[1] = &msm8625_l2_pmu_device;
 		msm8625_cpu_pmu_device.dev.platform_data = &multicore_data;
 	}
 #endif