160 lines
4.1 KiB
C
160 lines
4.1 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_types.h"
|
|
#include "hal_sysfreq.h"
|
|
#include "hal_location.h"
|
|
#include "hal_trace.h"
|
|
#include "cmsis.h"
|
|
#ifndef ROM_BUILD
|
|
#include "pmu.h"
|
|
#endif
|
|
|
|
static uint32_t BOOT_BSS_LOC sysfreq_bundle[(HAL_SYSFREQ_USER_QTY + 3) / 4];
|
|
|
|
static uint8_t * const sysfreq_per_user = (uint8_t *)&sysfreq_bundle[0];
|
|
|
|
static enum HAL_SYSFREQ_USER_T BOOT_DATA_LOC top_user = HAL_SYSFREQ_USER_QTY;
|
|
|
|
static enum HAL_CMU_FREQ_T BOOT_DATA_LOC min_sysfreq = HAL_CMU_FREQ_26M;
|
|
|
|
static enum HAL_CMU_FREQ_T hal_sysfreq_revise_freq(enum HAL_CMU_FREQ_T freq)
|
|
{
|
|
return freq > min_sysfreq ? freq : min_sysfreq;
|
|
}
|
|
|
|
void hal_sysfreq_set_min_freq(enum HAL_CMU_FREQ_T freq)
|
|
{
|
|
uint32_t lock;
|
|
|
|
lock = int_lock();
|
|
|
|
if (min_sysfreq < freq) {
|
|
min_sysfreq = freq;
|
|
if (min_sysfreq > hal_sysfreq_get()) {
|
|
hal_cmu_sys_set_freq(min_sysfreq);
|
|
}
|
|
}
|
|
|
|
int_unlock(lock);
|
|
}
|
|
|
|
int hal_sysfreq_req(enum HAL_SYSFREQ_USER_T user, enum HAL_CMU_FREQ_T freq)
|
|
{
|
|
uint32_t lock;
|
|
enum HAL_CMU_FREQ_T cur_sys_freq;
|
|
int i;
|
|
|
|
if (user >= HAL_SYSFREQ_USER_QTY) {
|
|
return 1;
|
|
}
|
|
if (freq >= HAL_CMU_FREQ_QTY) {
|
|
return 2;
|
|
}
|
|
|
|
lock = int_lock();
|
|
|
|
cur_sys_freq = hal_sysfreq_get();
|
|
|
|
sysfreq_per_user[user] = freq;
|
|
|
|
if (freq == cur_sys_freq) {
|
|
top_user = user;
|
|
} else if (freq > cur_sys_freq) {
|
|
top_user = user;
|
|
freq = hal_sysfreq_revise_freq(freq);
|
|
#ifndef ROM_BUILD
|
|
pmu_sys_freq_config(freq);
|
|
#ifdef ULTRA_LOW_POWER
|
|
// Enable PLL if required
|
|
hal_cmu_low_freq_mode_disable(hal_sysfreq_revise_freq(cur_sys_freq), freq);
|
|
#endif
|
|
#endif
|
|
hal_cmu_sys_set_freq(freq);
|
|
} else /* if (freq < cur_sys_freq) */ {
|
|
if (top_user == user || top_user == HAL_SYSFREQ_USER_QTY) {
|
|
if (top_user == user) {
|
|
freq = sysfreq_per_user[0];
|
|
user = 0;
|
|
for (i = 1; i < HAL_SYSFREQ_USER_QTY; i++) {
|
|
if (freq < sysfreq_per_user[i]) {
|
|
freq = sysfreq_per_user[i];
|
|
user = i;
|
|
}
|
|
}
|
|
}
|
|
top_user = user;
|
|
if (freq != cur_sys_freq) {
|
|
freq = hal_sysfreq_revise_freq(freq);
|
|
hal_cmu_sys_set_freq(freq);
|
|
#ifndef ROM_BUILD
|
|
#ifdef ULTRA_LOW_POWER
|
|
// Disable PLL if capable
|
|
hal_cmu_low_freq_mode_enable(hal_sysfreq_revise_freq(cur_sys_freq), freq);
|
|
#endif
|
|
pmu_sys_freq_config(freq);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
int_unlock(lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
enum HAL_CMU_FREQ_T hal_sysfreq_get(void)
|
|
{
|
|
if (top_user < HAL_SYSFREQ_USER_QTY) {
|
|
return sysfreq_per_user[top_user];
|
|
} else {
|
|
return hal_cmu_sys_get_freq();
|
|
}
|
|
}
|
|
|
|
enum HAL_CMU_FREQ_T hal_sysfreq_get_hw_freq(void)
|
|
{
|
|
if (top_user < HAL_SYSFREQ_USER_QTY) {
|
|
return hal_sysfreq_revise_freq(sysfreq_per_user[top_user]);
|
|
} else {
|
|
return hal_cmu_sys_get_freq();
|
|
}
|
|
}
|
|
|
|
int hal_sysfreq_busy(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(sysfreq_bundle); i++) {
|
|
if (sysfreq_bundle[i] != 0) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void hal_sysfreq_print(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < HAL_SYSFREQ_USER_QTY; i++) {
|
|
if (sysfreq_per_user[i] != 0) {
|
|
TRACE(2,"*** SYSFREQ user=%d freq=%d", i, sysfreq_per_user[i]);
|
|
}
|
|
}
|
|
TRACE(1,"*** SYSFREQ top_user=%d", top_user);
|
|
}
|
|
|