From: "Hector.Yuan" <hector.y...@mediatek.com>

Register CPU power table to energy model framework

Signed-off-by: Hector.Yuan <hector.y...@mediatek.com>
---
 drivers/cpufreq/mediatek-cpufreq-hw.c |   50 +++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c 
b/drivers/cpufreq/mediatek-cpufreq-hw.c
index 8fa12e5..3808ea0 100644
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
@@ -5,6 +5,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/cpufreq.h>
+#include <linux/energy_model.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -17,9 +18,10 @@
 #define LUT_ROW_SIZE                   0x4
 
 enum {
-       REG_LUT_TABLE,
-       REG_ENABLE,
-       REG_PERF_STATE,
+       REG_FREQ_LUT_TABLE,
+       REG_FREQ_ENABLE,
+       REG_FREQ_PERF_STATE,
+       REG_EM_POWER_TBL,
 
        REG_ARRAY_SIZE,
 };
@@ -27,23 +29,44 @@ enum {
 struct cpufreq_mtk {
        struct cpufreq_frequency_table *table;
        void __iomem *reg_bases[REG_ARRAY_SIZE];
+       int nr_opp;
        cpumask_t related_cpus;
 };
 
 static const u16 cpufreq_mtk_offsets[REG_ARRAY_SIZE] = {
-       [REG_LUT_TABLE]         = 0x0,
-       [REG_ENABLE]            = 0x84,
-       [REG_PERF_STATE]        = 0x88,
+       [REG_FREQ_LUT_TABLE]    = 0x0,
+       [REG_FREQ_ENABLE]       = 0x84,
+       [REG_FREQ_PERF_STATE]   = 0x88,
+       [REG_EM_POWER_TBL]      = 0x3D0,
 };
 
 static struct cpufreq_mtk *mtk_freq_domain_map[NR_CPUS];
 
+static int mtk_cpufreq_get_cpu_power(unsigned long *mW,
+                                    unsigned long *KHz, int cpu)
+{
+       struct cpufreq_mtk *c = mtk_freq_domain_map[cpu];
+       int i;
+
+       for (i = 0; i < c->nr_opp; i++) {
+               if (c->table[i].frequency < *KHz)
+                       break;
+       }
+       i--;
+
+       *KHz = c->table[i].frequency;
+       *mW = readl_relaxed(c->reg_bases[REG_EM_POWER_TBL] +
+                           i * LUT_ROW_SIZE) / 1000;
+
+       return 0;
+}
+
 static int mtk_cpufreq_hw_target_index(struct cpufreq_policy *policy,
                                       unsigned int index)
 {
        struct cpufreq_mtk *c = policy->driver_data;
 
-       writel_relaxed(index, c->reg_bases[REG_PERF_STATE]);
+       writel_relaxed(index, c->reg_bases[REG_FREQ_PERF_STATE]);
 
        return 0;
 }
@@ -55,7 +78,7 @@ static unsigned int mtk_cpufreq_hw_get(unsigned int cpu)
 
        c = mtk_freq_domain_map[cpu];
 
-       index = readl_relaxed(c->reg_bases[REG_PERF_STATE]);
+       index = readl_relaxed(c->reg_bases[REG_FREQ_PERF_STATE]);
        index = min(index, LUT_MAX_ENTRIES - 1);
 
        return c->table[index].frequency;
@@ -64,6 +87,7 @@ static unsigned int mtk_cpufreq_hw_get(unsigned int cpu)
 static int mtk_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpufreq_mtk *c;
+       struct em_data_callback em_cb = EM_DATA_CB(mtk_cpufreq_get_cpu_power);
 
        c = mtk_freq_domain_map[policy->cpu];
        if (!c) {
@@ -77,7 +101,8 @@ static int mtk_cpufreq_hw_cpu_init(struct cpufreq_policy 
*policy)
        policy->driver_data = c;
 
        /* HW should be in enabled state to proceed now */
-       writel_relaxed(0x1, c->reg_bases[REG_ENABLE]);
+       writel_relaxed(0x1, c->reg_bases[REG_FREQ_ENABLE]);
+       em_register_perf_domain(policy->cpus, c->nr_opp, &em_cb);
 
        return 0;
 }
@@ -93,7 +118,7 @@ static int mtk_cpufreq_hw_cpu_exit(struct cpufreq_policy 
*policy)
        }
 
        /* HW should be in paused state now */
-       writel_relaxed(0x0, c->reg_bases[REG_ENABLE]);
+       writel_relaxed(0x0, c->reg_bases[REG_FREQ_ENABLE]);
 
        return 0;
 }
@@ -122,7 +147,7 @@ static int mtk_cpu_create_freq_table(struct platform_device 
*pdev,
        if (!c->table)
                return -ENOMEM;
 
-       base_table = c->reg_bases[REG_LUT_TABLE];
+       base_table = c->reg_bases[REG_FREQ_LUT_TABLE];
 
        for (i = 0; i < LUT_MAX_ENTRIES; i++) {
                data = readl_relaxed(base_table + (i * LUT_ROW_SIZE));
@@ -140,6 +165,7 @@ static int mtk_cpu_create_freq_table(struct platform_device 
*pdev,
        }
 
        c->table[i].frequency = CPUFREQ_TABLE_END;
+       c->nr_opp = i;
 
        return 0;
 }
@@ -192,7 +218,7 @@ static int mtk_cpu_resources_init(struct platform_device 
*pdev,
        if (IS_ERR(base))
                return PTR_ERR(base);
 
-       for (i = REG_LUT_TABLE; i < REG_ARRAY_SIZE; i++)
+       for (i = REG_FREQ_LUT_TABLE; i < REG_ARRAY_SIZE; i++)
                c->reg_bases[i] = base + offsets[i];
 
        ret = mtk_get_related_cpus(index, c);
-- 
1.7.9.5

Reply via email to