Skip to content

Commit 81b9d53

Browse files
Magnus Dammhorms
authored andcommitted
ARM: shmobile: Setup r8a7790 arch timer based on MD pins
Update the r8a7790 arch timer setup code to configure the frequency dynamically at boot time. This means that the arch timer driver will be able to detect a timer frequency that has been calculated based on the MD pins instead of a fixed and potentially incorrect 13 MHz. With this patch applied the Linux kernel will correctly support the r8a7790 Lager board that uses a 20 Mhz EXTAL. The arch timer will operate on 10 MHz and the Linux arch timer driver will be correctly configured to use 10 MHz. Without this patch the 20 MHz EXTAL will be used to drive the arch timer at 10 MHz, but the Linux arch timer driver will believe it is counting at 13 Mhz. Reported-by: Ulrich Hecht <[email protected]> Signed-off-by: Magnus Damm <[email protected]> Tested-by: Ulrich Hecht <[email protected]> Signed-off-by: Simon Horman <[email protected]>
1 parent 512e53b commit 81b9d53

File tree

1 file changed

+45
-6
lines changed

1 file changed

+45
-6
lines changed

arch/arm/mach-shmobile/setup-r8a7790.c

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,53 @@ u32 __init r8a7790_read_mode_pins(void)
210210
return mode;
211211
}
212212

213+
#define CNTCR 0
214+
#define CNTFID0 0x20
215+
213216
void __init r8a7790_timer_init(void)
214217
{
215-
void __iomem *cntcr;
216-
217-
/* make sure arch timer is started by setting bit 0 of CNTCT */
218-
cntcr = ioremap(0xe6080000, PAGE_SIZE);
219-
iowrite32(1, cntcr);
220-
iounmap(cntcr);
218+
#ifdef CONFIG_ARM_ARCH_TIMER
219+
u32 mode = r8a7790_read_mode_pins();
220+
void __iomem *base;
221+
int extal_mhz = 0;
222+
u32 freq;
223+
224+
/* At Linux boot time the r8a7790 arch timer comes up
225+
* with the counter disabled. Moreover, it may also report
226+
* a potentially incorrect fixed 13 MHz frequency. To be
227+
* correct these registers need to be updated to use the
228+
* frequency EXTAL / 2 which can be determined by the MD pins.
229+
*/
230+
231+
switch (mode & (MD(14) | MD(13))) {
232+
case 0:
233+
extal_mhz = 15;
234+
break;
235+
case MD(13):
236+
extal_mhz = 20;
237+
break;
238+
case MD(14):
239+
extal_mhz = 26;
240+
break;
241+
case MD(13) | MD(14):
242+
extal_mhz = 30;
243+
break;
244+
}
245+
246+
/* The arch timer frequency equals EXTAL / 2 */
247+
freq = extal_mhz * (1000000 / 2);
248+
249+
/* Remap "armgcnt address map" space */
250+
base = ioremap(0xe6080000, PAGE_SIZE);
251+
252+
/* Update registers with correct frequency */
253+
iowrite32(freq, base + CNTFID0);
254+
asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
255+
256+
/* make sure arch timer is started by setting bit 0 of CNTCR */
257+
iowrite32(1, base + CNTCR);
258+
iounmap(base);
259+
#endif /* CONFIG_ARM_ARCH_TIMER */
221260

222261
shmobile_timer_init();
223262
}

0 commit comments

Comments
 (0)