This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
@@ -0,0 +1,507 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".clock_manager.data.bss")
#pragma data_seg(".clock_manager.data")
#pragma const_seg(".clock_manager.text.const")
#pragma code_seg(".clock_manager.text")
#endif
#include "clock_manager.h"
#include "system/init.h"
#include "system/timer.h"
#include "system/task.h"
#include "os/os_api.h"
#include "clock.h"
#include "list.h"
#include "app_config.h"
#include "power/power_manage.h"
#define CLOCK_DETECT_PERIOD (4 * 1000) //4s
#define CLOCK_DETECT_COUNTER (7) //7 times
#define CLOCK_MINIMUM_FREQ (24 * 1000000) //24MHz
#define CLOCK_MAXIMUM_FREQ clk_get_max_frequency()
typedef struct clock_manager_st {
struct list_head entry;
u32 freq;
u32 name;
} clock_manager_item;
static u8 ref_cnt;
static u8 clk_adjust_step = 0;
static u8 clk_adjust_fast = 0;
static u16 clk_ref_timer;
static clock_manager_item clk_locker;
static struct list_head clk_mgr_head = LIST_HEAD_INIT(clk_mgr_head);
static const int clock_table[] = {
24 * MHz, 48 * MHz, 60 * MHz, 64 * MHz, 76 * MHz,
80 * MHz, 96 * MHz, 120 * MHz, 128 * MHz, 140 * MHz, 160 * MHz,
200 * MHz, 240 * MHz, 280 * MHz, 320 * MHz,
};
static u32 __get_clock(u32 dest_clk)
{
for (int i = 0; i < ARRAY_SIZE(clock_table); i++) {
if (dest_clk <= clock_table[i]) {
return clock_table[i];
}
}
return clock_table[ARRAY_SIZE(clock_table) - 1];
}
#if (defined CONFIG_EARPHONE_CASE_ENABLE)
static u8 cpu_usage_limit[] = {75, 80, 85};
#elif (defined CONFIG_WATCH_CASE_ENABLE)
static u8 cpu_usage_limit[] = {75, 80, 85};
#else
static u8 cpu_usage_limit[] = {50, 55, 60};
#endif
#if 0
#define CLOCK_MANAGER_INIT_CRITICAL()
#define CLOCK_MANAGER_ENTER_CRITICAL() local_irq_disable()
#define CLOCK_MANAGER_EXIT_CRITICAL() local_irq_enable()
#else
static OS_MUTEX clk_mutex;
#define CLOCK_MANAGER_INIT_CRITICAL() os_mutex_create(&clk_mutex)
#define CLOCK_MANAGER_ENTER_CRITICAL() os_mutex_pend(&clk_mutex, 0)
#define CLOCK_MANAGER_EXIT_CRITICAL() os_mutex_post(&clk_mutex)
#endif
extern void core_voltage_dump(); //debug info api
/* --------------------------------------------------------------------------*/
/**
* @brief clock_alloc,此函数会触发时钟频率设置
*
* @param name
* @param clk
*
* @return 0:succ
*/
/* ----------------------------------------------------------------------------*/
int clock_alloc(const char *name, u32 clk)
{
clock_manager_item *p;
u32 hash = JBHash((u8 *)name, strlen(name));
CLOCK_MANAGER_ENTER_CRITICAL();
list_for_each_entry(p, &clk_mgr_head, entry) {
if (p->name == hash) {
CLOCK_MANAGER_EXIT_CRITICAL();
return -1;
}
}
clock_manager_item *it = malloc(sizeof(clock_manager_item));
if (it == NULL) {
CLOCK_MANAGER_EXIT_CRITICAL();
return -1;
}
it->name = hash;
it->freq = clk;
list_add_tail(&it->entry, &clk_mgr_head);
clock_refurbish();
CLOCK_MANAGER_EXIT_CRITICAL();
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_free,此函数会触发时钟频率设置
*
* @param name
*
* @return 0:succ
*/
/* ----------------------------------------------------------------------------*/
int clock_free(char *name)
{
clock_manager_item *p, *n;
u32 hash = JBHash((u8 *)name, strlen(name));
CLOCK_MANAGER_ENTER_CRITICAL();
list_for_each_entry_safe(p, n, &clk_mgr_head, entry) {
if (p->name == hash) {
__list_del_entry(&p->entry);
free(p);
break;
}
}
clock_refurbish();
CLOCK_MANAGER_EXIT_CRITICAL();
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_manager_dump
*/
/* ----------------------------------------------------------------------------*/
static u32 clock_list_sum(void)
{
clock_manager_item *p;
u32 total = CLOCK_MINIMUM_FREQ;
list_for_each_entry(p, &clk_mgr_head, entry) {
/*printf("%s : %dHz", p->name, p->freq);*/
total += p->freq;
}
/*printf("%s : %dHz", "total", total);*/
return total;
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_manager_test
*/
/* ----------------------------------------------------------------------------*/
void clock_manager_test(void)
{
clock_alloc("clk_mgr_1", 2 * 1000000U);
clock_manager_dump();
clock_alloc("clk_mgr_2", 2 * 1000000U);
clock_manager_dump();
clock_free("clk_mgr_1");
clock_manager_dump();
clock_free("clk_mgr_2");
clock_manager_dump();
printf("test over");
while (1);
}
void clock_lock_dump(void)
{
printf("clock_lock owner : %x", clk_locker.name);
printf("clock_lock freq : %d", clk_locker.freq);
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_lock_deal
*
* @param name: owner name
* @param clk: lock_freq
* @param check: check is locked
*
* @return 0:succ, other:err code
*/
/* ----------------------------------------------------------------------------*/
int clock_lock_deal(const char *name, u32 clk, u8 check)
{
u32 hash = JBHash((u8 *)name, strlen(name));
CLOCK_MANAGER_ENTER_CRITICAL();
if (check && clk_locker.freq) {
//has been locked, lock fail
CLOCK_MANAGER_EXIT_CRITICAL();
return -1;
}
clk_locker.freq = clk;
clk_locker.name = hash;
clk_set_api("sys", clk);
CLOCK_MANAGER_EXIT_CRITICAL();
return 0;
}
int clock_lock(const char *name, u32 clk)
{
return clock_lock_deal(name, clk, 1);
}
int clock_force_lock(const char *name, u32 clk)
{
return clock_lock_deal(name, clk, 0);
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_unlock
*
* @param name: owner name
*
* @return 0:succ, other:err code
*/
/* ----------------------------------------------------------------------------*/
int clock_unlock(char *name)
{
u32 hash = JBHash((u8 *)name, strlen(name));
printf("%s", __func__);
CLOCK_MANAGER_ENTER_CRITICAL();
clock_lock_dump();
if (clk_locker.freq == 0) {
//has been locked
/* ASSERT(0, "please lock it befor unlock"); */
CLOCK_MANAGER_EXIT_CRITICAL();
return -1;
}
if (clk_locker.name != hash) {
/* ASSERT(0, "locker owner is %s", clk_locker.name); */
CLOCK_MANAGER_EXIT_CRITICAL();
return -2;
}
clk_locker.freq = 0;
//refurbish clock after unlock succ
clock_refurbish();
CLOCK_MANAGER_EXIT_CRITICAL();
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_manager_reflash
*/
/* ----------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/**
* @brief clk_ref_cal
*/
/* ----------------------------------------------------------------------------*/
static void clk_ref_cal(void)
{
u32 clk_freq;
u32 clk_decr;
u32 pct;
#if 0 //效率统计
extern void CacheReport(void);
CacheReport();
task_info_output(0);
#endif
int usage[2] = { 0, 0 };
int a = os_cpu_usage(NULL, usage);
task_info_reset();
if (a < 0) {
return;
}
int usage_max = MAX(usage[0], usage[1]);
int curr_clk = clk_get("sys");
int dest_clk = curr_clk;
__again:
switch (clk_adjust_step) {
case 0:
dest_clk = __get_clock(curr_clk / 50 * usage_max);
clk_adjust_step = 1;
break;
case 1:
if (usage_max < cpu_usage_limit[0]) {
dest_clk = __get_clock(curr_clk / cpu_usage_limit[1] * usage_max);
} else if (usage_max > cpu_usage_limit[2]) {
dest_clk = __get_clock(curr_clk / (cpu_usage_limit[1] - 10) * usage_max);
} else {
clk_adjust_step = 2;
}
break;
case 2:
if (usage_max >= cpu_usage_limit[0] && usage_max <= cpu_usage_limit[2]) {
break;
}
clk_adjust_step = 1;
goto __again;
}
int min_clk = clock_list_sum();
if (dest_clk < min_clk) {
dest_clk = min_clk;
}
r_printf("cpu: %d %d clk:%d %d %d, %d\n", usage[0], usage[1],
curr_clk, min_clk, dest_clk, clk_adjust_step);
//clock lock
if (clk_locker.freq) {
dest_clk = clk_locker.freq;
} else if (dest_clk < min_clk) {
dest_clk = min_clk;
}
clk_set_api("sys", dest_clk);
}
/* --------------------------------------------------------------------------*/
/**
* @brief clk_ref_fun
*
* @param p
*/
/* ----------------------------------------------------------------------------*/
static void clk_ref_fun(void *p)
{
CLOCK_MANAGER_ENTER_CRITICAL();
if (ref_cnt < CLOCK_DETECT_COUNTER) {
/* printf("CLOCK_DETECT_COUNTER:%d\n", ref_cnt); */
ref_cnt++;
clk_ref_cal();
} else {
#if TCFG_CFG_TOOL_ENABLE
task_info_reset();
/* printf("clock_reflash_reset"); */
#else
sys_timer_del(clk_ref_timer);
clk_ref_timer = 0;
/* printf("clock_reflash_stop"); */
#endif
}
CLOCK_MANAGER_EXIT_CRITICAL();
}
/* --------------------------------------------------------------------------*/
/**
* @brief clock_refurbishMIPS变化时调用此函数刷新。
*/
/* ----------------------------------------------------------------------------*/
void clock_refurbish(void)
{
if (cpu_in_irq() || cpu_irq_disabled()) {
//以上情况,需要改为在APP任务上设置
int msg[3];
msg[0] = (int)clock_refurbish;
msg[1] = 1;
msg[2] = 0;
os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
/* sys_timeout_add(NULL, (void *)clock_refurbish, 1); */
return;
}
CLOCK_MANAGER_ENTER_CRITICAL();
//clk driver 需要提供每个芯片可以设置的最高挡位
clk_set_api("sys", CLOCK_MAXIMUM_FREQ);
ref_cnt = 0;
clk_adjust_step = 0;
clk_adjust_fast = 0;
if (clk_ref_timer) {
sys_timer_modify(clk_ref_timer, CLOCK_DETECT_PERIOD);
} else {
clk_ref_timer = sys_timer_add(NULL, clk_ref_fun, CLOCK_DETECT_PERIOD);
}
ASSERT(clk_ref_timer);
task_info_reset();
CLOCK_MANAGER_EXIT_CRITICAL();
}
_NOINLINE_
int clk_set_unused(const char *name, int clk)
{
return 0;
}
static u8 extern_clk_ref_suspend(u32 timeout)
{
if (clk_ref_timer && (clk_adjust_fast == 0)) {
/* printf("\n\n enter lowerpower:%d \n\n", timeout); */
clk_adjust_fast = 1;
// 能进低功耗,快速收敛
sys_timer_modify(clk_ref_timer, 500);
return 1;
}
return 0;
}
REGISTER_LP_REQUEST(power_clk_ref_target) = {
.name = "clk_ref",
.request_enter = extern_clk_ref_suspend,
};
/* --------------------------------------------------------------------------*/
/**
* @brief init
*/
/* ----------------------------------------------------------------------------*/
static int clock_manager_init(void)
{
CLOCK_MANAGER_INIT_CRITICAL();
return 0;
}
early_initcall(clock_manager_init);
/* --------------------------------------------------------------------------*/
/**
* @brief clock_manager_test
*/
/* ----------------------------------------------------------------------------*/
static void clk_test2_tmr_fun(void *p)
{
clk_set_api("sys", CLOCK_MAXIMUM_FREQ);
clock_refurbish();
}
void clock_manager_test2(void)
{
sys_timer_add(NULL, clk_test2_tmr_fun, 60 * 1000);
}
static void clk_test3_tmr_fun(void *p)
{
/* int ret; */
clock_unlock("test");
/* ASSERT(ret == 0); */
}
void clock_manager_test3(void)
{
int ret;
ret = clock_lock("test", 128 * 1000000U);
ASSERT(ret == 0);
sys_timeout_add(NULL, clk_test3_tmr_fun, 30 * 1000);
/* void mpu_set(int idx, u32 begin, u32 end, u32 inv, const char *format, ...); */
/* u32 addr = (u32)(&clk_locker.freq); */
/* mpu_set(2, addr, addr+3, 0, "Cr"); */
}
@@ -0,0 +1,76 @@
#ifndef _CLOCK_MANAGER_
#define _CLOCK_MANAGER_
#include "typedef.h"
// #include "asm/clock.h"
// int clk_set(const char *name, int clk);
/* --------------------------------------------------------------------------*/
/**
* @brief clock_alloc,此函数会触发时钟频率设置
*
* @param name
* @param clk
*
* @return 0:succ
*/
/* ----------------------------------------------------------------------------*/
int clock_alloc(const char *name, u32 clk);
/* --------------------------------------------------------------------------*/
/**
* @brief clock_free,此函数会触发时钟频率设置
*
* @param name
*
* @return 0:succ
*/
/* ----------------------------------------------------------------------------*/
int clock_free(char *name);
/* --------------------------------------------------------------------------*/
/**
* @brief clock_manager_dump
*/
/* ----------------------------------------------------------------------------*/
void clock_manager_dump(void);
/* --------------------------------------------------------------------------*/
/**
* @brief clock_refurbish,当CPU运行代码有改变时候,建议调用此函数刷新时钟频率
*/
/* ----------------------------------------------------------------------------*/
void clock_refurbish(void);
/* --------------------------------------------------------------------------*/
/**
* @brief clock_lock_deal
*
* @param name: owner name
* @param clk: lock_freq
* @param check: check is locked
*
* @return 0:succ, other:err code
*/
/* ----------------------------------------------------------------------------*/
int clock_lock_deal(const char *name, u32 clk, u8 check);
int clock_lock(const char *name, u32 clk); // 检查是否已经锁定
int clock_force_lock(const char *name, u32 clk); // 不检查,强制设定时钟频率
/* --------------------------------------------------------------------------*/
/**
* @brief clock_unlock
*
* @param name: owner name
*
* @return 0:succ, other:err code
*/
/* ----------------------------------------------------------------------------*/
int clock_unlock(char *name);
#endif //_CLOCK_MANAGER_