From f82540008afd57475c1be865c68ff668a5e09b80 Mon Sep 17 00:00:00 2001 From: Raptor Engineering Development Team Date: Sat, 20 Aug 2022 19:22:29 -0500 Subject: [PATCH] Port bare metal Arctic Tern LPC clock setup to Zephyr firmware --- kestrel/src/aquila.h | 7 ++++++- kestrel/src/kestrel.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/kestrel/src/aquila.h b/kestrel/src/aquila.h index b089d3f..6519f8d 100644 --- a/kestrel/src/aquila.h +++ b/kestrel/src/aquila.h @@ -1,4 +1,4 @@ -// © 2020 Raptor Engineering, LLC +// © 2020-2022 Raptor Engineering, LLC // // Released under the terms of the GPL v3 // See the LICENSE file for full details @@ -141,6 +141,11 @@ #define AQUILA_LPC_VUART_WFIFO_FULL_MASK 0x1 #define AQUILA_LPC_VUART_WFIFO_FULL_SHIFT 24 +#define AQUILA_LPC_CLOCK_VALID_MASK 0x1 +#define AQUILA_LPC_CLOCK_VALID_SHIFT 24 +#define AQUILA_LPC_CLK_PLL_RESET_MASK 0x1 +#define AQUILA_LPC_CLK_PLL_RESET_SHIFT 31 + #define AQUILA_EV_MASTER_IRQ 0x1 static inline uint32_t read_aquila_register(unsigned long base_address, uint8_t reg) diff --git a/kestrel/src/kestrel.c b/kestrel/src/kestrel.c index 1efb6a0..f1e5732 100644 --- a/kestrel/src/kestrel.c +++ b/kestrel/src/kestrel.c @@ -2319,6 +2319,7 @@ int power_on_chassis(int has_lock) int cpu_count = 1; int i2c_read_retcode; uint8_t byte; + uint32_t dword; if (!has_lock) { if (k_sem_take(&chassis_control_semaphore, K_MSEC(10)) != 0) { @@ -2426,6 +2427,36 @@ int power_on_chassis(int has_lock) return -5; } + // Force the LPC clock PLL into reset, if present + // If no PLL is present, this operation does nothing + dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1); + dword |= (AQUILA_LPC_CLK_PLL_RESET_MASK << AQUILA_LPC_CLK_PLL_RESET_SHIFT); + write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1, dword); + + // Enable LPC clock buffer + gpio1_out_write(gpio1_out_read() | (0x01 << 12)); + + // Wait a few ms for the external clock buffer to stabilize + k_usleep(16 * 1000); + + // Bring the LPC PLL back out of reset, if present + // If no PLL is present, this operation does nothing + dword = read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1); + dword &= ~(AQUILA_LPC_CLK_PLL_RESET_MASK << AQUILA_LPC_CLK_PLL_RESET_SHIFT); + write_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_CONTROL1, dword); + + // Wait for LPC clock to stabilize + uint64_t clock_valid_timer = k_uptime_get(); + do + { + if ((k_uptime_get() - clock_valid_timer) > 1000) + { + printf("LPC clock did not come online, aborting!\n"); + power_off_chassis(1); + return -6; + } + } while (!((read_aquila_register(HOSTLPCSLAVE_BASE, AQUILA_LPC_REG_STATUS4) >> AQUILA_LPC_CLOCK_VALID_SHIFT) & AQUILA_LPC_CLOCK_VALID_MASK)); + host_power_status = HOST_POWER_STATUS_IPLING; host_power_status_changed(); display_character('0' + 2 + host_power_status, 0); // STATUS CODE -- 2.30.2