1 // SPDX-License-Identifier: GPL-2.0-only
3 * exynos_ppmu.c - EXYNOS PPMU (Platform Performance Monitoring Unit) support
5 * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
6 * Author : Chanwoo Choi <cw00.choi@samsung.com>
8 * This driver is based on drivers/devfreq/exynos/exynos_ppmu.c
11 #include <linux/clk.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/of_address.h>
16 #include <linux/platform_device.h>
17 #include <linux/regmap.h>
18 #include <linux/suspend.h>
19 #include <linux/devfreq-event.h>
21 #include "exynos-ppmu.h"
23 struct exynos_ppmu_data
{
28 struct devfreq_event_dev
**edev
;
29 struct devfreq_event_desc
*desc
;
30 unsigned int num_events
;
33 struct regmap
*regmap
;
35 struct exynos_ppmu_data ppmu
;
38 #define PPMU_EVENT(name) \
39 { "ppmu-event0-"#name, PPMU_PMNCNT0 }, \
40 { "ppmu-event1-"#name, PPMU_PMNCNT1 }, \
41 { "ppmu-event2-"#name, PPMU_PMNCNT2 }, \
42 { "ppmu-event3-"#name, PPMU_PMNCNT3 }
44 static struct __exynos_ppmu_events
{
48 /* For Exynos3250, Exynos4 and Exynos5260 */
52 /* For Exynos4 SoCs and Exynos3250 */
61 /* Only for Exynos3250 and Exynos5260 */
64 /* Only for Exynos4 SoCs */
66 PPMU_EVENT(mfc
-right
),
68 /* Only for Exynos5260 SoCs */
82 /* Only for Exynos5433 SoCs */
84 PPMU_EVENT(d0
-general
),
87 PPMU_EVENT(d1
-general
),
91 static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev
*edev
)
95 for (i
= 0; i
< ARRAY_SIZE(ppmu_events
); i
++)
96 if (!strcmp(edev
->desc
->name
, ppmu_events
[i
].name
))
97 return ppmu_events
[i
].id
;
103 * The devfreq-event ops structure for PPMU v1.1
105 static int exynos_ppmu_disable(struct devfreq_event_dev
*edev
)
107 struct exynos_ppmu
*info
= devfreq_event_get_drvdata(edev
);
111 /* Disable all counters */
112 ret
= regmap_write(info
->regmap
, PPMU_CNTENC
,
122 ret
= regmap_read(info
->regmap
, PPMU_PMNC
, &pmnc
);
126 pmnc
&= ~PPMU_PMNC_ENABLE_MASK
;
127 ret
= regmap_write(info
->regmap
, PPMU_PMNC
, pmnc
);
134 static int exynos_ppmu_set_event(struct devfreq_event_dev
*edev
)
136 struct exynos_ppmu
*info
= devfreq_event_get_drvdata(edev
);
137 int id
= exynos_ppmu_find_ppmu_id(edev
);
144 /* Enable specific counter */
145 ret
= regmap_read(info
->regmap
, PPMU_CNTENS
, &cntens
);
149 cntens
|= (PPMU_CCNT_MASK
| (PPMU_ENABLE
<< id
));
150 ret
= regmap_write(info
->regmap
, PPMU_CNTENS
, cntens
);
154 /* Set the event of Read/Write data count */
155 ret
= regmap_write(info
->regmap
, PPMU_BEVTxSEL(id
),
156 PPMU_RO_DATA_CNT
| PPMU_WO_DATA_CNT
);
160 /* Reset cycle counter/performance counter and enable PPMU */
161 ret
= regmap_read(info
->regmap
, PPMU_PMNC
, &pmnc
);
165 pmnc
&= ~(PPMU_PMNC_ENABLE_MASK
166 | PPMU_PMNC_COUNTER_RESET_MASK
167 | PPMU_PMNC_CC_RESET_MASK
);
168 pmnc
|= (PPMU_ENABLE
<< PPMU_PMNC_ENABLE_SHIFT
);
169 pmnc
|= (PPMU_ENABLE
<< PPMU_PMNC_COUNTER_RESET_SHIFT
);
170 pmnc
|= (PPMU_ENABLE
<< PPMU_PMNC_CC_RESET_SHIFT
);
171 ret
= regmap_write(info
->regmap
, PPMU_PMNC
, pmnc
);
178 static int exynos_ppmu_get_event(struct devfreq_event_dev
*edev
,
179 struct devfreq_event_data
*edata
)
181 struct exynos_ppmu
*info
= devfreq_event_get_drvdata(edev
);
182 int id
= exynos_ppmu_find_ppmu_id(edev
);
183 unsigned int total_count
, load_count
;
184 unsigned int pmcnt3_high
, pmcnt3_low
;
185 unsigned int pmnc
, cntenc
;
192 ret
= regmap_read(info
->regmap
, PPMU_PMNC
, &pmnc
);
196 pmnc
&= ~PPMU_PMNC_ENABLE_MASK
;
197 ret
= regmap_write(info
->regmap
, PPMU_PMNC
, pmnc
);
201 /* Read cycle count */
202 ret
= regmap_read(info
->regmap
, PPMU_CCNT
, &total_count
);
205 edata
->total_count
= total_count
;
207 /* Read performance count */
212 ret
= regmap_read(info
->regmap
, PPMU_PMNCT(id
), &load_count
);
215 edata
->load_count
= load_count
;
218 ret
= regmap_read(info
->regmap
, PPMU_PMCNT3_HIGH
, &pmcnt3_high
);
222 ret
= regmap_read(info
->regmap
, PPMU_PMCNT3_LOW
, &pmcnt3_low
);
226 edata
->load_count
= ((pmcnt3_high
<< 8) | pmcnt3_low
);
232 /* Disable specific counter */
233 ret
= regmap_read(info
->regmap
, PPMU_CNTENC
, &cntenc
);
237 cntenc
|= (PPMU_CCNT_MASK
| (PPMU_ENABLE
<< id
));
238 ret
= regmap_write(info
->regmap
, PPMU_CNTENC
, cntenc
);
242 dev_dbg(&edev
->dev
, "%s (event: %ld/%ld)\n", edev
->desc
->name
,
243 edata
->load_count
, edata
->total_count
);
248 static const struct devfreq_event_ops exynos_ppmu_ops
= {
249 .disable
= exynos_ppmu_disable
,
250 .set_event
= exynos_ppmu_set_event
,
251 .get_event
= exynos_ppmu_get_event
,
255 * The devfreq-event ops structure for PPMU v2.0
257 static int exynos_ppmu_v2_disable(struct devfreq_event_dev
*edev
)
259 struct exynos_ppmu
*info
= devfreq_event_get_drvdata(edev
);
263 /* Disable all counters */
264 clear
= (PPMU_CCNT_MASK
| PPMU_PMCNT0_MASK
| PPMU_PMCNT1_MASK
265 | PPMU_PMCNT2_MASK
| PPMU_PMCNT3_MASK
);
266 ret
= regmap_write(info
->regmap
, PPMU_V2_FLAG
, clear
);
270 ret
= regmap_write(info
->regmap
, PPMU_V2_INTENC
, clear
);
274 ret
= regmap_write(info
->regmap
, PPMU_V2_CNTENC
, clear
);
278 ret
= regmap_write(info
->regmap
, PPMU_V2_CNT_RESET
, clear
);
282 ret
= regmap_write(info
->regmap
, PPMU_V2_CIG_CFG0
, 0x0);
286 ret
= regmap_write(info
->regmap
, PPMU_V2_CIG_CFG1
, 0x0);
290 ret
= regmap_write(info
->regmap
, PPMU_V2_CIG_CFG2
, 0x0);
294 ret
= regmap_write(info
->regmap
, PPMU_V2_CIG_RESULT
, 0x0);
298 ret
= regmap_write(info
->regmap
, PPMU_V2_CNT_AUTO
, 0x0);
302 ret
= regmap_write(info
->regmap
, PPMU_V2_CH_EV0_TYPE
, 0x0);
306 ret
= regmap_write(info
->regmap
, PPMU_V2_CH_EV1_TYPE
, 0x0);
310 ret
= regmap_write(info
->regmap
, PPMU_V2_CH_EV2_TYPE
, 0x0);
314 ret
= regmap_write(info
->regmap
, PPMU_V2_CH_EV3_TYPE
, 0x0);
318 ret
= regmap_write(info
->regmap
, PPMU_V2_SM_ID_V
, 0x0);
322 ret
= regmap_write(info
->regmap
, PPMU_V2_SM_ID_A
, 0x0);
326 ret
= regmap_write(info
->regmap
, PPMU_V2_SM_OTHERS_V
, 0x0);
330 ret
= regmap_write(info
->regmap
, PPMU_V2_SM_OTHERS_A
, 0x0);
334 ret
= regmap_write(info
->regmap
, PPMU_V2_INTERRUPT_RESET
, 0x0);
339 ret
= regmap_read(info
->regmap
, PPMU_V2_PMNC
, &pmnc
);
343 pmnc
&= ~PPMU_PMNC_ENABLE_MASK
;
344 ret
= regmap_write(info
->regmap
, PPMU_V2_PMNC
, pmnc
);
351 static int exynos_ppmu_v2_set_event(struct devfreq_event_dev
*edev
)
353 struct exynos_ppmu
*info
= devfreq_event_get_drvdata(edev
);
354 unsigned int pmnc
, cntens
;
355 int id
= exynos_ppmu_find_ppmu_id(edev
);
358 /* Enable all counters */
359 ret
= regmap_read(info
->regmap
, PPMU_V2_CNTENS
, &cntens
);
363 cntens
|= (PPMU_CCNT_MASK
| (PPMU_ENABLE
<< id
));
364 ret
= regmap_write(info
->regmap
, PPMU_V2_CNTENS
, cntens
);
368 /* Set the event of Read/Write data count */
373 ret
= regmap_write(info
->regmap
, PPMU_V2_CH_EVx_TYPE(id
),
374 PPMU_V2_RO_DATA_CNT
| PPMU_V2_WO_DATA_CNT
);
379 ret
= regmap_write(info
->regmap
, PPMU_V2_CH_EVx_TYPE(id
),
380 PPMU_V2_EVT3_RW_DATA_CNT
);
386 /* Reset cycle counter/performance counter and enable PPMU */
387 ret
= regmap_read(info
->regmap
, PPMU_V2_PMNC
, &pmnc
);
391 pmnc
&= ~(PPMU_PMNC_ENABLE_MASK
392 | PPMU_PMNC_COUNTER_RESET_MASK
393 | PPMU_PMNC_CC_RESET_MASK
394 | PPMU_PMNC_CC_DIVIDER_MASK
395 | PPMU_V2_PMNC_START_MODE_MASK
);
396 pmnc
|= (PPMU_ENABLE
<< PPMU_PMNC_ENABLE_SHIFT
);
397 pmnc
|= (PPMU_ENABLE
<< PPMU_PMNC_COUNTER_RESET_SHIFT
);
398 pmnc
|= (PPMU_ENABLE
<< PPMU_PMNC_CC_RESET_SHIFT
);
399 pmnc
|= (PPMU_V2_MODE_MANUAL
<< PPMU_V2_PMNC_START_MODE_SHIFT
);
401 ret
= regmap_write(info
->regmap
, PPMU_V2_PMNC
, pmnc
);
408 static int exynos_ppmu_v2_get_event(struct devfreq_event_dev
*edev
,
409 struct devfreq_event_data
*edata
)
411 struct exynos_ppmu
*info
= devfreq_event_get_drvdata(edev
);
412 int id
= exynos_ppmu_find_ppmu_id(edev
);
414 unsigned int pmnc
, cntenc
;
415 unsigned int pmcnt_high
, pmcnt_low
;
416 unsigned int total_count
, count
;
417 unsigned long load_count
= 0;
420 ret
= regmap_read(info
->regmap
, PPMU_V2_PMNC
, &pmnc
);
424 pmnc
&= ~PPMU_PMNC_ENABLE_MASK
;
425 ret
= regmap_write(info
->regmap
, PPMU_V2_PMNC
, pmnc
);
429 /* Read cycle count and performance count */
430 ret
= regmap_read(info
->regmap
, PPMU_V2_CCNT
, &total_count
);
433 edata
->total_count
= total_count
;
439 ret
= regmap_read(info
->regmap
, PPMU_V2_PMNCT(id
), &count
);
445 ret
= regmap_read(info
->regmap
, PPMU_V2_PMCNT3_HIGH
,
450 ret
= regmap_read(info
->regmap
, PPMU_V2_PMCNT3_LOW
, &pmcnt_low
);
454 load_count
= ((u64
)((pmcnt_high
& 0xff)) << 32)+ (u64
)pmcnt_low
;
457 edata
->load_count
= load_count
;
459 /* Disable all counters */
460 ret
= regmap_read(info
->regmap
, PPMU_V2_CNTENC
, &cntenc
);
464 cntenc
|= (PPMU_CCNT_MASK
| (PPMU_ENABLE
<< id
));
465 ret
= regmap_write(info
->regmap
, PPMU_V2_CNTENC
, cntenc
);
469 dev_dbg(&edev
->dev
, "%25s (load: %ld / %ld)\n", edev
->desc
->name
,
470 edata
->load_count
, edata
->total_count
);
474 static const struct devfreq_event_ops exynos_ppmu_v2_ops
= {
475 .disable
= exynos_ppmu_v2_disable
,
476 .set_event
= exynos_ppmu_v2_set_event
,
477 .get_event
= exynos_ppmu_v2_get_event
,
480 static const struct of_device_id exynos_ppmu_id_match
[] = {
482 .compatible
= "samsung,exynos-ppmu",
483 .data
= (void *)&exynos_ppmu_ops
,
485 .compatible
= "samsung,exynos-ppmu-v2",
486 .data
= (void *)&exynos_ppmu_v2_ops
,
490 MODULE_DEVICE_TABLE(of
, exynos_ppmu_id_match
);
492 static struct devfreq_event_ops
*exynos_bus_get_ops(struct device_node
*np
)
494 const struct of_device_id
*match
;
496 match
= of_match_node(exynos_ppmu_id_match
, np
);
497 return (struct devfreq_event_ops
*)match
->data
;
500 static int of_get_devfreq_events(struct device_node
*np
,
501 struct exynos_ppmu
*info
)
503 struct devfreq_event_desc
*desc
;
504 struct devfreq_event_ops
*event_ops
;
505 struct device
*dev
= info
->dev
;
506 struct device_node
*events_np
, *node
;
509 events_np
= of_get_child_by_name(np
, "events");
512 "failed to get child node of devfreq-event devices\n");
515 event_ops
= exynos_bus_get_ops(np
);
517 count
= of_get_child_count(events_np
);
518 desc
= devm_kcalloc(dev
, count
, sizeof(*desc
), GFP_KERNEL
);
521 info
->num_events
= count
;
524 for_each_child_of_node(events_np
, node
) {
525 for (i
= 0; i
< ARRAY_SIZE(ppmu_events
); i
++) {
526 if (!ppmu_events
[i
].name
)
529 if (of_node_name_eq(node
, ppmu_events
[i
].name
))
533 if (i
== ARRAY_SIZE(ppmu_events
)) {
535 "don't know how to configure events : %pOFn\n",
540 desc
[j
].ops
= event_ops
;
541 desc
[j
].driver_data
= info
;
543 of_property_read_string(node
, "event-name", &desc
[j
].name
);
549 of_node_put(events_np
);
554 static struct regmap_config exynos_ppmu_regmap_config
= {
560 static int exynos_ppmu_parse_dt(struct platform_device
*pdev
,
561 struct exynos_ppmu
*info
)
563 struct device
*dev
= info
->dev
;
564 struct device_node
*np
= dev
->of_node
;
565 struct resource
*res
;
570 dev_err(dev
, "failed to find devicetree node\n");
574 /* Maps the memory mapped IO to control PPMU register */
575 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
576 base
= devm_ioremap_resource(dev
, res
);
578 return PTR_ERR(base
);
580 exynos_ppmu_regmap_config
.max_register
= resource_size(res
) - 4;
581 info
->regmap
= devm_regmap_init_mmio(dev
, base
,
582 &exynos_ppmu_regmap_config
);
583 if (IS_ERR(info
->regmap
)) {
584 dev_err(dev
, "failed to initialize regmap\n");
585 return PTR_ERR(info
->regmap
);
588 info
->ppmu
.clk
= devm_clk_get(dev
, "ppmu");
589 if (IS_ERR(info
->ppmu
.clk
)) {
590 info
->ppmu
.clk
= NULL
;
591 dev_warn(dev
, "cannot get PPMU clock\n");
594 ret
= of_get_devfreq_events(np
, info
);
596 dev_err(dev
, "failed to parse exynos ppmu dt node\n");
603 static int exynos_ppmu_probe(struct platform_device
*pdev
)
605 struct exynos_ppmu
*info
;
606 struct devfreq_event_dev
**edev
;
607 struct devfreq_event_desc
*desc
;
608 int i
, ret
= 0, size
;
610 info
= devm_kzalloc(&pdev
->dev
, sizeof(*info
), GFP_KERNEL
);
614 info
->dev
= &pdev
->dev
;
616 /* Parse dt data to get resource */
617 ret
= exynos_ppmu_parse_dt(pdev
, info
);
620 "failed to parse devicetree for resource\n");
625 size
= sizeof(struct devfreq_event_dev
*) * info
->num_events
;
626 info
->edev
= devm_kzalloc(&pdev
->dev
, size
, GFP_KERNEL
);
631 platform_set_drvdata(pdev
, info
);
633 for (i
= 0; i
< info
->num_events
; i
++) {
634 edev
[i
] = devm_devfreq_event_add_edev(&pdev
->dev
, &desc
[i
]);
635 if (IS_ERR(edev
[i
])) {
636 ret
= PTR_ERR(edev
[i
]);
638 "failed to add devfreq-event device\n");
639 return PTR_ERR(edev
[i
]);
642 pr_info("exynos-ppmu: new PPMU device registered %s (%s)\n",
643 dev_name(&pdev
->dev
), desc
[i
].name
);
646 ret
= clk_prepare_enable(info
->ppmu
.clk
);
648 dev_err(&pdev
->dev
, "failed to prepare ppmu clock\n");
655 static int exynos_ppmu_remove(struct platform_device
*pdev
)
657 struct exynos_ppmu
*info
= platform_get_drvdata(pdev
);
659 clk_disable_unprepare(info
->ppmu
.clk
);
664 static struct platform_driver exynos_ppmu_driver
= {
665 .probe
= exynos_ppmu_probe
,
666 .remove
= exynos_ppmu_remove
,
668 .name
= "exynos-ppmu",
669 .of_match_table
= exynos_ppmu_id_match
,
672 module_platform_driver(exynos_ppmu_driver
);
674 MODULE_DESCRIPTION("Exynos PPMU(Platform Performance Monitoring Unit) driver");
675 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
676 MODULE_LICENSE("GPL");