2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
8 /*********************************
10 **********************************/
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/cpu.h>
15 #include <linux/earlysuspend.h>
16 #include <linux/proc_fs.h>
17 #include <linux/wakelock.h>
18 #include <linux/platform_device.h>
19 #include <asm/uaccess.h>
20 #include <mach/hotplug.h>
21 #include <mach/sync_write.h>
22 #include <linux/seq_file.h>
25 /*********************************
27 **********************************/
28 #ifdef CONFIG_HAS_EARLYSUSPEND
30 #define STATE_ENTER_EARLY_SUSPEND 1
31 #define STATE_ENTER_LATE_RESUME 2
32 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
34 #define FORCE_CPU_OFF_DELAYED_WORK_TIME 3 //second
35 #define FORCE_CPU_OFF_WAKE_LOCK_TIME 5 //second
39 /*********************************
41 **********************************/
42 static int g_enable
= 1;
44 #ifdef CONFIG_HAS_EARLYSUSPEND
45 static int g_enable_cpu_rush_boost
= 0;
46 static int g_prev_cpu_rush_boost_enable
= 0;
48 static struct early_suspend mt_hotplug_mechanism_early_suspend_handler
=
50 .level
= EARLY_SUSPEND_LEVEL_DISABLE_FB
+ 250,
54 static int g_cur_state
= STATE_ENTER_LATE_RESUME
;
55 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
57 static int g_enable_dynamic_cpu_hotplug_at_suspend
= 0;
58 static int g_prev_dynamic_cpu_hotplug_enable
= 0;
59 static int mt_hotplug_mechanism_probe(struct platform_device
*pdev
);
60 static int mt_hotplug_mechanism_suspend(struct platform_device
*pdev
, pm_message_t state
);
61 static int mt_hotplug_mechanism_resume(struct platform_device
*pdev
);
62 static struct platform_driver mt_hotplug_mechanism_pdrv
=
66 .probe
= mt_hotplug_mechanism_probe
,
67 .suspend
= mt_hotplug_mechanism_suspend
,
68 .resume
= mt_hotplug_mechanism_resume
,
70 .name
= "mt_cpu_hotplug",
74 static int g_test0
= 0;
75 static int g_test1
= 0;
77 /*********************************
79 **********************************/
80 #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
81 extern int hp_get_cpu_rush_boost_enable(void);
82 extern void hp_set_cpu_rush_boost_enable(int enable
);
83 extern int hp_get_dynamic_cpu_hotplug_enable(void);
84 extern void hp_set_dynamic_cpu_hotplug_enable(int enable
);
89 /*********************************
90 * early suspend callback function
91 **********************************/
92 #ifdef CONFIG_HAS_EARLYSUSPEND
93 static void mt_hotplug_mechanism_early_suspend(struct early_suspend
*h
)
95 HOTPLUG_INFO("mt_hotplug_mechanism_early_suspend");
98 goto early_suspend_end
;
100 if (!g_enable_cpu_rush_boost
)
102 #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
103 g_prev_cpu_rush_boost_enable
= hp_get_cpu_rush_boost_enable();
104 hp_set_cpu_rush_boost_enable(0);
105 #endif //#ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
109 g_cur_state
= STATE_ENTER_EARLY_SUSPEND
;
113 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
117 /*******************************
118 * late resume callback function
119 ********************************/
120 #ifdef CONFIG_HAS_EARLYSUSPEND
121 static void mt_hotplug_mechanism_late_resume(struct early_suspend
*h
)
123 HOTPLUG_INFO("mt_hotplug_mechanism_late_resume");
126 goto late_resume_end
;
128 if (!g_enable_cpu_rush_boost
)
130 #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
131 hp_set_cpu_rush_boost_enable(g_prev_cpu_rush_boost_enable
);
132 #endif //#ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
136 g_cur_state
= STATE_ENTER_LATE_RESUME
;
140 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
144 /*******************************
145 * probe callback function
146 ********************************/
147 static int mt_hotplug_mechanism_probe(struct platform_device
*pdev
)
149 HOTPLUG_INFO("mt_hotplug_mechanism_probe\n");
156 /*******************************
157 * suspend callback function
158 ********************************/
159 static int mt_hotplug_mechanism_suspend(struct platform_device
*pdev
, pm_message_t state
)
161 HOTPLUG_INFO("mt_hotplug_mechanism_suspend\n");
166 if (!g_enable_dynamic_cpu_hotplug_at_suspend
)
168 #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
169 g_prev_dynamic_cpu_hotplug_enable
= hp_get_dynamic_cpu_hotplug_enable();
170 hp_set_dynamic_cpu_hotplug_enable(0);
171 #endif //#ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
179 /*******************************
180 * resume callback function
181 ********************************/
182 static int mt_hotplug_mechanism_resume(struct platform_device
*pdev
)
184 HOTPLUG_INFO("mt_hotplug_mechanism_resume\n");
189 if (!g_enable_dynamic_cpu_hotplug_at_suspend
)
191 #ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
192 hp_set_dynamic_cpu_hotplug_enable(g_prev_dynamic_cpu_hotplug_enable
);
193 #endif //#ifdef CONFIG_CPU_FREQ_GOV_HOTPLUG
200 /**************************************************************
201 * mt hotplug mechanism control interface for procfs test0
202 ***************************************************************/
203 static int mt_hotplug_mechanism_test0_show(struct seq_file
*s
, void *v
)
205 seq_printf(s
, "%d\n", g_test0
);
207 HOTPLUG_INFO("mt_hotplug_mechanism_read_test0, hotplug_cpu_count: %d\n", atomic_read(&hotplug_cpu_count
));
208 on_each_cpu((smp_call_func_t
)dump_stack
, NULL
, 1);
210 mt65xx_reg_sync_writel(8, 0xf0200080);
211 printk(KERN_EMERG
"CPU%u, debug event: 0x%08x, debug monitor: 0x%08x\n", 0, *(volatile u32
*)(0xf0200080), *(volatile u32
*)(0xf0200084));
212 mt65xx_reg_sync_writel(9, 0xf0200080);
213 printk(KERN_EMERG
"CPU%u, debug event: 0x%08x, debug monitor: 0x%08x\n", 1, *(volatile u32
*)(0xf0200080), *(volatile u32
*)(0xf0200084));
214 mt65xx_reg_sync_writel(10, 0xf0200080);
215 printk(KERN_EMERG
"CPU%u, debug event: 0x%08x, debug monitor: 0x%08x\n", 2, *(volatile u32
*)(0xf0200080), *(volatile u32
*)(0xf0200084));
216 mt65xx_reg_sync_writel(11, 0xf0200080);
217 printk(KERN_EMERG
"CPU%u, debug event: 0x%08x, debug monitor: 0x%08x\n", 3, *(volatile u32
*)(0xf0200080), *(volatile u32
*)(0xf0200084));
222 static int mt_hotplug_mechanism_test0_open(struct inode
*inode
, struct file
*file
)
224 return single_open(file
, mt_hotplug_mechanism_test0_show
, NULL
);
227 static int mt_hotplug_mechanism_test0_write(struct file
*file
, const char *buffer
, size_t count
, loff_t
*data
)
229 int len
= 0, test0
= 0;
232 len
= (count
< (sizeof(desc
) - 1)) ? count
: (sizeof(desc
) - 1);
233 if (copy_from_user(desc
, buffer
, len
))
239 if (sscanf(desc
, "%d", &test0
) == 1)
246 HOTPLUG_INFO("mt_hotplug_mechanism_write_test0, bad argument\n");
252 static const struct file_operations mt_hotplug_mechanism_test0_fops
= {
253 .owner
= THIS_MODULE
,
254 .write
= mt_hotplug_mechanism_test0_write
,
255 .open
= mt_hotplug_mechanism_test0_open
,
258 .release
= single_release
,
261 /**************************************************************
262 * mt hotplug mechanism control interface for procfs test1
263 ***************************************************************/
264 extern int g_cpus_sum_load_current
; //set global for information purpose
266 extern long g_cpu_up_sum_load
;
267 extern int g_cpu_up_count
;
268 extern int g_cpu_up_load_index
;
270 extern long g_cpu_down_sum_load
;
271 extern int g_cpu_down_count
;
272 extern int g_cpu_down_load_index
;
275 CPU_HOTPLUG_WORK_TYPE_NONE
= 0,
276 CPU_HOTPLUG_WORK_TYPE_BASE
,
277 CPU_HOTPLUG_WORK_TYPE_LIMIT
,
278 CPU_HOTPLUG_WORK_TYPE_UP
,
279 CPU_HOTPLUG_WORK_TYPE_DOWN
,
280 CPU_HOTPLUG_WORK_TYPE_RUSH
,
281 } cpu_hotplug_work_type_t
;
282 extern cpu_hotplug_work_type_t g_trigger_hp_work
;
284 extern int g_tlp_avg_current
; //set global for information purpose
285 extern int g_tlp_avg_sum
;
286 extern int g_tlp_avg_count
;
287 extern int g_tlp_avg_index
;
288 extern int g_tlp_avg_average
;
290 static int mt_hotplug_mechanism_test1_show(struct seq_file
*s
, void *v
)
292 seq_printf(s
, "%d\n", g_test1
);
294 #if 0 /* These variables are not public in cpufreq_hotplug.c */
295 HOTPLUG_INFO("[power/hotplug] thermal_debug_1 (%d)(%d)(%d)(%d)(%ld)(%ld)\n", g_trigger_hp_work
, g_tlp_avg_average
, g_tlp_avg_current
,
296 g_cpus_sum_load_current
, g_cpu_up_sum_load
, g_cpu_down_sum_load
);
297 HOTPLUG_INFO("[power/hotplug] thermal_debug_2 (%d)(%d)(%d)(%d)\n", g_cpu_up_count
, g_cpu_up_load_index
, g_cpu_down_count
, g_cpu_down_load_index
);
303 static int mt_hotplug_mechanism_test1_open(struct inode
*inode
, struct file
*file
)
305 return single_open(file
, mt_hotplug_mechanism_test1_show
, NULL
);
308 static int mt_hotplug_mechanism_test1_write(struct file
*file
, const char *buffer
, size_t count
, loff_t
*data
)
310 int len
= 0, test1
= 0;
313 len
= (count
< (sizeof(desc
) - 1)) ? count
: (sizeof(desc
) - 1);
314 if (copy_from_user(desc
, buffer
, len
))
320 if (sscanf(desc
, "%d", &test1
) == 1)
327 HOTPLUG_INFO("mt_hotplug_mechanism_write_test1, bad argument\n");
333 static const struct file_operations mt_hotplug_mechanism_test1_fops
= {
334 .owner
= THIS_MODULE
,
335 .write
= mt_hotplug_mechanism_test1_write
,
336 .open
= mt_hotplug_mechanism_test1_open
,
339 .release
= single_release
,
342 /*******************************
343 * kernel module init function
344 ********************************/
345 static int __init
mt_hotplug_mechanism_init(void)
347 struct proc_dir_entry
*entry
= NULL
;
348 struct proc_dir_entry
*mt_hotplug_dir
= NULL
;
351 HOTPLUG_INFO("mt_hotplug_mechanism_init");
353 mt_hotplug_dir
= proc_mkdir("mt_hotplug", NULL
);
356 HOTPLUG_INFO("mkdir /proc/mt_hotplug failed");
360 entry
= proc_create("test0", S_IRUGO
| S_IWUSR
, mt_hotplug_dir
, &mt_hotplug_mechanism_test0_fops
);
363 pr_err("[%s]: mkdir /proc/mt_hotplug/test0 failed\n", __func__
);
365 entry
= proc_create("test1", S_IRUGO
| S_IWUSR
, mt_hotplug_dir
, &mt_hotplug_mechanism_test1_fops
);
368 pr_err("[%s]: mkdir /proc/mt_hotplug/test1 failed\n", __func__
);
372 #ifdef CONFIG_HAS_EARLYSUSPEND
373 mt_hotplug_mechanism_early_suspend_handler
.suspend
= mt_hotplug_mechanism_early_suspend
;
374 mt_hotplug_mechanism_early_suspend_handler
.resume
= mt_hotplug_mechanism_late_resume
;
375 register_early_suspend(&mt_hotplug_mechanism_early_suspend_handler
);
376 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
378 r
= platform_driver_register(&mt_hotplug_mechanism_pdrv
);
380 HOTPLUG_INFO("platform_driver_register failed (%d)\n", r
);
384 module_init(mt_hotplug_mechanism_init
);
388 /*******************************
389 * kernel module exit function
390 ********************************/
391 static void __exit
mt_hotplug_mechanism_exit(void)
393 HOTPLUG_INFO("mt_hotplug_mechanism_exit");
395 module_exit(mt_hotplug_mechanism_exit
);
399 /**************************************************************
400 * mt hotplug mechanism control interface for thermal protect
401 ***************************************************************/
402 void mt_hotplug_mechanism_thermal_protect(int limited_cpus
)
404 HOTPLUG_INFO("mt_hotplug_mechanism_thermal_protect\n");
407 EXPORT_SYMBOL(mt_hotplug_mechanism_thermal_protect
);
411 module_param(g_enable
, int, 0644);
412 #ifdef CONFIG_HAS_EARLYSUSPEND
413 module_param(g_enable_cpu_rush_boost
, int, 0644);
414 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
415 module_param(g_enable_dynamic_cpu_hotplug_at_suspend
, int, 0644);
419 MODULE_DESCRIPTION("MediaTek CPU Hotplug Mechanism");
420 MODULE_LICENSE("GPL");