summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMegan Wachs <megan@sifive.com>2017-02-01 18:03:37 -0800
committerMegan Wachs <megan@sifive.com>2017-02-01 18:03:37 -0800
commitb003c52b0f5460c6e0e15cb29171164530490e08 (patch)
treea9749852b36fed0e66fa663dcea16972dc75f6c5
parent08a72bb956a25fd94d965fb4474f3ddcca1ed1e6 (diff)
PRCI: add control for the target CPU frequency (to allow a minimum, maximum, or closest match)
-rw-r--r--bsp/drivers/fe300prci/fe300prci_driver.c63
-rw-r--r--bsp/drivers/fe300prci/fe300prci_driver.h10
-rw-r--r--bsp/drivers/plic/plic_driver.h1
3 files changed, 61 insertions, 13 deletions
diff --git a/bsp/drivers/fe300prci/fe300prci_driver.c b/bsp/drivers/fe300prci/fe300prci_driver.c
index 9a16d5d..0e555a6 100644
--- a/bsp/drivers/fe300prci/fe300prci_driver.c
+++ b/bsp/drivers/fe300prci/fe300prci_driver.c
@@ -177,7 +177,7 @@ void PRCI_use_hfxosc(uint32_t finaldiv)
// this way.
// It returns the actual measured CPU frequency.
-uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu)
+uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target )
{
int hfrosctrim = 16;
@@ -186,23 +186,62 @@ uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu)
// Ignore the first run (for icache reasons)
uint32_t cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
+ int prev_trim = hfrosctrim;
+ int prev_freq = cpu_freq;
if (cpu_freq > F_CPU) {
- while((cpu_freq > F_CPU) && (hfrosctrim >= 0) ){
- PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, hfrosctrim );
- cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
- hfrosctrim--;
- }
+ while((cpu_freq > F_CPU) && (hfrosctrim > 0) ){
+ prev_freq = cpu_freq;
+ prev_trim = hfrosctrim;
+ hfrosctrim--;
+ PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, hfrosctrim );
+ cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
+ }
+
+ // Check for over/undershoot
+ switch(target) {
+ case(PRCI_FREQ_CLOSEST):
+ if ((prev_freq - F_CPU) < (F_CPU - cpu_freq) && target == PRCI_FREQ_CLOSEST) {
+ PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, prev_trim);
+ cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
+ }
+ break;
+ case(PRCI_FREQ_OVERSHOOT):
+ PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, prev_trim);
+ cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
+ break;
+ //default:
+ // Do Nothing
+ }
+
return cpu_freq;
}
-
- while(cpu_freq < F_CPU) {
- if (hfrosctrim >= 0x20) {
- break;
- }
+
+ while(cpu_freq < F_CPU && hfrosctrim < 0x20) {
+ prev_freq = cpu_freq;
+ prev_trim = hfrosctrim;
+ hfrosctrim ++;
PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, hfrosctrim );
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
- hfrosctrim++;
}
+
+
+ // Check for over/undershoot
+ switch(target) {
+ case(PRCI_FREQ_CLOSEST):
+ if ((F_CPU - prev_freq) < (cpu_freq - F_CPU)) {
+ PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, prev_trim);
+ cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
+ }
+ break;
+ case(PRCI_FREQ_UNDERSHOOT):
+ PRCI_use_pll(0, 0, 1, 31, 1, 1, 4, prev_trim);
+ cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
+ break;
+ //default:
+ // Do Nothing
+ }
+
return cpu_freq;
+
}
diff --git a/bsp/drivers/fe300prci/fe300prci_driver.h b/bsp/drivers/fe300prci/fe300prci_driver.h
index 75dcf00..243e6de 100644
--- a/bsp/drivers/fe300prci/fe300prci_driver.h
+++ b/bsp/drivers/fe300prci/fe300prci_driver.h
@@ -7,6 +7,14 @@ __BEGIN_DECLS
#include <unistd.h>
+typedef enum prci_freq_target {
+
+ PRCI_FREQ_OVERSHOOT,
+ PRCI_FREQ_CLOSEST,
+ PRCI_FREQ_UNDERSHOOT
+
+} PRCI_freq_target;
+
/* Measure and return the approximate frequency of the
* CPU, as given by measuring the mcycle counter against
* the mtime ticks.
@@ -55,7 +63,7 @@ void PRCI_use_default_clocks();
* achievable with this function, and not all
* are guaranteed to actually work.
*/
-uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu);
+uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target);
__END_DECLS
diff --git a/bsp/drivers/plic/plic_driver.h b/bsp/drivers/plic/plic_driver.h
index b14b442..e7d609b 100644
--- a/bsp/drivers/plic/plic_driver.h
+++ b/bsp/drivers/plic/plic_driver.h
@@ -3,6 +3,7 @@
#ifndef PLIC_DRIVER_H
#define PLIC_DRIVER_H
+
__BEGIN_DECLS
#include "platform.h"