diff options
-rw-r--r-- | drivers/cpufreq/Kconfig.arm | 9 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 3 | ||||
-rw-r--r-- | drivers/cpufreq/arm_dt_big_little.c | 101 |
3 files changed, 113 insertions, 0 deletions
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 55c53bd742e..84d08cabbac 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -118,6 +118,15 @@ config ARM_BIG_LITTLE_CPUFREQ tristate depends on ARM_CPU_TOPOLOGY +config ARM_DT_BL_CPUFREQ + tristate "Generic ARM big LITTLE CPUfreq driver probed via DT" + select ARM_BIG_LITTLE_CPUFREQ + depends on OF + default y + help + This enables the Generic CPUfreq driver for ARM big.LITTLE platform. + This gets frequency tables from DT. + config ARM_VEXPRESS_BL_CPUFREQ tristate "ARM Vexpress big LITTLE CPUfreq driver" select ARM_BIG_LITTLE_CPUFREQ diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index f26fd28849e..6148eac24fc 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -59,6 +59,9 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o obj-$(CONFIG_ARM_VEXPRESS_BL_CPUFREQ) += vexpress_big_little.o +#Keep DT_BL_CPUFREQ as the last entry in all big LITTLE drivers, so that it is +#probed last. +obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_dt_big_little.o ################################################################################## # PowerPC platform drivers diff --git a/drivers/cpufreq/arm_dt_big_little.c b/drivers/cpufreq/arm_dt_big_little.c new file mode 100644 index 00000000000..2a41854bd4c --- /dev/null +++ b/drivers/cpufreq/arm_dt_big_little.c @@ -0,0 +1,101 @@ +/* + * Generic 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) 2012 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/module.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/types.h> +#include "arm_big_little.h" + +static struct cpufreq_frequency_table *generic_get_freq_tbl(u32 cluster, + int *count) +{ + struct device_node *np = NULL; + const struct property *pp; + unsigned int *table = NULL; + int cluster_id; + struct cpufreq_frequency_table *cpufreq_table; + + while ((np = of_find_node_by_name(np, "cluster"))) { + if (of_property_read_u32(np, "reg", &cluster_id)) + continue; + + if (cluster_id != cluster) + continue; + + pp = of_find_property(np, "freqs", NULL); + if (!pp) + continue; + + *count = pp->length / sizeof(u32); + if (!*count) + continue; + + table = kmalloc(sizeof(*table) * (*count), GFP_KERNEL); + if (!table) { + pr_err("%s: Failed to allocate memory for table\n", + __func__); + return NULL; + } + + of_property_read_u32_array(np, "freqs", table, *count); + break; + } + + if (!table) { + pr_err("%s: Unable to retrieve Freq table from Device Tree", + __func__); + return NULL; + } + + cpufreq_table = arm_bl_copy_table_from_array(table, *count); + kfree(table); + + return cpufreq_table; +} + +static void generic_put_freq_tbl(u32 cluster) +{ + arm_bl_free_freq_table(cluster); +} + +static struct cpufreq_arm_bl_ops generic_bl_ops = { + .name = "generic-bl", + .get_freq_tbl = generic_get_freq_tbl, + .put_freq_tbl = generic_put_freq_tbl, +}; + +static int generic_bl_init(void) +{ + return bl_cpufreq_register(&generic_bl_ops); +} +module_init(generic_bl_init); + +static void generic_bl_exit(void) +{ + return bl_cpufreq_unregister(&generic_bl_ops); +} +module_exit(generic_bl_exit); + +MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver"); +MODULE_LICENSE("GPL"); |