diff options
author | Frank Li <Frank.Li@nxp.com> | 2016-11-07 12:30:48 -0500 |
---|---|---|
committer | Shawn Guo <shawnguo@kernel.org> | 2016-11-14 00:34:45 -0500 |
commit | c47c6fe41c152a1b6dd5c195bdea06c24cf2ac30 (patch) | |
tree | 74cb6c3b0a2fcf7ba7deab764c4910fd312dc4b1 /arch/arm/mach-imx/mmdc.c | |
parent | e76bdfd7403aae582461901955d0136381e34435 (diff) |
ARM: imx: mmdc perf function support i.MX6QP
i.MX6QP added new register bit PROFILE_SEL in MADPCR0.
need set it at perf start.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
Diffstat (limited to 'arch/arm/mach-imx/mmdc.c')
-rw-r--r-- | arch/arm/mach-imx/mmdc.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c index d82d14ceb2e9..ba96bf979625 100644 --- a/arch/arm/mach-imx/mmdc.c +++ b/arch/arm/mach-imx/mmdc.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #define DBG_RST 0x2 | 44 | #define DBG_RST 0x2 |
45 | #define PRF_FRZ 0x4 | 45 | #define PRF_FRZ 0x4 |
46 | #define CYC_OVF 0x8 | 46 | #define CYC_OVF 0x8 |
47 | #define PROFILE_SEL 0x10 | ||
47 | 48 | ||
48 | #define MMDC_MADPCR0 0x410 | 49 | #define MMDC_MADPCR0 0x410 |
49 | #define MMDC_MADPSR0 0x418 | 50 | #define MMDC_MADPSR0 0x418 |
@@ -55,10 +56,29 @@ | |||
55 | 56 | ||
56 | #define MMDC_NUM_COUNTERS 6 | 57 | #define MMDC_NUM_COUNTERS 6 |
57 | 58 | ||
59 | #define MMDC_FLAG_PROFILE_SEL 0x1 | ||
60 | |||
58 | #define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu) | 61 | #define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu) |
59 | 62 | ||
60 | static int ddr_type; | 63 | static int ddr_type; |
61 | 64 | ||
65 | struct fsl_mmdc_devtype_data { | ||
66 | unsigned int flags; | ||
67 | }; | ||
68 | |||
69 | static const struct fsl_mmdc_devtype_data imx6q_data = { | ||
70 | }; | ||
71 | |||
72 | static const struct fsl_mmdc_devtype_data imx6qp_data = { | ||
73 | .flags = MMDC_FLAG_PROFILE_SEL, | ||
74 | }; | ||
75 | |||
76 | static const struct of_device_id imx_mmdc_dt_ids[] = { | ||
77 | { .compatible = "fsl,imx6q-mmdc", .data = (void *)&imx6q_data}, | ||
78 | { .compatible = "fsl,imx6qp-mmdc", .data = (void *)&imx6qp_data}, | ||
79 | { /* sentinel */ } | ||
80 | }; | ||
81 | |||
62 | #ifdef CONFIG_PERF_EVENTS | 82 | #ifdef CONFIG_PERF_EVENTS |
63 | 83 | ||
64 | static DEFINE_IDA(mmdc_ida); | 84 | static DEFINE_IDA(mmdc_ida); |
@@ -83,6 +103,7 @@ struct mmdc_pmu { | |||
83 | struct device *dev; | 103 | struct device *dev; |
84 | struct perf_event *mmdc_events[MMDC_NUM_COUNTERS]; | 104 | struct perf_event *mmdc_events[MMDC_NUM_COUNTERS]; |
85 | struct hlist_node node; | 105 | struct hlist_node node; |
106 | struct fsl_mmdc_devtype_data *devtype_data; | ||
86 | }; | 107 | }; |
87 | 108 | ||
88 | /* | 109 | /* |
@@ -307,6 +328,7 @@ static void mmdc_pmu_event_start(struct perf_event *event, int flags) | |||
307 | struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); | 328 | struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu); |
308 | struct hw_perf_event *hwc = &event->hw; | 329 | struct hw_perf_event *hwc = &event->hw; |
309 | void __iomem *mmdc_base, *reg; | 330 | void __iomem *mmdc_base, *reg; |
331 | u32 val; | ||
310 | 332 | ||
311 | mmdc_base = pmu_mmdc->mmdc_base; | 333 | mmdc_base = pmu_mmdc->mmdc_base; |
312 | reg = mmdc_base + MMDC_MADPCR0; | 334 | reg = mmdc_base + MMDC_MADPCR0; |
@@ -321,7 +343,12 @@ static void mmdc_pmu_event_start(struct perf_event *event, int flags) | |||
321 | local64_set(&hwc->prev_count, 0); | 343 | local64_set(&hwc->prev_count, 0); |
322 | 344 | ||
323 | writel(DBG_RST, reg); | 345 | writel(DBG_RST, reg); |
324 | writel(DBG_EN, reg); | 346 | |
347 | val = DBG_EN; | ||
348 | if (pmu_mmdc->devtype_data->flags & MMDC_FLAG_PROFILE_SEL) | ||
349 | val |= PROFILE_SEL; | ||
350 | |||
351 | writel(val, reg); | ||
325 | } | 352 | } |
326 | 353 | ||
327 | static int mmdc_pmu_event_add(struct perf_event *event, int flags) | 354 | static int mmdc_pmu_event_add(struct perf_event *event, int flags) |
@@ -436,6 +463,8 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b | |||
436 | char *name; | 463 | char *name; |
437 | int mmdc_num; | 464 | int mmdc_num; |
438 | int ret; | 465 | int ret; |
466 | const struct of_device_id *of_id = | ||
467 | of_match_device(imx_mmdc_dt_ids, &pdev->dev); | ||
439 | 468 | ||
440 | pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL); | 469 | pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL); |
441 | if (!pmu_mmdc) { | 470 | if (!pmu_mmdc) { |
@@ -450,6 +479,8 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b | |||
450 | name = devm_kasprintf(&pdev->dev, | 479 | name = devm_kasprintf(&pdev->dev, |
451 | GFP_KERNEL, "mmdc%d", mmdc_num); | 480 | GFP_KERNEL, "mmdc%d", mmdc_num); |
452 | 481 | ||
482 | pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data; | ||
483 | |||
453 | hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC, | 484 | hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC, |
454 | HRTIMER_MODE_REL); | 485 | HRTIMER_MODE_REL); |
455 | pmu_mmdc->hrtimer.function = mmdc_pmu_timer_handler; | 486 | pmu_mmdc->hrtimer.function = mmdc_pmu_timer_handler; |
@@ -524,11 +555,6 @@ int imx_mmdc_get_ddr_type(void) | |||
524 | return ddr_type; | 555 | return ddr_type; |
525 | } | 556 | } |
526 | 557 | ||
527 | static const struct of_device_id imx_mmdc_dt_ids[] = { | ||
528 | { .compatible = "fsl,imx6q-mmdc", }, | ||
529 | { /* sentinel */ } | ||
530 | }; | ||
531 | |||
532 | static struct platform_driver imx_mmdc_driver = { | 558 | static struct platform_driver imx_mmdc_driver = { |
533 | .driver = { | 559 | .driver = { |
534 | .name = "imx-mmdc", | 560 | .name = "imx-mmdc", |