[RESEND PATCH v1 09/11] perf: hisi: Miscellanous node(MN) event counting in perf

Anurup M anurupvasu at gmail.com
Wed Nov 2 22:42:05 PDT 2016


From: Shaokun Zhang <zhangshaokun at hisilicon.com>

	1. Add support to count MN hardware events.
	2. Mn events are listed in sysfs at /sys/devices/hisi_mn2/events/
	   The events can be selected as shown in perf list
	   e.g.: For MN_READ_REQUEST event for Super CPU cluster 2 the
		event format is
		-e "hisi_mn2/read_req/"

Signed-off-by: Shaokun Zhang <zhangshaokun at hisilicon.com>
Signed-off-by: Anurup M <anurup.m at huawei.com>
---
 drivers/perf/hisilicon/Makefile         |   2 +-
 drivers/perf/hisilicon/hisi_uncore_mn.c | 571 ++++++++++++++++++++++++++++++++
 drivers/perf/hisilicon/hisi_uncore_mn.h |  68 ++++
 3 files changed, 640 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn.c
 create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn.h

diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makefile
index e1766cf..8975104 100644
--- a/drivers/perf/hisilicon/Makefile
+++ b/drivers/perf/hisilicon/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c.o
+obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c.o hisi_uncore_mn.o
diff --git a/drivers/perf/hisilicon/hisi_uncore_mn.c b/drivers/perf/hisilicon/hisi_uncore_mn.c
new file mode 100644
index 0000000..920e346
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_mn.c
@@ -0,0 +1,571 @@
+/*
+ * HiSilicon SoC MN Hardware event counters support
+ *
+ * Copyright (C) 2016 Huawei Technologies Limited
+ * Author: Shaokun Zhang <zhangshaokun at hisilicon.com>
+ *
+ * This code is based on the uncore PMU's like arm-cci and
+ * arm-ccn.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/bitmap.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/perf_event.h>
+#include "hisi_uncore_mn.h"
+
+static inline int hisi_mn_counter_valid(int idx)
+{
+	return (idx >= HISI_IDX_MN_COUNTER0 &&
+			idx <= HISI_IDX_MN_COUNTER_MAX);
+}
+
+static u32 hisi_read_mn_counter(struct hisi_mn_data *mn_hwmod_data,
+								int idx)
+{
+	u32 module_id = mn_hwmod_data->mn_hwcfg.module_id;
+	struct hisi_djtag_client *client = mn_hwmod_data->client;
+	u32 cfg_en, reg_offset, value;
+
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+	reg_offset = mn_hwmod_data->mn_hwcfg.counter_reg0_off + (idx * 4);
+
+	hisi_djtag_readreg(module_id,
+				cfg_en,
+				reg_offset,
+				client, &value);
+
+	return value;
+}
+
+static u64 hisi_mn_event_update(struct perf_event *event,
+				struct hw_perf_event *hwc, int idx)
+{
+	struct hisi_pmu *pmn_pmu = to_hisi_pmu(event->pmu);
+	struct hisi_mn_data *mn_hwmod_data;
+	u64 delta, prev_raw_count, new_raw_count = 0;
+	u32 cfg_en;
+
+	if (!hisi_mn_counter_valid(idx)) {
+		dev_err(pmn_pmu->dev,
+				"Unsupported event index:%d!\n", idx);
+		return 0;
+	}
+
+	mn_hwmod_data = pmn_pmu->hwmod_data;
+
+	/* Check if the MN data is initialized for this SCCL */
+	if (!mn_hwmod_data->client) {
+		dev_err(pmn_pmu->dev,
+			"SCL=%d not initialized!\n", pmn_pmu->scl_id);
+		return 0;
+	}
+
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+
+	do {
+		prev_raw_count = local64_read(&hwc->prev_count);
+		new_raw_count =
+			hisi_read_mn_counter(mn_hwmod_data, idx);
+		delta = (new_raw_count - prev_raw_count) &
+						HISI_MAX_PERIOD;
+
+		local64_add(delta, &event->count);
+	} while (local64_cmpxchg(
+			&hwc->prev_count, prev_raw_count, new_raw_count) !=
+							prev_raw_count);
+
+	return new_raw_count;
+}
+
+static void hisi_set_mn_evtype(struct hisi_pmu *pmn_pmu, int idx, u32 val)
+{
+	struct hisi_djtag_client *client;
+	struct hisi_mn_data *mn_hwmod_data = pmn_pmu->hwmod_data;
+	u32 reg_offset = mn_hwmod_data->mn_hwcfg.evtype_reg0_off;
+	u32 module_id = mn_hwmod_data->mn_hwcfg.module_id;
+	u32 cfg_en, event_value, value = 0;
+
+	event_value = (val -
+			HISI_HWEVENT_MN_EO_BARR_REQ);
+
+	/* Value to write to event type register */
+	val = event_value << (8 * idx);
+
+	/* Find the djtag Identifier of the Unit */
+	client = mn_hwmod_data->client;
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+
+	/*
+	 * Set the event in MN_EVENT_TYPE Register
+	 */
+	hisi_djtag_readreg(module_id,
+			   cfg_en,
+			   reg_offset,
+			   client, &value);
+
+	value &= ~(0xff << (8 * idx));
+	value |= val;
+
+	hisi_djtag_writereg(module_id,
+				cfg_en,
+				reg_offset,
+				value,
+				client);
+}
+
+static u32 hisi_write_mn_counter(struct hisi_pmu *pmn_pmu,
+				struct hw_perf_event *hwc, u32 value)
+{
+	struct hisi_djtag_client *client;
+	struct hisi_mn_data *mn_hwmod_data = pmn_pmu->hwmod_data;
+	u32 module_id = mn_hwmod_data->mn_hwcfg.module_id;
+	u32 cfg_en, reg_offset;
+	int ret;
+	int idx = GET_CNTR_IDX(hwc);
+
+	if (!hisi_mn_counter_valid(idx)) {
+		dev_err(pmn_pmu->dev,
+				"Unsupported event index:%d!\n", idx);
+		return -EINVAL;
+	}
+
+	reg_offset = mn_hwmod_data->mn_hwcfg.counter_reg0_off +
+							(idx * 4);
+	/* Find the djtag Identifier of the Unit */
+	client = mn_hwmod_data->client;
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+
+	ret = hisi_djtag_writereg(module_id,
+				  cfg_en,
+				  reg_offset,
+				  value,
+				  client);
+
+	return ret;
+}
+
+static void hisi_enable_mn_counter(struct hisi_pmu *pmn_pmu, int idx)
+{
+	struct hisi_djtag_client *client;
+	struct hisi_mn_data *mn_hwmod_data = pmn_pmu->hwmod_data;
+	u32 reg_offset = mn_hwmod_data->mn_hwcfg.event_ctrl_reg_off;
+	u32 module_id = mn_hwmod_data->mn_hwcfg.module_id;
+	u32 event_en = mn_hwmod_data->mn_hwcfg.event_enable;
+	u32 cfg_en, value;
+
+	if (!hisi_mn_counter_valid(idx)) {
+		dev_err(pmn_pmu->dev,
+				"Unsupported event index:%d!\n", idx);
+		return;
+	}
+
+	/* Find the djtag Identifier of the Unit */
+	client = mn_hwmod_data->client;
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+
+	/*
+	 * Set the event_bus_en bit in MN_EVENT_CTRL to enable counting
+	 */
+	hisi_djtag_readreg(module_id,
+				cfg_en,
+				reg_offset,
+				client,
+				&value);
+
+	value |= event_en;
+	hisi_djtag_writereg(module_id,
+				cfg_en,
+				reg_offset,
+				value,
+				client);
+}
+
+static void hisi_disable_mn_counter(struct hisi_pmu *pmn_pmu, int idx)
+{
+	struct hisi_djtag_client *client;
+	struct hisi_mn_data *mn_hwmod_data = pmn_pmu->hwmod_data;
+	u32 reg_offset = mn_hwmod_data->mn_hwcfg.event_ctrl_reg_off;
+	u32 module_id = mn_hwmod_data->mn_hwcfg.module_id;
+	u32 event_en = mn_hwmod_data->mn_hwcfg.event_enable;
+	u32 cfg_en, value;
+
+	if (!hisi_mn_counter_valid(idx)) {
+		dev_err(pmn_pmu->dev,
+				"Unsupported event index:%d!\n", idx);
+		return;
+	}
+
+	/* Find the djtag Identifier of the Unit */
+	client = mn_hwmod_data->client;
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+
+	/*
+	 * Clear the event_bus_en bit in MN event control
+	 */
+	hisi_djtag_readreg(module_id,
+				cfg_en,
+				reg_offset,
+				client, &value);
+
+	value &= ~(event_en);
+	hisi_djtag_writereg(module_id,
+				cfg_en,
+				reg_offset,
+				value,
+				client);
+}
+
+static void hisi_clear_mn_event_idx(struct hisi_pmu *pmn_pmu, int idx)
+{
+	struct hisi_djtag_client *client;
+	struct hisi_mn_data *mn_hwmod_data = pmn_pmu->hwmod_data;
+	u32 reg_offset = mn_hwmod_data->mn_hwcfg.evtype_reg0_off;
+	u32 module_id = mn_hwmod_data->mn_hwcfg.module_id;
+	void *bitmap_addr;
+	u32 cfg_en, value;
+
+	if (!hisi_mn_counter_valid(idx)) {
+		dev_err(pmn_pmu->dev,
+				"Unsupported event index:%d!\n", idx);
+		return;
+	}
+
+	bitmap_addr = mn_hwmod_data->hisi_mn_event_used_mask;
+
+	__clear_bit(idx, bitmap_addr);
+
+	/* Find the djtag Identifier of the Unit */
+	client = mn_hwmod_data->client;
+	cfg_en = mn_hwmod_data->mn_hwcfg.bank_cfgen;
+
+	/*
+	 * Clear the event in MN_EVENT_TYPE Register
+	 */
+	hisi_djtag_readreg(module_id,
+				cfg_en,
+				reg_offset,
+				client, &value);
+
+	value &= ~(0xff << (8 * idx));
+	value |= (0xff << (8 * idx));
+	hisi_djtag_writereg(module_id,
+				cfg_en,
+				reg_offset,
+				value,
+				client);
+}
+
+static int hisi_mn_get_event_idx(struct hisi_pmu *pmn_pmu)
+{
+	struct hisi_mn_data *mn_hwmod_data = pmn_pmu->hwmod_data;
+	int event_idx;
+
+	event_idx =
+		find_first_zero_bit(
+			mn_hwmod_data->hisi_mn_event_used_mask,
+					HISI_MAX_CFG_MN_CNTR);
+
+	if (event_idx == HISI_MAX_CFG_MN_CNTR)
+		return -EAGAIN;
+
+	__set_bit(event_idx,
+		mn_hwmod_data->hisi_mn_event_used_mask);
+
+	return event_idx;
+}
+
+static void hisi_free_mn_data(struct hisi_pmu *pmn_pmu)
+{
+	kfree(pmn_pmu->hwmod_data);
+	pmn_pmu->hwmod_data = NULL;
+}
+
+static int init_hisi_mn_hwcfg(struct device *dev,
+				struct hisi_mn_data *pmn_data)
+{
+	struct hisi_mn_hwcfg *pmn_hwcfg = &pmn_data->mn_hwcfg;
+	struct device_node *node = dev->of_node;
+
+	if (of_property_read_u32(node, "counter-reg",
+				     &pmn_hwcfg->counter_reg0_off)) {
+		dev_err(dev, "DT:Couldnot read counter-reg!\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "evctrl-reg",
+				     &pmn_hwcfg->event_ctrl_reg_off)) {
+		dev_err(dev, "DT:Couldnot read evctrl-reg!\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "event-en",
+				     &pmn_hwcfg->event_enable)) {
+		dev_err(dev, "DT:Couldnot read event-en property!\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "evtype-reg",
+				     &pmn_hwcfg->evtype_reg0_off)) {
+		dev_err(dev, "DT:Couldnot read evtype-reg!\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "module-id",
+				     &pmn_hwcfg->module_id)) {
+		dev_err(dev, "DT:Couldnot read module-id property!\n");
+		return -EINVAL;
+	}
+
+	if (of_property_read_u32(node, "cfgen-map",
+					&pmn_hwcfg->bank_cfgen)) {
+		dev_err(dev, "DT:Couldnot read cfgen-map property!\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int init_hisi_mn_data(struct device *dev,
+					struct hisi_pmu *pmn_pmu,
+					struct hisi_djtag_client *client)
+{
+	struct hisi_mn_data *mn_hwmod_data;
+	int ret;
+
+	mn_hwmod_data = kzalloc(sizeof(struct hisi_mn_data),
+							GFP_KERNEL);
+	if (!mn_hwmod_data)
+		return -ENOMEM;
+
+	/* Set the djtag Identifier */
+	mn_hwmod_data->client = client;
+
+	pmn_pmu->hw_events.events = devm_kcalloc(dev,
+					pmn_pmu->num_counters,
+					sizeof(*pmn_pmu->hw_events.events),
+					GFP_KERNEL);
+	if (!pmn_pmu->hw_events.events) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	raw_spin_lock_init(&pmn_pmu->hw_events.pmu_lock);
+
+	pmn_pmu->hwmod_data = mn_hwmod_data;
+
+	ret = init_hisi_mn_hwcfg(dev, mn_hwmod_data);
+	if (ret)
+		goto fail;
+
+	return 0;
+
+fail:
+	hisi_free_mn_data(pmn_pmu);
+	return ret;
+}
+
+static struct attribute *hisi_mn_format_attr[] = {
+	HISI_PMU_FORMAT_ATTR(event, "config:0-11"),
+	NULL,
+};
+
+static struct attribute_group hisi_mn_format_group = {
+	.name = "format",
+	.attrs = hisi_mn_format_attr,
+};
+
+static struct attribute *hisi_mn_events_attr[] = {
+	HISI_PMU_EVENT_ATTR_STR(eo_barrier_req,
+				"event=0x0"),
+	HISI_PMU_EVENT_ATTR_STR(ec_barrier_req,
+				"event=0x01"),
+	HISI_PMU_EVENT_ATTR_STR(dvm_op_req,
+				"event=0x02"),
+	HISI_PMU_EVENT_ATTR_STR(dvm_sync_req,
+				"event=0x03"),
+	HISI_PMU_EVENT_ATTR_STR(read_req,
+				"event=0x04"),
+	HISI_PMU_EVENT_ATTR_STR(write_req,
+				"event=0x05"),
+	NULL,
+};
+
+static struct attribute_group hisi_mn_events_group = {
+	.name = "events",
+	.attrs = hisi_mn_events_attr,
+};
+
+static struct attribute *hisi_mn_attrs[] = {
+	NULL,
+};
+
+struct attribute_group hisi_mn_attr_group = {
+	.attrs = hisi_mn_attrs,
+};
+
+static DEVICE_ATTR(cpumask, 0444, hisi_cpumask_sysfs_show, NULL);
+
+static struct attribute *hisi_mn_cpumask_attrs[] = {
+	&dev_attr_cpumask.attr,
+	NULL,
+};
+
+static const struct attribute_group hisi_mn_cpumask_attr_group = {
+	.attrs = hisi_mn_cpumask_attrs,
+};
+
+static const struct attribute_group *hisi_mn_pmu_attr_groups[] = {
+	&hisi_mn_attr_group,
+	&hisi_mn_format_group,
+	&hisi_mn_events_group,
+	&hisi_mn_cpumask_attr_group,
+	NULL,
+};
+
+static struct hisi_uncore_ops hisi_uncore_mn_ops = {
+	.set_evtype = hisi_set_mn_evtype,
+	.set_event_period = hisi_pmu_set_event_period,
+	.get_event_idx = hisi_mn_get_event_idx,
+	.clear_event_idx = hisi_clear_mn_event_idx,
+	.event_update = hisi_mn_event_update,
+	.enable_counter = hisi_enable_mn_counter,
+	.disable_counter = hisi_disable_mn_counter,
+	.write_counter = hisi_write_mn_counter,
+};
+
+static int hisi_mn_pmu_init(struct device *dev,
+					struct hisi_pmu *pmn_pmu)
+{
+	int ret;
+	/* Read common PMU properties */
+	ret = hisi_uncore_common_fwprop_read(dev, pmn_pmu);
+	if (ret)
+		return ret;
+
+	pmn_pmu->name = kasprintf(GFP_KERNEL, "hisi_mn%d",
+						pmn_pmu->scl_id);
+	pmn_pmu->ops = &hisi_uncore_mn_ops;
+
+	pmn_pmu->dev = dev;
+	/* Pick one core to use for cpumask attributes */
+	cpumask_set_cpu(smp_processor_id(), &pmn_pmu->cpu);
+
+	return 0;
+}
+
+static int hisi_pmu_mn_dev_probe(struct hisi_djtag_client *client)
+{
+	struct hisi_pmu *pmn_pmu = NULL;
+	struct device *dev = &client->dev;
+	int ret;
+
+	pmn_pmu = hisi_pmu_alloc(dev);
+	if (IS_ERR(pmn_pmu))
+		return PTR_ERR(pmn_pmu);
+
+	ret = hisi_mn_pmu_init(dev, pmn_pmu);
+	if (ret)
+		return ret;
+
+	ret = init_hisi_mn_data(dev, pmn_pmu, client);
+	if (ret)
+		goto fail_init;
+
+	/* Register with perf PMU */
+	pmn_pmu->pmu = (struct pmu) {
+		.name = pmn_pmu->name,
+		.task_ctx_nr = perf_invalid_context,
+		.event_init = hisi_uncore_pmu_event_init,
+		.add = hisi_uncore_pmu_add,
+		.del = hisi_uncore_pmu_del,
+		.start = hisi_uncore_pmu_start,
+		.stop = hisi_uncore_pmu_stop,
+		.read = hisi_uncore_pmu_read,
+		.attr_groups = hisi_mn_pmu_attr_groups,
+	};
+
+	ret = hisi_uncore_pmu_setup(pmn_pmu, pmn_pmu->name);
+	if (ret) {
+		dev_err(pmn_pmu->dev, "hisi_uncore_pmu_init FAILED!!\n");
+		goto fail;
+	}
+
+	/* Set the drv data to mn_pmu */
+	dev_set_drvdata(dev, pmn_pmu);
+
+	return 0;
+
+fail:
+	hisi_free_mn_data(pmn_pmu);
+
+fail_init:
+	if (pmn_pmu)
+		devm_kfree(dev, pmn_pmu);
+	dev_err(pmn_pmu->dev, "%s failed\n", __func__);
+
+	return ret;
+}
+
+static int hisi_pmu_mn_dev_remove(struct hisi_djtag_client *client)
+{
+	struct hisi_pmu *pmn_pmu = NULL;
+	struct device *dev = &client->dev;
+
+	pmn_pmu = dev_get_drvdata(dev);
+
+	perf_pmu_unregister(&pmn_pmu->pmu);
+	hisi_free_mn_data(pmn_pmu);
+
+	return 0;
+}
+
+static const struct of_device_id mn_of_match[] = {
+	{ .compatible = "hisilicon,hisi-pmu-mn-v1", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, mn_of_match);
+
+static struct hisi_djtag_driver hisi_pmu_mn_driver = {
+	.driver = {
+		.name = "hisi-pmu-mn",
+		.of_match_table = mn_of_match,
+	},
+	.probe = hisi_pmu_mn_dev_probe,
+	.remove = hisi_pmu_mn_dev_remove,
+};
+
+static int __init hisi_pmu_mn_init(void)
+{
+	int rc;
+
+	rc = hisi_djtag_register_driver(THIS_MODULE, &hisi_pmu_mn_driver);
+	if (rc < 0) {
+		pr_err("hisi pmu mn init failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+module_init(hisi_pmu_mn_init);
+
+static void __exit hisi_pmu_mn_exit(void)
+{
+	hisi_djtag_unregister_driver(&hisi_pmu_mn_driver);
+}
+module_exit(hisi_pmu_mn_exit);
+
+MODULE_DESCRIPTION("HiSilicon SoC HIP0x MN PMU driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Shaokun Zhang");
diff --git a/drivers/perf/hisilicon/hisi_uncore_mn.h b/drivers/perf/hisilicon/hisi_uncore_mn.h
new file mode 100644
index 0000000..4cac2f3
--- /dev/null
+++ b/drivers/perf/hisilicon/hisi_uncore_mn.h
@@ -0,0 +1,68 @@
+/*
+ * HiSilicon SoC MN Hardware event counters support
+ *
+ * Copyright (C) 2016 Huawei Technologies Limited
+ * Author: Shaokun Zhang <zhangshaokun at hisilicon.com>
+ *
+ * This code is based on the uncore PMU's like arm-cci and
+ * arm-ccn.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __HISI_UNCORE_MN_H__
+#define __HISI_UNCORE_MN_H__
+
+#include "hisi_uncore_pmu.h"
+
+/*
+ * ARMv8 HiSilicon MN RAW event types.
+ */
+enum armv8_hisi_mn_event_types {
+	HISI_HWEVENT_MN_EO_BARR_REQ	= 0x0,
+	HISI_HWEVENT_MN_EC_BARR_REQ	= 0x01,
+	HISI_HWEVENT_MN_DVM_OP_REQ	= 0x02,
+	HISI_HWEVENT_MN_DVM_SYNC_REQ	= 0x03,
+	HISI_HWEVENT_MN_READ_REQ	= 0x04,
+	HISI_HWEVENT_MN_WRITE_REQ	= 0x05,
+	HISI_HWEVENT_MN_COPYBK_REQ	= 0x06,
+	HISI_HWEVENT_MN_OTHER_REQ	= 0x07,
+	HISI_HWEVENT_MN_EVENT_MAX	= 0x08,
+};
+
+/*
+ * ARMv8 HiSilicon Hardware counter Index.
+ */
+enum armv8_hisi_mn_counters {
+	HISI_IDX_MN_COUNTER0	= 0x0,
+	HISI_IDX_MN_COUNTER_MAX	= 0x4,
+};
+
+#define HISI_MAX_CFG_MN_CNTR	0x04
+
+struct hisi_mn_hwcfg {
+	u32 evtype_reg0_off;
+	u32 counter_reg0_off;
+	u32 event_ctrl_reg_off;
+	u32 event_enable;
+	u32 module_id;
+	u32 bank_cfgen;
+};
+
+struct hisi_mn_data {
+	struct hisi_djtag_client *client;
+	DECLARE_BITMAP(hisi_mn_event_used_mask,
+				HISI_MAX_CFG_MN_CNTR);
+	struct hisi_mn_hwcfg mn_hwcfg;
+};
+
+#endif /* __HISI_UNCORE_MN_H__ */
-- 
2.1.4




More information about the linux-arm-kernel mailing list