summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorYilun Lin <yllin@chromium.org>2019-04-25 07:16:21 +0000
committerchrome-bot <chrome-bot@chromium.org>2019-04-26 09:09:10 -0700
commitbd4273f88da59e8beecaee8e891f1a558e513fbf (patch)
tree30013dfc7418b9be967134db46785eb6a0d6ad9a /chip
parent5c87411b3a573eb8d9d6f3b63e099e7ab44cbd5b (diff)
downloadchrome-ec-bd4273f88da59e8beecaee8e891f1a558e513fbf.tar.gz
Revert "kukui: scp: calibrate ULPOSC1&2"
This reverts commit e08a71fd05bfc9e32dd64b7e15840e7232d72788. Reason for revert: SCP will hang with this CL. Original change's description: > kukui: scp: calibrate ULPOSC1&2 > > ULPOSC generates clock for SCP core and peripherals. The calibration > process adjust 2 values, div and cali. Both values are positive > correlated to OSC frequency. The frequency function is: > f(div, cali) = k1 * (div + k2) / R(cali) * C > Where: > R(cali) = k3 / (1 + k4 * (cali - k4)) > > The actual frequency is not linear to cali parameter. This change > selects the div that generates closest frequency when cali == 32. And > then adjust cali to get better output. > > BRANCH=none > BUG=b:120176040,b:120169529 > TEST=manual > check SCP console command: > > ulposc > ULPOSC1 frequency: 248 MHz > ULPOSC2 frequency: 330 MHz > > Change-Id: Ifac9d481e654064ee60d84819added5e164ed7c2 > Signed-off-by: Rong Chang <rongchang@chromium.org> > Reviewed-on: https://chromium-review.googlesource.com/1520571 > Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Bug: b:120176040, b:120169529, b:131273034 Change-Id: Ifaeb9a7835a35556587fac4c039b9fde6d66504d Reviewed-on: https://chromium-review.googlesource.com/1583481 Commit-Ready: Yilun Lin <yllin@chromium.org> Tested-by: Yilun Lin <yllin@chromium.org> Reviewed-by: Yilun Lin <yllin@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/mt_scp/clock.c247
-rw-r--r--chip/mt_scp/registers.h2
2 files changed, 66 insertions, 183 deletions
diff --git a/chip/mt_scp/clock.c b/chip/mt_scp/clock.c
index 218ff1e9db..c58c4671a1 100644
--- a/chip/mt_scp/clock.c
+++ b/chip/mt_scp/clock.c
@@ -6,7 +6,6 @@
/* Clocks, PLL and power settings */
#include "clock.h"
-#include "clock_chip.h"
#include "common.h"
#include "console.h"
#include "registers.h"
@@ -14,19 +13,6 @@
#include "timer.h"
#include "util.h"
-#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args)
-
-/* Default ULPOSC clock speed in Hz */
-#ifndef ULPOSC1_CLOCK_HZ
-#define ULPOSC1_CLOCK_HZ 250000000
-#endif
-#ifndef ULPOSC2_CLOCK_HZ
-#define ULPOSC2_CLOCK_HZ 330000000
-#endif
-
-#define ULPOSC_DIV_MAX (1 << OSC_DIV_BITS)
-#define ULPOSC_CALI_MAX (1 << OSC_CALI_BITS)
-
void clock_init(void)
{
/* Set VREQ to HW mode */
@@ -77,20 +63,33 @@ void clock_init(void)
task_enable_irq(SCP_IRQ_CLOCK2);
}
-static void scp_ulposc_config(int osc, uint32_t osc_div, uint32_t osc_cali)
+/* TODO(b/120176040): add ULPOSC calibration */
+static const struct {
+ uint8_t div;
+ uint8_t cali;
+} ulposc_config[] = {
+ /* Default config */
+ { .div = 12, .cali = 32},
+ { .div = 16, .cali = 32},
+};
+
+static void scp_ulposc_config(int osc)
{
uint32_t val;
+ if (osc != 0 && osc != 1)
+ return;
+
/* Clear all bits */
val = 0;
/* Enable CP */
val |= OSC_CP_EN;
/* Set div */
- val |= osc_div << 17;
+ val |= ulposc_config[osc].div << 17;
/* F-band = 0, I-band = 4 */
val |= 4 << 6;
/* Set calibration */
- val |= osc_cali;
+ val |= ulposc_config[osc].cali;
/* Set control register 1 */
AP_ULPOSC_CON02(osc) = val;
/* Set control register 2, enable div2 */
@@ -110,153 +109,7 @@ static inline void busy_udelay(int usec)
;
}
-static unsigned int scp_measure_ulposc_freq(int osc)
-{
- unsigned int result = 0;
-
- /* Before select meter clock input, bit[1:0] = b00 */
- AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) |
- DBG_MODE_SET_CLOCK;
-
- /* Select source, bit[21:16] = clk_src */
- AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) |
- (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 :
- DBG_BIST_SOURCE_ULPOSC2);
-
- /* Set meter divisor to 1, bit[31:24] = b00000000 */
- AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) |
- MISC_METER_DIV_1;
-
- /* Enable frequency meter, without start */
- AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE;
-
- /* Trigger frequency meter start */
- AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN;
-
- /*
- * Frequency meter counts cycles in 1 / (26 * 1000) second period.
- * freq_in_hz = freq_counter * 26 * 1000
- *
- * The hardware takes 38us to count cycles. Delay 50us then check
- * METER_RUN flag.
- */
- udelay(50);
- if (!(AP_SCP_CFG_0 & CFG_FREQ_METER_RUN))
- result = CFG_FREQ_COUNTER(AP_SCP_CFG_1);
-
- /* Disable freq meter */
- AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE;
- return result;
-}
-
-static inline int signum(int v)
-{
- return (v > 0) - (v < 0);
-}
-
-static inline int abs(int v)
-{
- return (v >= 0) ? v : -v;
-}
-
-static int scp_ulposc_config_measure(int osc, int div, int cali)
-{
- int freq;
-
- scp_ulposc_config(osc, div, cali);
- freq = scp_measure_ulposc_freq(osc);
- CPRINTF("ULPOSC%d: %d %d %d (%dMHz)\n",
- osc + 1, div, cali, freq,
- freq * 26 / 1000);
-
- return freq;
-}
-
-/**
- * Calibrate ULPOSC to target frequency.
- *
- * @param osc 0:ULPOSC1, 1:ULPOSC2
- * @param target_hz Target frequency to set
- * @return Frequency counter output
- *
- */
-static int scp_calibrate_ulposc(int osc, int target_hz)
-{
- int target_freq = target_hz / (26 * 1000);
- struct ulposc {
- int div; /* frequency divisor/multiplier */
- int cali; /* variable resistor calibrator */
- int freq; /* frequency counter measure result */
- int inc; /* next div or cali param diff */
- } curr, prev = {0};
-
- curr.div = ULPOSC_DIV_MAX / 2;
- curr.cali = ULPOSC_CALI_MAX / 2;
-
- /*
- * In the loop below, linear search closest div value to get desired
- * frequency counter value. Then adjust cali to get a better result.
- * Note that this doesn't give optimal output frequency. The search
- * starts on cali==CALI_MAX/2 line to find best div value, then linear
- * search cali value with a fixed div. The output result is usually
- * good enough for core clock.
- */
- while (1) {
- curr.freq = scp_ulposc_config_measure(osc, curr.div, curr.cali);
-
- if (!curr.freq)
- return 0;
- if (curr.freq == target_freq)
- return curr.freq;
-
- /* Linear search is enough for both div and cali params */
- curr.inc = signum(target_freq - curr.freq);
-
- /* Search div value */
- if (prev.div != curr.div) {
- if (!prev.freq) {
- prev = curr;
- if (target_freq > curr.freq) {
- curr.div++;
- curr.inc = prev.inc = 1;
- } else {
- curr.div--;
- curr.inc = prev.inc = -1;
- }
- continue;
- }
- if (curr.inc == prev.inc) {
- prev = curr;
- curr.div += curr.inc;
- if (curr.div < 0 || curr.div >= ULPOSC_DIV_MAX)
- return 0;
- } else {
- prev = curr;
- curr.cali += curr.inc;
- }
- continue;
- }
-
- /* Search cali value */
- if (curr.inc == prev.inc) {
- prev = curr;
- curr.cali += curr.inc;
- if (curr.cali < 0 || curr.cali >= ULPOSC_CALI_MAX)
- return 0;
- continue;
- }
-
- if (abs(target_freq - curr.freq) >
- abs(target_freq - prev.freq)) {
- scp_ulposc_config_measure(osc, prev.div, prev.cali);
- return prev.freq;
- }
- }
-
- return 0;
-}
-
-static void scp_clock_high_enable(int osc)
+void scp_clock_high_enable(int osc)
{
/* Enable high speed clock */
SCP_CLK_EN |= EN_CLK_HIGH;
@@ -303,15 +156,11 @@ void scp_enable_clock(void)
/* Turn off ULPOSC2 */
SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB;
- scp_ulposc_config(0, ULPOSC_DIV_MAX / 2, ULPOSC_CALI_MAX / 2);
+ scp_ulposc_config(0);
scp_clock_high_enable(0); /* Turn on ULPOSC1 */
- scp_ulposc_config(1, ULPOSC_DIV_MAX / 2, ULPOSC_CALI_MAX / 2);
+ scp_ulposc_config(1);
scp_clock_high_enable(1); /* Turn on ULPOSC2 */
- /* Calibrate ULPOSC */
- scp_calibrate_ulposc(0, ULPOSC1_CLOCK_HZ);
- scp_calibrate_ulposc(1, ULPOSC2_CLOCK_HZ);
-
/* Select ULPOSC2 high speed CPU clock */
SCP_CLK_SEL = CLK_SEL_ULPOSC_2;
@@ -320,6 +169,49 @@ void scp_enable_clock(void)
CG_I2C_M | CG_MAD_M;
}
+unsigned int clock_measure_ulposc_freq(int osc)
+{
+ timestamp_t deadline;
+ unsigned int result = 0;
+
+ if (osc != 0 && osc != 1)
+ return result;
+
+ /* Before select meter clock input, bit[1:0] = b00 */
+ AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_MODE_MASK) |
+ DBG_MODE_SET_CLOCK;
+
+ /* Select source, bit[21:16] = clk_src */
+ AP_CLK_DBG_CFG = (AP_CLK_DBG_CFG & ~DBG_BIST_SOURCE_MASK) |
+ (osc == 0 ? DBG_BIST_SOURCE_ULPOSC1 :
+ DBG_BIST_SOURCE_ULPOSC2);
+
+ /* Set meter divisor to 1, bit[31:24] = b00000000 */
+ AP_CLK_MISC_CFG_0 = (AP_CLK_MISC_CFG_0 & ~MISC_METER_DIVISOR_MASK) |
+ MISC_METER_DIV_1;
+
+ /* Enable frequency meter, without start */
+ AP_SCP_CFG_0 |= CFG_FREQ_METER_ENABLE;
+
+ /* Trigger frequency meter start */
+ AP_SCP_CFG_0 |= CFG_FREQ_METER_RUN;
+
+ deadline.val = get_time().val + 400 * MSEC;
+ while (AP_SCP_CFG_0 & CFG_FREQ_METER_RUN) {
+ if (timestamp_expired(deadline, NULL))
+ goto exit;
+ msleep(1);
+ }
+
+ /* Get result */
+ result = CFG_FREQ_COUNTER(AP_SCP_CFG_1);
+
+exit:
+ /* Disable freq meter */
+ AP_SCP_CFG_0 &= ~CFG_FREQ_METER_ENABLE;
+ return result;
+}
+
void clock_control_irq(void)
{
/* Read ack CLK_IRQ */
@@ -339,19 +231,12 @@ DECLARE_IRQ(SCP_IRQ_CLOCK2, clock_fast_wakeup_irq, 3);
/* Console command */
int command_ulposc(int argc, char *argv[])
{
- if (argc > 1 && !strncmp(argv[1], "cal", 3)) {
- scp_calibrate_ulposc(0, ULPOSC1_CLOCK_HZ);
- scp_calibrate_ulposc(1, ULPOSC2_CLOCK_HZ);
- }
-
- /* SCP clock meter counts every (26MHz / 1000) tick */
+ /* SCP clock meter counts every (26MHz / 1024) tick */
ccprintf("ULPOSC1 frequency: %u MHz\n",
- scp_measure_ulposc_freq(0) * 26 / 1000);
+ clock_measure_ulposc_freq(0) * 26 / 1024);
ccprintf("ULPOSC2 frequency: %u MHz\n",
- scp_measure_ulposc_freq(1) * 26 / 1000);
+ clock_measure_ulposc_freq(1) * 26 / 1024);
return EC_SUCCESS;
}
-DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[calibrate]",
- "Calibrate ULPOSC frequency");
-
+DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, NULL, NULL);
diff --git a/chip/mt_scp/registers.h b/chip/mt_scp/registers.h
index 07db4df07c..e6bcbecac3 100644
--- a/chip/mt_scp/registers.h
+++ b/chip/mt_scp/registers.h
@@ -527,11 +527,9 @@
* bit24-31: reserved
*/
#define OSC_CALI_MSK (0x3f << 0)
-#define OSC_CALI_BITS 6
#define OSC_IBAND_MASK (0x7f << 6)
#define OSC_FBAND_MASK (0x0f << 13)
#define OSC_DIV_MASK (0x1f << 17)
-#define OSC_DIV_BITS 5
#define OSC_CP_EN BIT(23)
#define OSC_RESERVED_MASK (0xff << 24)
/* AP_ULPOSC_CON[1,3] */