From patchwork Tue May 5 11:49:07 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 6337141 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id A54BABEEE1 for ; Tue, 5 May 2015 11:53:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9E6FF201B9 for ; Tue, 5 May 2015 11:53:57 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 77EC820138 for ; Tue, 5 May 2015 11:53:56 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YpbNe-0006v3-Cm; Tue, 05 May 2015 11:51:18 +0000 Received: from eu-smtp-delivery-143.mimecast.com ([207.82.80.143]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YpbMA-000581-Ql for linux-arm-kernel@lists.infradead.org; Tue, 05 May 2015 11:49:53 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by uk-mta-4.uk.mimecast.lan; Tue, 05 May 2015 12:49:25 +0100 Received: from e106634-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 5 May 2015 12:49:22 +0100 From: "Suzuki K. Poulose" To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 6/7] arm-cci: Add CCI-500 PMU support Date: Tue, 5 May 2015 12:49:07 +0100 Message-Id: <1430826548-29960-7-git-send-email-suzuki.poulose@arm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1430826548-29960-1-git-send-email-suzuki.poulose@arm.com> References: <1430826548-29960-1-git-send-email-suzuki.poulose@arm.com> X-OriginalArrivalTime: 05 May 2015 11:49:22.0209 (UTC) FILETIME=[87003110:01D08729] X-MC-Unique: pD16z5wPTeGhwH6XPHUVGA-7 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150505_044947_301108_E52F8851 X-CRM114-Status: GOOD ( 14.48 ) X-Spam-Score: -2.3 (--) Cc: Mark Rutland , devicetree@vger.kernel.org, Lorenzo Pieralisi , Arnd Bergmann , Pawel Moll , "Suzuki K. Poulose" , Punit Agrawal , Will Deacon , linux-kernel@vger.kernel.org, arm@kernel.org, Olof Johansson X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Suzuki K. Poulose" CCI-500 provides 8 event counters which can count any of the supported events independently. The PMU event id is a 9-bit value made of two parts. bits [8:5] - Source port 0x0-0x6 Slave Ports 0x8-0xD Master Ports 0xf Global Events to CCI 0x7,0xe Reserved bits [0:4] - Event code (specific to each type of port) The generic CCI-500 controlling interface remains the same with CCI-400. However there are some differences in the PMU event counters. - No cycle counter - Upto 8 counters(4 in CCI-400) - Each counter area is 64K(4K in CCI400) - The counter0 starts at offset 0x10000 from the base of CCI Cc: Punit Agrawal Cc: Mark Rutland Cc: Will Deacon Cc: devicetree@vger.kernel.org Signed-off-by: Suzuki K. Poulose Acked-by: Punit Agrawal --- Documentation/devicetree/bindings/arm/cci.txt | 4 +- drivers/bus/Kconfig | 12 +++ drivers/bus/arm-cci.c | 133 +++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/cci.txt b/Documentation/devicetree/bindings/arm/cci.txt index 3c5c631..aef1d20 100644 --- a/Documentation/devicetree/bindings/arm/cci.txt +++ b/Documentation/devicetree/bindings/arm/cci.txt @@ -31,8 +31,9 @@ specific to ARM. - compatible Usage: required Value type: - Definition: must be set to + Definition: must contain one of the following: "arm,cci-400" + "arm,cci-500" - reg Usage: required @@ -99,6 +100,7 @@ specific to ARM. "arm,cci-400-pmu,r1" "arm,cci-400-pmu" - DEPRECATED, permitted only where OS has secure acces to CCI registers + "arm,cci-500-pmu,r0" - reg: Usage: required Value type: Integer cells. A register entry, expressed diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index be66b7c..5fb3150 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -36,6 +36,18 @@ config ARM_CCI400_PORT_CTRL Low level power management driver for CCI400 cache coherent interconnect for ARM platforms. +config ARM_CCI500_PMU + bool "ARM CCI500 PMU support" + default y + depends on ARM || ARM64 + depends on HW_PERF_EVENTS + select ARM_CCI_PMU + help + Support for PMU events monitoring on the ARM CCI-500 cache coherent + interconnect. + + If unsure, say Y + config ARM_CCN bool "ARM CCN driver support" depends on ARM || ARM64 diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c index 2b43cea..e12ddba 100644 --- a/drivers/bus/arm-cci.c +++ b/drivers/bus/arm-cci.c @@ -52,6 +52,9 @@ static const struct of_device_id arm_cci_matches[] = { #ifdef CONFIG_ARM_CCI400_COMMON {.compatible = "arm,cci-400", .data = CCI400_PORTS_DATA }, #endif +#ifdef CONFIG_ARM_CCI500_PMU + { .compatible = "arm,cci-500", }, +#endif {}, }; @@ -89,6 +92,9 @@ static const struct of_device_id arm_cci_matches[] = { enum { CCI_IF_SLAVE, CCI_IF_MASTER, +#ifdef CONFIG_ARM_CCI500_PMU + CCI_IF_GLOBAL, +#endif CCI_IF_MAX, }; @@ -145,6 +151,9 @@ enum cci_models { CCI400_R0, CCI400_R1, #endif +#ifdef CONFIG_ARM_CCI500_PMU + CCI500_R0, +#endif CCI_MODEL_MAX }; @@ -294,6 +303,101 @@ static inline struct cci_pmu_model *probe_cci_model(struct platform_device *pdev } #endif /* CONFIG_ARM_CCI400_PMU */ +#ifdef CONFIG_ARM_CCI500_PMU + +/* + * CCI500 provides 8 independent event counters that can count + * any of the events available. + * + * CCI500 PMU event id is an 9-bit value made of two parts. + * bits [8:5] - Source for the event + * 0x0-0x6 - Slave interfaces + * 0x8-0xD - Master interfaces + * 0xf - Global Events + * 0x7,0xe - Reserved + * + * bits [4:0] - Event code (specific to type of interface) + */ + +/* Port ids */ +#define CCI500_PORT_S0 0x0 +#define CCI500_PORT_S1 0x1 +#define CCI500_PORT_S2 0x2 +#define CCI500_PORT_S3 0x3 +#define CCI500_PORT_S4 0x4 +#define CCI500_PORT_S5 0x5 +#define CCI500_PORT_S6 0x6 + +#define CCI500_PORT_M0 0x8 +#define CCI500_PORT_M1 0x9 +#define CCI500_PORT_M2 0xa +#define CCI500_PORT_M3 0xb +#define CCI500_PORT_M4 0xc +#define CCI500_PORT_M5 0xd + +#define CCI500_PORT_GLOBAL 0xf + +#define CCI500_PMU_EVENT_MASK 0x1ffUL +#define CCI500_PMU_EVENT_SOURCE_SHIFT 0x5 +#define CCI500_PMU_EVENT_SOURCE_MASK 0xf +#define CCI500_PMU_EVENT_CODE_SHIFT 0x0 +#define CCI500_PMU_EVENT_CODE_MASK 0x1f + +#define CCI500_PMU_EVENT_SOURCE(event) \ + ((event >> CCI500_PMU_EVENT_SOURCE_SHIFT) & CCI500_PMU_EVENT_SOURCE_MASK) +#define CCI500_PMU_EVENT_CODE(event) \ + ((event >> CCI500_PMU_EVENT_CODE_SHIFT) & CCI500_PMU_EVENT_CODE_MASK) + +#define CCI500_SLAVE_PORT_MIN_EV 0x00 +#define CCI500_SLAVE_PORT_MAX_EV 0x1f +#define CCI500_MASTER_PORT_MIN_EV 0x00 +#define CCI500_MASTER_PORT_MAX_EV 0x06 +#define CCI500_GLOBAL_PORT_MIN_EV 0x00 +#define CCI500_GLOBAL_PORT_MAX_EV 0x0f + +static int cci500_validate_hw_event(struct cci_pmu *cci_pmu, + unsigned long hw_event) +{ + u32 ev_source = CCI500_PMU_EVENT_SOURCE(hw_event); + u32 ev_code = CCI500_PMU_EVENT_CODE(hw_event); + int if_type; + + if (hw_event & ~CCI500_PMU_EVENT_MASK) + return -ENOENT; + + switch (ev_source) { + case CCI500_PORT_S0: + case CCI500_PORT_S1: + case CCI500_PORT_S2: + case CCI500_PORT_S3: + case CCI500_PORT_S4: + case CCI500_PORT_S5: + case CCI500_PORT_S6: + if_type = CCI_IF_SLAVE; + break; + case CCI500_PORT_M0: + case CCI500_PORT_M1: + case CCI500_PORT_M2: + case CCI500_PORT_M3: + case CCI500_PORT_M4: + case CCI500_PORT_M5: + if_type = CCI_IF_MASTER; + break; + case CCI500_PORT_GLOBAL: + if_type = CCI_IF_GLOBAL; + break; + default: + return -ENOENT; + } + + if (ev_code >= cci_pmu->model->event_ranges[if_type].min && + ev_code <= cci_pmu->model->event_ranges[if_type].max) + return hw_event; + + return -ENOENT; +} +#endif /* CONFIG_ARM_CCI500_PMU */ + static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx) { return 0 <= idx && idx <= CCI_PMU_CNTR_LAST(cci_pmu); @@ -981,6 +1085,29 @@ static struct cci_pmu_model cci_pmu_models[] = { .get_event_idx = cci400_get_event_idx, }, #endif +#ifdef CONFIG_ARM_CCI500_PMU + [CCI500_R0] = { + .name = "CCI_500", + .fixed_hw_cntrs = 0, + .num_hw_cntrs = 8, + .cntr_size = SZ_64K, + .event_ranges = { + [CCI_IF_SLAVE] = { + CCI500_SLAVE_PORT_MIN_EV, + CCI500_SLAVE_PORT_MAX_EV, + }, + [CCI_IF_MASTER] = { + CCI500_MASTER_PORT_MIN_EV, + CCI500_MASTER_PORT_MAX_EV, + }, + [CCI_IF_GLOBAL] = { + CCI500_GLOBAL_PORT_MIN_EV, + CCI500_GLOBAL_PORT_MAX_EV, + }, + }, + .validate_hw_event = cci500_validate_hw_event, + }, +#endif }; static const struct of_device_id arm_cci_pmu_matches[] = { @@ -998,6 +1125,12 @@ static const struct of_device_id arm_cci_pmu_matches[] = { .data = &cci_pmu_models[CCI400_R1], }, #endif +#ifdef CONFIG_ARM_CCI500_PMU + { + .compatible = "arm,cci-500-pmu,r0", + .data = &cci_pmu_models[CCI500_R0], + }, +#endif {}, };