From ea2a5a33ca880e4f5e3950350bf4dbb4187f51b8 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 27 Jul 2019 17:59:25 +0200 Subject: [PATCH] bcm64: fix wrong prescaler for generic timer on rpi4 the raspberry pi 4 uses 54 instead of 19.2 MHz crystal. detect which frequency is used by reading OTP bootmode register: https://www.raspberrypi.org/documentation/hardware/raspberrypi/otpbits.md Bit 1: sets the oscillator frequency to 19.2MHz --- sys/src/9/bcm64/clock.c | 13 +++++++++++-- sys/src/9/bcm64/sysreg.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sys/src/9/bcm64/clock.c b/sys/src/9/bcm64/clock.c index 71ffd91b5..f24fedb93 100644 --- a/sys/src/9/bcm64/clock.c +++ b/sys/src/9/bcm64/clock.c @@ -121,14 +121,23 @@ clockinit(void) syswr(CNTP_TVAL_EL0, ~0UL); if(m->machno == 0){ + int oscfreq; + syswr(CNTP_CTL_EL0, Imask); *(u32int*)(ARMLOCAL + GPUirqroute) = 0; - /* input clock is 19.2Mhz crystal */ + /* bit 1 from OTP bootmode register determines OSC frequency */ + if(*((u32int*)(VIRTIO+0x20f000)) & (1<<1)) + oscfreq = 19200000; + else + oscfreq = 54000000; + + /* input clock to OSC */ *(u32int*)(ARMLOCAL + Localctl) = 0; + /* divide by (2^31/Prescaler) */ - *(u32int*)(ARMLOCAL + Prescaler) = (((uvlong)SystimerFreq<<31)/19200000)&~1UL; + *(u32int*)(ARMLOCAL + Prescaler) = (((uvlong)SystimerFreq<<31)/oscfreq)&~1UL; } else { syswr(CNTP_CTL_EL0, Enable); intrenable(IRQcntpns, localclockintr, nil, BUSUNKNOWN, "clock"); diff --git a/sys/src/9/bcm64/sysreg.h b/sys/src/9/bcm64/sysreg.h index c5d8ac152..c057bbba8 100644 --- a/sys/src/9/bcm64/sysreg.h +++ b/sys/src/9/bcm64/sysreg.h @@ -31,6 +31,7 @@ #define PMCCNTR_EL0 SYSREG(3,3,9,13,0) #define PMUSERENR_EL0 SYSREG(3,3,9,14,0) +#define CNTPCT_EL0 SYSREG(3,3,14,0,1) #define CNTP_TVAL_EL0 SYSREG(3,3,14,2,0) #define CNTP_CTL_EL0 SYSREG(3,3,14,2,1) #define CNTP_CVAL_EL0 SYSREG(3,3,14,2,2)