ddrfreq: add more auto freq point
author陈亮 <cl@rock-chips.com>
Wed, 7 May 2014 13:30:33 +0000 (06:30 -0700)
committer陈亮 <cl@rock-chips.com>
Wed, 7 May 2014 13:30:33 +0000 (06:30 -0700)
arch/arm/boot/dts/rk3288-p977.dts
arch/arm/boot/dts/rk3288-tb.dts
arch/arm/mach-rockchip/ddr_freq.c [changed mode: 0755->0644]
include/dt-bindings/clock/ddr.h

index 53f4b404e6f218ff1eb7103faf1721d71a8d69f5..ea09ace26805b11ef92fe50fe950c9da53e4c0a5 100755 (executable)
                533000 1050000
                >;
 
-       freq_table = <
+       freq-table = <
                /*status                freq(KHz)*/
                SYS_STATUS_NORMAL       400000
                SYS_STATUS_SUSPEND      200000
                SYS_STATUS_VIDEO        300000
                SYS_STATUS_DUALVIEW     500000
+               SYS_STATUS_BOOST        324000
                >;
-       auto_freq=<1>;
+       auto-freq-table = <
+               240000
+               324000
+               396000
+               528000
+               >;
+       auto-freq=<1>;
        status="okay";
 };
 
index fcf27607c3c5205a4af172630da2c08a47864868..fefdd2fa1be31776a302f323c787fac5fc494be6 100755 (executable)
@@ -682,14 +682,21 @@ rockchip,power_type = <GPIO>;
                533000 1050000
                >;
 
-       freq_table = <
+       freq-table = <
                /*status                freq(KHz)*/
                SYS_STATUS_NORMAL       400000
                SYS_STATUS_SUSPEND      200000
                SYS_STATUS_VIDEO        300000
                SYS_STATUS_DUALVIEW     500000
+               SYS_STATUS_BOOST        324000
                >;
-       auto_freq=<1>;
+       auto-freq-table = <
+               240000
+               324000
+               396000
+               528000
+               >;
+       auto-freq=<1>;
        status="okay";
 };
 
old mode 100755 (executable)
new mode 100644 (file)
index 2f02479..c9a5fee
@@ -1,4 +1,5 @@
 #define pr_fmt(fmt) "ddrfreq: " fmt
+#define DEBUG
 #include <linux/clk.h>
 #include <linux/fb.h>
 #include <linux/cpu.h>
 extern int rockchip_cpufreq_reboot_limit_freq(void);
 
 static struct dvfs_node *clk_cpu_dvfs_node = NULL;
-static int ddr_boost = 0;
 static int reboot_config_done = 0;
+static int ddr_boost = 0;
+static int print=0;
+static int watch=0;
+static int high_load = 70;
+static int low_load = 60;
+static int auto_freq_interval_ms = 20;
+static int high_load_last_ms = 0;
+static int low_load_last_ms = 200;
+static unsigned long *auto_freq_table = NULL;
+static int cur_freq_index;
+static int auto_freq_table_size;
 
 enum {
        DEBUG_DDR = 1U << 0,
@@ -41,7 +52,23 @@ enum {
 static int debug_mask = DEBUG_DDR;
 
 module_param(debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
-#define dprintk(mask, fmt, ...) do { if (mask & debug_mask) pr_info(fmt, ##__VA_ARGS__); } while (0)
+#define dprintk(mask, fmt, ...) do { if (mask & debug_mask) pr_debug(fmt, ##__VA_ARGS__); } while (0)
+
+enum ddr_bandwidth_id{
+    ddrbw_wr_num=0,
+    ddrbw_rd_num,
+    ddrbw_act_num,
+    ddrbw_time_num,
+    ddrbw_eff,
+    ddrbw_id_end
+};
+
+#define  ddr_monitor_start() grf_writel((((readl_relaxed(RK_PMU_VIRT + 0x9c)>>13)&7)==3)?0xc000c000:0xe000e000,RK3288_GRF_SOC_CON4)
+#define  ddr_monitor_stop() grf_writel(0xc0000000,RK3288_GRF_SOC_CON4)
+
+#define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
+#define grf_writel(v, offset)  do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
+
 
 #define MHZ    (1000*1000)
 #define KHZ    1000
@@ -54,6 +81,7 @@ struct ddr {
        unsigned long idle_rate;
        unsigned long suspend_rate;
        unsigned long reboot_rate;
+       unsigned long boost_rate;
        bool auto_freq;
        bool auto_self_refresh;
        char *mode;
@@ -67,6 +95,38 @@ module_param_named(sys_status, ddr.sys_status, ulong, S_IRUGO);
 module_param_named(auto_self_refresh, ddr.auto_self_refresh, bool, S_IRUGO);
 module_param_named(mode, ddr.mode, charp, S_IRUGO);
 
+static unsigned long get_freq_from_table(unsigned long freq)
+{
+       int i;
+
+       if (!auto_freq_table)
+               return 0;
+
+       for (i = 0; auto_freq_table[i] != 0; i++) {
+               if (auto_freq_table[i] >= freq) {
+                       return auto_freq_table[i];
+               }
+       }
+
+       return auto_freq_table[i-1];
+}
+
+static unsigned long get_index_from_table(unsigned long freq)
+{
+       int i;
+
+       if (!auto_freq_table)
+               return 0;
+
+       for (i = 0; auto_freq_table[i] != 0; i++) {
+               if (auto_freq_table[i] >= freq) {
+                       return i;
+               }
+       }
+       return i-1;
+}
+
+
 static noinline void ddrfreq_set_sys_status(int status)
 {
        ddr.sys_status |= status;
@@ -90,8 +150,12 @@ static void ddrfreq_mode(bool auto_self_refresh, unsigned long *target_rate, cha
                ddr.auto_self_refresh = auto_self_refresh;
                dprintk(DEBUG_DDR, "change auto self refresh to %d when %s\n", auto_self_refresh, name);
        }
+
+       cur_freq_index = get_index_from_table(*target_rate);
+
        if (*target_rate != dvfs_clk_get_rate(ddr.clk_dvfs_node)) {
                freq_limit_en = dvfs_clk_get_limit(clk_cpu_dvfs_node, &min_rate, &max_rate);
+
                dvfs_clk_enable_limit(clk_cpu_dvfs_node, 600000000, -1);
                if (dvfs_clk_set_rate(ddr.clk_dvfs_node, *target_rate) == 0) {
                        *target_rate = dvfs_clk_get_rate(ddr.clk_dvfs_node);
@@ -106,127 +170,6 @@ static void ddrfreq_mode(bool auto_self_refresh, unsigned long *target_rate, cha
        }
 }
 
-static void ddr_freq_input_event(struct input_handle *handle, unsigned int type,
-               unsigned int code, int value)
-{
-       if (type == EV_ABS)
-               ddr_boost = 1;
-}
-
-static int ddr_freq_input_connect(struct input_handler *handler,
-               struct input_dev *dev, const struct input_device_id *id)
-{
-       struct input_handle *handle;
-       int error;
-
-       handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
-       if (!handle)
-               return -ENOMEM;
-
-       handle->dev = dev;
-       handle->handler = handler;
-       handle->name = "ddr_freq";
-
-       error = input_register_handle(handle);
-       if (error)
-               goto err2;
-
-       error = input_open_device(handle);
-       if (error)
-               goto err1;
-
-       return 0;
-err1:
-       input_unregister_handle(handle);
-err2:
-       kfree(handle);
-       return error;
-}
-
-static void ddr_freq_input_disconnect(struct input_handle *handle)
-{
-       input_close_device(handle);
-       input_unregister_handle(handle);
-       kfree(handle);
-}
-
-static const struct input_device_id ddr_freq_ids[] = {
-       
-       {
-               .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
-                       INPUT_DEVICE_ID_MATCH_ABSBIT,
-               .evbit = { BIT_MASK(EV_ABS) },
-               .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
-                       BIT_MASK(ABS_MT_POSITION_X) |
-                       BIT_MASK(ABS_MT_POSITION_Y) },
-       },
-       
-       {
-               .flags = INPUT_DEVICE_ID_MATCH_KEYBIT |
-                       INPUT_DEVICE_ID_MATCH_ABSBIT,
-               .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
-               .absbit = { [BIT_WORD(ABS_X)] =
-                       BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
-       },
-       
-       {
-               .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
-               .evbit = { BIT_MASK(EV_KEY) },
-       },
-       { },
-};
-
-static struct input_handler ddr_freq_input_handler = {
-       .event          = ddr_freq_input_event,
-       .connect        = ddr_freq_input_connect,
-       .disconnect     = ddr_freq_input_disconnect,
-       .name           = "ddr_freq",
-       .id_table       = ddr_freq_ids,
-};
-
-enum ddr_bandwidth_id{
-    ddrbw_wr_num=0,
-    ddrbw_rd_num,
-    ddrbw_act_num,
-    ddrbw_time_num,  
-    ddrbw_eff,
-    ddrbw_id_end
-};
-
-
-
-#define DDR_BOOST_HOLD_MS      300
-#define HIGH_LOAD_HOLD_MS      300
-#define HIGH_LOAD_DELAY_MS     0
-#define LOW_LOAD_DELAY_MS      200
-#define DDR_BOOST_HOLD         (DDR_BOOST_HOLD_MS/ddrbw_work_delay_ms)
-#define HIGH_LOAD_HOLD         (DDR_BOOST_HOLD_MS/ddrbw_work_delay_ms)
-#define HIGH_LOAD_DELAY                (HIGH_LOAD_DELAY_MS/ddrbw_work_delay_ms)
-#define LOW_LOAD_DELAY         (LOW_LOAD_DELAY_MS/ddrbw_work_delay_ms)
-#define DDR_RATE_NORMAL        240000000
-#define DDR_RATE_BOOST         324000000
-#define DDR_RATE_HIGH_LOAD     533000000
-#define DDR_RATE_1080P         240000000
-#define DDR_RATE_4K            300000000
-#define HIGH_LOAD_NORMAL       70
-#define HGIH_LOAD_VIDEO                50
-
-static struct workqueue_struct *ddr_freq_wq;
-static u32 high_load = HIGH_LOAD_NORMAL;
-static u32 ddrbw_work_delay_ms = 20; 
-static u32 ddr_rate_normal = DDR_RATE_NORMAL;
-static u32 ddr_rate_boost = DDR_RATE_BOOST;
-static u32 ddr_rate_high_load = DDR_RATE_HIGH_LOAD;
-
-
-//#define  ddr_monitor_start() grf_writel(0xc000c000,RK3288_GRF_SOC_CON4)
-#define  ddr_monitor_start() grf_writel((((readl_relaxed(RK_PMU_VIRT + 0x9c)>>13)&7)==3)?0xc000c000:0xe000e000,RK3288_GRF_SOC_CON4)
-#define  ddr_monitor_stop() grf_writel(0xc0000000,RK3288_GRF_SOC_CON4)
-
-#define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
-#define grf_writel(v, offset)  do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
-
-
 void ddr_bandwidth_get(u32 *ch0_eff, u32 *ch1_eff)
 {
        u32 ddr_bw_val[2][ddrbw_id_end];
@@ -250,63 +193,64 @@ void ddr_bandwidth_get(u32 *ch0_eff, u32 *ch1_eff)
        *ch1_eff = temp64;
 }
 
-
-static void ddrbw_work_fn(struct work_struct *work)
+static void ddr_auto_freq(void)
 {
-       unsigned long rate;
-       u32 ch0_eff, ch1_eff;
-       static u32 ddr_boost_hold=0, high_load_hold=0;
-       static u32 high_load_delay = 0, low_load_delay = 0;
+       unsigned long freq;
+       u32 ch0_eff, ch1_eff, max_eff;
+       static u32 high_load_last = 0, low_load_last = 0;
+
+       freq = dvfs_clk_get_rate(ddr.clk_dvfs_node);
        
        ddr_monitor_stop();
         ddr_bandwidth_get(&ch0_eff, &ch1_eff);
+       max_eff = (ch0_eff > ch1_eff) ? ch0_eff : ch1_eff;
+
+       if (watch) {
+               printk("%d %d\n", ch0_eff, ch1_eff);
+               ddr_monitor_start();
+               return;
+       }
+
+       if (print) {
+               printk("%d %d\n", ch0_eff, ch1_eff);
+       }
 
        if (ddr_boost) {
                ddr_boost = 0;
-               //dvfs_clk_set_rate(ddr.clk_dvfs_node, DDR_BOOST_RATE);
-               if (!high_load_hold && !low_load_delay) {
-                       rate = ddr_rate_boost;
-                       ddrfreq_mode(false, &rate, "boost");
-                       ddr_boost_hold = DDR_BOOST_HOLD;
+               if (freq < ddr.boost_rate) {
+                       low_load_last = low_load_last_ms/auto_freq_interval_ms;
+                       freq = ddr.boost_rate;
+                       ddrfreq_mode(false, &freq, "boost");
                }
-       } else if(!ddr_boost_hold && ((ch0_eff>high_load)||(ch1_eff>high_load))){
-               low_load_delay = LOW_LOAD_DELAY;
-               if (!high_load_delay) {
-                       //dvfs_clk_set_rate(ddr.clk_dvfs_node, HIGH_LOAD_RATE);
-                       rate = ddr_rate_high_load;
-                       ddrfreq_mode(false, &rate, "high load");
-                       high_load_hold = HIGH_LOAD_HOLD;
+       } else if(max_eff > high_load){
+               low_load_last = low_load_last_ms/auto_freq_interval_ms;
+               if (!high_load_last) {
+                       if (cur_freq_index < auto_freq_table_size-1) {
+                               freq = auto_freq_table[cur_freq_index+1];
+                               ddrfreq_mode(false, &freq, "high load");
+                       }
                } else {
-                       high_load_delay--;
+                       high_load_last--;
                }
-       } else {
-               if (ddr_boost_hold) {
-                       ddr_boost_hold--;
-               } else if (high_load_hold) {
-                       high_load_hold--;
+       } else if (max_eff < low_load){
+               high_load_last = high_load_last_ms/auto_freq_interval_ms;
+               if (!low_load_last) {
+                       freq = max_eff*(freq/low_load);
+                       freq = get_freq_from_table(freq);
+                       ddrfreq_mode(false, &freq, "low load");
                } else {
-                       high_load_delay = HIGH_LOAD_DELAY;
-                       //dvfs_clk_set_rate(ddr.clk_dvfs_node, DDR_NORMAL_RATE);
-                       if (!low_load_delay) {
-                               rate = ddr_rate_normal;
-                               ddrfreq_mode(false, &rate, "normal");
-                       } else {
-                               low_load_delay--;
-                       }
+                       low_load_last--;
                }
-         }
+       }
 
        ddr_monitor_start();
-
-       queue_delayed_work_on(0, ddr_freq_wq, to_delayed_work(work), HZ*ddrbw_work_delay_ms/1000);
 }
 
-static DECLARE_DELAYED_WORK(ddrbw_work, ddrbw_work_fn);
-
-static noinline void ddrfreq_work(unsigned long sys_status)
+static noinline long ddrfreq_work(unsigned long sys_status)
 {
        static struct clk *cpu = NULL;
        static struct clk *gpu = NULL;
+       long timeout = MAX_SCHEDULE_TIMEOUT;
        unsigned long s = sys_status;
 
        if (!cpu)
@@ -315,9 +259,6 @@ static noinline void ddrfreq_work(unsigned long sys_status)
                gpu = clk_get(NULL, "gpu");
        
        dprintk(DEBUG_VERBOSE, "sys_status %02lx\n", sys_status);
-
-       if (ddr.auto_freq)
-               cancel_delayed_work_sync(&ddrbw_work);
        
        if (ddr.reboot_rate && (s & SYS_STATUS_REBOOT)) {
                ddrfreq_mode(false, &ddr.reboot_rate, "shutdown/reboot");
@@ -341,22 +282,29 @@ static noinline void ddrfreq_work(unsigned long sys_status)
                ) {
                ddrfreq_mode(false, &ddr.idle_rate, "idle");
        } else {
-               if (ddr.auto_freq)
-                       queue_delayed_work_on(0, ddr_freq_wq, &ddrbw_work, 0);
-               else
+               if (ddr.auto_freq) {
+                       ddr_auto_freq();
+                       timeout = auto_freq_interval_ms;
+               }
+               else {
                        ddrfreq_mode(false, &ddr.normal_rate, "normal");
+               }
        }
+
+       return timeout;
 }
 
 static int ddrfreq_task(void *data)
 {
+       long timeout;
+
        set_freezable();
 
        do {
                unsigned long status = ddr.sys_status;
-               ddrfreq_work(status);
-               wait_event_freezable(ddr.wait, (status != ddr.sys_status) || kthread_should_stop());
-       } while (!kthread_should_stop() && !reboot_config_done);
+               timeout = ddrfreq_work(status);
+               wait_event_freezable_timeout(ddr.wait, (status != ddr.sys_status) || kthread_should_stop(), timeout);
+       } while (!kthread_should_stop());
 
        return 0;
 }
@@ -364,7 +312,6 @@ static int ddrfreq_task(void *data)
 static int video_state_release(struct inode *inode, struct file *file)
 {
        dprintk(DEBUG_VIDEO_STATE, "video_state release\n");
-       ddrfreq_clear_sys_status(SYS_STATUS_VIDEO);
        return 0;
 }
 
@@ -412,16 +359,14 @@ static ssize_t video_state_write(struct file *file, const char __user *buffer,
 
        switch (state) {
        case '0':
-               high_load = HIGH_LOAD_NORMAL;
-               ddr_rate_normal = DDR_RATE_NORMAL;
-               ddr_rate_high_load = DDR_RATE_HIGH_LOAD;
+               high_load = 70;
+               low_load = 60;
                if (!ddr.auto_freq)
                        ddrfreq_clear_sys_status(SYS_STATUS_VIDEO);
                break;
        case '1':
-               high_load = HGIH_LOAD_VIDEO;
-               ddr_rate_normal = DDR_RATE_1080P;
-               ddr_rate_high_load = DDR_RATE_4K;
+               high_load = 35;
+               low_load = 25;
                if( (v_width == 0) && (v_height == 0)){
                        if (!ddr.auto_freq)
                                ddrfreq_set_sys_status(SYS_STATUS_VIDEO_1080P);
@@ -458,6 +403,83 @@ static struct miscdevice video_state_dev = {
        .name   = "video_state",
        .minor  = MISC_DYNAMIC_MINOR,
 };
+
+static void ddr_freq_input_event(struct input_handle *handle, unsigned int type,
+               unsigned int code, int value)
+{
+       if (type == EV_ABS)
+               ddr_boost = 1;
+}
+
+static int ddr_freq_input_connect(struct input_handler *handler,
+               struct input_dev *dev, const struct input_device_id *id)
+{
+       struct input_handle *handle;
+       int error;
+
+       handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
+       if (!handle)
+               return -ENOMEM;
+
+       handle->dev = dev;
+       handle->handler = handler;
+       handle->name = "ddr_freq";
+
+       error = input_register_handle(handle);
+       if (error)
+               goto err2;
+
+       error = input_open_device(handle);
+       if (error)
+               goto err1;
+
+       return 0;
+err1:
+       input_unregister_handle(handle);
+err2:
+       kfree(handle);
+       return error;
+}
+
+static void ddr_freq_input_disconnect(struct input_handle *handle)
+{
+       input_close_device(handle);
+       input_unregister_handle(handle);
+       kfree(handle);
+}
+
+static const struct input_device_id ddr_freq_ids[] = {
+       {
+               .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
+                       INPUT_DEVICE_ID_MATCH_ABSBIT,
+               .evbit = { BIT_MASK(EV_ABS) },
+               .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
+                       BIT_MASK(ABS_MT_POSITION_X) |
+                       BIT_MASK(ABS_MT_POSITION_Y) },
+       },
+       {
+               .flags = INPUT_DEVICE_ID_MATCH_KEYBIT |
+                       INPUT_DEVICE_ID_MATCH_ABSBIT,
+               .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
+               .absbit = { [BIT_WORD(ABS_X)] =
+                       BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
+       },
+       {
+               .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+               .evbit = { BIT_MASK(EV_KEY) },
+       },
+       { },
+};
+
+static struct input_handler ddr_freq_input_handler = {
+       .event          = ddr_freq_input_event,
+       .connect        = ddr_freq_input_connect,
+       .disconnect     = ddr_freq_input_disconnect,
+       .name           = "ddr_freq",
+       .id_table       = ddr_freq_ids,
+};
+
+
 /*
 static int ddrfreq_clk_event(int status, unsigned long event)
 {
@@ -511,7 +533,6 @@ static int ddrfreq_reboot_notifier_event(struct notifier_block *this, unsigned l
        if (!timeout) {
                pr_err("failed to set ddr clk from %luMHz to %luMHz when shutdown/reboot\n", dvfs_clk_get_rate(ddr.clk_dvfs_node) / MHZ, ddr.reboot_rate / MHZ);
        }
-
        return NOTIFY_OK;
 }
 
@@ -519,12 +540,44 @@ static struct notifier_block ddrfreq_reboot_notifier = {
        .notifier_call = ddrfreq_reboot_notifier_event,
 };
 
+static int ddr_freq_suspend_notifier_call(struct notifier_block *self,
+                               unsigned long action, void *data)
+{
+       struct fb_event *event = data;
+       int blank_mode = *((int *)event->data);
+
+       if (action == FB_EARLY_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_UNBLANK:
+                       ddrfreq_clear_sys_status(SYS_STATUS_SUSPEND);
+                       break;
+               default:
+                       break;
+               }
+       }
+       else if (action == FB_EVENT_BLANK) {
+               switch (blank_mode) {
+               case FB_BLANK_POWERDOWN:
+                       ddrfreq_set_sys_status(SYS_STATUS_SUSPEND);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block ddr_freq_suspend_notifier = {
+               .notifier_call = ddr_freq_suspend_notifier_call,
+};
+
 int of_init_ddr_freq_table(void)
 {
        struct device_node *clk_ddr_dev_node;
        const struct property *prop;
        const __be32 *val;
-       int nr;
+       int nr, i=0;
        
        clk_ddr_dev_node = of_find_node_by_name(NULL, "clk_ddr");
        if (IS_ERR_OR_NULL(clk_ddr_dev_node)) {
@@ -532,11 +585,24 @@ int of_init_ddr_freq_table(void)
                return PTR_ERR(clk_ddr_dev_node);
        }
 
-       prop = of_find_property(clk_ddr_dev_node, "auto_freq", NULL);
+       prop = of_find_property(clk_ddr_dev_node, "auto-freq", NULL);
        if (prop && prop->value)
                ddr.auto_freq = be32_to_cpup(prop->value);
 
-       prop = of_find_property(clk_ddr_dev_node, "freq_table", NULL);
+       prop = of_find_property(clk_ddr_dev_node, "auto-freq-table", NULL);
+       if (prop && prop->value) {
+               nr = prop->length / sizeof(u32);
+               auto_freq_table = kzalloc((sizeof(u32) *(nr+1)), GFP_KERNEL);
+               val = prop->value;
+               while (nr) {
+                       auto_freq_table[i++] = 1000 * be32_to_cpup(val++);
+                       nr--;
+               }
+               cur_freq_index = 0;
+               auto_freq_table_size = i;
+       }
+
+       prop = of_find_property(clk_ddr_dev_node, "freq-table", NULL);
        if (!prop)
                return -ENODEV;
        if (!prop->value)
@@ -565,56 +631,24 @@ int of_init_ddr_freq_table(void)
                        ddr.idle_rate= rate;
                if (status & SYS_STATUS_REBOOT)
                        ddr.reboot_rate= rate;
+               if (status & SYS_STATUS_BOOST)
+                       ddr.boost_rate= rate;
 
                nr -= 2;
        }
 
        return 0;
 }
-#if 0//defined(CONFIG_RK_PM_TESTS)
+
+#if defined(CONFIG_RK_PM_TESTS)
 static void ddrfreq_tst_init(void);
 #endif
 
-static int ddr_freq_suspend_notifier_call(struct notifier_block *self,
-                               unsigned long action, void *data)
-{
-       struct fb_event *event = data;
-       int blank_mode = *((int *)event->data);
-
-       if (action == FB_EARLY_EVENT_BLANK) {
-               switch (blank_mode) {
-               case FB_BLANK_UNBLANK:
-                       ddrfreq_clear_sys_status(SYS_STATUS_SUSPEND);
-                       break;
-               default:
-                       break;
-               }
-       }
-       else if (action == FB_EVENT_BLANK) {
-               switch (blank_mode) {
-               case FB_BLANK_POWERDOWN:
-                       ddrfreq_set_sys_status(SYS_STATUS_SUSPEND);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       return NOTIFY_OK;
-}
-
-static struct notifier_block ddr_freq_suspend_notifier = {
-               .notifier_call = ddr_freq_suspend_notifier_call,
-};
-
-
-
-
 static int ddrfreq_init(void)
 {
        struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
        int ret;
-#if 0//defined(CONFIG_RK_PM_TESTS)
+#if defined(CONFIG_RK_PM_TESTS)
         ddrfreq_tst_init();
 #endif
        clk_cpu_dvfs_node = clk_get_dvfs_node("clk_core");
@@ -629,8 +663,6 @@ static int ddrfreq_init(void)
        }
        
        clk_enable_dvfs(ddr.clk_dvfs_node);
-
-       ddr_freq_wq = alloc_workqueue("ddr_freq", WQ_NON_REENTRANT | WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_FREEZABLE, 1);    
        
        init_waitqueue_head(&ddr.wait);
        ddr.mode = "normal";
@@ -663,7 +695,6 @@ static int ddrfreq_init(void)
                goto err;
        }
 
-
        ddr.task = kthread_create(ddrfreq_task, NULL, "ddrfreqd");
        if (IS_ERR(ddr.task)) {
                ret = PTR_ERR(ddr.task);
@@ -702,120 +733,50 @@ err:
        return ret;
 }
 late_initcall(ddrfreq_init);
-
 /****************************ddr bandwith tst************************************/
-#if 0//defined(CONFIG_RK_PM_TESTS)
-
-#define USE_NORMAL_TIME
-
-#ifdef USE_NORMAL_TIME
-static struct timer_list ddrbw_timer;
-#else
-static struct hrtimer ddrbw_hrtimer;
-#endif
-enum ddr_bandwidth_id{
-    ddrbw_wr_num=0,
-    ddrbw_rd_num,
-    ddrbw_act_num,
-    ddrbw_time_num,  
-    ddrbw_eff,
-    ddrbw_id_end
-};
-#define grf_readl(offset)      readl_relaxed(RK_GRF_VIRT + offset)
-#define grf_writel(v, offset)  do { writel_relaxed(v, RK_GRF_VIRT + offset); dsb(); } while (0)
-
-static u32 ddr_bw_show_st=0;
-
-#define  ddr_monitor_start() grf_writel(0xc000c000,RK3288_GRF_SOC_CON4)
-#define  ddr_monitor_end() grf_writel(0xc0000000,RK3288_GRF_SOC_CON4)
-
+#if defined(CONFIG_RK_PM_TESTS)
 static ssize_t ddrbw_dyn_show(struct kobject *kobj, struct kobj_attribute *attr,
                char *buf)
 {
-       char *s = buf;
-       return (s - buf);
+       char *str = buf;
+       str += sprintf(str, "print: %d\n", print);
+       str += sprintf(str, "watch: %d\n", watch);
+       str += sprintf(str, "high_load: %d\n", high_load);
+       str += sprintf(str, "low_load: %d\n", low_load);
+       str += sprintf(str, "auto_freq_interval_ms: %d\n", auto_freq_interval_ms);
+       str += sprintf(str, "high_load_last_ms: %d\n", high_load_last_ms);
+       str += sprintf(str, "low_load_last_ms: %d\n", low_load_last_ms);
+       if (str != buf)
+               *(str - 1) = '\n';
+       return (str - buf);
 }
 
 static ssize_t ddrbw_dyn_store(struct kobject *kobj, struct kobj_attribute *attr,
                const char *buf, size_t n)
 {
-       //const char *pbuf;
-
-       if((strncmp(buf, "start", strlen("start")) == 0)) {
-            ddr_bw_show_st=1;
-            ddr_monitor_start();
-            
-            #ifdef USE_NORMAL_TIME
-            mod_timer(&ddrbw_timer, jiffies + msecs_to_jiffies(500));
-            #else
-            hrtimer_start(&ddrbw_hrtimer, ktime_set(0, 5 * 1000 * 1000*1000), HRTIMER_MODE_REL);
-            #endif
-
-       } else if((strncmp(buf, "stop", strlen("stop")) == 0)) {
-           ddr_bw_show_st=0;
-            ddr_monitor_end();
+       int value;
+       char var_name[64];
+
+       sscanf(buf, "%s %u", var_name, &value);
+
+       if((strncmp(buf, "print", strlen("print")) == 0)) {
+               print = value;
+       } else if((strncmp(buf, "watch", strlen("watch")) == 0)) {
+               watch = value;;
+       } else if((strncmp(buf, "high", strlen("high")) == 0)) {
+               high_load = value;;
+       } else if((strncmp(buf, "low", strlen("low")) == 0)) {
+               low_load = value;;
+       } else if((strncmp(buf, "interval", strlen("interval")) == 0)) {
+               auto_freq_interval_ms = value;;
+       } else if((strncmp(buf, "high_last", strlen("high_last")) == 0)) {
+               high_load_last_ms = value;;
+       } else if((strncmp(buf, "low_last", strlen("low_last")) == 0)) {
+               low_load_last_ms = value;;
        }
-
        return n;
 }
 
-static void ddr_bandwidth_get(void)
-{
-    u32 ddr_bw_val[2][ddrbw_id_end];
-    int i,j;
-    u64 temp64;
-    
-    
-    for(j=0;j<2;j++)
-    for(i=0;i<ddrbw_eff;i++)
-    {
-        ddr_bw_val[j][i]=grf_readl(RK3288_GRF_SOC_STATUS11+i*4+j*16);
-    }
-    ddr_monitor_end();//stop
-    ddr_monitor_start();
-    
-    temp64=((u64)ddr_bw_val[0][0]+ddr_bw_val[0][1])*8*100;
-    
-   // printk("ch0 %llu\n",temp64);
-
-    do_div(temp64,ddr_bw_val[0][ddrbw_time_num]);
-    ddr_bw_val[0][ddrbw_eff]= temp64;
-    temp64=((u64)ddr_bw_val[1][0]+ddr_bw_val[1][1])*8*100;
-    
-    //printk("ch1 %llu\n",temp64);
-
-    do_div(temp64,ddr_bw_val[1][ddrbw_time_num]);   
-    ddr_bw_val[1][ddrbw_eff]=  temp64;
-
-    printk("ddrch0,wr,rd,act,time,percent(%x,%x,%x,%x,%d)\n", 
-                               ddr_bw_val[0][0],ddr_bw_val[0][1],ddr_bw_val[0][2],ddr_bw_val[0][3],ddr_bw_val[0][4]);
-    printk("ddrch1,wr,rd,act,time,percent(%x,%x,%x,%x,%d)\n", 
-                               ddr_bw_val[1][0],ddr_bw_val[1][1],ddr_bw_val[1][2],ddr_bw_val[1][3],ddr_bw_val[1][4]);
-    
-}
-
-#ifdef USE_NORMAL_TIME
-static void ddrbw_timer_fn(unsigned long data)
-{
-       //int i;
-        ddr_bandwidth_get();
-        if(ddr_bw_show_st)
-        {
-            mod_timer(&ddrbw_timer, jiffies + msecs_to_jiffies(500));
-         }
-}
-#else
-struct hrtimer ddrbw_hrtimer;
-static enum hrtimer_restart ddrbw_hrtimer_timer_func(struct hrtimer *timer)
-{
-       int i;
-        ddr_bandwidth_get();
-        if(ddr_bw_show_st)
-        hrtimer_start(timer, ktime_set(0, 1 * 1000 * 1000), HRTIMER_MODE_REL);
-
-}
-#endif
-
 struct ddrfreq_attribute {
        struct attribute        attr;
        ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
@@ -826,30 +787,20 @@ struct ddrfreq_attribute {
 
 static struct ddrfreq_attribute ddrfreq_attrs[] = {
        /*     node_name        permision               show_func       store_func */    
-       __ATTR(ddrbw,   S_IRUSR | S_IRGRP | S_IWUSR,ddrbw_dyn_show,     ddrbw_dyn_store),
+       __ATTR(ddrfreq, S_IRUSR|S_IRGRP|S_IWUSR,        ddrbw_dyn_show, ddrbw_dyn_store),
 };
 int rk_pm_tests_kobj_atrradd(const struct attribute *attr);
 
 static void ddrfreq_tst_init(void)
 {
-        int i,ret;
-#ifdef USE_NORMAL_TIME
-            init_timer(&ddrbw_timer);
-            //ddrbw_timer.expires = jiffies+msecs_to_jiffies(1);
-            ddrbw_timer.function = ddrbw_timer_fn;
-            //mod_timer(&ddrbw_timer,jiffies+msecs_to_jiffies(1));
-#else
-            hrtimer_init(&ddrbw_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-            ddrbw_hrtimer.function = ddrbw_hrtimer_timer_func;
-            //hrtimer_start(&ddrbw_hrtimer,ktime_set(0, 5*1000*1000),HRTIMER_MODE_REL);
-#endif
-            printk("*****%s*****\n",__FUNCTION__);
+       int ret;
 
-            ret = rk_pm_tests_kobj_atrradd(&ddrfreq_attrs[0].attr);
-            if (ret != 0) {
-                printk("create ddrfreq sysfs node error\n");
-                return;
-            }
+       ret = rk_pm_tests_kobj_atrradd(&ddrfreq_attrs[0].attr);
+
+       if (ret) {
+               printk("%s: create ddrfreq sysfs node error, ret: %d\n", __func__, ret);
+               return;
+       }
 
 }
 #endif
index 66b06071c5a3ab57f3a8c958814cb77ffee4cae7..a26d6653fa3f32a26ddd4dcd6c09cdb08c3262d5 100644 (file)
@@ -56,6 +56,7 @@
 #define SYS_STATUS_CIF1                (1<<9)
 #define SYS_STATUS_LCDC0       (1<<10)
 #define SYS_STATUS_LCDC1       (1<<11)
+#define SYS_STATUS_BOOST       (1<<12)
 
 #define SYS_STATUS_VIDEO       (SYS_STATUS_VIDEO_720P|SYS_STATUS_VIDEO_1080P)
 #define SYS_STATUS_DUALVIEW    (SYS_STATUS_LCDC0|SYS_STATUS_LCDC1)