Skip to content

Commit

Permalink
Merge pull request #224 from sifive/pll-lock-race
Browse files Browse the repository at this point in the history
Wait 100usec before testing FE310 PLL for lock
  • Loading branch information
nategraff-sifive authored Mar 9, 2020
2 parents da65264 + 3a896df commit 1504333
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
3 changes: 3 additions & 0 deletions metal/drivers/riscv_clint0.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ struct __metal_driver_riscv_clint0 {
};
#undef __METAL_MACHINE_MACROS

int __metal_driver_riscv_clint0_command_request(
struct metal_interrupt *controller, int command, void *data);

#endif
3 changes: 3 additions & 0 deletions metal/drivers/sifive_clic0.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,7 @@ struct __metal_driver_sifive_clic0 {
};
#undef __METAL_MACHINE_MACROS

int __metal_driver_sifive_clic0_command_request(
struct metal_interrupt *controller, int command, void *data);

#endif
38 changes: 38 additions & 0 deletions src/drivers/sifive_fe310-g000_pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <metal/init.h>
#include <metal/machine.h>
#include <metal/machine/platform.h>

#include <metal/drivers/sifive_fe310-g000_pll.h>
#include <stdlib.h>
Expand Down Expand Up @@ -270,6 +271,19 @@ static int find_closest_config(long ref_hz, long rate) {
return closest_index;
}

/* The PLL needs 100 usec to stabilize before we test PLL_LOCK. Since LFROSC
* on all targets with the FE310-G000 PLL runs at 32768 Hz, we need to wait
* at least
*
* ceil(100 usec * 32768 ticks/sec * 1 sec / 1000000 usec) = 4 ticks
*
* of mtime before we test PLL_LOCK.
*
* TODO: Determine the mtime timebase at compile or runtime and use that
* here.
*/
#define PLL_LOCK_WAIT_TICKS 4

/* Configure the PLL and wait for it to lock */
static void configure_pll(__metal_io_u32 *pllcfg, __metal_io_u32 *plloutdiv,
const struct pll_config_t *config) {
Expand Down Expand Up @@ -297,6 +311,30 @@ static void configure_pll(__metal_io_u32 *pllcfg, __metal_io_u32 *plloutdiv,

__METAL_ACCESS_ONCE(pllcfg) &= ~(PLL_BYPASS);

/* Wait for the PLL to stabilize before testing it for lock */
#ifdef __METAL_DT_RISCV_CLINT0_HANDLE
unsigned long long mtime, mtime_end;
__metal_driver_riscv_clint0_command_request(__METAL_DT_RISCV_CLINT0_HANDLE,
METAL_TIMER_MTIME_GET, &mtime);
mtime_end = mtime + PLL_LOCK_WAIT_TICKS;
while (mtime <= mtime_end) {
__metal_driver_riscv_clint0_command_request(
__METAL_DT_RISCV_CLINT0_HANDLE, METAL_TIMER_MTIME_GET, &mtime);
}
#elif __METAL_DT_RISCV_CLIC0_HANDLE
unsigned long long mtime, mtime_end;
__metal_driver_sifive_clic0_command_request(__METAL_DT_RISCV_CLIC0_HANDLE,
METAL_TIMER_MTIME_GET, &mtime);
mtime_end = mtime + PLL_LOCK_WAIT_TICKS;
while (mtime <= mtime_end) {
__metal_driver_sifive_clic0_command_request(
__METAL_DT_RISCV_CLIC0_HANDLE, METAL_TIMER_MTIME_GET, &mtime);
}
#else
#pragma message( \
No handle for CLINT or CLIC found, PLL might race with lock signal !)
#endif

/* Wait for PLL to lock */
while ((__METAL_ACCESS_ONCE(pllcfg) & PLL_LOCK) == 0)
;
Expand Down

0 comments on commit 1504333

Please sign in to comment.