Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

PM / devfreq: rockchip-dfi: double count on RK3588

On RK3588 with LPDDR4X memory, the cycle count as returned by

perf stat -a -e rockchip_ddr/cycles/ sleep 1

consistently reads half as much as what the actual DDR frequency is at.
For a LPDDR4X module running at 2112MHz, I get more like 1056059916
cycles per second, which is almost bang-on half what it should be. No,
I'm not mixing up megatransfers and megahertz.

Consulting the downstream driver, this appears to be because the RK3588
hardware specifically (and RK3528 as well, for future reference) needs a
multiplier of 2 to get to the correct frequency with everything but
LPDDR5.

The RK3588's actual memory bandwidth measurements in MB/s are correct
however, as confirmed with stress-ng --stream. This makes me think the
access counters are not affected in the same way. This tracks with the
vendor kernel not multiplying the access counts either.

Solve this by adding a new member to the dfi struct, which each SoC can
set to whatever they want, but defaults to 1 if left unset by the SoC
init functions. The event_get_count op can then use this multiplier if
the cycle count is requested.

The cycle multiplier is not used in rockchip_dfi_get_event because the
vendor driver doesn't use it there either, and we don't do other actual
bandwidth unit conversion stuff in there anyway.

Fixes: 481d97ba61e1 ("PM / devfreq: rockchip-dfi: add support for RK3588")
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Link: https://lore.kernel.org/lkml/20250530-rk3588-dfi-improvements-v1-1-6e077c243a95@collabora.com/

authored by

Nicolas Frattaroli and committed by
Chanwoo Choi
f89c7fb8 6d0982ae

+6 -1
+6 -1
drivers/devfreq/event/rockchip-dfi.c
··· 116 116 int buswidth[DMC_MAX_CHANNELS]; 117 117 int ddrmon_stride; 118 118 bool ddrmon_ctrl_single; 119 + unsigned int count_multiplier; /* number of data clocks per count */ 119 120 }; 120 121 121 122 static int rockchip_dfi_enable(struct rockchip_dfi *dfi) ··· 436 435 437 436 switch (event->attr.config) { 438 437 case PERF_EVENT_CYCLES: 439 - count = total.c[0].clock_cycles; 438 + count = total.c[0].clock_cycles * dfi->count_multiplier; 440 439 break; 441 440 case PERF_EVENT_READ_BYTES: 442 441 for (i = 0; i < dfi->max_channels; i++) ··· 656 655 break; 657 656 } 658 657 658 + if (!dfi->count_multiplier) 659 + dfi->count_multiplier = 1; 660 + 659 661 ret = perf_pmu_register(pmu, "rockchip_ddr", -1); 660 662 if (ret) 661 663 return ret; ··· 755 751 dfi->max_channels = 4; 756 752 757 753 dfi->ddrmon_stride = 0x4000; 754 + dfi->count_multiplier = 2; 758 755 759 756 return 0; 760 757 };