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.

clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled

The Renesas Compare Match Timer 0 and 1 (CMT0/1) variants have a
register to control the clock supply to the individual channels.
Currently the driver does not touch this register, and relies on the
documented initial value, which has the clock supply enabled for all
channels present.

However, when Linux starts on the APE6-EVM development board, only the
clock supply to the first CMT1 channel is enabled. Hence the first
channel (used as a clockevent) works, while the second channel (used as
a clocksource) does not. Note that the default system clocksource is
the Cortex-A15 architectured timer, and the user needs to manually
switch to the CMT1 clocksource to trigger the broken behavior.

Fix this by removing the fragile dependency on implicit reset and/or
boot loader state, and by enabling the clock supply explicitly for all
channels used instead. This requires postponing the clk_disable() call,
else the timer's registers cannot be accessed in sh_cmt_setup_channel().

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20201210194648.2901899-1-geert+renesas@glider.be

authored by

Geert Uytterhoeven and committed by
Daniel Lezcano
2a97d553 7a3b8758

+13 -3
+13 -3
drivers/clocksource/sh_cmt.c
··· 235 235 #define CMCNT 1 /* channel register */ 236 236 #define CMCOR 2 /* channel register */ 237 237 238 + #define CMCLKE 0x1000 /* CLK Enable Register (R-Car Gen2) */ 239 + 238 240 static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch) 239 241 { 240 242 if (ch->iostart) ··· 855 853 unsigned int hwidx, bool clockevent, 856 854 bool clocksource, struct sh_cmt_device *cmt) 857 855 { 856 + u32 value; 858 857 int ret; 859 858 860 859 /* Skip unused channels. */ ··· 885 882 ch->iostart = cmt->mapbase + ch->hwidx * 0x100; 886 883 ch->ioctrl = ch->iostart + 0x10; 887 884 ch->timer_bit = 0; 885 + 886 + /* Enable the clock supply to the channel */ 887 + value = ioread32(cmt->mapbase + CMCLKE); 888 + value |= BIT(hwidx); 889 + iowrite32(value, cmt->mapbase + CMCLKE); 888 890 break; 889 891 } 890 892 ··· 1022 1014 else 1023 1015 cmt->rate = clk_get_rate(cmt->clk) / 8; 1024 1016 1025 - clk_disable(cmt->clk); 1026 - 1027 1017 /* Map the memory resource(s). */ 1028 1018 ret = sh_cmt_map_memory(cmt); 1029 1019 if (ret < 0) 1030 - goto err_clk_unprepare; 1020 + goto err_clk_disable; 1031 1021 1032 1022 /* Allocate and setup the channels. */ 1033 1023 cmt->num_channels = hweight8(cmt->hw_channels); ··· 1053 1047 mask &= ~(1 << hwidx); 1054 1048 } 1055 1049 1050 + clk_disable(cmt->clk); 1051 + 1056 1052 platform_set_drvdata(pdev, cmt); 1057 1053 1058 1054 return 0; ··· 1062 1054 err_unmap: 1063 1055 kfree(cmt->channels); 1064 1056 iounmap(cmt->mapbase); 1057 + err_clk_disable: 1058 + clk_disable(cmt->clk); 1065 1059 err_clk_unprepare: 1066 1060 clk_unprepare(cmt->clk); 1067 1061 err_clk_put: