448 lines
12 KiB
C
448 lines
12 KiB
C
|
/***************************************************************************
|
||
|
*
|
||
|
* Copyright 2015-2019 BES.
|
||
|
* All rights reserved. All unpublished rights reserved.
|
||
|
*
|
||
|
* No part of this work may be used or reproduced in any form or by any
|
||
|
* means, or stored in a database or retrieval system, without prior written
|
||
|
* permission of BES.
|
||
|
*
|
||
|
* Use of this work is governed by a license granted by BES.
|
||
|
* This work contains confidential and proprietary information of
|
||
|
* BES. which is protected by copyright, trade secret,
|
||
|
* trademark and other intellectual property rights.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
#include "plat_addr_map.h"
|
||
|
#include "hal_cmu.h"
|
||
|
#include CHIP_SPECIFIC_HDR(reg_cmu)
|
||
|
#ifdef AON_CMU_BASE
|
||
|
#include CHIP_SPECIFIC_HDR(reg_aoncmu)
|
||
|
#endif
|
||
|
#include "cmsis.h"
|
||
|
#include "hal_analogif.h"
|
||
|
#include "hal_bootmode.h"
|
||
|
#include "hal_cache.h"
|
||
|
#include "hal_chipid.h"
|
||
|
#include "hal_iomux.h"
|
||
|
#include "hal_location.h"
|
||
|
#include "hal_norflash.h"
|
||
|
#include "hal_sleep.h"
|
||
|
#include "hal_sysfreq.h"
|
||
|
#include "hal_timer.h"
|
||
|
#include "hal_trace.h"
|
||
|
|
||
|
#if defined(CHIP_HAS_USB) && (defined(MCU_HIGH_PERFORMANCE_MODE) && !(defined(ULTRA_LOW_POWER) || defined(OSC_26M_X4_AUD2BB)))
|
||
|
#define USB_PLL_INIT_ON
|
||
|
#endif
|
||
|
#if (!defined(ULTRA_LOW_POWER) && !defined(OSC_26M_X4_AUD2BB)) || \
|
||
|
(!defined(FLASH_LOW_SPEED) && !defined(OSC_26M_X4_AUD2BB)) || \
|
||
|
(defined(PSRAM_ENABLE) && !defined(PSRAM_LOW_SPEED))
|
||
|
#define AUD_PLL_INIT_ON
|
||
|
#endif
|
||
|
|
||
|
// SIMU_RES
|
||
|
#define CMU_SIMU_RES_PASSED (0x9A55)
|
||
|
#define CMU_SIMU_RES_FAILED (0xFA11)
|
||
|
|
||
|
typedef void (*HAL_POWER_DOWN_WAKEUP_HANDLER)(void);
|
||
|
|
||
|
static struct CMU_T * const cmu = (struct CMU_T *)CMU_BASE;
|
||
|
#ifdef AON_CMU_BASE
|
||
|
static struct AONCMU_T * const POSSIBLY_UNUSED aoncmu = (struct AONCMU_T *)AON_CMU_BASE;
|
||
|
#endif
|
||
|
|
||
|
#ifdef HAL_CMU_VALID_CRYSTAL_FREQ
|
||
|
static const uint32_t valid_crystal_freq_list[] = HAL_CMU_VALID_CRYSTAL_FREQ;
|
||
|
#define CRYSTAL_FREQ_ATTR BOOT_DATA_LOC
|
||
|
#else
|
||
|
#define CRYSTAL_FREQ_ATTR const
|
||
|
#endif
|
||
|
|
||
|
static uint32_t CRYSTAL_FREQ_ATTR crystal_freq = HAL_CMU_DEFAULT_CRYSTAL_FREQ;
|
||
|
|
||
|
void BOOT_TEXT_FLASH_LOC hal_cmu_set_crystal_freq_index(uint32_t index)
|
||
|
{
|
||
|
#ifdef HAL_CMU_VALID_CRYSTAL_FREQ
|
||
|
if (index >= ARRAY_SIZE(valid_crystal_freq_list)) {
|
||
|
index %= ARRAY_SIZE(valid_crystal_freq_list);
|
||
|
}
|
||
|
crystal_freq = valid_crystal_freq_list[index];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
uint32_t BOOT_TEXT_SRAM_LOC hal_cmu_get_crystal_freq(void)
|
||
|
{
|
||
|
return crystal_freq;
|
||
|
}
|
||
|
|
||
|
uint32_t BOOT_TEXT_FLASH_LOC hal_cmu_get_default_crystal_freq(void)
|
||
|
{
|
||
|
return HAL_CMU_DEFAULT_CRYSTAL_FREQ;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_write_lock(void)
|
||
|
{
|
||
|
cmu->WRITE_UNLOCK = 0xCAFE0000;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_write_unlock(void)
|
||
|
{
|
||
|
cmu->WRITE_UNLOCK = 0xCAFE0001;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_sys_reboot(void)
|
||
|
{
|
||
|
hal_cmu_reset_set(HAL_CMU_MOD_GLOBAL);
|
||
|
}
|
||
|
|
||
|
void hal_cmu_simu_init(void)
|
||
|
{
|
||
|
cmu->SIMU_RES = 0;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_simu_pass(void)
|
||
|
{
|
||
|
cmu->SIMU_RES = CMU_SIMU_RES_PASSED;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_simu_fail(void)
|
||
|
{
|
||
|
cmu->SIMU_RES = CMU_SIMU_RES_FAILED;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_simu_tag(uint8_t shift)
|
||
|
{
|
||
|
cmu->SIMU_RES |= (1 << shift);
|
||
|
}
|
||
|
|
||
|
void hal_cmu_simu_set_val(uint32_t val)
|
||
|
{
|
||
|
cmu->SIMU_RES = val;
|
||
|
}
|
||
|
|
||
|
uint32_t hal_cmu_simu_get_val(void)
|
||
|
{
|
||
|
return cmu->SIMU_RES;
|
||
|
}
|
||
|
|
||
|
void hal_cmu_set_wakeup_pc(uint32_t pc)
|
||
|
{
|
||
|
#ifdef RAMRET_BASE
|
||
|
uint32_t *wake_pc =
|
||
|
#ifdef CHIP_BEST2000
|
||
|
(uint32_t *)RAMRET_BASE;
|
||
|
#else
|
||
|
(uint32_t *)&aoncmu->WAKEUP_PC;
|
||
|
|
||
|
STATIC_ASSERT(sizeof(HAL_POWER_DOWN_WAKEUP_HANDLER) <= sizeof(uint32_t), "Invalid func ptr size");
|
||
|
#endif
|
||
|
|
||
|
*wake_pc = pc;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void hal_cmu_rom_wakeup_check(void)
|
||
|
{
|
||
|
#ifdef RAMRET_BASE
|
||
|
union HAL_HW_BOOTMODE_T hw;
|
||
|
uint32_t sw;
|
||
|
HAL_POWER_DOWN_WAKEUP_HANDLER *wake_fn =
|
||
|
#ifdef CHIP_BEST2000
|
||
|
(HAL_POWER_DOWN_WAKEUP_HANDLER *)RAMRET_BASE;
|
||
|
#else
|
||
|
(HAL_POWER_DOWN_WAKEUP_HANDLER *)&aoncmu->WAKEUP_PC;
|
||
|
#endif
|
||
|
|
||
|
hw = hal_rom_hw_bootmode_get();
|
||
|
if (hw.watchdog == 0 && hw.global == 0) {
|
||
|
sw = hal_sw_bootmode_get();
|
||
|
if ((sw & HAL_SW_BOOTMODE_POWER_DOWN_WAKEUP) && *wake_fn) {
|
||
|
(*wake_fn)();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*wake_fn = NULL;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifndef HAL_CMU_PLL_T
|
||
|
void hal_cmu_rom_enable_pll(void)
|
||
|
{
|
||
|
#ifdef CHIP_HAS_USB
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_USB, HAL_CMU_PLL_USER_SYS);
|
||
|
hal_cmu_sys_select_pll(HAL_CMU_PLL_USB);
|
||
|
hal_cmu_flash_select_pll(HAL_CMU_PLL_USB);
|
||
|
#else
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_SYS);
|
||
|
hal_cmu_sys_select_pll(HAL_CMU_PLL_AUD);
|
||
|
hal_cmu_flash_select_pll(HAL_CMU_PLL_AUD);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void hal_cmu_programmer_enable_pll(void)
|
||
|
{
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_SYS);
|
||
|
hal_cmu_flash_select_pll(HAL_CMU_PLL_AUD);
|
||
|
hal_cmu_sys_select_pll(HAL_CMU_PLL_AUD);
|
||
|
}
|
||
|
|
||
|
void BOOT_TEXT_FLASH_LOC hal_cmu_init_pll_selection(void)
|
||
|
{
|
||
|
// !!!!!!
|
||
|
// CAUTION:
|
||
|
// hal_cmu_pll_enable()/hal_cmu_pll_disable() must be called after hal_chipid_init(),
|
||
|
// for the init div values are extracted in hal_chipid_init().
|
||
|
// !!!!!!
|
||
|
|
||
|
#if defined(CHIP_BEST1000) || defined(CHIP_BEST2000)
|
||
|
#ifdef CHIP_HAS_USB
|
||
|
// Enable USB PLL before switching (clock mux requirement)
|
||
|
// -- USB PLL might not be started in ROM
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_USB, HAL_CMU_PLL_USER_SYS);
|
||
|
#endif
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_SYS);
|
||
|
#else // !(best1000 || best2000)
|
||
|
// Disable the PLL which might be enabled in ROM
|
||
|
#ifdef CHIP_HAS_USB
|
||
|
hal_cmu_pll_disable(HAL_CMU_PLL_USB, HAL_CMU_PLL_USER_ALL);
|
||
|
#else
|
||
|
hal_cmu_pll_disable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_ALL);
|
||
|
#endif
|
||
|
#endif // !(best1000 || best2000)
|
||
|
|
||
|
#ifdef FLASH_LOW_SPEED
|
||
|
#ifdef CHIP_HAS_USB
|
||
|
// Switch flash clock to USB PLL, and then shutdown USB PLL,
|
||
|
// to save power consumed in clock divider
|
||
|
hal_cmu_flash_select_pll(HAL_CMU_PLL_USB);
|
||
|
#endif
|
||
|
#else
|
||
|
// Switch flash clock to audio PLL
|
||
|
hal_cmu_flash_select_pll(HAL_CMU_PLL_AUD);
|
||
|
#endif
|
||
|
|
||
|
#ifdef CHIP_HAS_PSRAM
|
||
|
#ifdef PSRAM_LOW_SPEED
|
||
|
#ifdef CHIP_HAS_USB
|
||
|
// Switch psram clock to USB PLL, and then shutdown USB PLL,
|
||
|
// to save power consumed in clock divider
|
||
|
hal_cmu_mem_select_pll(HAL_CMU_PLL_USB);
|
||
|
#endif
|
||
|
#else
|
||
|
// Switch psram clock to audio PLL
|
||
|
hal_cmu_mem_select_pll(HAL_CMU_PLL_AUD);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
// Select system PLL after selecting flash/psram PLLs
|
||
|
#ifdef ULTRA_LOW_POWER
|
||
|
hal_cmu_low_freq_mode_init();
|
||
|
#else
|
||
|
#if defined(MCU_HIGH_PERFORMANCE_MODE) && defined(CHIP_HAS_USB)
|
||
|
// Switch system clocks to USB PLL
|
||
|
hal_cmu_sys_select_pll(HAL_CMU_PLL_USB);
|
||
|
#else
|
||
|
// Switch system clocks to audio PLL
|
||
|
hal_cmu_sys_select_pll(HAL_CMU_PLL_AUD);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if defined(CHIP_BEST1000) || defined(CHIP_BEST2000)
|
||
|
#ifndef USB_PLL_INIT_ON
|
||
|
// Disable USB PLL after switching (clock mux requirement)
|
||
|
hal_cmu_pll_disable(HAL_CMU_PLL_USB, HAL_CMU_PLL_USER_SYS);
|
||
|
#endif
|
||
|
#ifndef AUD_PLL_INIT_ON
|
||
|
hal_cmu_pll_disable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_SYS);
|
||
|
#endif
|
||
|
#else // !(best1000 || best2000)
|
||
|
#ifdef USB_PLL_INIT_ON
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_USB, HAL_CMU_PLL_USER_SYS);
|
||
|
#endif
|
||
|
#ifdef AUD_PLL_INIT_ON
|
||
|
hal_cmu_pll_enable(HAL_CMU_PLL_AUD, HAL_CMU_PLL_USER_SYS);
|
||
|
#endif
|
||
|
#endif // !(best1000 || best2000)
|
||
|
|
||
|
#if defined(MCU_HIGH_PERFORMANCE_MODE) && !defined(ULTRA_LOW_POWER) && defined(OSC_26M_X4_AUD2BB)
|
||
|
#error "Error configuration: MCU_HIGH_PERFORMANCE_MODE has no effect"
|
||
|
#endif
|
||
|
}
|
||
|
#endif // !HAL_CMU_PLL_T
|
||
|
|
||
|
static void BOOT_TEXT_FLASH_LOC hal_cmu_init_periph_clock(void)
|
||
|
{
|
||
|
#ifdef PERIPH_PLL_FREQ
|
||
|
hal_cmu_periph_set_div(1);
|
||
|
#endif
|
||
|
|
||
|
// TODO: Move the following SDIO freq setting to hal_sdio.c
|
||
|
#ifdef CHIP_HAS_SDIO
|
||
|
hal_cmu_sdio_set_freq(HAL_CMU_PERIPH_FREQ_26M);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void hal_cmu_rom_setup(void)
|
||
|
{
|
||
|
hal_cmu_lpu_wait_26m_ready();
|
||
|
hal_cmu_simu_init();
|
||
|
hal_cmu_rom_clock_init();
|
||
|
hal_cmu_timer0_select_slow();
|
||
|
#ifdef TIMER1_BASE
|
||
|
hal_cmu_timer1_select_fast();
|
||
|
#endif
|
||
|
hal_sys_timer_open();
|
||
|
|
||
|
// Init sys clock
|
||
|
hal_cmu_sys_set_freq(HAL_CMU_FREQ_26M);
|
||
|
|
||
|
// Init flash clock (this should be done before load_boot_settings, for security register read)
|
||
|
hal_cmu_flash_set_freq(HAL_CMU_FREQ_26M);
|
||
|
// Reset flash controller (for JTAG reset and run)
|
||
|
// Enable flash controller (flash controller is reset by default since BEST1400)
|
||
|
hal_cmu_reset_set(HAL_CMU_MOD_O_FLASH);
|
||
|
hal_cmu_reset_set(HAL_CMU_MOD_H_FLASH);
|
||
|
hal_cmu_reset_clear(HAL_CMU_MOD_H_FLASH);
|
||
|
hal_cmu_reset_clear(HAL_CMU_MOD_O_FLASH);
|
||
|
|
||
|
// Disable cache (for JTAG reset and run)
|
||
|
hal_cache_disable(HAL_CACHE_ID_I_CACHE);
|
||
|
hal_cache_disable(HAL_CACHE_ID_D_CACHE);
|
||
|
|
||
|
// Init APB clock
|
||
|
hal_cmu_apb_init_div();
|
||
|
}
|
||
|
|
||
|
void hal_cmu_programmer_setup(void)
|
||
|
{
|
||
|
hal_cmu_ema_init();
|
||
|
hal_sys_timer_open();
|
||
|
|
||
|
#ifdef JTAG_ENABLE
|
||
|
hal_iomux_set_jtag();
|
||
|
hal_cmu_jtag_clock_enable();
|
||
|
#endif
|
||
|
|
||
|
#ifndef FPGA
|
||
|
int ret;
|
||
|
// Open analogif (ISPI)
|
||
|
ret = hal_analogif_open();
|
||
|
if (ret) {
|
||
|
hal_cmu_simu_tag(31);
|
||
|
do { volatile int i = 0; i++; } while (1);
|
||
|
}
|
||
|
// Init chip id
|
||
|
// 1) Read id from ana/rf/pmu
|
||
|
// 2) Init clock settings in ana/rf/pmu if the default h/w register values are bad
|
||
|
hal_chipid_init();
|
||
|
|
||
|
// Enable OSC X2/X4 in cmu after enabling their source in hal_chipid_init()
|
||
|
hal_cmu_osc_x2_enable();
|
||
|
hal_cmu_osc_x4_enable();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#ifdef FPGA
|
||
|
|
||
|
void BOOT_TEXT_FLASH_LOC hal_cmu_fpga_setup(void)
|
||
|
{
|
||
|
hal_cmu_timer0_select_slow();
|
||
|
hal_sys_timer_open();
|
||
|
|
||
|
hal_sysfreq_req(HAL_SYSFREQ_USER_INIT, HAL_CMU_FREQ_52M);
|
||
|
|
||
|
hal_cmu_apb_init_div();
|
||
|
hal_cmu_ispi_set_freq(HAL_CMU_PERIPH_FREQ_26M);
|
||
|
|
||
|
// Init peripheral clocks
|
||
|
hal_cmu_init_periph_clock();
|
||
|
|
||
|
hal_norflash_init();
|
||
|
#if defined(CHIP_HAS_PSRAM) && defined(PSRAM_ENABLE)
|
||
|
hal_psram_init();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#else // !FPGA
|
||
|
|
||
|
void BOOT_TEXT_FLASH_LOC hal_cmu_setup(void)
|
||
|
{
|
||
|
int ret;
|
||
|
enum HAL_CMU_FREQ_T freq;
|
||
|
|
||
|
hal_iomux_set_default_config();
|
||
|
#ifdef JTAG_ENABLE
|
||
|
hal_iomux_set_jtag();
|
||
|
hal_cmu_jtag_clock_enable();
|
||
|
#endif
|
||
|
hal_cmu_module_init_state();
|
||
|
hal_cmu_ema_init();
|
||
|
hal_cmu_timer0_select_slow();
|
||
|
#ifdef TIMER1_BASE
|
||
|
hal_cmu_timer1_select_fast();
|
||
|
#endif
|
||
|
hal_sys_timer_open();
|
||
|
hal_hw_bootmode_init();
|
||
|
|
||
|
// Init system/flash/memory clocks before initializing clock setting
|
||
|
// and before switching PLL
|
||
|
hal_norflash_set_freq(HAL_CMU_FREQ_26M);
|
||
|
hal_cmu_mem_set_freq(HAL_CMU_FREQ_26M);
|
||
|
hal_cmu_sys_set_freq(HAL_CMU_FREQ_26M);
|
||
|
|
||
|
// Set ISPI module freq
|
||
|
hal_cmu_ispi_set_freq(HAL_CMU_PERIPH_FREQ_26M);
|
||
|
// Open analogif (ISPI)
|
||
|
ret = hal_analogif_open();
|
||
|
if (ret) {
|
||
|
hal_cmu_simu_tag(31);
|
||
|
do { volatile int i = 0; i++; } while (1);
|
||
|
}
|
||
|
// Init chip id
|
||
|
// 1) Read id from ana/rf/pmu
|
||
|
// 2) Init clock settings in ana/rf/pmu if the default h/w register values are bad
|
||
|
hal_chipid_init();
|
||
|
|
||
|
#ifdef CALIB_SLOW_TIMER
|
||
|
// Calib slow timer after determining the crystal freq
|
||
|
hal_sys_timer_calib();
|
||
|
#endif
|
||
|
|
||
|
// Enable OSC X2/X4 in cmu after enabling their source in hal_chipid_init()
|
||
|
hal_cmu_osc_x2_enable();
|
||
|
hal_cmu_osc_x4_enable();
|
||
|
|
||
|
// Init PLL selection
|
||
|
hal_cmu_init_pll_selection();
|
||
|
|
||
|
// Init peripheral clocks
|
||
|
hal_cmu_init_periph_clock();
|
||
|
|
||
|
// Sleep setting
|
||
|
#ifdef NO_LPU_26M
|
||
|
while (hal_cmu_lpu_init(HAL_CMU_LPU_CLK_NONE) == -1);
|
||
|
#else
|
||
|
while (hal_cmu_lpu_init(HAL_CMU_LPU_CLK_26M) == -1);
|
||
|
#endif
|
||
|
// Init sys freq after applying the sleep setting (which might change sys freq)
|
||
|
#ifdef NO_LPU_26M
|
||
|
hal_sys_timer_delay(MS_TO_TICKS(20));
|
||
|
#endif
|
||
|
|
||
|
// Init system clock
|
||
|
#ifdef ULTRA_LOW_POWER
|
||
|
freq = HAL_CMU_FREQ_52M;
|
||
|
#else
|
||
|
freq = HAL_CMU_FREQ_104M;
|
||
|
#endif
|
||
|
hal_sysfreq_req(HAL_SYSFREQ_USER_INIT, freq);
|
||
|
|
||
|
// Init flash
|
||
|
hal_norflash_init();
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif // !FPGA
|
||
|
|