修复nanopi t2 cpu调频不起作用
nanopi t2 s5p4418超频
驱动相关文件
内核版本:linux-3.4.y
相关代码:
drivers/cpufreq/nxp-cpufreq.c
驱动主逻辑
drivers/cpufreq/s5p4418-cpufreq.c
驱动预设配置
arch/plat-s5p4418/nanopi2/device.c
自定义配置
频率电压表
有两个配置相应的就会有两个频率电压表
drivers/cpufreq/s5p4418-cpufreq.c
#define ASB_FREQ_MHZ { \
[ 0] = 1600, \
[ 1] = 1500, \
[ 2] = 1400, \
[ 3] = 1300, \
[ 4] = 1200, \
[ 5] = 1100, \
[ 6] = 1000, \
[ 7] = 900, \
[ 8] = 800, \
[ 9] = 700, \
[10] = 600, \
[11] = 500, \
[12] = 400, \
}
static struct asv_tb_info asv_tables[] = {
[0] = { .ids = 10, .ro = 110,
.Mhz = ASB_FREQ_MHZ,
.uV = { UV(1350), UV(1350), /* OVER FREQ */
UV(1350), UV(1300), UV(1250), UV(1200), UV(1175), UV(1150),
UV(1125), UV(1100), UV(1075), UV(1075), UV(1075) },
},
[1] = { .ids = 15, .ro = 130,
.Mhz = ASB_FREQ_MHZ,
.uV = { UV(1300), UV(1300), /* OVER FREQ */
UV(1300), UV(1250), UV(1200), UV(1150), UV(1125), UV(1100),
UV(1075), UV(1050), UV(1025), UV(1025), UV(1025) },
},
[2] = { .ids = 20, .ro = 140,
.Mhz = ASB_FREQ_MHZ,
.uV = { UV(1250), UV(1250), /* OVER FREQ */
UV(1250), UV(1200), UV(1150), UV(1100), UV(1075), UV(1050),
UV(1025), UV(1000), UV(1000), UV(1000), UV(1000) },
},
[3] = { .ids = 50, .ro = 170,
.Mhz = ASB_FREQ_MHZ,
.uV = { UV(1200), UV(1200), /* OVER FREQ */
UV(1200), UV(1150), UV(1100), UV(1050), UV(1025), UV(1000),
UV(1000), UV(1000), UV(1000), UV(1000), UV(1000) },
},
[4] = { .ids = 50, .ro = 170,
.Mhz = ASB_FREQ_MHZ,
.uV = { UV(1175), UV(1175), /* OVER FREQ */
UV(1175), UV(1100), UV(1050), UV(1000), UV(1000), UV(1000),
UV(1000), UV(1000), UV(1000), UV(1000), UV(1000) },
},
};
#define ASV_ARRAY_SIZE ARRAY_SIZE(asv_tables)
驱动预设值里面已经由1500Mhz以及1600Mhz的频率电压配置了,可以参考这个配置超频
arch/plat-s5p4418/nanopi2/device.c
#if defined(CONFIG_ARM_NXP_CPUFREQ)
static unsigned long dfs_freq_table[][2] = {
{ 1400000, 1260000, },
{ 1200000, 1200000, },
{ 1000000, 1140000, },
{ 800000, 1100000, },
{ 700000, 1080000, },
{ 600000, 1040000, },
{ 500000, 1040000, },
{ 400000, 1040000, },
};
struct nxp_cpufreq_plat_data dfs_plat_data = {
.pll_dev = CONFIG_NXP_CPUFREQ_PLLDEV,
.supply_name = "vdd_arm_1.3V", // refer to CONFIG_REGULATOR_NXE2000
.freq_table = dfs_freq_table,
.table_size = ARRAY_SIZE(dfs_freq_table),
.max_cpufreq = 1400*1000,
.max_retention = 10*1000,
.rest_cpufreq = 800*1000,
.rest_retention = 2*1000,
.fixed_voltage = 1280*1000,
};
可以看到频率表定义最高只到了1400Mhz,下面吧它超到1600Mhz
频率表加载逻辑
频率表加载在nxp_cpufreq_make_table
函数完成
static void *nxp_cpufreq_make_table(struct platform_device *pdev,
int *table_size, unsigned long (*dvfs_tables)[2])
{
struct nxp_cpufreq_plat_data *pdata = pdev->dev.platform_data;
struct cpufreq_frequency_table *freq_table;
struct cpufreq_asv_ops *ops = &asv_ops;
unsigned long (*plat_tbs)[2] = NULL;
unsigned long plat_n_voltage = 0;
int tb_size, asv_size = 0;
int id = 0, n = 0;
/* user defined dvfs */
if (pdata->freq_table && pdata->table_size)
plat_tbs = (unsigned long(*)[2])pdata->freq_table;
/* asv dvfs tables */
if (ops->setup_table)
asv_size = ops->setup_table(dvfs_tables);
if (!pdata->table_size && !asv_size) {
dev_err(&pdev->dev, "failed no freq table !!!\n");
return NULL;
}
tb_size = (pdata->table_size ? pdata->table_size : asv_size);
/* alloc with end table */
freq_table = kzalloc((sizeof(*freq_table) * (tb_size + 1)), GFP_KERNEL);
if (!freq_table) {
dev_err(&pdev->dev, "failed allocate freq table !!!\n");
return NULL;
}
/* make frequency table with platform data */
if (asv_size > 0) {
for (n = 0, id = 0; tb_size > id && asv_size > n; n++) {
if (plat_tbs && plat_tbs[id][1] > 0)
plat_n_voltage = plat_tbs[id][1];
if (plat_n_voltage) {
dvfs_tables[id][0] = plat_tbs[id][0]; /* frequency */
dvfs_tables[id][1] = plat_n_voltage; /* voltage */
} else if (plat_tbs) {
for (n = 0; asv_size > n; n++) {
if (plat_tbs[id][0] == dvfs_tables[n][0]) {
dvfs_tables[id][0] = dvfs_tables[n][0]; /* frequency */
dvfs_tables[id][1] = dvfs_tables[n][1]; /* voltage */
break;
}
}
} else {
if (dvfs_tables[n][0] > FREQ_MAX_FREQ_KHZ)
continue;
dvfs_tables[id][0] = dvfs_tables[n][0]; /* frequency */
dvfs_tables[id][1] = dvfs_tables[n][1]; /* voltage */
}
freq_table[id].index = id;
freq_table[id].frequency = dvfs_tables[id][0];
printk(KERN_DEBUG "ASV %2d = %8ld khz, %4ld mV\n", id,
dvfs_tables[id][0], dvfs_tables[id][1]/1000);
/* next */
id++;
}
} else {
for (id = 0; tb_size > id; id++) {
dvfs_tables[id][0] = plat_tbs[id][0]; /* frequency */
dvfs_tables[id][1] = plat_tbs[id][1]; /* voltage */
freq_table[id].index = id;
freq_table[id].frequency = dvfs_tables[id][0];
printk("DTB %2d = %8ldkhz, %8ld uV \n", id, dvfs_tables[id][0], dvfs_tables[id][1]);
}
}
/* End table */
freq_table[id].index = id;
freq_table[id].frequency = CPUFREQ_TABLE_END;
*table_size = id;
return (void*)freq_table;
}
pdev
为arch/plat-s5p4418/nanopi2/device.c
频率电压表配置
dvfs_tables
为drivers/cpufreq/s5p4418-cpufreq.c
频率电压表配置
可以看到pdev
的优先级更高,所以参考驱动预设值修改arch/plat-s5p4418/nanopi2/device.c
即可
添加频率表加到1600Mhz,最大频率也改成1600Mhz,不是使用电池,电压就不吝啬了,直接上到最高1.35V,稳定超频
效果
[root@minicoco ~]# cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_fr
equencies
1600000 1500000 1400000 1200000 1000000 800000 700000 600000 500000 400000
[root@minicoco ~]#
成功,收工