4141#define SLLC_SRCID_CMD_SHIFT 1
4242#define SLLC_SRCID_MSK_SHIFT 12
4343#define SLLC_NR_EVENTS 0x80
44+ #define SLLC_EVENT_CNTn (cnt0 , n ) ((cnt0) + (n) * 8)
4445
4546HISI_PMU_EVENT_ATTR_EXTRACTOR (tgtid_min , config1 , 10 , 0 );
4647HISI_PMU_EVENT_ATTR_EXTRACTOR (tgtid_max , config1 , 21 , 11 );
4748HISI_PMU_EVENT_ATTR_EXTRACTOR (srcid_cmd , config1 , 32 , 22 );
4849HISI_PMU_EVENT_ATTR_EXTRACTOR (srcid_msk , config1 , 43 , 33 );
4950HISI_PMU_EVENT_ATTR_EXTRACTOR (tracetag_en , config1 , 44 , 44 );
5051
52+ struct hisi_sllc_pmu_regs {
53+ u32 int_mask ;
54+ u32 int_clear ;
55+ u32 int_status ;
56+ u32 perf_ctrl ;
57+ u32 srcid_ctrl ;
58+ u32 srcid_cmd_shift ;
59+ u32 srcid_mask_shift ;
60+ u32 tgtid_ctrl ;
61+ u32 tgtid_min_shift ;
62+ u32 tgtid_max_shift ;
63+ u32 event_ctrl ;
64+ u32 event_type0 ;
65+ u32 version ;
66+ u32 event_cnt0 ;
67+ };
68+
5169static bool tgtid_is_valid (u32 max , u32 min )
5270{
5371 return max > 0 && max >= min ;
@@ -56,96 +74,104 @@ static bool tgtid_is_valid(u32 max, u32 min)
5674static void hisi_sllc_pmu_enable_tracetag (struct perf_event * event )
5775{
5876 struct hisi_pmu * sllc_pmu = to_hisi_pmu (event -> pmu );
77+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
5978 u32 tt_en = hisi_get_tracetag_en (event );
6079
6180 if (tt_en ) {
6281 u32 val ;
6382
64- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
83+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
6584 val |= SLLC_TRACETAG_EN | SLLC_FILT_EN ;
66- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
85+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
6786 }
6887}
6988
7089static void hisi_sllc_pmu_disable_tracetag (struct perf_event * event )
7190{
7291 struct hisi_pmu * sllc_pmu = to_hisi_pmu (event -> pmu );
92+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
7393 u32 tt_en = hisi_get_tracetag_en (event );
7494
7595 if (tt_en ) {
7696 u32 val ;
7797
78- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
98+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
7999 val &= ~(SLLC_TRACETAG_EN | SLLC_FILT_EN );
80- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
100+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
81101 }
82102}
83103
84104static void hisi_sllc_pmu_config_tgtid (struct perf_event * event )
85105{
86106 struct hisi_pmu * sllc_pmu = to_hisi_pmu (event -> pmu );
107+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
87108 u32 min = hisi_get_tgtid_min (event );
88109 u32 max = hisi_get_tgtid_max (event );
89110
90111 if (tgtid_is_valid (max , min )) {
91- u32 val = (max << SLLC_TGTID_MAX_SHIFT ) | (min << SLLC_TGTID_MIN_SHIFT );
112+ u32 val = (max << regs -> tgtid_max_shift ) |
113+ (min << regs -> tgtid_min_shift );
92114
93- writel (val , sllc_pmu -> base + SLLC_TGTID_CTRL );
115+ writel (val , sllc_pmu -> base + regs -> tgtid_ctrl );
94116 /* Enable the tgtid */
95- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
117+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
96118 val |= SLLC_TGTID_EN | SLLC_FILT_EN ;
97- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
119+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
98120 }
99121}
100122
101123static void hisi_sllc_pmu_clear_tgtid (struct perf_event * event )
102124{
103125 struct hisi_pmu * sllc_pmu = to_hisi_pmu (event -> pmu );
126+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
104127 u32 min = hisi_get_tgtid_min (event );
105128 u32 max = hisi_get_tgtid_max (event );
106129
107130 if (tgtid_is_valid (max , min )) {
108131 u32 val ;
109132
110- writel (SLLC_TGTID_NONE , sllc_pmu -> base + SLLC_TGTID_CTRL );
133+ writel (SLLC_TGTID_NONE , sllc_pmu -> base + regs -> tgtid_ctrl );
111134 /* Disable the tgtid */
112- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
135+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
113136 val &= ~(SLLC_TGTID_EN | SLLC_FILT_EN );
114- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
137+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
115138 }
116139}
117140
118141static void hisi_sllc_pmu_config_srcid (struct perf_event * event )
119142{
120143 struct hisi_pmu * sllc_pmu = to_hisi_pmu (event -> pmu );
144+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
121145 u32 cmd = hisi_get_srcid_cmd (event );
122146
123147 if (cmd ) {
124148 u32 val , msk ;
125149
126150 msk = hisi_get_srcid_msk (event );
127- val = (cmd << SLLC_SRCID_CMD_SHIFT ) | (msk << SLLC_SRCID_MSK_SHIFT );
128- writel (val , sllc_pmu -> base + SLLC_SRCID_CTRL );
151+ val = (cmd << regs -> srcid_cmd_shift ) |
152+ (msk << regs -> srcid_mask_shift );
153+ writel (val , sllc_pmu -> base + regs -> srcid_ctrl );
129154 /* Enable the srcid */
130- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
155+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
131156 val |= SLLC_SRCID_EN | SLLC_FILT_EN ;
132- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
157+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
133158 }
134159}
135160
136161static void hisi_sllc_pmu_clear_srcid (struct perf_event * event )
137162{
138163 struct hisi_pmu * sllc_pmu = to_hisi_pmu (event -> pmu );
164+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
139165 u32 cmd = hisi_get_srcid_cmd (event );
140166
141167 if (cmd ) {
142168 u32 val ;
143169
144- writel (SLLC_SRCID_NONE , sllc_pmu -> base + SLLC_SRCID_CTRL );
170+ writel (SLLC_SRCID_NONE , sllc_pmu -> base + regs -> srcid_ctrl );
145171 /* Disable the srcid */
146- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
172+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
147173 val &= ~(SLLC_SRCID_EN | SLLC_FILT_EN );
148- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
174+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
149175 }
150176}
151177
@@ -167,29 +193,27 @@ static void hisi_sllc_pmu_clear_filter(struct perf_event *event)
167193 }
168194}
169195
170- static u32 hisi_sllc_pmu_get_counter_offset (int idx )
171- {
172- return (SLLC_EVENT_CNT0_L + idx * 8 );
173- }
174-
175196static u64 hisi_sllc_pmu_read_counter (struct hisi_pmu * sllc_pmu ,
176197 struct hw_perf_event * hwc )
177198{
178- return readq (sllc_pmu -> base +
179- hisi_sllc_pmu_get_counter_offset (hwc -> idx ));
199+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
200+
201+ return readq (sllc_pmu -> base + SLLC_EVENT_CNTn (regs -> event_cnt0 , hwc -> idx ));
180202}
181203
182204static void hisi_sllc_pmu_write_counter (struct hisi_pmu * sllc_pmu ,
183205 struct hw_perf_event * hwc , u64 val )
184206{
185- writeq (val , sllc_pmu -> base +
186- hisi_sllc_pmu_get_counter_offset (hwc -> idx ));
207+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
208+
209+ writeq (val , sllc_pmu -> base + SLLC_EVENT_CNTn (regs -> event_cnt0 , hwc -> idx ));
187210}
188211
189212static void hisi_sllc_pmu_write_evtype (struct hisi_pmu * sllc_pmu , int idx ,
190213 u32 type )
191214{
192- u32 reg , reg_idx , shift , val ;
215+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
216+ u32 reg , val ;
193217
194218 /*
195219 * Select the appropriate event select register(SLLC_EVENT_TYPE0/1).
@@ -198,96 +222,98 @@ static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx,
198222 * SLLC_EVENT_TYPE0 is chosen. For the latter 4 hardware counters,
199223 * SLLC_EVENT_TYPE1 is chosen.
200224 */
201- reg = SLLC_EVENT_TYPE0 + (idx / 4 ) * 4 ;
202- reg_idx = idx % 4 ;
203- shift = 8 * reg_idx ;
225+ reg = regs -> event_type0 + (idx / 4 ) * 4 ;
204226
205227 /* Write event code to SLLC_EVENT_TYPEx Register */
206228 val = readl (sllc_pmu -> base + reg );
207- val &= ~(SLLC_EVTYPE_MASK << shift );
208- val |= (type << shift );
229+ val &= ~(SLLC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT ( idx ) );
230+ val |= (type << HISI_PMU_EVTYPE_SHIFT ( idx ) );
209231 writel (val , sllc_pmu -> base + reg );
210232}
211233
212234static void hisi_sllc_pmu_start_counters (struct hisi_pmu * sllc_pmu )
213235{
236+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
214237 u32 val ;
215238
216- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
239+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
217240 val |= SLLC_PERF_CTRL_EN ;
218- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
241+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
219242}
220243
221244static void hisi_sllc_pmu_stop_counters (struct hisi_pmu * sllc_pmu )
222245{
246+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
223247 u32 val ;
224248
225- val = readl (sllc_pmu -> base + SLLC_PERF_CTRL );
249+ val = readl (sllc_pmu -> base + regs -> perf_ctrl );
226250 val &= ~(SLLC_PERF_CTRL_EN );
227- writel (val , sllc_pmu -> base + SLLC_PERF_CTRL );
251+ writel (val , sllc_pmu -> base + regs -> perf_ctrl );
228252}
229253
230254static void hisi_sllc_pmu_enable_counter (struct hisi_pmu * sllc_pmu ,
231255 struct hw_perf_event * hwc )
232256{
257+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
233258 u32 val ;
234259
235- val = readl (sllc_pmu -> base + SLLC_EVENT_CTRL );
236- val |= 1 << hwc -> idx ;
237- writel (val , sllc_pmu -> base + SLLC_EVENT_CTRL );
260+ val = readl (sllc_pmu -> base + regs -> event_ctrl );
261+ val |= BIT_ULL ( hwc -> idx ) ;
262+ writel (val , sllc_pmu -> base + regs -> event_ctrl );
238263}
239264
240265static void hisi_sllc_pmu_disable_counter (struct hisi_pmu * sllc_pmu ,
241266 struct hw_perf_event * hwc )
242267{
268+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
243269 u32 val ;
244270
245- val = readl (sllc_pmu -> base + SLLC_EVENT_CTRL );
246- val &= ~( 1 << hwc -> idx );
247- writel (val , sllc_pmu -> base + SLLC_EVENT_CTRL );
271+ val = readl (sllc_pmu -> base + regs -> event_ctrl );
272+ val &= ~BIT_ULL ( hwc -> idx );
273+ writel (val , sllc_pmu -> base + regs -> event_ctrl );
248274}
249275
250276static void hisi_sllc_pmu_enable_counter_int (struct hisi_pmu * sllc_pmu ,
251277 struct hw_perf_event * hwc )
252278{
279+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
253280 u32 val ;
254281
255- val = readl (sllc_pmu -> base + SLLC_INT_MASK );
256- /* Write 0 to enable interrupt */
257- val &= ~(1 << hwc -> idx );
258- writel (val , sllc_pmu -> base + SLLC_INT_MASK );
282+ val = readl (sllc_pmu -> base + regs -> int_mask );
283+ val &= ~BIT_ULL (hwc -> idx );
284+ writel (val , sllc_pmu -> base + regs -> int_mask );
259285}
260286
261287static void hisi_sllc_pmu_disable_counter_int (struct hisi_pmu * sllc_pmu ,
262288 struct hw_perf_event * hwc )
263289{
290+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
264291 u32 val ;
265292
266- val = readl (sllc_pmu -> base + SLLC_INT_MASK );
267- /* Write 1 to mask interrupt */
268- val |= 1 << hwc -> idx ;
269- writel (val , sllc_pmu -> base + SLLC_INT_MASK );
293+ val = readl (sllc_pmu -> base + regs -> int_mask );
294+ val |= BIT_ULL (hwc -> idx );
295+ writel (val , sllc_pmu -> base + regs -> int_mask );
270296}
271297
272298static u32 hisi_sllc_pmu_get_int_status (struct hisi_pmu * sllc_pmu )
273299{
274- return readl (sllc_pmu -> base + SLLC_INT_STATUS );
300+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
301+
302+ return readl (sllc_pmu -> base + regs -> int_status );
275303}
276304
277305static void hisi_sllc_pmu_clear_int_status (struct hisi_pmu * sllc_pmu , int idx )
278306{
279- writel (1 << idx , sllc_pmu -> base + SLLC_INT_CLEAR );
280- }
307+ struct hisi_sllc_pmu_regs * regs = sllc_pmu -> dev_info -> private ;
281308
282- static const struct acpi_device_id hisi_sllc_pmu_acpi_match [] = {
283- { "HISI0263" , },
284- {}
285- };
286- MODULE_DEVICE_TABLE (acpi , hisi_sllc_pmu_acpi_match );
309+ writel (BIT_ULL (idx ), sllc_pmu -> base + regs -> int_clear );
310+ }
287311
288312static int hisi_sllc_pmu_init_data (struct platform_device * pdev ,
289313 struct hisi_pmu * sllc_pmu )
290314{
315+ struct hisi_sllc_pmu_regs * regs ;
316+
291317 hisi_uncore_pmu_init_topology (sllc_pmu , & pdev -> dev );
292318
293319 /*
@@ -304,13 +330,18 @@ static int hisi_sllc_pmu_init_data(struct platform_device *pdev,
304330 return - EINVAL ;
305331 }
306332
333+ sllc_pmu -> dev_info = device_get_match_data (& pdev -> dev );
334+ if (!sllc_pmu -> dev_info )
335+ return - ENODEV ;
336+
307337 sllc_pmu -> base = devm_platform_ioremap_resource (pdev , 0 );
308338 if (IS_ERR (sllc_pmu -> base )) {
309339 dev_err (& pdev -> dev , "ioremap failed for sllc_pmu resource.\n" );
310340 return PTR_ERR (sllc_pmu -> base );
311341 }
312342
313- sllc_pmu -> identifier = readl (sllc_pmu -> base + SLLC_VERSION );
343+ regs = sllc_pmu -> dev_info -> private ;
344+ sllc_pmu -> identifier = readl (sllc_pmu -> base + regs -> version );
314345
315346 return 0 ;
316347}
@@ -352,6 +383,27 @@ static const struct attribute_group *hisi_sllc_pmu_v2_attr_groups[] = {
352383 NULL
353384};
354385
386+ static struct hisi_sllc_pmu_regs hisi_sllc_v2_pmu_regs = {
387+ .int_mask = SLLC_INT_MASK ,
388+ .int_clear = SLLC_INT_CLEAR ,
389+ .int_status = SLLC_INT_STATUS ,
390+ .perf_ctrl = SLLC_PERF_CTRL ,
391+ .srcid_ctrl = SLLC_SRCID_CTRL ,
392+ .srcid_cmd_shift = SLLC_SRCID_CMD_SHIFT ,
393+ .srcid_mask_shift = SLLC_SRCID_MSK_SHIFT ,
394+ .tgtid_ctrl = SLLC_TGTID_CTRL ,
395+ .tgtid_min_shift = SLLC_TGTID_MIN_SHIFT ,
396+ .tgtid_max_shift = SLLC_TGTID_MAX_SHIFT ,
397+ .event_ctrl = SLLC_EVENT_CTRL ,
398+ .event_type0 = SLLC_EVENT_TYPE0 ,
399+ .version = SLLC_VERSION ,
400+ .event_cnt0 = SLLC_EVENT_CNT0_L ,
401+ };
402+
403+ static const struct hisi_pmu_dev_info hisi_sllc_v2 = {
404+ .private = & hisi_sllc_v2_pmu_regs ,
405+ };
406+
355407static const struct hisi_uncore_ops hisi_uncore_sllc_ops = {
356408 .write_evtype = hisi_sllc_pmu_write_evtype ,
357409 .get_event_idx = hisi_uncore_pmu_get_event_idx ,
@@ -443,6 +495,12 @@ static void hisi_sllc_pmu_remove(struct platform_device *pdev)
443495 & sllc_pmu -> node );
444496}
445497
498+ static const struct acpi_device_id hisi_sllc_pmu_acpi_match [] = {
499+ { "HISI0263" , (kernel_ulong_t )& hisi_sllc_v2 },
500+ {}
501+ };
502+ MODULE_DEVICE_TABLE (acpi , hisi_sllc_pmu_acpi_match );
503+
446504static struct platform_driver hisi_sllc_pmu_driver = {
447505 .driver = {
448506 .name = "hisi_sllc_pmu" ,
0 commit comments