Эх сурвалжийг харах

arm-cci: CoreLink CCI-550 PMU driver

Add ARM CoreLink CCI-550  cache coherent interconnect PMU
driver support. The CCI-550 PMU shares all the attributes of CCI-500
PMU, except for an additional master interface (MI-6 - 0xe).
CCI-550 requires the same work around as for CCI-500 to
write to the PMU counter.

Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Punit Agrawal <punit.agrawal@arm.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Suzuki K Poulose 9 жил өмнө
parent
commit
d7dd5fd773

+ 2 - 0
Documentation/devicetree/bindings/arm/cci.txt

@@ -34,6 +34,7 @@ specific to ARM.
 		Definition: must contain one of the following:
 		Definition: must contain one of the following:
 			    "arm,cci-400"
 			    "arm,cci-400"
 			    "arm,cci-500"
 			    "arm,cci-500"
+			    "arm,cci-550"
 
 
 	- reg
 	- reg
 		Usage: required
 		Usage: required
@@ -101,6 +102,7 @@ specific to ARM.
 				 "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
 				 "arm,cci-400-pmu"  - DEPRECATED, permitted only where OS has
 						      secure acces to CCI registers
 						      secure acces to CCI registers
 				 "arm,cci-500-pmu,r0"
 				 "arm,cci-500-pmu,r0"
+				 "arm,cci-550-pmu,r0"
 		- reg:
 		- reg:
 			Usage: required
 			Usage: required
 			Value type: Integer cells. A register entry, expressed
 			Value type: Integer cells. A register entry, expressed

+ 4 - 4
drivers/bus/Kconfig

@@ -35,14 +35,14 @@ config ARM_CCI400_PORT_CTRL
 	  interconnect for ARM platforms.
 	  interconnect for ARM platforms.
 
 
 config ARM_CCI5xx_PMU
 config ARM_CCI5xx_PMU
-	bool "ARM CCI500 PMU support"
+	bool "ARM CCI-500/CCI-550 PMU support"
 	depends on (ARM && CPU_V7) || ARM64
 	depends on (ARM && CPU_V7) || ARM64
 	depends on PERF_EVENTS
 	depends on PERF_EVENTS
 	select ARM_CCI_PMU
 	select ARM_CCI_PMU
 	help
 	help
-	  Support for PMU events monitoring on the ARM CCI-500 cache coherent
-	  interconnect. CCI-500 provides 8 independent event counters, which
-	  can count events pertaining to the slave/master interfaces as well
+	  Support for PMU events monitoring on the ARM CCI-500/CCI-550 cache
+	  coherent interconnects. Both of them provide 8 independent event counters,
+	  which can count events pertaining to the slave/master interfaces as well
 	  as the internal events to the CCI.
 	  as the internal events to the CCI.
 
 
 	  If unsure, say Y
 	  If unsure, say Y

+ 84 - 1
drivers/bus/arm-cci.c

@@ -54,6 +54,7 @@ static const struct of_device_id arm_cci_matches[] = {
 #endif
 #endif
 #ifdef CONFIG_ARM_CCI5xx_PMU
 #ifdef CONFIG_ARM_CCI5xx_PMU
 	{ .compatible = "arm,cci-500", },
 	{ .compatible = "arm,cci-500", },
+	{ .compatible = "arm,cci-550", },
 #endif
 #endif
 	{},
 	{},
 };
 };
@@ -156,6 +157,7 @@ enum cci_models {
 #endif
 #endif
 #ifdef CONFIG_ARM_CCI5xx_PMU
 #ifdef CONFIG_ARM_CCI5xx_PMU
 	CCI500_R0,
 	CCI500_R0,
+	CCI550_R0,
 #endif
 #endif
 	CCI_MODEL_MAX
 	CCI_MODEL_MAX
 };
 };
@@ -451,6 +453,7 @@ static inline struct cci_pmu_model *probe_cci_model(struct platform_device *pdev
 #define CCI5xx_PORT_M3			0xb
 #define CCI5xx_PORT_M3			0xb
 #define CCI5xx_PORT_M4			0xc
 #define CCI5xx_PORT_M4			0xc
 #define CCI5xx_PORT_M5			0xd
 #define CCI5xx_PORT_M5			0xd
+#define CCI5xx_PORT_M6			0xe
 
 
 #define CCI5xx_PORT_GLOBAL		0xf
 #define CCI5xx_PORT_GLOBAL		0xf
 
 
@@ -611,6 +614,58 @@ static int cci500_validate_hw_event(struct cci_pmu *cci_pmu,
 	return -ENOENT;
 	return -ENOENT;
 }
 }
 
 
+/*
+ * CCI550 provides 8 independent event counters that can count
+ * any of the events available.
+ * CCI550 PMU event source ids
+ *	0x0-0x6 - Slave interfaces
+ *	0x8-0xe - Master interfaces
+ *	0xf     - Global Events
+ *	0x7	- Reserved
+ */
+static int cci550_validate_hw_event(struct cci_pmu *cci_pmu,
+					unsigned long hw_event)
+{
+	u32 ev_source = CCI5xx_PMU_EVENT_SOURCE(hw_event);
+	u32 ev_code = CCI5xx_PMU_EVENT_CODE(hw_event);
+	int if_type;
+
+	if (hw_event & ~CCI5xx_PMU_EVENT_MASK)
+		return -ENOENT;
+
+	switch (ev_source) {
+	case CCI5xx_PORT_S0:
+	case CCI5xx_PORT_S1:
+	case CCI5xx_PORT_S2:
+	case CCI5xx_PORT_S3:
+	case CCI5xx_PORT_S4:
+	case CCI5xx_PORT_S5:
+	case CCI5xx_PORT_S6:
+		if_type = CCI_IF_SLAVE;
+		break;
+	case CCI5xx_PORT_M0:
+	case CCI5xx_PORT_M1:
+	case CCI5xx_PORT_M2:
+	case CCI5xx_PORT_M3:
+	case CCI5xx_PORT_M4:
+	case CCI5xx_PORT_M5:
+	case CCI5xx_PORT_M6:
+		if_type = CCI_IF_MASTER;
+		break;
+	case CCI5xx_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_CCI5xx_PMU */
 #endif	/* CONFIG_ARM_CCI5xx_PMU */
 
 
 /*
 /*
@@ -898,7 +953,7 @@ static void pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
 #ifdef CONFIG_ARM_CCI5xx_PMU
 #ifdef CONFIG_ARM_CCI5xx_PMU
 
 
 /*
 /*
- * CCI-500 has advanced power saving policies, which could gate the
+ * CCI-500/CCI-550 has advanced power saving policies, which could gate the
  * clocks to the PMU counters, which makes the writes to them ineffective.
  * clocks to the PMU counters, which makes the writes to them ineffective.
  * The only way to write to those counters is when the global counters
  * The only way to write to those counters is when the global counters
  * are enabled and the particular counter is enabled.
  * are enabled and the particular counter is enabled.
@@ -1546,6 +1601,30 @@ static struct cci_pmu_model cci_pmu_models[] = {
 		.validate_hw_event = cci500_validate_hw_event,
 		.validate_hw_event = cci500_validate_hw_event,
 		.write_counters	= cci5xx_pmu_write_counters,
 		.write_counters	= cci5xx_pmu_write_counters,
 	},
 	},
+	[CCI550_R0] = {
+		.name = "CCI_550",
+		.fixed_hw_cntrs = 0,
+		.num_hw_cntrs = 8,
+		.cntr_size = SZ_64K,
+		.format_attrs = cci5xx_pmu_format_attrs,
+		.event_attrs = cci5xx_pmu_event_attrs,
+		.event_ranges = {
+			[CCI_IF_SLAVE] = {
+				CCI5xx_SLAVE_PORT_MIN_EV,
+				CCI5xx_SLAVE_PORT_MAX_EV,
+			},
+			[CCI_IF_MASTER] = {
+				CCI5xx_MASTER_PORT_MIN_EV,
+				CCI5xx_MASTER_PORT_MAX_EV,
+			},
+			[CCI_IF_GLOBAL] = {
+				CCI5xx_GLOBAL_PORT_MIN_EV,
+				CCI5xx_GLOBAL_PORT_MAX_EV,
+			},
+		},
+		.validate_hw_event = cci550_validate_hw_event,
+		.write_counters	= cci5xx_pmu_write_counters,
+	},
 #endif
 #endif
 };
 };
 
 
@@ -1569,6 +1648,10 @@ static const struct of_device_id arm_cci_pmu_matches[] = {
 		.compatible = "arm,cci-500-pmu,r0",
 		.compatible = "arm,cci-500-pmu,r0",
 		.data = &cci_pmu_models[CCI500_R0],
 		.data = &cci_pmu_models[CCI500_R0],
 	},
 	},
+	{
+		.compatible = "arm,cci-550-pmu,r0",
+		.data = &cci_pmu_models[CCI550_R0],
+	},
 #endif
 #endif
 	{},
 	{},
 };
 };