summaryrefslogtreecommitdiff
path: root/chip/max32660/clock_chip.c
diff options
context:
space:
mode:
authorJerry Bradshaw <jerry.bradshaw@maximintegrated.com>2019-06-06 08:52:13 -0500
committerCommit Bot <commit-bot@chromium.org>2019-07-17 21:27:38 +0000
commit21a255ea953e8ac64d05147ad7f11491db126cf4 (patch)
treec71d32772410dd7748b599619d8741b10d152b93 /chip/max32660/clock_chip.c
parent0e3dd9d2cc19b65654f8090aa02f8dac20358c2e (diff)
downloadchrome-ec-21a255ea953e8ac64d05147ad7f11491db126cf4.tar.gz
Basic implentation of the Maxim Integrated MAX32660 within the EC OS
Includes System Clock, Timer, Uart, Watchdog Change-Id: I195059c87d97e70c6a134304143613b86b623e22 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1647741 Reviewed-by: Jes Klinke <jbk@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Jerry Bradshaw <jerry.bradshaw@maximintegrated.com> Commit-Queue: Jes Klinke <jbk@chromium.org>
Diffstat (limited to 'chip/max32660/clock_chip.c')
-rw-r--r--chip/max32660/clock_chip.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/chip/max32660/clock_chip.c b/chip/max32660/clock_chip.c
new file mode 100644
index 0000000000..901c5d559c
--- /dev/null
+++ b/chip/max32660/clock_chip.c
@@ -0,0 +1,141 @@
+/* Copyright 2019 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.
+ */
+
+/* MAX32660 Clocks and Power Management Module for Chrome EC */
+
+#include "clock.h"
+#include "common.h"
+#include "console.h"
+#include "cpu.h"
+#include "hooks.h"
+#include "hwtimer.h"
+#include "registers.h"
+#include "system.h"
+#include "timer.h"
+#include "util.h"
+#include "watchdog.h"
+#include "tmr_regs.h"
+#include "gcr_regs.h"
+#include "pwrseq_regs.h"
+
+#define MAX32660_SYSTEMCLOCK SYS_CLOCK_HIRC
+
+/** Clock source */
+typedef enum {
+ SYS_CLOCK_NANORING = MXC_V_GCR_CLKCN_CLKSEL_NANORING, /**< 8KHz nanoring
+ on MAX32660 */
+ SYS_CLOCK_HFXIN =
+ MXC_V_GCR_CLKCN_CLKSEL_HFXIN, /**< 32KHz on MAX32660 */
+ SYS_CLOCK_HFXIN_DIGITAL = 0x9, /**< External Clock Input*/
+ SYS_CLOCK_HIRC = MXC_V_GCR_CLKCN_CLKSEL_HIRC, /**< High Frequency
+ Internal Oscillator */
+} sys_system_clock_t;
+
+/***** Functions ******/
+static void clock_wait_ready(uint32_t ready)
+{
+ // Start timeout, wait for ready
+ do {
+ if (MXC_GCR->clkcn & ready) {
+ return;
+ }
+ } while (1);
+}
+
+extern void (*const __isr_vector[])(void);
+uint32_t SystemCoreClock = HIRC96_FREQ;
+
+static void clock_update(void)
+{
+ uint32_t base_freq, divide, ovr;
+
+ // Get the clock source and frequency
+ ovr = (MXC_PWRSEQ->lp_ctrl & MXC_F_PWRSEQ_LP_CTRL_OVR);
+ if (ovr == MXC_S_PWRSEQ_LP_CTRL_OVR_0_9V) {
+ base_freq = HIRC96_FREQ / 4;
+ } else {
+ if (ovr == MXC_S_PWRSEQ_LP_CTRL_OVR_1_0V) {
+ base_freq = HIRC96_FREQ / 2;
+ } else {
+ base_freq = HIRC96_FREQ;
+ }
+ }
+
+ // Get the clock divider
+ divide = (MXC_GCR->clkcn & MXC_F_GCR_CLKCN_PSC) >>
+ MXC_F_GCR_CLKCN_PSC_POS;
+
+ SystemCoreClock = base_freq >> divide;
+}
+
+void clock_init(void)
+{
+ /* Switch system clock to HIRC */
+ uint32_t ovr, divide;
+
+ // Set FWS higher than what the minimum for the fastest clock is
+ MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x5UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+
+ // Enable 96MHz Clock
+ MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC_EN;
+
+ // Wait for the 96MHz clock
+ clock_wait_ready(MXC_F_GCR_CLKCN_HIRC_RDY);
+
+ // Set 96MHz clock as System Clock
+ MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL,
+ MXC_S_GCR_CLKCN_CLKSEL_HIRC);
+
+ // Wait for system clock to be ready
+ clock_wait_ready(MXC_F_GCR_CLKCN_CKRDY);
+
+ // Update the system core clock
+ clock_update();
+
+ // Get the clock divider
+ divide = (MXC_GCR->clkcn & MXC_F_GCR_CLKCN_PSC) >>
+ MXC_F_GCR_CLKCN_PSC_POS;
+
+ // get ovr setting
+ ovr = (MXC_PWRSEQ->lp_ctrl & MXC_F_PWRSEQ_LP_CTRL_OVR);
+
+ // Set flash wait settings
+ if (ovr == MXC_S_PWRSEQ_LP_CTRL_OVR_0_9V) {
+ if (divide == 0) {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x2UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ } else {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x1UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ }
+ } else if (ovr == MXC_S_PWRSEQ_LP_CTRL_OVR_1_0V) {
+ if (divide == 0) {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x2UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ } else {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x1UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ }
+ } else {
+ if (divide == 0) {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x4UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ } else if (divide == 1) {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x2UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ } else {
+ MXC_GCR->memckcn =
+ (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) |
+ (0x1UL << MXC_F_GCR_MEMCKCN_FWS_POS);
+ }
+ }
+}