87 lines
2.2 KiB
C
87 lines
2.2 KiB
C
/*
|
|
* Vexpress big.LITTLE CPUFreq Interface driver
|
|
*
|
|
* It provides necessary ops to arm_big_little cpufreq driver and gets
|
|
* Frequency information from Device Tree. Freq table in DT must be in KHz.
|
|
*
|
|
* Copyright (C) 2013 Linaro.
|
|
* Viresh Kumar <viresh.kumar@linaro.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
|
* kind, whether express or implied; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/cpufreq.h>
|
|
#include <linux/export.h>
|
|
#include <linux/opp.h>
|
|
#include <linux/module.h>
|
|
#include <linux/types.h>
|
|
#include <linux/vexpress.h>
|
|
#include "arm_big_little.h"
|
|
|
|
static int vexpress_init_opp_table(struct device *cpu_dev)
|
|
{
|
|
int i = -1, count, cluster = cpu_to_cluster(cpu_dev->id);
|
|
u32 *table;
|
|
int ret;
|
|
|
|
count = vexpress_spc_get_freq_table(cluster, &table);
|
|
if (!table || !count) {
|
|
pr_err("SPC controller returned invalid freq table");
|
|
return -EINVAL;
|
|
}
|
|
|
|
while (++i < count) {
|
|
/* FIXME: Voltage value */
|
|
ret = opp_add(cpu_dev, table[i] * 1000, 900000);
|
|
if (ret) {
|
|
dev_warn(cpu_dev, "%s: Failed to add OPP %d, err: %d\n",
|
|
__func__, table[i] * 1000, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int vexpress_get_transition_latency(struct device *cpu_dev)
|
|
{
|
|
/* 1 ms */
|
|
return 1000000;
|
|
}
|
|
|
|
static struct cpufreq_arm_bL_ops vexpress_bL_ops = {
|
|
.name = "vexpress-bL",
|
|
.get_transition_latency = vexpress_get_transition_latency,
|
|
.init_opp_table = vexpress_init_opp_table,
|
|
};
|
|
|
|
static int vexpress_bL_init(void)
|
|
{
|
|
if (!vexpress_spc_check_loaded()) {
|
|
pr_info("%s: No SPC found\n", __func__);
|
|
return -ENOENT;
|
|
}
|
|
|
|
return bL_cpufreq_register(&vexpress_bL_ops);
|
|
}
|
|
module_init(vexpress_bL_init);
|
|
|
|
static void vexpress_bL_exit(void)
|
|
{
|
|
return bL_cpufreq_unregister(&vexpress_bL_ops);
|
|
}
|
|
module_exit(vexpress_bL_exit);
|
|
|
|
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
|
MODULE_DESCRIPTION("ARM Vexpress big LITTLE cpufreq driver");
|
|
MODULE_LICENSE("GPL");
|