File Index
Files and directories
Sign in
FILE

hisi_uncore_sllc_pmu.c

File preview with syntax highlighting.

linux-6.19.14/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * HiSilicon SLLC uncore Hardware event counters support
  4 *
  5 * Copyright (C) 2020 HiSilicon Limited
  6 * Author: Shaokun Zhang <zhangshaokun@hisilicon.com>
  7 *
  8 * This code is based on the uncore PMUs like arm-cci and arm-ccn.
  9 */
 10#include <linux/acpi.h>
 11#include <linux/cpuhotplug.h>
 12#include <linux/interrupt.h>
 13#include <linux/irq.h>
 14#include <linux/list.h>
 15#include <linux/smp.h>
 16
 17#include "hisi_uncore_pmu.h"
 18
 19/* SLLC register definition */
 20#define SLLC_INT_MASK			0x0814
 21#define SLLC_INT_STATUS			0x0818
 22#define SLLC_INT_CLEAR			0x081c
 23#define SLLC_PERF_CTRL			0x1c00
 24#define SLLC_SRCID_CTRL			0x1c04
 25#define SLLC_TGTID_CTRL			0x1c08
 26#define SLLC_EVENT_CTRL			0x1c14
 27#define SLLC_EVENT_TYPE0		0x1c18
 28#define SLLC_VERSION			0x1cf0
 29#define SLLC_EVENT_CNT0_L		0x1d00
 30
 31/* SLLC registers definition in v3 */
 32#define SLLC_V3_INT_MASK		0x6834
 33#define SLLC_V3_INT_STATUS		0x6838
 34#define SLLC_V3_INT_CLEAR		0x683c
 35#define SLLC_V3_VERSION			0x6c00
 36#define SLLC_V3_PERF_CTRL		0x6d00
 37#define SLLC_V3_SRCID_CTRL		0x6d04
 38#define SLLC_V3_TGTID_CTRL		0x6d08
 39#define SLLC_V3_EVENT_CTRL		0x6d14
 40#define SLLC_V3_EVENT_TYPE0		0x6d18
 41#define SLLC_V3_EVENT_CNT0_L		0x6e00
 42
 43#define SLLC_EVTYPE_MASK		0xff
 44#define SLLC_PERF_CTRL_EN		BIT(0)
 45#define SLLC_FILT_EN			BIT(1)
 46#define SLLC_TRACETAG_EN		BIT(2)
 47#define SLLC_SRCID_EN			BIT(4)
 48#define SLLC_SRCID_NONE			0x0
 49#define SLLC_TGTID_EN			BIT(5)
 50#define SLLC_TGTID_NONE			0x0
 51#define SLLC_TGTID_MIN_SHIFT		1
 52#define SLLC_TGTID_MAX_SHIFT		12
 53#define SLLC_SRCID_CMD_SHIFT		1
 54#define SLLC_SRCID_MSK_SHIFT		12
 55
 56#define SLLC_V3_TGTID_MIN_SHIFT		1
 57#define SLLC_V3_TGTID_MAX_SHIFT		10
 58#define SLLC_V3_SRCID_CMD_SHIFT		1
 59#define SLLC_V3_SRCID_MSK_SHIFT		10
 60
 61#define SLLC_NR_EVENTS			0xff
 62#define SLLC_EVENT_CNTn(cnt0, n)	((cnt0) + (n) * 8)
 63
 64HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0);
 65HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_max, config1, 21, 11);
 66HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22);
 67HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33);
 68HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44);
 69
 70struct hisi_sllc_pmu_regs {
 71	u32 int_mask;
 72	u32 int_clear;
 73	u32 int_status;
 74	u32 perf_ctrl;
 75	u32 srcid_ctrl;
 76	u32 srcid_cmd_shift;
 77	u32 srcid_mask_shift;
 78	u32 tgtid_ctrl;
 79	u32 tgtid_min_shift;
 80	u32 tgtid_max_shift;
 81	u32 event_ctrl;
 82	u32 event_type0;
 83	u32 version;
 84	u32 event_cnt0;
 85};
 86
 87static bool tgtid_is_valid(u32 max, u32 min)
 88{
 89	return max > 0 && max >= min;
 90}
 91
 92static void hisi_sllc_pmu_enable_tracetag(struct perf_event *event)
 93{
 94	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
 95	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
 96	u32 tt_en = hisi_get_tracetag_en(event);
 97
 98	if (tt_en) {
 99		u32 val;
100
101		val = readl(sllc_pmu->base + regs->perf_ctrl);
102		val |= SLLC_TRACETAG_EN | SLLC_FILT_EN;
103		writel(val, sllc_pmu->base + regs->perf_ctrl);
104	}
105}
106
107static void hisi_sllc_pmu_disable_tracetag(struct perf_event *event)
108{
109	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
110	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
111	u32 tt_en = hisi_get_tracetag_en(event);
112
113	if (tt_en) {
114		u32 val;
115
116		val = readl(sllc_pmu->base + regs->perf_ctrl);
117		val &= ~(SLLC_TRACETAG_EN | SLLC_FILT_EN);
118		writel(val, sllc_pmu->base + regs->perf_ctrl);
119	}
120}
121
122static void hisi_sllc_pmu_config_tgtid(struct perf_event *event)
123{
124	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
125	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
126	u32 min = hisi_get_tgtid_min(event);
127	u32 max = hisi_get_tgtid_max(event);
128
129	if (tgtid_is_valid(max, min)) {
130		u32 val = (max << regs->tgtid_max_shift) |
131			  (min << regs->tgtid_min_shift);
132
133		writel(val, sllc_pmu->base + regs->tgtid_ctrl);
134		/* Enable the tgtid */
135		val = readl(sllc_pmu->base + regs->perf_ctrl);
136		val |= SLLC_TGTID_EN | SLLC_FILT_EN;
137		writel(val, sllc_pmu->base + regs->perf_ctrl);
138	}
139}
140
141static void hisi_sllc_pmu_clear_tgtid(struct perf_event *event)
142{
143	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
144	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
145	u32 min = hisi_get_tgtid_min(event);
146	u32 max = hisi_get_tgtid_max(event);
147
148	if (tgtid_is_valid(max, min)) {
149		u32 val;
150
151		writel(SLLC_TGTID_NONE, sllc_pmu->base + regs->tgtid_ctrl);
152		/* Disable the tgtid */
153		val = readl(sllc_pmu->base + regs->perf_ctrl);
154		val &= ~(SLLC_TGTID_EN | SLLC_FILT_EN);
155		writel(val, sllc_pmu->base + regs->perf_ctrl);
156	}
157}
158
159static void hisi_sllc_pmu_config_srcid(struct perf_event *event)
160{
161	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
162	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
163	u32 cmd = hisi_get_srcid_cmd(event);
164
165	if (cmd) {
166		u32 val, msk;
167
168		msk = hisi_get_srcid_msk(event);
169		val = (cmd << regs->srcid_cmd_shift) |
170		      (msk << regs->srcid_mask_shift);
171		writel(val, sllc_pmu->base + regs->srcid_ctrl);
172		/* Enable the srcid */
173		val = readl(sllc_pmu->base + regs->perf_ctrl);
174		val |= SLLC_SRCID_EN | SLLC_FILT_EN;
175		writel(val, sllc_pmu->base + regs->perf_ctrl);
176	}
177}
178
179static void hisi_sllc_pmu_clear_srcid(struct perf_event *event)
180{
181	struct hisi_pmu *sllc_pmu = to_hisi_pmu(event->pmu);
182	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
183	u32 cmd = hisi_get_srcid_cmd(event);
184
185	if (cmd) {
186		u32 val;
187
188		writel(SLLC_SRCID_NONE, sllc_pmu->base + regs->srcid_ctrl);
189		/* Disable the srcid */
190		val = readl(sllc_pmu->base + regs->perf_ctrl);
191		val &= ~(SLLC_SRCID_EN | SLLC_FILT_EN);
192		writel(val, sllc_pmu->base + regs->perf_ctrl);
193	}
194}
195
196static void hisi_sllc_pmu_enable_filter(struct perf_event *event)
197{
198	if (event->attr.config1 != 0x0) {
199		hisi_sllc_pmu_enable_tracetag(event);
200		hisi_sllc_pmu_config_srcid(event);
201		hisi_sllc_pmu_config_tgtid(event);
202	}
203}
204
205static void hisi_sllc_pmu_clear_filter(struct perf_event *event)
206{
207	if (event->attr.config1 != 0x0) {
208		hisi_sllc_pmu_disable_tracetag(event);
209		hisi_sllc_pmu_clear_srcid(event);
210		hisi_sllc_pmu_clear_tgtid(event);
211	}
212}
213
214static u64 hisi_sllc_pmu_read_counter(struct hisi_pmu *sllc_pmu,
215				      struct hw_perf_event *hwc)
216{
217	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
218
219	return readq(sllc_pmu->base + SLLC_EVENT_CNTn(regs->event_cnt0, hwc->idx));
220}
221
222static void hisi_sllc_pmu_write_counter(struct hisi_pmu *sllc_pmu,
223					struct hw_perf_event *hwc, u64 val)
224{
225	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
226
227	writeq(val, sllc_pmu->base + SLLC_EVENT_CNTn(regs->event_cnt0, hwc->idx));
228}
229
230static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx,
231				       u32 type)
232{
233	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
234	u32 reg, val;
235
236	/*
237	 * Select the appropriate event select register(SLLC_EVENT_TYPE0/1).
238	 * There are 2 event select registers for the 8 hardware counters.
239	 * Event code is 8-bits and for the former 4 hardware counters,
240	 * SLLC_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
241	 * SLLC_EVENT_TYPE1 is chosen.
242	 */
243	reg = regs->event_type0 + (idx / 4) * 4;
244
245	/* Write event code to SLLC_EVENT_TYPEx Register */
246	val = readl(sllc_pmu->base + reg);
247	val &= ~(SLLC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx));
248	val |= (type << HISI_PMU_EVTYPE_SHIFT(idx));
249	writel(val, sllc_pmu->base + reg);
250}
251
252static void hisi_sllc_pmu_start_counters(struct hisi_pmu *sllc_pmu)
253{
254	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
255	u32 val;
256
257	val = readl(sllc_pmu->base + regs->perf_ctrl);
258	val |= SLLC_PERF_CTRL_EN;
259	writel(val, sllc_pmu->base + regs->perf_ctrl);
260}
261
262static void hisi_sllc_pmu_stop_counters(struct hisi_pmu *sllc_pmu)
263{
264	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
265	u32 val;
266
267	val = readl(sllc_pmu->base + regs->perf_ctrl);
268	val &= ~(SLLC_PERF_CTRL_EN);
269	writel(val, sllc_pmu->base + regs->perf_ctrl);
270}
271
272static void hisi_sllc_pmu_enable_counter(struct hisi_pmu *sllc_pmu,
273					 struct hw_perf_event *hwc)
274{
275	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
276	u32 val;
277
278	val = readl(sllc_pmu->base + regs->event_ctrl);
279	val |= BIT_ULL(hwc->idx);
280	writel(val, sllc_pmu->base + regs->event_ctrl);
281}
282
283static void hisi_sllc_pmu_disable_counter(struct hisi_pmu *sllc_pmu,
284					  struct hw_perf_event *hwc)
285{
286	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
287	u32 val;
288
289	val = readl(sllc_pmu->base + regs->event_ctrl);
290	val &= ~BIT_ULL(hwc->idx);
291	writel(val, sllc_pmu->base + regs->event_ctrl);
292}
293
294static void hisi_sllc_pmu_enable_counter_int(struct hisi_pmu *sllc_pmu,
295					     struct hw_perf_event *hwc)
296{
297	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
298	u32 val;
299
300	val = readl(sllc_pmu->base + regs->int_mask);
301	val &= ~BIT_ULL(hwc->idx);
302	writel(val, sllc_pmu->base + regs->int_mask);
303}
304
305static void hisi_sllc_pmu_disable_counter_int(struct hisi_pmu *sllc_pmu,
306					      struct hw_perf_event *hwc)
307{
308	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
309	u32 val;
310
311	val = readl(sllc_pmu->base + regs->int_mask);
312	val |= BIT_ULL(hwc->idx);
313	writel(val, sllc_pmu->base + regs->int_mask);
314}
315
316static u32 hisi_sllc_pmu_get_int_status(struct hisi_pmu *sllc_pmu)
317{
318	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
319
320	return readl(sllc_pmu->base + regs->int_status);
321}
322
323static void hisi_sllc_pmu_clear_int_status(struct hisi_pmu *sllc_pmu, int idx)
324{
325	struct hisi_sllc_pmu_regs *regs = sllc_pmu->dev_info->private;
326
327	writel(BIT_ULL(idx), sllc_pmu->base + regs->int_clear);
328}
329
330static int hisi_sllc_pmu_init_data(struct platform_device *pdev,
331				   struct hisi_pmu *sllc_pmu)
332{
333	struct hisi_sllc_pmu_regs *regs;
334
335	hisi_uncore_pmu_init_topology(sllc_pmu, &pdev->dev);
336
337	/*
338	 * Use the SCCL_ID and the index ID to identify the SLLC PMU,
339	 * while SCCL_ID is from MPIDR_EL1 by CPU.
340	 */
341	if (sllc_pmu->topo.sccl_id < 0) {
342		dev_err(&pdev->dev, "Cannot read sccl-id!\n");
343		return -EINVAL;
344	}
345
346	if (sllc_pmu->topo.index_id < 0) {
347		dev_err(&pdev->dev, "Cannot read idx-id!\n");
348		return -EINVAL;
349	}
350
351	sllc_pmu->dev_info = device_get_match_data(&pdev->dev);
352	if (!sllc_pmu->dev_info)
353		return -ENODEV;
354
355	sllc_pmu->base = devm_platform_ioremap_resource(pdev, 0);
356	if (IS_ERR(sllc_pmu->base)) {
357		dev_err(&pdev->dev, "ioremap failed for sllc_pmu resource.\n");
358		return PTR_ERR(sllc_pmu->base);
359	}
360
361	regs = sllc_pmu->dev_info->private;
362	sllc_pmu->identifier = readl(sllc_pmu->base + regs->version);
363
364	return 0;
365}
366
367static struct attribute *hisi_sllc_pmu_v2_format_attr[] = {
368	HISI_PMU_FORMAT_ATTR(event, "config:0-7"),
369	HISI_PMU_FORMAT_ATTR(tgtid_min, "config1:0-10"),
370	HISI_PMU_FORMAT_ATTR(tgtid_max, "config1:11-21"),
371	HISI_PMU_FORMAT_ATTR(srcid_cmd, "config1:22-32"),
372	HISI_PMU_FORMAT_ATTR(srcid_msk, "config1:33-43"),
373	HISI_PMU_FORMAT_ATTR(tracetag_en, "config1:44"),
374	NULL
375};
376
377static const struct attribute_group hisi_sllc_pmu_v2_format_group = {
378	.name = "format",
379	.attrs = hisi_sllc_pmu_v2_format_attr,
380};
381
382static struct attribute *hisi_sllc_pmu_v2_events_attr[] = {
383	HISI_PMU_EVENT_ATTR(rx_req,             0x30),
384	HISI_PMU_EVENT_ATTR(rx_data,            0x31),
385	HISI_PMU_EVENT_ATTR(tx_req,             0x34),
386	HISI_PMU_EVENT_ATTR(tx_data,            0x35),
387	HISI_PMU_EVENT_ATTR(cycles,             0x09),
388	NULL
389};
390
391static const struct attribute_group hisi_sllc_pmu_v2_events_group = {
392	.name = "events",
393	.attrs = hisi_sllc_pmu_v2_events_attr,
394};
395
396static const struct attribute_group *hisi_sllc_pmu_v2_attr_groups[] = {
397	&hisi_sllc_pmu_v2_format_group,
398	&hisi_sllc_pmu_v2_events_group,
399	&hisi_pmu_cpumask_attr_group,
400	&hisi_pmu_identifier_group,
401	NULL
402};
403
404static struct hisi_sllc_pmu_regs hisi_sllc_v2_pmu_regs = {
405	.int_mask = SLLC_INT_MASK,
406	.int_clear = SLLC_INT_CLEAR,
407	.int_status = SLLC_INT_STATUS,
408	.perf_ctrl = SLLC_PERF_CTRL,
409	.srcid_ctrl = SLLC_SRCID_CTRL,
410	.srcid_cmd_shift = SLLC_SRCID_CMD_SHIFT,
411	.srcid_mask_shift = SLLC_SRCID_MSK_SHIFT,
412	.tgtid_ctrl = SLLC_TGTID_CTRL,
413	.tgtid_min_shift = SLLC_TGTID_MIN_SHIFT,
414	.tgtid_max_shift = SLLC_TGTID_MAX_SHIFT,
415	.event_ctrl = SLLC_EVENT_CTRL,
416	.event_type0 = SLLC_EVENT_TYPE0,
417	.version = SLLC_VERSION,
418	.event_cnt0 = SLLC_EVENT_CNT0_L,
419};
420
421static const struct hisi_pmu_dev_info hisi_sllc_v2 = {
422	.private = &hisi_sllc_v2_pmu_regs,
423};
424
425static struct hisi_sllc_pmu_regs hisi_sllc_v3_pmu_regs = {
426	.int_mask = SLLC_V3_INT_MASK,
427	.int_clear = SLLC_V3_INT_CLEAR,
428	.int_status = SLLC_V3_INT_STATUS,
429	.perf_ctrl = SLLC_V3_PERF_CTRL,
430	.srcid_ctrl = SLLC_V3_SRCID_CTRL,
431	.srcid_cmd_shift = SLLC_V3_SRCID_CMD_SHIFT,
432	.srcid_mask_shift = SLLC_V3_SRCID_MSK_SHIFT,
433	.tgtid_ctrl = SLLC_V3_TGTID_CTRL,
434	.tgtid_min_shift = SLLC_V3_TGTID_MIN_SHIFT,
435	.tgtid_max_shift = SLLC_V3_TGTID_MAX_SHIFT,
436	.event_ctrl = SLLC_V3_EVENT_CTRL,
437	.event_type0 = SLLC_V3_EVENT_TYPE0,
438	.version = SLLC_V3_VERSION,
439	.event_cnt0 = SLLC_V3_EVENT_CNT0_L,
440};
441
442static const struct hisi_pmu_dev_info hisi_sllc_v3 = {
443	.private = &hisi_sllc_v3_pmu_regs,
444};
445
446static const struct hisi_uncore_ops hisi_uncore_sllc_ops = {
447	.write_evtype		= hisi_sllc_pmu_write_evtype,
448	.get_event_idx		= hisi_uncore_pmu_get_event_idx,
449	.start_counters		= hisi_sllc_pmu_start_counters,
450	.stop_counters		= hisi_sllc_pmu_stop_counters,
451	.enable_counter		= hisi_sllc_pmu_enable_counter,
452	.disable_counter	= hisi_sllc_pmu_disable_counter,
453	.enable_counter_int	= hisi_sllc_pmu_enable_counter_int,
454	.disable_counter_int	= hisi_sllc_pmu_disable_counter_int,
455	.write_counter		= hisi_sllc_pmu_write_counter,
456	.read_counter		= hisi_sllc_pmu_read_counter,
457	.get_int_status		= hisi_sllc_pmu_get_int_status,
458	.clear_int_status	= hisi_sllc_pmu_clear_int_status,
459	.enable_filter		= hisi_sllc_pmu_enable_filter,
460	.disable_filter		= hisi_sllc_pmu_clear_filter,
461};
462
463static int hisi_sllc_pmu_dev_probe(struct platform_device *pdev,
464				   struct hisi_pmu *sllc_pmu)
465{
466	int ret;
467
468	ret = hisi_sllc_pmu_init_data(pdev, sllc_pmu);
469	if (ret)
470		return ret;
471
472	ret = hisi_uncore_pmu_init_irq(sllc_pmu, pdev);
473	if (ret)
474		return ret;
475
476	sllc_pmu->pmu_events.attr_groups = hisi_sllc_pmu_v2_attr_groups;
477	sllc_pmu->ops = &hisi_uncore_sllc_ops;
478	sllc_pmu->check_event = SLLC_NR_EVENTS;
479	sllc_pmu->counter_bits = 64;
480	sllc_pmu->num_counters = 8;
481	sllc_pmu->dev = &pdev->dev;
482	sllc_pmu->on_cpu = -1;
483
484	return 0;
485}
486
487static int hisi_sllc_pmu_probe(struct platform_device *pdev)
488{
489	struct hisi_pmu *sllc_pmu;
490	char *name;
491	int ret;
492
493	sllc_pmu = devm_kzalloc(&pdev->dev, sizeof(*sllc_pmu), GFP_KERNEL);
494	if (!sllc_pmu)
495		return -ENOMEM;
496
497	ret = hisi_sllc_pmu_dev_probe(pdev, sllc_pmu);
498	if (ret)
499		return ret;
500
501	name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%d_sllc%d",
502			      sllc_pmu->topo.sccl_id, sllc_pmu->topo.index_id);
503	if (!name)
504		return -ENOMEM;
505
506	ret = cpuhp_state_add_instance(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
507				       &sllc_pmu->node);
508	if (ret) {
509		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
510		return ret;
511	}
512
513	hisi_pmu_init(sllc_pmu, THIS_MODULE);
514
515	ret = perf_pmu_register(&sllc_pmu->pmu, name, -1);
516	if (ret) {
517		dev_err(sllc_pmu->dev, "PMU register failed, ret = %d\n", ret);
518		cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
519						    &sllc_pmu->node);
520		return ret;
521	}
522
523	platform_set_drvdata(pdev, sllc_pmu);
524
525	return ret;
526}
527
528static void hisi_sllc_pmu_remove(struct platform_device *pdev)
529{
530	struct hisi_pmu *sllc_pmu = platform_get_drvdata(pdev);
531
532	perf_pmu_unregister(&sllc_pmu->pmu);
533	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
534					    &sllc_pmu->node);
535}
536
537static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] = {
538	{ "HISI0263", (kernel_ulong_t)&hisi_sllc_v2 },
539	{ "HISI0264", (kernel_ulong_t)&hisi_sllc_v3 },
540	{}
541};
542MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match);
543
544static struct platform_driver hisi_sllc_pmu_driver = {
545	.driver = {
546		.name = "hisi_sllc_pmu",
547		.acpi_match_table = hisi_sllc_pmu_acpi_match,
548		.suppress_bind_attrs = true,
549	},
550	.probe = hisi_sllc_pmu_probe,
551	.remove = hisi_sllc_pmu_remove,
552};
553
554static int __init hisi_sllc_pmu_module_init(void)
555{
556	int ret;
557
558	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE,
559				      "AP_PERF_ARM_HISI_SLLC_ONLINE",
560				      hisi_uncore_pmu_online_cpu,
561				      hisi_uncore_pmu_offline_cpu);
562	if (ret) {
563		pr_err("SLLC PMU: cpuhp state setup failed, ret = %d\n", ret);
564		return ret;
565	}
566
567	ret = platform_driver_register(&hisi_sllc_pmu_driver);
568	if (ret)
569		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
570
571	return ret;
572}
573module_init(hisi_sllc_pmu_module_init);
574
575static void __exit hisi_sllc_pmu_module_exit(void)
576{
577	platform_driver_unregister(&hisi_sllc_pmu_driver);
578	cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_HISI_SLLC_ONLINE);
579}
580module_exit(hisi_sllc_pmu_module_exit);
581
582MODULE_IMPORT_NS("HISI_PMU");
583MODULE_DESCRIPTION("HiSilicon SLLC uncore PMU driver");
584MODULE_LICENSE("GPL v2");
585MODULE_AUTHOR("Shaokun Zhang <zhangshaokun@hisilicon.com>");
586MODULE_AUTHOR("Qi Liu <liuqi115@huawei.com>");
~/ Read-only file preview.