VIM3/VIM3L: support setup max CPU freq in command line
authorNick Xie <nick@khadas.com>
Tue, 21 Jul 2020 06:38:01 +0000 (14:38 +0800)
committerNick Xie <nick@khadas.com>
Thu, 13 Aug 2020 03:27:42 +0000 (11:27 +0800)
Signed-off-by: Nick Xie <nick@khadas.com>
drivers/amlogic/cpufreq/meson-cpufreq.c

index 039272e0dc5427d8e6340920cdfb4358b67b9bc5..3ed0a333855d5c9897e2ebaebb809b62d2221556 100644 (file)
 #include <linux/amlogic/scpi_protocol.h>
 #include "../../base/power/opp/opp.h"
 #include "meson-cpufreq.h"
+#include <linux/amlogic/cpu_version.h>
+
+#define VIM3_A53_DEFAULT       1800000 /* VIM3 Little Core A53 */
+#define VIM3_A73_DEFAULT       2208000 /* VIM3 Big Core A73 */
+#define VIM3L_A55_DEFAULT      1908000 /* VIM3L Core A55 */
+
+
+static unsigned long max_freq[2] = {0, 0};
 
 static unsigned int meson_cpufreq_get_rate(unsigned int cpu)
 {
@@ -574,6 +582,17 @@ static int meson_cpufreq_init(struct cpufreq_policy *policy)
                goto free_reg;
        }
 
+       if (is_meson_g12b_cpu() || is_meson_sm1_cpu()) {
+               int i = 0;
+
+               max_freq[cur_cluster] = min(max_freq[cur_cluster], (unsigned long)get_table_max(freq_table[cur_cluster]));
+               for (i = 0; (freq_table[cur_cluster][i].frequency != CPUFREQ_TABLE_END) && max_freq[cur_cluster]; i++) {
+                       if (freq_table[cur_cluster][i].frequency > max_freq[cur_cluster]) {
+                               freq_table[cur_cluster][i].frequency = CPUFREQ_TABLE_END;
+                       }
+               }
+       }
+
        ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]);
        if (ret) {
                dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
@@ -647,6 +666,51 @@ free_np:
        return ret;
 }
 
+static int __init get_max_freq(unsigned int cluster, char *str)
+{
+       int ret;
+       unsigned long value;
+
+       if (!str || (cluster >= ARRAY_SIZE(max_freq)))
+               return -EINVAL;
+
+       ret = kstrtoul(str, 0, &value);
+       if (ret == 0) {
+               max_freq[cluster] = value * 1000;
+               pr_info("max cpufreq of cluster%d : %ldMHz\n", cluster, max_freq[cluster] / 1000);
+
+               return 0;
+       }
+
+       pr_err("[%s] invalid data, error: %d, str %s\n", __func__, ret, str);
+
+       return -EINVAL;
+}
+
+static int __init get_max_freq_a53(char *str)
+{
+       if (0 == strcmp(machine_model, "Khadas VIM3"))
+               return get_max_freq(0, str);
+       return -EINVAL;
+}
+__setup("max_freq_a53=", get_max_freq_a53);
+
+static int __init get_max_freq_a55(char *str)
+{
+       if (0 == strcmp(machine_model, "Khadas VIM3L"))
+               return get_max_freq(0, str);
+       return -EINVAL;
+}
+__setup("max_freq_a55=", get_max_freq_a55);
+
+static int __init get_max_freq_a73(char *str)
+{
+       if (0 == strcmp(machine_model, "Khadas VIM3"))
+               return get_max_freq(1, str);
+       return -EINVAL;
+}
+__setup("max_freq_a73=", get_max_freq_a73);
+
 static int meson_cpufreq_exit(struct cpufreq_policy *policy)
 {
        struct device *cpu_dev;
@@ -737,6 +801,18 @@ static int meson_cpufreq_probe(struct platform_device *pdev)
        unsigned int cpu = 0;
        int ret, i;
 
+       if (is_meson_g12b_cpu()) {
+               if (!max_freq[0]) {
+                       max_freq[0] = VIM3_A53_DEFAULT;
+               }
+               if (!max_freq[1]) {
+                       max_freq[1] = VIM3_A73_DEFAULT;
+               }
+       } else if (is_meson_sm1_cpu()) {
+               if (!max_freq[0])
+                       max_freq[0] = VIM3L_A55_DEFAULT;
+       }
+
        for (i = 0; i < MAX_CLUSTERS; i++)
                mutex_init(&cluster_lock[i]);