1 /*
2  * ARM DynamIQ Shared Unit (DSU) PMU Low level register access routines.
3  *
4  * Copyright (C) ARM Limited, 2017.
5  *
6  * Author: Suzuki K Poulose <suzuki.poulose@arm.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2, as published by the Free Software Foundation.
11  */
12 
13 #include <linux/bitops.h>
14 #include <linux/build_bug.h>
15 #include <linux/compiler.h>
16 #include <linux/types.h>
17 #include <asm/barrier.h>
18 #include <asm/sysreg.h>
19 
20 
21 #define CLUSTERPMCR_EL1			sys_reg(3, 0, 15, 5, 0)
22 #define CLUSTERPMCNTENSET_EL1		sys_reg(3, 0, 15, 5, 1)
23 #define CLUSTERPMCNTENCLR_EL1		sys_reg(3, 0, 15, 5, 2)
24 #define CLUSTERPMOVSSET_EL1		sys_reg(3, 0, 15, 5, 3)
25 #define CLUSTERPMOVSCLR_EL1		sys_reg(3, 0, 15, 5, 4)
26 #define CLUSTERPMSELR_EL1		sys_reg(3, 0, 15, 5, 5)
27 #define CLUSTERPMINTENSET_EL1		sys_reg(3, 0, 15, 5, 6)
28 #define CLUSTERPMINTENCLR_EL1		sys_reg(3, 0, 15, 5, 7)
29 #define CLUSTERPMCCNTR_EL1		sys_reg(3, 0, 15, 6, 0)
30 #define CLUSTERPMXEVTYPER_EL1		sys_reg(3, 0, 15, 6, 1)
31 #define CLUSTERPMXEVCNTR_EL1		sys_reg(3, 0, 15, 6, 2)
32 #define CLUSTERPMMDCR_EL1		sys_reg(3, 0, 15, 6, 3)
33 #define CLUSTERPMCEID0_EL1		sys_reg(3, 0, 15, 6, 4)
34 #define CLUSTERPMCEID1_EL1		sys_reg(3, 0, 15, 6, 5)
35 
36 static inline u32 __dsu_pmu_read_pmcr(void)
37 {
38 	return read_sysreg_s(CLUSTERPMCR_EL1);
39 }
40 
41 static inline void __dsu_pmu_write_pmcr(u32 val)
42 {
43 	write_sysreg_s(val, CLUSTERPMCR_EL1);
44 	isb();
45 }
46 
47 static inline u32 __dsu_pmu_get_reset_overflow(void)
48 {
49 	u32 val = read_sysreg_s(CLUSTERPMOVSCLR_EL1);
50 	/* Clear the bit */
51 	write_sysreg_s(val, CLUSTERPMOVSCLR_EL1);
52 	isb();
53 	return val;
54 }
55 
56 static inline void __dsu_pmu_select_counter(int counter)
57 {
58 	write_sysreg_s(counter, CLUSTERPMSELR_EL1);
59 	isb();
60 }
61 
62 static inline u64 __dsu_pmu_read_counter(int counter)
63 {
64 	__dsu_pmu_select_counter(counter);
65 	return read_sysreg_s(CLUSTERPMXEVCNTR_EL1);
66 }
67 
68 static inline void __dsu_pmu_write_counter(int counter, u64 val)
69 {
70 	__dsu_pmu_select_counter(counter);
71 	write_sysreg_s(val, CLUSTERPMXEVCNTR_EL1);
72 	isb();
73 }
74 
75 static inline void __dsu_pmu_set_event(int counter, u32 event)
76 {
77 	__dsu_pmu_select_counter(counter);
78 	write_sysreg_s(event, CLUSTERPMXEVTYPER_EL1);
79 	isb();
80 }
81 
82 static inline u64 __dsu_pmu_read_pmccntr(void)
83 {
84 	return read_sysreg_s(CLUSTERPMCCNTR_EL1);
85 }
86 
87 static inline void __dsu_pmu_write_pmccntr(u64 val)
88 {
89 	write_sysreg_s(val, CLUSTERPMCCNTR_EL1);
90 	isb();
91 }
92 
93 static inline void __dsu_pmu_disable_counter(int counter)
94 {
95 	write_sysreg_s(BIT(counter), CLUSTERPMCNTENCLR_EL1);
96 	isb();
97 }
98 
99 static inline void __dsu_pmu_enable_counter(int counter)
100 {
101 	write_sysreg_s(BIT(counter), CLUSTERPMCNTENSET_EL1);
102 	isb();
103 }
104 
105 static inline void __dsu_pmu_counter_interrupt_enable(int counter)
106 {
107 	write_sysreg_s(BIT(counter), CLUSTERPMINTENSET_EL1);
108 	isb();
109 }
110 
111 static inline void __dsu_pmu_counter_interrupt_disable(int counter)
112 {
113 	write_sysreg_s(BIT(counter), CLUSTERPMINTENCLR_EL1);
114 	isb();
115 }
116 
117 
118 static inline u32 __dsu_pmu_read_pmceid(int n)
119 {
120 	switch (n) {
121 	case 0:
122 		return read_sysreg_s(CLUSTERPMCEID0_EL1);
123 	case 1:
124 		return read_sysreg_s(CLUSTERPMCEID1_EL1);
125 	default:
126 		BUILD_BUG();
127 		return 0;
128 	}
129 }
130