1 // SPDX-License-Identifier: GPL-2.0-only
3 * StarFive's StarLink PMU driver
5 * Copyright (C) 2023 StarFive Technology Co., Ltd.
7 * Author: Ji Sheng Teoh <jisheng.teoh@starfivetech.com>
11 #define STARLINK_PMU_PDEV_NAME "starfive_starlink_pmu"
12 #define pr_fmt(fmt) STARLINK_PMU_PDEV_NAME ": " fmt
14 #include <linux/bitmap.h>
15 #include <linux/cpu_pm.h>
17 #include <linux/irq.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/mod_devicetable.h>
21 #include <linux/perf_event.h>
22 #include <linux/platform_device.h>
23 #include <linux/sysfs.h>
25 #define STARLINK_PMU_MAX_COUNTERS 64
26 #define STARLINK_PMU_NUM_COUNTERS 16
27 #define STARLINK_PMU_IDX_CYCLE_COUNTER 63
29 #define STARLINK_PMU_EVENT_SELECT 0x060
30 #define STARLINK_PMU_EVENT_COUNTER 0x160
31 #define STARLINK_PMU_COUNTER_MASK GENMASK_ULL(63, 0)
32 #define STARLINK_PMU_CYCLE_COUNTER 0x058
34 #define STARLINK_PMU_CONTROL 0x040
35 #define STARLINK_PMU_GLOBAL_ENABLE BIT_ULL(0)
37 #define STARLINK_PMU_INTERRUPT_ENABLE 0x050
38 #define STARLINK_PMU_COUNTER_OVERFLOW_STATUS 0x048
39 #define STARLINK_PMU_CYCLE_OVERFLOW_MASK BIT_ULL(63)
41 #define STARLINK_CYCLES 0x058
42 #define CACHE_READ_REQUEST 0x04000701
43 #define CACHE_WRITE_REQUEST 0x03000001
44 #define CACHE_RELEASE_REQUEST 0x0003e001
45 #define CACHE_READ_HIT 0x00901202
46 #define CACHE_READ_MISS 0x04008002
47 #define CACHE_WRITE_HIT 0x006c0002
48 #define CACHE_WRITE_MISS 0x03000002
49 #define CACHE_WRITEBACK 0x00000403
51 #define to_starlink_pmu(p) (container_of(p, struct starlink_pmu, pmu))
53 #define STARLINK_FORMAT_ATTR(_name, _config) \
54 (&((struct dev_ext_attribute[]) { \
55 { .attr = __ATTR(_name, 0444, starlink_pmu_sysfs_format_show, NULL), \
56 .var = (void *)_config, } \
59 #define STARLINK_EVENT_ATTR(_name, _id) \
60 PMU_EVENT_ATTR_ID(_name, starlink_pmu_sysfs_event_show, _id)
62 static int starlink_pmu_cpuhp_state
;
64 struct starlink_hw_events
{
65 struct perf_event
*events
[STARLINK_PMU_MAX_COUNTERS
];
66 DECLARE_BITMAP(used_mask
, STARLINK_PMU_MAX_COUNTERS
);
71 struct starlink_hw_events __percpu
*hw_events
;
72 struct hlist_node node
;
73 struct notifier_block starlink_pmu_pm_nb
;
74 void __iomem
*pmu_base
;
80 starlink_pmu_sysfs_format_show(struct device
*dev
,
81 struct device_attribute
*attr
,
84 struct dev_ext_attribute
*eattr
= container_of(attr
,
85 struct dev_ext_attribute
, attr
);
87 return sysfs_emit(buf
, "%s\n", (char *)eattr
->var
);
90 static struct attribute
*starlink_pmu_format_attrs
[] = {
91 STARLINK_FORMAT_ATTR(event
, "config:0-31"),
95 static const struct attribute_group starlink_pmu_format_attr_group
= {
97 .attrs
= starlink_pmu_format_attrs
,
101 starlink_pmu_sysfs_event_show(struct device
*dev
,
102 struct device_attribute
*attr
,
105 struct perf_pmu_events_attr
*eattr
= container_of(attr
,
106 struct perf_pmu_events_attr
, attr
);
108 return sysfs_emit(buf
, "event=0x%02llx\n", eattr
->id
);
111 static struct attribute
*starlink_pmu_event_attrs
[] = {
112 STARLINK_EVENT_ATTR(cycles
, STARLINK_CYCLES
),
113 STARLINK_EVENT_ATTR(read_request
, CACHE_READ_REQUEST
),
114 STARLINK_EVENT_ATTR(write_request
, CACHE_WRITE_REQUEST
),
115 STARLINK_EVENT_ATTR(release_request
, CACHE_RELEASE_REQUEST
),
116 STARLINK_EVENT_ATTR(read_hit
, CACHE_READ_HIT
),
117 STARLINK_EVENT_ATTR(read_miss
, CACHE_READ_MISS
),
118 STARLINK_EVENT_ATTR(write_hit
, CACHE_WRITE_HIT
),
119 STARLINK_EVENT_ATTR(write_miss
, CACHE_WRITE_MISS
),
120 STARLINK_EVENT_ATTR(writeback
, CACHE_WRITEBACK
),
124 static const struct attribute_group starlink_pmu_events_attr_group
= {
126 .attrs
= starlink_pmu_event_attrs
,
130 cpumask_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
132 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(dev_get_drvdata(dev
));
134 return cpumap_print_to_pagebuf(true, buf
, &starlink_pmu
->cpumask
);
137 static DEVICE_ATTR_RO(cpumask
);
139 static struct attribute
*starlink_pmu_cpumask_attrs
[] = {
140 &dev_attr_cpumask
.attr
,
144 static const struct attribute_group starlink_pmu_cpumask_attr_group
= {
145 .attrs
= starlink_pmu_cpumask_attrs
,
148 static const struct attribute_group
*starlink_pmu_attr_groups
[] = {
149 &starlink_pmu_format_attr_group
,
150 &starlink_pmu_events_attr_group
,
151 &starlink_pmu_cpumask_attr_group
,
155 static void starlink_pmu_set_event_period(struct perf_event
*event
)
157 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
158 struct hw_perf_event
*hwc
= &event
->hw
;
159 int idx
= event
->hw
.idx
;
162 * Program counter to half of it's max count to handle
163 * cases of extreme interrupt latency.
165 u64 val
= STARLINK_PMU_COUNTER_MASK
>> 1;
167 local64_set(&hwc
->prev_count
, val
);
168 if (hwc
->config
== STARLINK_CYCLES
)
169 writeq(val
, starlink_pmu
->pmu_base
+ STARLINK_PMU_CYCLE_COUNTER
);
171 writeq(val
, starlink_pmu
->pmu_base
+ STARLINK_PMU_EVENT_COUNTER
+
175 static void starlink_pmu_counter_start(struct perf_event
*event
,
176 struct starlink_pmu
*starlink_pmu
)
178 struct hw_perf_event
*hwc
= &event
->hw
;
179 int idx
= event
->hw
.idx
;
183 * Enable counter overflow interrupt[63:0],
184 * which is mapped as follow:
186 * event counter 0 - Bit [0]
187 * event counter 1 - Bit [1]
189 * cycle counter - Bit [63]
191 val
= readq(starlink_pmu
->pmu_base
+ STARLINK_PMU_INTERRUPT_ENABLE
);
193 if (hwc
->config
== STARLINK_CYCLES
) {
195 * Cycle count has its dedicated register, and it starts
196 * counting as soon as STARLINK_PMU_GLOBAL_ENABLE is set.
198 val
|= STARLINK_PMU_CYCLE_OVERFLOW_MASK
;
200 writeq(event
->hw
.config
, starlink_pmu
->pmu_base
+
201 STARLINK_PMU_EVENT_SELECT
+ idx
* sizeof(u64
));
206 writeq(val
, starlink_pmu
->pmu_base
+ STARLINK_PMU_INTERRUPT_ENABLE
);
208 writeq(STARLINK_PMU_GLOBAL_ENABLE
, starlink_pmu
->pmu_base
+
209 STARLINK_PMU_CONTROL
);
212 static void starlink_pmu_counter_stop(struct perf_event
*event
,
213 struct starlink_pmu
*starlink_pmu
)
215 struct hw_perf_event
*hwc
= &event
->hw
;
216 int idx
= event
->hw
.idx
;
219 val
= readq(starlink_pmu
->pmu_base
+ STARLINK_PMU_CONTROL
);
220 val
&= ~STARLINK_PMU_GLOBAL_ENABLE
;
221 writeq(val
, starlink_pmu
->pmu_base
+ STARLINK_PMU_CONTROL
);
223 val
= readq(starlink_pmu
->pmu_base
+ STARLINK_PMU_INTERRUPT_ENABLE
);
224 if (hwc
->config
== STARLINK_CYCLES
)
225 val
&= ~STARLINK_PMU_CYCLE_OVERFLOW_MASK
;
227 val
&= ~BIT_ULL(idx
);
229 writeq(val
, starlink_pmu
->pmu_base
+ STARLINK_PMU_INTERRUPT_ENABLE
);
232 static void starlink_pmu_update(struct perf_event
*event
)
234 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
235 struct hw_perf_event
*hwc
= &event
->hw
;
237 u64 prev_raw_count
, new_raw_count
;
242 prev_raw_count
= local64_read(&hwc
->prev_count
);
243 if (hwc
->config
== STARLINK_CYCLES
)
244 new_raw_count
= readq(starlink_pmu
->pmu_base
+
245 STARLINK_PMU_CYCLE_COUNTER
);
247 new_raw_count
= readq(starlink_pmu
->pmu_base
+
248 STARLINK_PMU_EVENT_COUNTER
+
250 oldval
= local64_cmpxchg(&hwc
->prev_count
, prev_raw_count
,
252 } while (oldval
!= prev_raw_count
);
254 delta
= (new_raw_count
- prev_raw_count
) & STARLINK_PMU_COUNTER_MASK
;
255 local64_add(delta
, &event
->count
);
258 static void starlink_pmu_start(struct perf_event
*event
, int flags
)
260 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
261 struct hw_perf_event
*hwc
= &event
->hw
;
263 if (WARN_ON_ONCE(!(hwc
->state
& PERF_HES_STOPPED
)))
266 if (flags
& PERF_EF_RELOAD
)
267 WARN_ON_ONCE(!(event
->hw
.state
& PERF_HES_UPTODATE
));
271 starlink_pmu_set_event_period(event
);
272 starlink_pmu_counter_start(event
, starlink_pmu
);
274 perf_event_update_userpage(event
);
277 static void starlink_pmu_stop(struct perf_event
*event
, int flags
)
279 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
280 struct hw_perf_event
*hwc
= &event
->hw
;
282 if (hwc
->state
& PERF_HES_STOPPED
)
285 starlink_pmu_counter_stop(event
, starlink_pmu
);
286 starlink_pmu_update(event
);
287 hwc
->state
|= PERF_HES_STOPPED
| PERF_HES_UPTODATE
;
290 static int starlink_pmu_add(struct perf_event
*event
, int flags
)
292 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
293 struct starlink_hw_events
*hw_events
=
294 this_cpu_ptr(starlink_pmu
->hw_events
);
295 struct hw_perf_event
*hwc
= &event
->hw
;
296 unsigned long *used_mask
= hw_events
->used_mask
;
297 u32 n_events
= STARLINK_PMU_NUM_COUNTERS
;
301 * Cycle counter has dedicated register to hold counter value.
302 * Event other than cycle count has to be enabled through
303 * event select register, and assigned with independent counter
307 if (hwc
->config
== STARLINK_CYCLES
) {
308 idx
= STARLINK_PMU_IDX_CYCLE_COUNTER
;
310 idx
= find_first_zero_bit(used_mask
, n_events
);
311 /* All counter are in use */
315 set_bit(idx
, used_mask
);
319 hw_events
->events
[idx
] = event
;
320 hwc
->state
= PERF_HES_UPTODATE
| PERF_HES_STOPPED
;
322 if (flags
& PERF_EF_START
)
323 starlink_pmu_start(event
, PERF_EF_RELOAD
);
325 perf_event_update_userpage(event
);
330 static void starlink_pmu_del(struct perf_event
*event
, int flags
)
332 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
333 struct starlink_hw_events
*hw_events
=
334 this_cpu_ptr(starlink_pmu
->hw_events
);
335 struct hw_perf_event
*hwc
= &event
->hw
;
337 starlink_pmu_stop(event
, PERF_EF_UPDATE
);
338 hw_events
->events
[hwc
->idx
] = NULL
;
339 clear_bit(hwc
->idx
, hw_events
->used_mask
);
341 perf_event_update_userpage(event
);
344 static bool starlink_pmu_validate_event_group(struct perf_event
*event
)
346 struct perf_event
*leader
= event
->group_leader
;
347 struct perf_event
*sibling
;
351 * Ensure hardware events in the group are on the same PMU,
352 * software events are acceptable.
354 if (event
->group_leader
->pmu
!= event
->pmu
&&
355 !is_software_event(event
->group_leader
))
358 for_each_sibling_event(sibling
, leader
) {
359 if (sibling
->pmu
!= event
->pmu
&& !is_software_event(sibling
))
365 return counter
<= STARLINK_PMU_NUM_COUNTERS
;
368 static int starlink_pmu_event_init(struct perf_event
*event
)
370 struct starlink_pmu
*starlink_pmu
= to_starlink_pmu(event
->pmu
);
371 struct hw_perf_event
*hwc
= &event
->hw
;
374 * Sampling is not supported, as counters are shared
377 if (hwc
->sample_period
)
381 * Per-task and attach to a task are not supported,
382 * as uncore events are not specific to any CPU.
384 if (event
->cpu
< 0 || event
->attach_state
& PERF_ATTACH_TASK
)
387 if (!starlink_pmu_validate_event_group(event
))
391 hwc
->config
= event
->attr
.config
;
392 event
->cpu
= cpumask_first(&starlink_pmu
->cpumask
);
397 static irqreturn_t
starlink_pmu_handle_irq(int irq_num
, void *data
)
399 struct starlink_pmu
*starlink_pmu
= data
;
400 struct starlink_hw_events
*hw_events
=
401 this_cpu_ptr(starlink_pmu
->hw_events
);
402 bool handled
= false;
406 for (idx
= 0; idx
< STARLINK_PMU_MAX_COUNTERS
; idx
++) {
407 struct perf_event
*event
= hw_events
->events
[idx
];
412 overflow_status
= readq(starlink_pmu
->pmu_base
+
413 STARLINK_PMU_COUNTER_OVERFLOW_STATUS
);
414 if (!(overflow_status
& BIT_ULL(idx
)))
417 writeq(BIT_ULL(idx
), starlink_pmu
->pmu_base
+
418 STARLINK_PMU_COUNTER_OVERFLOW_STATUS
);
420 starlink_pmu_update(event
);
421 starlink_pmu_set_event_period(event
);
424 return IRQ_RETVAL(handled
);
427 static int starlink_setup_irqs(struct starlink_pmu
*starlink_pmu
,
428 struct platform_device
*pdev
)
432 irq
= platform_get_irq(pdev
, 0);
436 ret
= devm_request_irq(&pdev
->dev
, irq
, starlink_pmu_handle_irq
,
437 0, STARLINK_PMU_PDEV_NAME
, starlink_pmu
);
439 return dev_err_probe(&pdev
->dev
, ret
, "Failed to request IRQ\n");
441 starlink_pmu
->irq
= irq
;
446 static int starlink_pmu_pm_notify(struct notifier_block
*b
,
447 unsigned long cmd
, void *v
)
449 struct starlink_pmu
*starlink_pmu
= container_of(b
, struct starlink_pmu
,
451 struct starlink_hw_events
*hw_events
=
452 this_cpu_ptr(starlink_pmu
->hw_events
);
453 int enabled
= bitmap_weight(hw_events
->used_mask
,
454 STARLINK_PMU_MAX_COUNTERS
);
455 struct perf_event
*event
;
461 for (idx
= 0; idx
< STARLINK_PMU_MAX_COUNTERS
; idx
++) {
462 event
= hw_events
->events
[idx
];
468 /* Stop and update the counter */
469 starlink_pmu_stop(event
, PERF_EF_UPDATE
);
472 case CPU_PM_ENTER_FAILED
:
473 /* Restore and enable the counter */
474 starlink_pmu_start(event
, PERF_EF_RELOAD
);
484 static int starlink_pmu_pm_register(struct starlink_pmu
*starlink_pmu
)
486 if (!IS_ENABLED(CONFIG_CPU_PM
))
489 starlink_pmu
->starlink_pmu_pm_nb
.notifier_call
= starlink_pmu_pm_notify
;
490 return cpu_pm_register_notifier(&starlink_pmu
->starlink_pmu_pm_nb
);
493 static void starlink_pmu_pm_unregister(struct starlink_pmu
*starlink_pmu
)
495 if (!IS_ENABLED(CONFIG_CPU_PM
))
498 cpu_pm_unregister_notifier(&starlink_pmu
->starlink_pmu_pm_nb
);
501 static void starlink_pmu_destroy(struct starlink_pmu
*starlink_pmu
)
503 starlink_pmu_pm_unregister(starlink_pmu
);
504 cpuhp_state_remove_instance(starlink_pmu_cpuhp_state
,
505 &starlink_pmu
->node
);
508 static int starlink_pmu_probe(struct platform_device
*pdev
)
510 struct starlink_pmu
*starlink_pmu
;
511 struct starlink_hw_events
*hw_events
;
512 struct resource
*res
;
515 starlink_pmu
= devm_kzalloc(&pdev
->dev
, sizeof(*starlink_pmu
), GFP_KERNEL
);
519 starlink_pmu
->pmu_base
=
520 devm_platform_get_and_ioremap_resource(pdev
, 0, &res
);
521 if (IS_ERR(starlink_pmu
->pmu_base
))
522 return PTR_ERR(starlink_pmu
->pmu_base
);
524 starlink_pmu
->hw_events
= alloc_percpu_gfp(struct starlink_hw_events
,
526 if (!starlink_pmu
->hw_events
) {
527 dev_err(&pdev
->dev
, "Failed to allocate per-cpu PMU data\n");
531 for_each_possible_cpu(cpuid
) {
532 hw_events
= per_cpu_ptr(starlink_pmu
->hw_events
, cpuid
);
533 for (i
= 0; i
< STARLINK_PMU_MAX_COUNTERS
; i
++)
534 hw_events
->events
[i
] = NULL
;
537 ret
= starlink_setup_irqs(starlink_pmu
, pdev
);
541 ret
= cpuhp_state_add_instance(starlink_pmu_cpuhp_state
,
542 &starlink_pmu
->node
);
544 dev_err(&pdev
->dev
, "Failed to register hotplug\n");
548 ret
= starlink_pmu_pm_register(starlink_pmu
);
550 cpuhp_state_remove_instance(starlink_pmu_cpuhp_state
,
551 &starlink_pmu
->node
);
555 starlink_pmu
->pmu
= (struct pmu
) {
556 .task_ctx_nr
= perf_invalid_context
,
557 .event_init
= starlink_pmu_event_init
,
558 .add
= starlink_pmu_add
,
559 .del
= starlink_pmu_del
,
560 .start
= starlink_pmu_start
,
561 .stop
= starlink_pmu_stop
,
562 .read
= starlink_pmu_update
,
563 .attr_groups
= starlink_pmu_attr_groups
,
566 ret
= perf_pmu_register(&starlink_pmu
->pmu
, STARLINK_PMU_PDEV_NAME
, -1);
568 starlink_pmu_destroy(starlink_pmu
);
573 static const struct of_device_id starlink_pmu_of_match
[] = {
574 { .compatible
= "starfive,jh8100-starlink-pmu" },
577 MODULE_DEVICE_TABLE(of
, starlink_pmu_of_match
);
579 static struct platform_driver starlink_pmu_driver
= {
581 .name
= STARLINK_PMU_PDEV_NAME
,
582 .of_match_table
= starlink_pmu_of_match
,
583 .suppress_bind_attrs
= true,
585 .probe
= starlink_pmu_probe
,
589 starlink_pmu_online_cpu(unsigned int cpu
, struct hlist_node
*node
)
591 struct starlink_pmu
*starlink_pmu
= hlist_entry_safe(node
,
595 if (cpumask_empty(&starlink_pmu
->cpumask
))
596 cpumask_set_cpu(cpu
, &starlink_pmu
->cpumask
);
598 WARN_ON(irq_set_affinity(starlink_pmu
->irq
, cpumask_of(cpu
)));
604 starlink_pmu_offline_cpu(unsigned int cpu
, struct hlist_node
*node
)
606 struct starlink_pmu
*starlink_pmu
= hlist_entry_safe(node
,
611 if (!cpumask_test_and_clear_cpu(cpu
, &starlink_pmu
->cpumask
))
614 target
= cpumask_any_but(cpu_online_mask
, cpu
);
615 if (target
>= nr_cpu_ids
)
618 perf_pmu_migrate_context(&starlink_pmu
->pmu
, cpu
, target
);
620 cpumask_set_cpu(target
, &starlink_pmu
->cpumask
);
621 WARN_ON(irq_set_affinity(starlink_pmu
->irq
, cpumask_of(target
)));
626 static int __init
starlink_pmu_init(void)
630 ret
= cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN
,
631 "soc/starfive/starlink_pmu:online",
632 starlink_pmu_online_cpu
,
633 starlink_pmu_offline_cpu
);
637 starlink_pmu_cpuhp_state
= ret
;
639 return platform_driver_register(&starlink_pmu_driver
);
642 device_initcall(starlink_pmu_init
);