summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorEric Yilun Lin <yllin@chromium.org>2020-01-03 14:17:43 +0800
committerCommit Bot <commit-bot@chromium.org>2020-01-07 06:14:34 +0000
commit628b59688aaa9e5b9b38264d42b66c57b9b889ee (patch)
treecec9906b6bbd469b12f85602602c626ed572228f /chip
parent32266fc1d08a7fdfb6dc018ae8b21f741d01325d (diff)
downloadchrome-ec-628b59688aaa9e5b9b38264d42b66c57b9b889ee.tar.gz
mt_scp/clock: Use ULPOSC1 when AP suspend
This CL does: 1. Move power_chipset_handle_host_sleep_event from board to chip folder 2. Uses ULPOSC1(240/2MHz) when AP suspend. When AP in suspend, Vcore decreases from 0.8V to 0.6V and thus it shouldn't use ULPOSC2 (330Mhz) which needs at least 0.7V to clock. ULPOSC1 only needs 0.6V to clock. TEST=run suspend/resume test for 2500 runs and ensure the SCP won't trigger watchdog. BUG=b:144820026 BRANCH=kukui Change-Id: I7b317a70b6ed93ff83e9543b2fc6cdfede112fd3 Signed-off-by: Eric Yilun Lin <yllin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1985728 Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Erin Lo <erin.lo@mediatek.corp-partner.google.com>
Diffstat (limited to 'chip')
-rw-r--r--chip/mt_scp/clock.c19
-rw-r--r--chip/mt_scp/clock_chip.h10
-rw-r--r--chip/mt_scp/ipi.c42
-rw-r--r--chip/mt_scp/registers.h4
4 files changed, 73 insertions, 2 deletions
diff --git a/chip/mt_scp/clock.c b/chip/mt_scp/clock.c
index e28106bcc3..a6f1883d31 100644
--- a/chip/mt_scp/clock.c
+++ b/chip/mt_scp/clock.c
@@ -276,10 +276,25 @@ static void scp_clock_high_enable(int osc)
}
}
+void scp_use_clock(enum scp_clock_source src)
+{
+ /*
+ * DIV2 divider takes precedence over clock selection to prevent
+ * over-clocking.
+ */
+ if (src == SCP_CLK_ULPOSC1)
+ SCP_CLK_DIV_SEL = CLK_DIV2;
+
+ SCP_CLK_SEL = src;
+
+ if (src != SCP_CLK_ULPOSC1)
+ SCP_CLK_DIV_SEL = CLK_DIV1;
+}
+
void scp_enable_clock(void)
{
/* Select default CPU clock */
- SCP_CLK_SEL = CLK_SEL_SYS_26M;
+ scp_use_clock(SCP_CLK_26M);
/* VREQ */
SCP_CPU_VREQ = 0x10001;
@@ -310,7 +325,7 @@ void scp_enable_clock(void)
scp_calibrate_ulposc(1, ULPOSC2_CLOCK_MHZ);
/* Select ULPOSC2 high speed CPU clock */
- SCP_CLK_SEL = CLK_SEL_ULPOSC_2;
+ scp_use_clock(SCP_CLK_ULPOSC2);
/* Enable default clock gate */
SCP_CLK_GATE |= CG_DMA_CH3 | CG_DMA_CH2 | CG_DMA_CH1 | CG_DMA_CH0 |
diff --git a/chip/mt_scp/clock_chip.h b/chip/mt_scp/clock_chip.h
index ab03d5c2f6..a16bf2e54e 100644
--- a/chip/mt_scp/clock_chip.h
+++ b/chip/mt_scp/clock_chip.h
@@ -21,4 +21,14 @@
void scp_enable_clock(void);
+enum scp_clock_source {
+ SCP_CLK_26M = CLK_SEL_SYS_26M,
+ SCP_CLK_32K = CLK_SEL_32K,
+ SCP_CLK_ULPOSC2 = CLK_SEL_ULPOSC_2,
+ SCP_CLK_ULPOSC1 = CLK_SEL_ULPOSC_1,
+};
+
+/* Switches to use 'src' clock */
+void scp_use_clock(enum scp_clock_source src);
+
#endif /* __CROS_EC_CLOCK_CHIP_H */
diff --git a/chip/mt_scp/ipi.c b/chip/mt_scp/ipi.c
index 222e117a79..f165031501 100644
--- a/chip/mt_scp/ipi.c
+++ b/chip/mt_scp/ipi.c
@@ -20,11 +20,13 @@
* Currently, we don't have IPC handlers for IPC1, IPC2, and IPC3.
*/
+#include "clock_chip.h"
#include "console.h"
#include "hooks.h"
#include "host_command.h"
#include "ipi_chip.h"
#include "mkbp_event.h"
+#include "power.h"
#include "system.h"
#include "task.h"
#include "util.h"
@@ -123,6 +125,39 @@ void ipi_enable_irq(int irq)
mutex_unlock(&ipc0_lock);
}
+__override void
+power_chipset_handle_host_sleep_event(enum host_sleep_event state,
+ struct host_sleep_event_context *ctx)
+{
+ int i;
+ const task_id_t s3_suspend_tasks[] = {
+#ifndef S3_SUSPEND_TASK_LIST
+#define S3_SUSPEND_TASK_LIST
+#endif
+#define TASK(n, ...) TASK_ID_##n,
+ S3_SUSPEND_TASK_LIST
+ };
+
+ if (state == HOST_SLEEP_EVENT_S3_SUSPEND) {
+ ccprints("AP suspend");
+ /*
+ * On AP suspend, Vcore is 0.6V, and we should not use ULPOSC2,
+ * which needs at least 0.7V. Switch to ULPOSC1 instead.
+ */
+ scp_use_clock(SCP_CLK_ULPOSC1);
+
+ for (i = 0; i < ARRAY_SIZE(s3_suspend_tasks); ++i)
+ task_disable_task(s3_suspend_tasks[i]);
+ } else if (state == HOST_SLEEP_EVENT_S3_RESUME) {
+ ccprints("AP resume");
+ /* Vcore is raised to >=0.7V, switch back to ULPSOC2 */
+ scp_use_clock(SCP_CLK_ULPOSC2);
+
+ for (i = 0; i < ARRAY_SIZE(s3_suspend_tasks); ++i)
+ task_enable_task(s3_suspend_tasks[i]);
+ }
+}
+
/* Send data from SCP to AP. */
int ipi_send(int32_t id, const void *buf, uint32_t len, int wait)
{
@@ -187,6 +222,13 @@ static void ipi_handler(void)
}
/*
+ * Only print IPI that is not host command channel, which will
+ * be printed by host command driver.
+ */
+ if (scp_recv_obj->id != IPI_HOST_COMMAND)
+ CPRINTS("IPI %d", scp_recv_obj->id);
+
+ /*
* Pass the buffer to handler. Each handler should be in charge of
* the buffer copying/reading before returning from handler.
*/
diff --git a/chip/mt_scp/registers.h b/chip/mt_scp/registers.h
index 6196a936e2..bce632c6b7 100644
--- a/chip/mt_scp/registers.h
+++ b/chip/mt_scp/registers.h
@@ -332,6 +332,10 @@
#define SPM_SLEEP_MODE BIT(8)
#define SPM_SLEEP_MODE_CLK_AO BIT(9)
#define SCP_CLK_DIV_SEL REG32(SCP_CLK_BASE + 0x24)
+#define CLK_DIV1 0
+#define CLK_DIV2 1
+#define CLK_DIV4 2
+#define CLK_DIV8 3
#define SCP_CLK_DEBUG REG32(SCP_CLK_BASE + 0x28)
#define SCP_CLK_SRAM_POWERDOWN REG32(SCP_CLK_BASE + 0x2C)
#define SCP_CLK_GATE REG32(SCP_CLK_BASE + 0x30)