summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/rcutorture/doc
diff options
context:
space:
mode:
authorAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>2022-06-13 16:38:19 +0300
committerDaniel Lezcano <daniel.lezcano@linaro.org>2022-07-16 01:41:51 +0300
commit327e93cf9a59b0d04eb3a31a7fdbf0f11cf13ecb (patch)
tree9406bd2480cac2319d2604b4efcb5e493e40d3c8 /tools/testing/selftests/rcutorture/doc
parent13b917a585c214c49cfb757fa4d5d6203e00159c (diff)
downloadlinux-327e93cf9a59b0d04eb3a31a7fdbf0f11cf13ecb.tar.xz
clocksource/drivers/timer-mediatek: Implement CPUXGPT timers
Some MediaTek platforms with a buggy TrustZone ATF firmware will not initialize the AArch64 System Timer correctly: in these cases, the System Timer address is correctly programmed, as well as the CNTFRQ_EL0 register (reading 13MHz, as it should be), but the assigned hardware timers are never started before (or after) booting Linux. In this condition, any call to function get_cycles() will be returning zero, as CNTVCT_EL0 will always read zero. One common critical symptom of that is trying to use the udelay() function (calling __delay()), which executes the following loop: start = get_cycles(); while ((get_cycles() - start) < cycles) cpu_relax(); which, when CNTVCT_EL0 always reads zero, translates to: while((0 - 0) < 0) ==> while(0 < 0) ... generating an infinite loop, even though zero is never less than zero, but always equal to it (this has to be researched, but it's out of the scope of this commit). To fix this issue on the affected MediaTek platforms, the solution is to simply start the timers that are designed to be System Timer(s). These timers, downstream, are called "CPUXGPT" and there is one timer per CPU core; luckily, it is not necessary to set a start bit on each CPUX General Purpose Timer, but it's conveniently enough to: - Set the clock divider (input = 26MHz, divider = 2, output = 13MHz); - Set the ENABLE bit on a global register (starts all CPUX timers). The only small hurdle with this setup is that it's all done through the MCUSYS wrapper, where it is needed, for each read or write, to select a register address (by writing it to an index register) and then to perform any R/W on a "CON" register. For example, writing "0x1" to the CPUXGPT register offset 0x4: - Write 0x4 to mcusys INDEX register - Write 0x1 to mcusys CON register Reading from CPUXGPT register offset 0x4: - Write 0x4 to mcusys INDEX register - Read mcusys CON register. Finally, starting this timer makes platforms affected by this issue to work correctly. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Matthias Brugger <matthias.bgg@gmail.com> Link: https://lore.kernel.org/r/20220613133819.35318-3-angelogioacchino.delregno@collabora.com Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Diffstat (limited to 'tools/testing/selftests/rcutorture/doc')
0 files changed, 0 insertions, 0 deletions