コード例 #1
0
/*
 * 调试接口,设置频率 BSP_ERROR 设置失败;BSP_OK 设置成功
 *
 */
int pwrctrl_dfs_target(int a9freq, int ddrfreq, int slowfreq)
{
	int target_profile = 0;
	target_profile = pwrctrl_find_min_profile((u32)a9freq, (u32)ddrfreq, (u32)slowfreq);
	cpufreq_debug("prolfie : %d\n", target_profile);
	pwrctrl_dfs_set_baseprofile(target_profile);
	return target_profile;
}
コード例 #2
0
/*
 * 锁定调频 DFS_PROFILE_LOCKFREQ=0锁定;DFS_PROFILE_LOCKFREQ=1解锁
 */
void pwrctrl_dfs_lock(u32 lock)
{
	struct cpufreq_msg set_msg = {0,0,0,0};
	cpufreq_debug("cpufreq lock status is: %d\n", g_cpufreq_lock_status_flag);
	g_cpufreq_lock_status_flag = (s32)lock;

	set_msg.content = lock;
	
	set_msg.msg_type = CPUFREQ_LOCK_MCORE_ACTION;
	set_msg.source = CPUFREQ_ACORE;
	balong_cpufreq_icc_send(&set_msg);
}
コード例 #3
0
void register_icc_for_cpufreq(void)
{
    s32 ret;
    u32 channel_id_set = ICC_CHN_MCORE_ACORE << 16 | MCU_ACORE_CPUFREQ;
    ret = bsp_icc_event_register(channel_id_set, (read_cb_func)balong_cpufreq_cb_getprofile, (void *)NULL, (write_cb_func)NULL, (void *)NULL);
    if (ret != BSP_OK)
    {
        cpufreq_err("icc register failed %d\n", ret);
    }
    else
    {
        ;
    }
    cpufreq_debug("register icc to mcore %d\n", ret);
}/*lint !e533 */
コード例 #4
0
/*
 * Here we notify other drivers of the proposed change and the final change.
 *
 *
 *根据relation做相应动作
 */
static s32 balong_cpufreq_target(struct cpufreq_policy *policy,
				     u32 target_freq,
				     u32 relation)
{
	u32 result = 2;
	u32 new_index = 0;
	int cur_profile = 0;
	struct cpufreq_msg task_msg = {0,0,0,0};
	
	
	cpufreq_frequency_table_target(policy, balong_clockrate_table,
					   target_freq, relation, &new_index);
					   
	cpufreq_debug("target_freq %d new_index%d\n", target_freq, new_index);

	cur_profile = pwrctrl_dfs_get_profile();
	
	if ((CPUFREQ_RELATION_H == relation) && (BALONG_FREQ_MAX != cur_profile))
	{
		result = DFS_PROFILE_UP_TARGET;
	}
	else if ((CPUFREQ_RELATION_L == relation) && (BALONG_FREQ_MIN != cur_profile))
	{
		result = DFS_PROFILE_DOWN_TARGET;
	}
	else
	{
		policy->cur = balong_clockrate_table[cur_profile].frequency;
		g_cur_freq = policy->cur;
		cpufreq_info("set target relation %d, cur pro %d\n", relation, policy->cur);
		return BSP_ERROR;
	}
	
	cpufreq_frequency_target_profile(balong_clockrate_table[new_index].frequency, relation, &new_index);

	task_msg.msg_type = CPUFREQ_ADJUST_FREQ;
	task_msg.source = CPUFREQ_ACORE;
	task_msg.content = result;
	task_msg.profile = new_index;
	balong_cpufreq_icc_send(&task_msg);
	
	policy->cur = balong_clockrate_table[cur_profile].frequency;
	g_cur_freq = policy->cur;
	return BSP_OK;
}
コード例 #5
0
/*find the first profile that is the target*/
static void cpufreq_frequency_target_profile( unsigned int target_freq,
				   unsigned int relation,  unsigned int *new_profile)
{
	int i = 0;
	int cur_profile = pwrctrl_dfs_get_profile();
	switch (relation)
	{
		case DFS_PROFILE_UP:
			*new_profile = balong_clockrate_table[BALONG_FREQ_MAX].index;
			return;
		case DFS_PROFILE_DOWN:
			cpufreq_debug("down to frequency\n");
			break;
		default :
			break;
	}

	for (i = cur_profile; i >= BALONG_FREQ_MIN; i--)
	{
		if (target_freq != balong_query_profile_table[i].cpu_frequency)
		{
			continue;
		}
		if ((u32)cur_profile == balong_query_profile_table[i].profile)
		{
			continue;
		}
		*new_profile = balong_query_profile_table[i].profile;
		goto out;
	}
	if (cur_profile != BALONG_FREQ_MIN)
	{
		*new_profile = balong_query_profile_table[cur_profile - 1].profile;
	}
	else
	{
		*new_profile = balong_query_profile_table[BALONG_FREQ_MIN].profile;
	}
out:
	return;
}
コード例 #6
0
static s32 cpufreq_governor_dbs(struct cpufreq_policy *policy, u32 event)
{
    s32 cpu = (s32)policy->cpu;
    struct cpu_dbs_info_s *dbs_info = NULL;
    u32 retValue = 0;
    ST_PWC_SWITCH_STRU cpufreq_control_nv = {0} ;
    /*cpu 信息*/
    dbs_info = &per_cpu(g_acpu_dbs_info, (u32)cpu);
    /*lint --e{744 } */
    switch (event) {
    case CPUFREQ_GOV_START:
        cpufreq_debug("CPUFREQ_GOV_START\n");
        mutex_lock(&dbs_mutex);

        dbs_enable++;

        /*cpu 信息初始化  函数??idle_time*/
        dbs_info->prev_cpu_idle = get_cpu_idle_time(0,
                                  &dbs_info->prev_cpu_wall);
        dbs_info->cur_policy = policy;
        dbs_info->cpu = cpu;
        dbs_info->freq_table = cpufreq_frequency_get_table((u32)cpu);
        dbs_info->cpu_down_time = 0;
        dbs_info->cpu_up_time = 0;
        retValue = bsp_nvm_read(NV_ID_DRV_NV_PWC_SWITCH,(u8*)&cpufreq_control_nv,sizeof(ST_PWC_SWITCH_STRU));
        if (NV_OK == retValue)
        {
            g_cpufreq_lock_status_flag = cpufreq_control_nv.dfs;
        }
        else
        {
            cpufreq_err("read nv failed %d\n", retValue);
        }

        if (1 == dbs_enable) {
            retValue = bsp_nvm_read(NV_ID_DRV_NV_DFS_SWITCH,(u8*)&g_stDfsSwitch,sizeof(ST_PWC_DFS_STRU));
            if (NV_OK != retValue)
            {
                cpufreq_err("read nv failed use default value\n");
                g_stDfsSwitch.AcpuDownLimit = 20;
                g_stDfsSwitch.AcpuDownNum = 3;
                g_stDfsSwitch.AcpuUpLimit = 80;
                g_stDfsSwitch.AcpuUpNum = 1;
                g_stDfsSwitch.DFSTimerLen = 400;
            }

            dbs_tuners_ins.up_threshold = g_stDfsSwitch.AcpuUpLimit;
            dbs_tuners_ins.down_threshold = g_stDfsSwitch.AcpuDownLimit;
            dbs_tuners_ins.down_threshold_times = g_stDfsSwitch.AcpuDownNum;
            dbs_tuners_ins.up_threshold_times = g_stDfsSwitch.AcpuUpNum;
            dbs_tuners_ins.sampling_rate = g_stDfsSwitch.DFSTimerLen * 10000; /*unit:us*/
            /*
             * Start the timerschedule work, when this governor
             * is used for first time
             */

            register_icc_for_cpufreq();

            dbs_timer_init(dbs_info);
        }
        mutex_unlock(&dbs_mutex);
        break;

    case CPUFREQ_GOV_STOP:
        dbs_timer_exit(dbs_info);

        mutex_lock(&dbs_mutex);
        dbs_enable--;
        mutex_unlock(&dbs_mutex);
        break;

    case CPUFREQ_GOV_LIMITS:

        mutex_lock(&info_mutex);
        dbs_info->cpu_down_time = 0;
        dbs_info->cpu_up_time = 0;
        mutex_unlock(&info_mutex);
        if (policy->max < dbs_info->cur_policy->cur)
            __cpufreq_driver_target(dbs_info->cur_policy,
                                    policy->max, CPUFREQ_RELATION_H);
        else if (policy->min > dbs_info->cur_policy->cur)
            __cpufreq_driver_target(dbs_info->cur_policy,
                                    policy->min, CPUFREQ_RELATION_L);

        break;
    }
    return 0;
}
コード例 #7
0
/*find a freq in all table*/
static int cpufreq_frequency_table_target(struct cpufreq_frequency_table *table,
				   unsigned int target_freq,
				   unsigned int relation,
				   unsigned int *index)
{/*lint !e578 */
	struct cpufreq_frequency_table optimal = {
		.index = ~0,
		.frequency = 0,
	};
	struct cpufreq_frequency_table suboptimal = {
		.index = ~0,
		.frequency = 0,
	};
	unsigned int i;
	/*lint --e{744} */
	switch (relation) {
	case DFS_PROFILE_UP:
		suboptimal.frequency = ~0;
		break;
	case DFS_PROFILE_DOWN:
		optimal.frequency = ~0;
		break;
	}

	for (i = 0; (table[i].frequency != (u32)CPUFREQ_TABLE_END); i++) {
		unsigned int freq = table[i].frequency;
		if (freq == (u32)CPUFREQ_ENTRY_INVALID)
			continue;
		if ((freq < balong_query_profile_table[BALONG_FREQ_MIN].cpu_frequency) || (freq > balong_query_profile_table[BALONG_FREQ_MAX].cpu_frequency))
			continue;
		switch (relation) {
		case DFS_PROFILE_UP:
			if (freq <= target_freq) {
				if (freq >= optimal.frequency) {
					optimal.frequency = freq;
					optimal.index = i;
				}
			} else {
				if (freq <= suboptimal.frequency) {
					suboptimal.frequency = freq;
					suboptimal.index = i;
				}
			}
			break;
		case DFS_PROFILE_DOWN:
			if (freq >= target_freq) {
				if (freq <= optimal.frequency) {
					optimal.frequency = freq;
					optimal.index = i;
				}
			} else {
				if (freq >= suboptimal.frequency) {
					suboptimal.frequency = freq;
					suboptimal.index = i;
				}
			}
			break;
		}
	}
	if (optimal.index > i) {
		if (suboptimal.index > i)
			return BSP_ERROR;
		*index = suboptimal.index;
	} else
		*index = optimal.index;

	return BSP_OK;
}
/*****************************************************************************
Function:   PWRCTRL_DfsMgrExcuteVoteResultCpu
Description:Handle the Profile Vote Result
Input:      enResult:   The Vote Value
Output:     None
Return:     None
Others:
*****************************************************************************/
static int  cpufreq_excute_result_cpu(u32 relation, u32 target_freq)
{
	u32 result = 2;
	u32 new_index = 0;
	int cur_profile = 0;
	struct cpufreq_msg task_msg = {0,0,0,0};

	cpufreq_frequency_table_target(balong_clockrate_table,
					   target_freq, relation, &new_index);

	cpufreq_debug("target_freq %d new_index%d\n", target_freq, new_index);

	cur_profile = pwrctrl_dfs_get_profile();
	if ((DFS_PROFILE_UP == relation) && (BALONG_FREQ_MAX != cur_profile))
	{
		result = DFS_PROFILE_UP_TARGET;
	}
	else if ((DFS_PROFILE_DOWN == relation) && (BALONG_FREQ_MIN != cur_profile))
	{
		result = DFS_PROFILE_DOWN_TARGET;
	}
	else
	{
		cpufreq_err("set target relation %d, cur pro %d\n", relation, cur_profile);
		return BSP_ERROR;
	}

	cpufreq_frequency_target_profile(balong_clockrate_table[new_index].frequency, relation, &new_index);

	task_msg.msg_type = CPUFREQ_ADJUST_FREQ;
	task_msg.source = CPUFREQ_CCORE;
	task_msg.content = result;
	task_msg.profile = new_index;
	balong_cpufreq_icc_send(&task_msg);
	g_stDfsCpuControl.enCurProfile = (u32)cur_profile;
	return BSP_OK;

}

unsigned int cpufreq_calccpu_cpuload(void)
{
	u32 end_time = 0;
	u32 idle_time = 0;
	u32 wall_time = 0;
	u32 cpu_load = 0;
	unsigned long irqlock = 0;
	local_irq_save(irqlock);
	end_time = bsp_get_slice_value();
	wall_time = get_timer_slice_delta(g_cpufreq_start_time, end_time);
	idle_time = g_ulDfsCcpuIdleTime_long;
	g_cpufreq_start_time = end_time;
	g_ulDfsCcpuIdleTime_long = 0;
	g_flowctrl_in_interr_times = 0;
	cpu_load = (wall_time == 0) ? (0) : (((wall_time - idle_time) * 100) / wall_time);
	local_irq_restore(irqlock);
	if (cpu_load > 100)
	{
		cpu_load = g_ulCCpuload;
		cpufreq_info("cpuload: %d, wall:%d, idle:%d\n", cpu_load, wall_time, idle_time);
	}
	return cpu_load;
}