/* Copyright (c) 2013 The Linux Foundation. All rights reserved. * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #if defined(CONFIG_ARCH_MSM_KRAITMP) static DEFINE_PER_CPU(u32, pmu_irq_cookie); static void pmu_enable_irq_callback(void *info) { int irq = *(unsigned int *)info; enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING); } static void pmu_disable_irq_callback(void *info) { int irq = *(unsigned int *)info; disable_percpu_irq(irq); } int multicore_request_irq(int irq, irq_handler_t *handle_irq) { int err = 0; int cpu; err = request_percpu_irq(irq, *handle_irq, "l1-armpmu", &pmu_irq_cookie); if (!err) { for_each_cpu(cpu, cpu_online_mask) { smp_call_function_single(cpu, pmu_enable_irq_callback, &irq, 1); } } return err; } void multicore_free_irq(int irq) { int cpu; if (irq >= 0) { for_each_cpu(cpu, cpu_online_mask) { smp_call_function_single(cpu, pmu_disable_irq_callback, &irq, 1); } free_percpu_irq(irq, &pmu_irq_cookie); } } #endif static struct resource cpu_pmu_resource[] = { { .start = INT_ARMQC_PERFMON, .end = INT_ARMQC_PERFMON, .flags = IORESOURCE_IRQ, }, }; #ifdef CONFIG_CPU_HAS_L2_PMU static struct resource l2_pmu_resource[] = { { .start = SC_SICL2PERFMONIRPTREQ, .end = SC_SICL2PERFMONIRPTREQ, .flags = IORESOURCE_IRQ, }, }; static struct platform_device l2_pmu_device = { .name = "l2-arm-pmu", .resource = l2_pmu_resource, .num_resources = ARRAY_SIZE(l2_pmu_resource), }; #endif static struct platform_device cpu_pmu_device = { .name = "cpu-arm-pmu", .id = -1, .resource = cpu_pmu_resource, .num_resources = ARRAY_SIZE(cpu_pmu_resource), }; static struct platform_device *pmu_devices[] = { &cpu_pmu_device, #ifdef CONFIG_CPU_HAS_L2_PMU &l2_pmu_device, #endif }; static int __init msm_pmu_init(void) { return platform_add_devices(pmu_devices, ARRAY_SIZE(pmu_devices)); } arch_initcall(msm_pmu_init);