summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTinghan Shen <tinghan.shen@mediatek.com>2021-06-04 05:48:06 +0800
committerCommit Bot <commit-bot@chromium.org>2021-07-13 07:26:25 +0000
commitd3cb154936240d90ec8c0e3f16483d06cce87ba5 (patch)
tree3a344726da7e94b3af67c89616b9340b282b5854
parent71683e5e404f4a8702410c5a1f46c5bd77bfbbcd (diff)
downloadchrome-ec-d3cb154936240d90ec8c0e3f16483d06cce87ba5.tar.gz
chip/mt_scp: support mt8195 clock
Supports mt8195 clock and move chip-specific clock registers from common to chip-specific. BRANCH=none BUG=b:189300514 TEST=make BOARD=asurada_scp && make BOARD=cherry_scp Change-Id: I8ef058f6314652050dead46e7f48d3420bbdd1d1 Signed-off-by: Roger Lu <roger.lu@mediatek.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2939167 Tested-by: tinghan shen <tinghan.shen@mediatek.com> Tested-by: Tzung-Bi Shih <tzungbi@chromium.org> Reviewed-by: Tzung-Bi Shih <tzungbi@chromium.org> Commit-Queue: Tzung-Bi Shih <tzungbi@chromium.org>
-rw-r--r--chip/mt_scp/mt8192/build.mk1
-rw-r--r--chip/mt_scp/mt8192/clock.c (renamed from chip/mt_scp/rv32i_common/clock.c)12
-rw-r--r--chip/mt_scp/mt8192/clock_regs.h85
-rw-r--r--chip/mt_scp/mt8195/build.mk1
-rw-r--r--chip/mt_scp/mt8195/clock.c432
-rw-r--r--chip/mt_scp/mt8195/clock_regs.h92
-rw-r--r--chip/mt_scp/rv32i_common/build.mk1
-rw-r--r--chip/mt_scp/rv32i_common/clock_chip.h23
-rw-r--r--chip/mt_scp/rv32i_common/registers.h73
9 files changed, 622 insertions, 98 deletions
diff --git a/chip/mt_scp/mt8192/build.mk b/chip/mt_scp/mt8192/build.mk
index 02ffdaeefe..5ca0f1033c 100644
--- a/chip/mt_scp/mt8192/build.mk
+++ b/chip/mt_scp/mt8192/build.mk
@@ -5,3 +5,4 @@
# Required chip modules
chip-y+=$(CHIP_VARIANT)/uart.o
+chip-y+=$(CHIP_VARIANT)/clock.o
diff --git a/chip/mt_scp/rv32i_common/clock.c b/chip/mt_scp/mt8192/clock.c
index a460d818c7..43f570fc62 100644
--- a/chip/mt_scp/rv32i_common/clock.c
+++ b/chip/mt_scp/mt8192/clock.c
@@ -1,4 +1,4 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -8,7 +8,6 @@
#include <assert.h>
#include <string.h>
-#include "clock_chip.h"
#include "clock.h"
#include "common.h"
#include "console.h"
@@ -21,6 +20,13 @@
#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args)
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args)
+enum scp_clock_source {
+ SCP_CLK_26M = CLK_SW_SEL_26M,
+ SCP_CLK_32K = CLK_SW_SEL_32K,
+ SCP_CLK_ULPOSC2 = CLK_SW_SEL_ULPOSC2,
+ SCP_CLK_ULPOSC1 = CLK_SW_SEL_ULPOSC1,
+};
+
static struct opp_ulposc_cfg {
uint32_t osc;
uint32_t div;
@@ -277,7 +283,7 @@ static void clock_calibrate_ulposc(struct opp_ulposc_cfg *opp)
#endif
}
-void clock_select_clock(enum scp_clock_source src)
+static void clock_select_clock(enum scp_clock_source src)
{
/*
* DIV2 divider takes precedence over clock selection to prevent
diff --git a/chip/mt_scp/mt8192/clock_regs.h b/chip/mt_scp/mt8192/clock_regs.h
new file mode 100644
index 0000000000..5928ca0473
--- /dev/null
+++ b/chip/mt_scp/mt8192/clock_regs.h
@@ -0,0 +1,85 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* SCP clock module registers */
+
+#ifndef __CROS_EC_CLOCK_REGS_H
+#define __CROS_EC_CLOCK_REGS_H
+
+/* clock source select */
+#define SCP_CLK_SW_SEL REG32(SCP_CLK_CTRL_BASE + 0x0000)
+#define CLK_SW_SEL_26M 0
+#define CLK_SW_SEL_32K 1
+#define CLK_SW_SEL_ULPOSC2 2
+#define CLK_SW_SEL_ULPOSC1 3
+#define SCP_CLK_ENABLE REG32(SCP_CLK_CTRL_BASE + 0x0004)
+#define CLK_HIGH_EN BIT(1) /* ULPOSC */
+#define CLK_HIGH_CG BIT(2)
+/* clock general control */
+#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_CTRL_BASE + 0x009C)
+#define VREQ_PMIC_WRAP_SEL (0x2)
+
+/* TOPCK clk */
+#define TOPCK_BASE AP_REG_BASE
+#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0140)
+#define MISC_METER_DIVISOR_MASK 0xff000000
+#define MISC_METER_DIV_1 0
+/* OSC meter */
+#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x017C)
+#define DBG_MODE_MASK 3
+#define DBG_MODE_SET_CLOCK 0
+#define DBG_BIST_SOURCE_MASK (0x3f << 16)
+#define DBG_BIST_SOURCE_ULPOSC1 (0x25 << 16)
+#define DBG_BIST_SOURCE_ULPOSC2 (0x24 << 16)
+#define AP_SCP_CFG_0 REG32(TOPCK_BASE + 0x0220)
+#define CFG_FREQ_METER_RUN BIT(4)
+#define CFG_FREQ_METER_ENABLE BIT(12)
+#define AP_SCP_CFG_1 REG32(TOPCK_BASE + 0x0224)
+#define CFG_FREQ_COUNTER(CFG1) ((CFG1) & 0xFFFF)
+/*
+ * ULPOSC
+ * osc: 0 for ULPOSC1, 1 for ULPOSC2.
+ */
+#define AP_ULPOSC_CON0_BASE (AP_REG_BASE + 0xC2B0)
+#define AP_ULPOSC_CON1_BASE (AP_REG_BASE + 0xC2B4)
+#define AP_ULPOSC_CON2_BASE (AP_REG_BASE + 0xC2B8)
+#define AP_ULPOSC_CON0(osc) \
+ REG32(AP_ULPOSC_CON0_BASE + (osc) * 0x10)
+#define AP_ULPOSC_CON1(osc) \
+ REG32(AP_ULPOSC_CON1_BASE + (osc) * 0x10)
+#define AP_ULPOSC_CON2(osc) \
+ REG32(AP_ULPOSC_CON2_BASE + (osc) * 0x10)
+/*
+ * AP_ULPOSC_CON0
+ * bit0-6: calibration
+ * bit7-13: iband
+ * bit14-17: fband
+ * bit18-23: div
+ * bit24: cp_en
+ * bit25-31: reserved
+ */
+#define OSC_CALI_MASK 0x7f
+#define OSC_IBAND_SHIFT 7
+#define OSC_FBAND_SHIFT 14
+#define OSC_DIV_SHIFT 18
+#define OSC_CP_EN BIT(24)
+/* AP_ULPOSC_CON1
+ * bit0-7: 32K calibration
+ * bit 8-15: rsv1
+ * bit 16-23: rsv2
+ * bit 24-25: mod
+ * bit26: div2_en
+ * bit27-31: reserved
+ */
+#define OSC_RSV1_SHIFT 8
+#define OSC_RSV2_SHIFT 16
+#define OSC_MOD_SHIFT 24
+#define OSC_DIV2_EN BIT(26)
+/* AP_ULPOSC_CON2
+ * bit0-7: bias
+ * bit8-31: reserved
+ */
+
+#endif /* __CROS_EC_CLOCK_REGS_H */
diff --git a/chip/mt_scp/mt8195/build.mk b/chip/mt_scp/mt8195/build.mk
index 02ffdaeefe..5ca0f1033c 100644
--- a/chip/mt_scp/mt8195/build.mk
+++ b/chip/mt_scp/mt8195/build.mk
@@ -5,3 +5,4 @@
# Required chip modules
chip-y+=$(CHIP_VARIANT)/uart.o
+chip-y+=$(CHIP_VARIANT)/clock.o
diff --git a/chip/mt_scp/mt8195/clock.c b/chip/mt_scp/mt8195/clock.c
new file mode 100644
index 0000000000..bf85af2254
--- /dev/null
+++ b/chip/mt_scp/mt8195/clock.c
@@ -0,0 +1,432 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Clocks, PLL and power settings */
+
+#include <assert.h>
+#include <string.h>
+
+#include "clock.h"
+#include "common.h"
+#include "console.h"
+#include "csr.h"
+#include "ec_commands.h"
+#include "power.h"
+#include "registers.h"
+#include "timer.h"
+
+#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ##args)
+#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ##args)
+
+enum scp_clock_source {
+ SCP_CLK_SYSTEM,
+ SCP_CLK_32K,
+ SCP_CLK_ULPOSC1,
+ SCP_CLK_ULPOSC2_LOW_SPEED,
+ SCP_CLK_ULPOSC2_HIGH_SPEED,
+};
+
+enum {
+ OPP_ULPOSC2_LOW_SPEED,
+ OPP_ULPOSC2_HIGH_SPEED,
+};
+
+static struct opp_ulposc_cfg {
+ uint32_t osc;
+ uint32_t div;
+ uint32_t fband;
+ uint32_t mod;
+ uint32_t cali;
+ uint32_t target_mhz;
+ uint32_t clk_div;
+} opp[] = {
+ [OPP_ULPOSC2_LOW_SPEED] = {
+ .osc = 1, .target_mhz = 326, .clk_div = CLK_DIV_SEL2, .div = 19,
+ .fband = 10, .mod = 0, .cali = 64, /* 326MHz / 2 = 163MHz */
+ },
+ [OPP_ULPOSC2_HIGH_SPEED] = {
+ .osc = 1, .target_mhz = 360, .clk_div = CLK_DIV_SEL1, .div = 21,
+ .fband = 10, .mod = 0, .cali = 64, /* 360MHz / 1 = 360MHz */
+ },
+};
+
+static inline void clock_busy_udelay(int usec)
+{
+ /*
+ * Delaying by busy-looping, for place that can't use udelay because of
+ * the clock not configured yet. The value 28 is chosen approximately
+ * from experiment.
+ *
+ * `volatile' in order to avoid compiler to optimize the function out
+ * (otherwise, the function will be eliminated).
+ */
+ volatile int i = usec * 28;
+
+ while (--i)
+ ;
+}
+
+static void clock_ulposc_config_default(struct opp_ulposc_cfg *opp)
+{
+ uint32_t val = 0;
+
+ /* set mod, div2_en = 0, cp_en = 0 */
+ val |= opp->mod << OSC_MOD_SHIFT;
+ /* set div */
+ val |= opp->div << OSC_DIV_SHIFT;
+ /* set F-band, I-band = 82 */
+ val |= (opp->fband << OSC_FBAND_SHIFT) | (82 << OSC_IBAND_SHIFT);
+ /* set calibration */
+ val |= opp->cali;
+ /* set control register 0 */
+ AP_ULPOSC_CON0(opp->osc) = val;
+
+ clock_busy_udelay(50);
+
+ /* bias = 65 */
+ val = 65 << OSC_BIAS_SHIFT;
+ /* rsv2 = 0, rsv1 = 41, cali_32k = 0 */
+ val |= 41 << OSC_RSV1_SHIFT;
+ /* set control register 1 */
+ AP_ULPOSC_CON1(opp->osc) = val;
+
+ /* set settle time */
+ SCP_CLK_HIGH_VAL =
+ (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | CLK_HIGH_VAL_VAL(2);
+}
+
+static void clock_ulposc_config_cali(struct opp_ulposc_cfg *opp,
+ uint32_t cali_val)
+{
+ uint32_t val;
+
+ val = AP_ULPOSC_CON0(opp->osc);
+ val &= ~OSC_CALI_MASK;
+ val |= cali_val;
+ AP_ULPOSC_CON0(opp->osc) = val;
+ opp->cali = cali_val;
+
+ clock_busy_udelay(50);
+}
+
+static uint32_t clock_ulposc_measure_freq(uint32_t osc)
+{
+ uint32_t result = 0;
+ int cnt;
+
+ /* Set ckgen_load_cnt: CLK26CALI_1[25:16] */
+ AP_CLK26CALI_1 = CFG_CKGEN_LOAD_CNT;
+
+ /* 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 monclk_ext2fqmtr_sel: AP_CLK_DBG_CFG[14:8] */
+ 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_CLK26CALI_0 |= CFG_FREQ_METER_ENABLE;
+
+ /* trigger frequency meter start */
+ AP_CLK26CALI_0 |= CFG_FREQ_METER_RUN;
+
+ clock_busy_udelay(45);
+
+ for (cnt = 10000; cnt > 0; --cnt) {
+ clock_busy_udelay(10);
+ if (!(AP_CLK26CALI_0 & CFG_FREQ_METER_RUN)) {
+ result = CFG_FREQ_COUNTER(AP_CLK26CALI_1);
+ break;
+ }
+ }
+
+ /* disable freq meter */
+ AP_CLK26CALI_0 &= ~CFG_FREQ_METER_ENABLE;
+
+ return result;
+}
+
+#define CAL_MIS_RATE 40
+static int clock_ulposc_is_calibrated(struct opp_ulposc_cfg *opp)
+{
+ uint32_t curr, target;
+
+ curr = clock_ulposc_measure_freq(opp->osc);
+ target = opp->target_mhz * 512 / 26;
+
+#ifdef DEBUG
+ CPRINTF("osc:%u, target=%uMHz, curr=%uMHz, cali:%u\n",
+ opp->osc, opp->target_mhz, (curr * 26) / 512, opp->cali);
+#endif
+
+ /* check if calibrated value is in the range of target value +- 4% */
+ if (curr > (target * (1000 - CAL_MIS_RATE) / 1000) &&
+ curr < (target * (1000 + CAL_MIS_RATE) / 1000))
+ return 1;
+ else
+ return 0;
+}
+
+static uint32_t clock_ulposc_process_cali(struct opp_ulposc_cfg *opp)
+{
+ uint32_t current_val = 0;
+ uint32_t target_val = opp->target_mhz * 512 / 26;
+ uint32_t middle, min = 0, max = OSC_CALI_MASK;
+ uint32_t diff_by_min, diff_by_max, cal_result;
+
+ do {
+ middle = (min + max) / 2;
+ if (middle == min)
+ break;
+
+ clock_ulposc_config_cali(opp, middle);
+ current_val = clock_ulposc_measure_freq(opp->osc);
+
+ if (current_val > target_val)
+ max = middle;
+ else
+ min = middle;
+ } while (min <= max);
+
+ clock_ulposc_config_cali(opp, min);
+ current_val = clock_ulposc_measure_freq(opp->osc);
+ if (current_val > target_val)
+ diff_by_min = current_val - target_val;
+ else
+ diff_by_min = target_val - current_val;
+
+ clock_ulposc_config_cali(opp, max);
+ current_val = clock_ulposc_measure_freq(opp->osc);
+ if (current_val > target_val)
+ diff_by_max = current_val - target_val;
+ else
+ diff_by_max = target_val - current_val;
+
+ if (diff_by_min < diff_by_max)
+ cal_result = min;
+ else
+ cal_result = max;
+
+ clock_ulposc_config_cali(opp, cal_result);
+ if (!clock_ulposc_is_calibrated(opp))
+ assert(0);
+
+ return cal_result;
+}
+
+static void clock_high_enable(int osc)
+{
+ /* enable high speed clock */
+ SCP_CLK_ENABLE |= CLK_HIGH_EN;
+
+ switch (osc) {
+ case 0:
+ /* after 150us, enable ULPOSC */
+ clock_busy_udelay(150);
+ SCP_CLK_ENABLE |= CLK_HIGH_CG | CLK_HIGH_EN;
+
+ /* topck ulposc1 clk gating off */
+ AP_CLK_CFG_29_CLR = PDN_F_ULPOSC_CK;
+ /* select topck ulposc1 as scp clk parent */
+ AP_CLK_CFG_29_CLR = ULPOSC1_CLK_SEL;
+
+ AP_CLK_CFG_UPDATE3 = F_ULPOSC_CK_UPDATE;
+ clock_busy_udelay(50);
+ break;
+ case 1:
+ /* turn off ULPOSC2 high-core-disable switch */
+ SCP_CLK_ON_CTRL &= ~HIGH_CORE_DIS_SUB;
+ /* after 150us, scp requests ULPOSC2 high core clock */
+ clock_busy_udelay(150);
+ SCP_CLK_HIGH_CORE_CG |= HIGH_CORE_CG;
+ SCP_CLK_ENABLE &= ~CLK_HIGH_CG;
+ clock_busy_udelay(50);
+
+ /* topck ulposc2 clk gating off */
+ AP_CLK_CFG_29_CLR = PDN_F_ULPOSC_CORE_CK;
+ /* select topck ulposc2 as scp clk parent */
+ AP_CLK_CFG_29_CLR = ULPOSC2_CLK_SEL;
+
+ AP_CLK_CFG_UPDATE3 = F_ULPOSC_CORE_CK_UPDATE;
+ clock_busy_udelay(50);
+ break;
+ default:
+ break;
+ }
+}
+
+static void clock_high_disable(int osc)
+{
+ switch (osc) {
+ case 0:
+ /* topck ulposc1 clk gating on */
+ AP_CLK_CFG_29_SET = PDN_F_ULPOSC_CK;
+ AP_CLK_CFG_UPDATE3 = F_ULPOSC_CK_UPDATE;
+ clock_busy_udelay(50);
+
+ /* scp doesn't request ulposc1 clk */
+ SCP_CLK_ENABLE &= ~CLK_HIGH_CG;
+ clock_busy_udelay(50);
+ SCP_CLK_ENABLE &= ~CLK_HIGH_EN;
+ clock_busy_udelay(50);
+ break;
+ case 1:
+ /* topck ulposc2 clk gating on */
+ AP_CLK_CFG_29_SET = PDN_F_ULPOSC_CORE_CK;
+ AP_CLK_CFG_UPDATE3 = F_ULPOSC_CORE_CK_UPDATE;
+ clock_busy_udelay(50);
+
+ /* scp doesn't request ulposc2 clk */
+ SCP_CLK_HIGH_CORE_CG &= ~HIGH_CORE_CG;
+ clock_busy_udelay(50);
+ SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB;
+ clock_busy_udelay(50);
+ break;
+ default:
+ break;
+ }
+}
+
+static void clock_calibrate_ulposc(struct opp_ulposc_cfg *opp)
+{
+ /*
+ * ULPOSC1(osc=0) is already
+ * - calibrated
+ * - enabled in coreboot
+ * - used by pmic wrapper
+ */
+ if (opp->osc != 0) {
+ clock_high_disable(opp->osc);
+ clock_ulposc_config_default(opp);
+ clock_high_enable(opp->osc);
+ }
+
+ /* Calibrate only if it is not accurate enough. */
+ if (!clock_ulposc_is_calibrated(opp))
+ opp->cali = clock_ulposc_process_cali(opp);
+}
+
+static void clock_select_clock(enum scp_clock_source src)
+{
+ uint32_t sel;
+ uint32_t div;
+
+ switch (src) {
+ case SCP_CLK_SYSTEM:
+ div = CLK_DIV_SEL1;
+ sel = CLK_SW_SEL_SYSTEM;
+ break;
+ case SCP_CLK_32K:
+ div = CLK_DIV_SEL1;
+ sel = CLK_SW_SEL_32K;
+ break;
+ case SCP_CLK_ULPOSC1:
+ div = CLK_DIV_SEL1;
+ sel = CLK_SW_SEL_ULPOSC1;
+ break;
+ case SCP_CLK_ULPOSC2_LOW_SPEED:
+ /* parking at scp system clk until ulposc clk is ready */
+ clock_select_clock(SCP_CLK_SYSTEM);
+
+ clock_ulposc_config_cali(&opp[OPP_ULPOSC2_LOW_SPEED],
+ opp[OPP_ULPOSC2_LOW_SPEED].cali);
+ div = opp[OPP_ULPOSC2_LOW_SPEED].clk_div;
+
+ sel = CLK_SW_SEL_ULPOSC2;
+ break;
+ case SCP_CLK_ULPOSC2_HIGH_SPEED:
+ /* parking at scp system clk until ulposc clk is ready */
+ clock_select_clock(SCP_CLK_SYSTEM);
+
+ clock_ulposc_config_cali(&opp[OPP_ULPOSC2_HIGH_SPEED],
+ opp[OPP_ULPOSC2_HIGH_SPEED].cali);
+ div = opp[OPP_ULPOSC2_HIGH_SPEED].clk_div;
+
+ sel = CLK_SW_SEL_ULPOSC2;
+ break;
+ default:
+ div = CLK_DIV_SEL1;
+ sel = CLK_SW_SEL_SYSTEM;
+ break;
+ }
+
+ SCP_CLK_DIV_SEL = div;
+ SCP_CLK_SW_SEL = sel;
+}
+
+__override void
+power_chipset_handle_host_sleep_event(enum host_sleep_event state,
+ struct host_sleep_event_context *ctx)
+{
+ if (state == HOST_SLEEP_EVENT_S3_SUSPEND) {
+ CPRINTS("AP suspend");
+ clock_select_clock(SCP_CLK_ULPOSC2_LOW_SPEED);
+ } else if (state == HOST_SLEEP_EVENT_S3_RESUME) {
+ CPRINTS("AP resume");
+ clock_select_clock(SCP_CLK_ULPOSC2_HIGH_SPEED);
+ }
+}
+
+void clock_init(void)
+{
+ uint32_t i;
+
+ /* select scp system clock (default 26MHz) */
+ clock_select_clock(SCP_CLK_SYSTEM);
+
+ /* set VREQ to HW mode */
+ SCP_CPU_VREQ_CTRL = VREQ_SEL | VREQ_DVFS_SEL;
+ SCP_CLK_CTRL_GENERAL_CTRL &= ~VREQ_PMIC_WRAP_SEL;
+ SCP_SEC_CTRL &= ~VREQ_SECURE_DIS;
+
+ /* set DDREN to auto mode */
+ SCP_SYS_CTRL |= AUTO_DDREN;
+
+ /* set settle time */
+ SCP_CLK_SYS_VAL =
+ (SCP_CLK_SYS_VAL & ~CLK_SYS_VAL_MASK) | CLK_SYS_VAL_VAL(1);
+ SCP_CLK_HIGH_VAL =
+ (SCP_CLK_HIGH_VAL & ~CLK_HIGH_VAL_MASK) | CLK_HIGH_VAL_VAL(1);
+ SCP_SLEEP_CTRL =
+ (SCP_SLEEP_CTRL & ~VREQ_COUNT_MASK) | VREQ_COUNT_VAL(1);
+
+ /* turn off ULPOSC2 */
+ SCP_CLK_ON_CTRL |= HIGH_CORE_DIS_SUB;
+
+ /* calibrate ULPOSC2 */
+ for (i = 0; i < ARRAY_SIZE(opp); ++i)
+ clock_calibrate_ulposc(&opp[i]);
+
+ /* select ULPOSC2 high speed SCP clock */
+ clock_select_clock(SCP_CLK_ULPOSC2_HIGH_SPEED);
+
+ /* select BCLK to use ULPOSC / 8 */
+ SCP_BCLK_CK_SEL = BCLK_CK_SEL_ULPOSC_DIV8;
+
+ /* enable default clock gate */
+ SCP_SET_CLK_CG |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 |
+ CG_I2C_MCLK | CG_MAD_MCLK | CG_AP2P_MCLK;
+}
+
+#ifdef DEBUG
+int command_ulposc(int argc, char *argv[])
+{
+ uint32_t osc;
+
+ for (osc = 0; osc <= OPP_ULPOSC2_HIGH_SPEED; ++osc)
+ ccprintf("ULPOSC%u frequency: %u kHz\n", osc + 1,
+ clock_ulposc_measure_freq(osc) * 26 * 1000 / 512);
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(ulposc, command_ulposc, "[ulposc]",
+ "Measure ULPOSC frequency");
+#endif
diff --git a/chip/mt_scp/mt8195/clock_regs.h b/chip/mt_scp/mt8195/clock_regs.h
new file mode 100644
index 0000000000..6e7ec6bdbb
--- /dev/null
+++ b/chip/mt_scp/mt8195/clock_regs.h
@@ -0,0 +1,92 @@
+/* Copyright 2021 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* SCP clock module registers */
+
+#ifndef __CROS_EC_CLOCK_REGS_H
+#define __CROS_EC_CLOCK_REGS_H
+
+/* clock source select */
+#define SCP_CLK_SW_SEL REG32(SCP_CLK_CTRL_BASE + 0x0000)
+#define CLK_SW_SEL_SYSTEM 0
+#define CLK_SW_SEL_32K 1
+#define CLK_SW_SEL_ULPOSC2 2
+#define CLK_SW_SEL_ULPOSC1 3
+#define SCP_CLK_ENABLE REG32(SCP_CLK_CTRL_BASE + 0x0004)
+#define CLK_HIGH_EN BIT(1) /* ULPOSC */
+#define CLK_HIGH_CG BIT(2)
+/* clock general control */
+#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_CTRL_BASE + 0x009C)
+#define VREQ_PMIC_WRAP_SEL (0x3)
+
+/* TOPCK clk */
+#define TOPCK_BASE AP_REG_BASE
+#define AP_CLK_CFG_UPDATE3 REG32(TOPCK_BASE + 0x0010)
+#define F_ULPOSC_CK_UPDATE BIT(21)
+#define F_ULPOSC_CORE_CK_UPDATE BIT(22)
+#define AP_CLK_CFG_29_SET REG32(TOPCK_BASE + 0x0180)
+#define AP_CLK_CFG_29_CLR REG32(TOPCK_BASE + 0x0184)
+#define ULPOSC1_CLK_SEL (0x3 << 8)
+#define PDN_F_ULPOSC_CK BIT(15)
+#define ULPOSC2_CLK_SEL (0x3 << 16)
+#define PDN_F_ULPOSC_CORE_CK BIT(23)
+/* OSC meter */
+#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x020C)
+#define DBG_MODE_MASK 3
+#define DBG_MODE_SET_CLOCK 0
+#define DBG_BIST_SOURCE_MASK (0x7f << 8)
+#define DBG_BIST_SOURCE_ULPOSC1 (0x30 << 8)
+#define DBG_BIST_SOURCE_ULPOSC2 (0x32 << 8)
+#define AP_CLK26CALI_0 REG32(TOPCK_BASE + 0x0218)
+#define CFG_FREQ_METER_RUN BIT(4)
+#define CFG_FREQ_METER_ENABLE BIT(7)
+#define AP_CLK26CALI_1 REG32(TOPCK_BASE + 0x021C)
+#define CFG_CKGEN_LOAD_CNT 0x01ff0000
+#define CFG_FREQ_COUNTER(CFG1) ((CFG1) & 0xFFFF)
+#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x022C)
+#define MISC_METER_DIVISOR_MASK 0xff000000
+#define MISC_METER_DIV_1 0
+/*
+ * ULPOSC
+ * osc: 0 for ULPOSC1, 1 for ULPOSC2.
+ */
+#define AP_ULPOSC_CON0_BASE (AP_REG_BASE + 0xC2B0)
+#define AP_ULPOSC_CON1_BASE (AP_REG_BASE + 0xC2B4)
+#define AP_ULPOSC_CON0(osc) \
+ REG32(AP_ULPOSC_CON0_BASE + (osc) * 0x10)
+#define AP_ULPOSC_CON1(osc) \
+ REG32(AP_ULPOSC_CON1_BASE + (osc) * 0x10)
+/*
+ * AP_ULPOSC_CON0
+ * bit0-6: calibration
+ * bit7-13: iband
+ * bit14-17: fband
+ * bit18-23: div
+ * bit24: cp_en
+ * bit25-26: mod
+ * bit27: div2_en
+ * bit28-31: reserved
+ */
+#define OSC_CALI_SHIFT 0
+#define OSC_CALI_MASK 0x7f
+#define OSC_IBAND_SHIFT 7
+#define OSC_FBAND_SHIFT 14
+#define OSC_DIV_SHIFT 18
+#define OSC_CP_EN BIT(24)
+#define OSC_MOD_SHIFT 25
+#define OSC_DIV2_EN BIT(27)
+/*
+ * AP_ULPOSC_CON1
+ * bit0-7: rsv1
+ * bit8-15: rsv2
+ * bit16-23: 32K calibration
+ * bit24-31: bias
+ */
+#define OSC_RSV1_SHIFT 0
+#define OSC_RSV2_SHIFT 8
+#define OSC_32KCALI_SHIFT 16
+#define OSC_BIAS_SHIFT 24
+
+#endif /* __CROS_EC_CLOCK_REGS_H */
diff --git a/chip/mt_scp/rv32i_common/build.mk b/chip/mt_scp/rv32i_common/build.mk
index 3c09548a8c..ac7e13db77 100644
--- a/chip/mt_scp/rv32i_common/build.mk
+++ b/chip/mt_scp/rv32i_common/build.mk
@@ -10,7 +10,6 @@ CORE:=riscv-rv32i
# Required chip modules
chip-y+=rv32i_common/cache.o
-chip-y+=rv32i_common/clock.o
chip-y+=rv32i_common/gpio.o
chip-y+=rv32i_common/intc.o
chip-y+=rv32i_common/memmap.o
diff --git a/chip/mt_scp/rv32i_common/clock_chip.h b/chip/mt_scp/rv32i_common/clock_chip.h
deleted file mode 100644
index ee1c22be92..0000000000
--- a/chip/mt_scp/rv32i_common/clock_chip.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright 2020 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* Clocks, PLL and power settings */
-
-#ifndef __CROS_EC_CLOCK_CHIP_H
-#define __CROS_EC_CLOCK_CHIP_H
-
-#include "registers.h"
-
-enum scp_clock_source {
- SCP_CLK_26M = CLK_SW_SEL_26M,
- SCP_CLK_32K = CLK_SW_SEL_32K,
- SCP_CLK_ULPOSC2 = CLK_SW_SEL_ULPOSC2,
- SCP_CLK_ULPOSC1 = CLK_SW_SEL_ULPOSC1,
-};
-
-/* Switches to use 'src' clock */
-void clock_select_clock(enum scp_clock_source src);
-
-#endif /* __CROS_EC_CLOCK_CHIP_H */
diff --git a/chip/mt_scp/rv32i_common/registers.h b/chip/mt_scp/rv32i_common/registers.h
index f4d03aa228..b19afe5e0d 100644
--- a/chip/mt_scp/rv32i_common/registers.h
+++ b/chip/mt_scp/rv32i_common/registers.h
@@ -17,15 +17,6 @@
/* clock control */
#define SCP_CLK_CTRL_BASE (SCP_REG_BASE + 0x21000)
-/* clock source select */
-#define SCP_CLK_SW_SEL REG32(SCP_CLK_CTRL_BASE + 0x0000)
-#define CLK_SW_SEL_26M 0
-#define CLK_SW_SEL_32K 1
-#define CLK_SW_SEL_ULPOSC2 2
-#define CLK_SW_SEL_ULPOSC1 3
-#define SCP_CLK_ENABLE REG32(SCP_CLK_CTRL_BASE + 0x0004)
-#define CLK_HIGH_EN BIT(1) /* ULPOSC */
-#define CLK_HIGH_CG BIT(2)
/* system clock counter value */
#define SCP_CLK_SYS_VAL REG32(SCP_CLK_CTRL_BASE + 0x0014)
#define CLK_SYS_VAL_MASK (0x3ff << 0)
@@ -117,9 +108,6 @@
#define HIGH_CORE_AO BIT(4)
#define HIGH_CORE_DIS_SUB BIT(5)
#define HIGH_CORE_CG_AO BIT(6)
-/* clock general control */
-#define SCP_CLK_CTRL_GENERAL_CTRL REG32(SCP_CLK_CTRL_BASE + 0x009C)
-#define VREQ_PMIC_WRAP_SEL (0x2)
/* system control */
#define SCP_SYS_CTRL REG32(SCP_REG_BASE + 0x24000)
@@ -212,22 +200,6 @@
/* external address: AP */
#define AP_REG_BASE 0x60000000 /* 0x10000000 remap to 0x6 */
-/* OSC meter */
-#define TOPCK_BASE AP_REG_BASE
-#define AP_CLK_MISC_CFG_0 REG32(TOPCK_BASE + 0x0140)
-#define MISC_METER_DIVISOR_MASK 0xff000000
-#define MISC_METER_DIV_1 0
-#define AP_CLK_DBG_CFG REG32(TOPCK_BASE + 0x017C)
-#define DBG_MODE_MASK 3
-#define DBG_MODE_SET_CLOCK 0
-#define DBG_BIST_SOURCE_MASK (0x3f << 16)
-#define DBG_BIST_SOURCE_ULPOSC1 (0x25 << 16)
-#define DBG_BIST_SOURCE_ULPOSC2 (0x24 << 16)
-#define AP_SCP_CFG_0 REG32(TOPCK_BASE + 0x0220)
-#define CFG_FREQ_METER_RUN BIT(4)
-#define CFG_FREQ_METER_ENABLE BIT(12)
-#define AP_SCP_CFG_1 REG32(TOPCK_BASE + 0x0224)
-#define CFG_FREQ_COUNTER(CFG1) ((CFG1) & 0xFFFF)
/* AP GPIO */
#define AP_GPIO_BASE (AP_REG_BASE + 0x5000)
#define AP_GPIO_MODE11_SET REG32(AP_GPIO_BASE + 0x03B4)
@@ -236,49 +208,8 @@
#define AP_GPIO_MODE12_CLR REG32(AP_GPIO_BASE + 0x03C8)
#define AP_GPIO_MODE20_SET REG32(AP_GPIO_BASE + 0x0444)
#define AP_GPIO_MODE20_CLR REG32(AP_GPIO_BASE + 0x0448)
-/*
- * ULPOSC
- * osc: 0 for ULPOSC1, 1 for ULPOSC2.
- */
-#define AP_ULPOSC_CON0_BASE (AP_REG_BASE + 0xC2B0)
-#define AP_ULPOSC_CON1_BASE (AP_REG_BASE + 0xC2B4)
-#define AP_ULPOSC_CON2_BASE (AP_REG_BASE + 0xC2B8)
-#define AP_ULPOSC_CON0(osc) \
- REG32(AP_ULPOSC_CON0_BASE + (osc) * 0x10)
-#define AP_ULPOSC_CON1(osc) \
- REG32(AP_ULPOSC_CON1_BASE + (osc) * 0x10)
-#define AP_ULPOSC_CON2(osc) \
- REG32(AP_ULPOSC_CON2_BASE + (osc) * 0x10)
-/*
- * AP_ULPOSC_CON0
- * bit0-6: calibration
- * bit7-13: iband
- * bit14-17: fband
- * bit18-23: div
- * bit24: cp_en
- * bit25-31: reserved
- */
-#define OSC_CALI_MASK 0x7f
-#define OSC_IBAND_SHIFT 7
-#define OSC_FBAND_SHIFT 14
-#define OSC_DIV_SHIFT 18
-#define OSC_CP_EN BIT(24)
-/* AP_ULPOSC_CON1
- * bit0-7: 32K calibration
- * bit 8-15: rsv1
- * bit 16-23: rsv2
- * bit 24-25: mod
- * bit26: div2_en
- * bit27-31: reserved
- */
-#define OSC_RSV1_SHIFT 8
-#define OSC_RSV2_SHIFT 16
-#define OSC_MOD_SHIFT 24
-#define OSC_DIV2_EN BIT(26)
-/* AP_ULPOSC_CON2
- * bit0-7: bias
- * bit8-31: reserved
- */
+
+#include "clock_regs.h"
/* IRQ numbers */
#define SCP_IRQ_GIPC_IN0 0