Merge tag 'v3.10.55' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mt_hotplug_mechanism.c
1 /*
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.
6 */
7
8 /*********************************
9 * include
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>
23
24
25 /*********************************
26 * macro
27 **********************************/
28 #ifdef CONFIG_HAS_EARLYSUSPEND
29 #define STATE_INIT 0
30 #define STATE_ENTER_EARLY_SUSPEND 1
31 #define STATE_ENTER_LATE_RESUME 2
32 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
33
34 #define FORCE_CPU_OFF_DELAYED_WORK_TIME 3 //second
35 #define FORCE_CPU_OFF_WAKE_LOCK_TIME 5 //second
36
37
38
39 /*********************************
40 * glabal variable
41 **********************************/
42 static int g_enable = 1;
43
44 #ifdef CONFIG_HAS_EARLYSUSPEND
45 static int g_enable_cpu_rush_boost = 0;
46 static int g_prev_cpu_rush_boost_enable = 0;
47
48 static struct early_suspend mt_hotplug_mechanism_early_suspend_handler =
49 {
50 .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 250,
51 .suspend = NULL,
52 .resume = NULL,
53 };
54 static int g_cur_state = STATE_ENTER_LATE_RESUME;
55 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
56
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 =
63 {
64 .remove = NULL,
65 .shutdown = NULL,
66 .probe = mt_hotplug_mechanism_probe,
67 .suspend = mt_hotplug_mechanism_suspend,
68 .resume = mt_hotplug_mechanism_resume,
69 .driver = {
70 .name = "mt_cpu_hotplug",
71 },
72 };
73
74 static int g_test0 = 0;
75 static int g_test1 = 0;
76
77 /*********************************
78 * extern function
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);
85 #endif
86
87
88
89 /*********************************
90 * early suspend callback function
91 **********************************/
92 #ifdef CONFIG_HAS_EARLYSUSPEND
93 static void mt_hotplug_mechanism_early_suspend(struct early_suspend *h)
94 {
95 HOTPLUG_INFO("mt_hotplug_mechanism_early_suspend");
96
97 if (!g_enable)
98 goto early_suspend_end;
99
100 if (!g_enable_cpu_rush_boost)
101 {
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
106 }
107
108 early_suspend_end:
109 g_cur_state = STATE_ENTER_EARLY_SUSPEND;
110
111 return;
112 }
113 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
114
115
116
117 /*******************************
118 * late resume callback function
119 ********************************/
120 #ifdef CONFIG_HAS_EARLYSUSPEND
121 static void mt_hotplug_mechanism_late_resume(struct early_suspend *h)
122 {
123 HOTPLUG_INFO("mt_hotplug_mechanism_late_resume");
124
125 if (!g_enable)
126 goto late_resume_end;
127
128 if (!g_enable_cpu_rush_boost)
129 {
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
133 }
134
135 late_resume_end:
136 g_cur_state = STATE_ENTER_LATE_RESUME;
137
138 return;
139 }
140 #endif //#ifdef CONFIG_HAS_EARLYSUSPEND
141
142
143
144 /*******************************
145 * probe callback function
146 ********************************/
147 static int mt_hotplug_mechanism_probe(struct platform_device *pdev)
148 {
149 HOTPLUG_INFO("mt_hotplug_mechanism_probe\n");
150
151 return 0;
152 }
153
154
155
156 /*******************************
157 * suspend callback function
158 ********************************/
159 static int mt_hotplug_mechanism_suspend(struct platform_device *pdev, pm_message_t state)
160 {
161 HOTPLUG_INFO("mt_hotplug_mechanism_suspend\n");
162
163 if (!g_enable)
164 return 0;
165
166 if (!g_enable_dynamic_cpu_hotplug_at_suspend)
167 {
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
172 }
173
174 return 0;
175 }
176
177
178
179 /*******************************
180 * resume callback function
181 ********************************/
182 static int mt_hotplug_mechanism_resume(struct platform_device *pdev)
183 {
184 HOTPLUG_INFO("mt_hotplug_mechanism_resume\n");
185
186 if (!g_enable)
187 return 0;
188
189 if (!g_enable_dynamic_cpu_hotplug_at_suspend)
190 {
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
194 }
195
196 return 0;
197 }
198
199
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)
204 {
205 seq_printf(s, "%d\n", g_test0);
206
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);
209
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));
218
219 return 0;
220 }
221
222 static int mt_hotplug_mechanism_test0_open(struct inode *inode, struct file *file)
223 {
224 return single_open(file, mt_hotplug_mechanism_test0_show, NULL);
225 }
226
227 static int mt_hotplug_mechanism_test0_write(struct file *file, const char *buffer, size_t count, loff_t *data)
228 {
229 int len = 0, test0 = 0;
230 char desc[32];
231
232 len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
233 if (copy_from_user(desc, buffer, len))
234 {
235 return 0;
236 }
237 desc[len] = '\0';
238
239 if (sscanf(desc, "%d", &test0) == 1)
240 {
241 g_test0 = test0;
242 return count;
243 }
244 else
245 {
246 HOTPLUG_INFO("mt_hotplug_mechanism_write_test0, bad argument\n");
247 }
248
249 return -EINVAL;
250 }
251
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,
256 .read = seq_read,
257 .llseek = seq_lseek,
258 .release = single_release,
259 };
260
261 /**************************************************************
262 * mt hotplug mechanism control interface for procfs test1
263 ***************************************************************/
264 extern int g_cpus_sum_load_current; //set global for information purpose
265
266 extern long g_cpu_up_sum_load;
267 extern int g_cpu_up_count;
268 extern int g_cpu_up_load_index;
269
270 extern long g_cpu_down_sum_load;
271 extern int g_cpu_down_count;
272 extern int g_cpu_down_load_index;
273
274 typedef enum {
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;
283
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;
289
290 static int mt_hotplug_mechanism_test1_show(struct seq_file *s, void *v)
291 {
292 seq_printf(s, "%d\n", g_test1);
293
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);
298 #endif
299
300 return 0;
301 }
302
303 static int mt_hotplug_mechanism_test1_open(struct inode *inode, struct file *file)
304 {
305 return single_open(file, mt_hotplug_mechanism_test1_show, NULL);
306 }
307
308 static int mt_hotplug_mechanism_test1_write(struct file *file, const char *buffer, size_t count, loff_t *data)
309 {
310 int len = 0, test1 = 0;
311 char desc[32];
312
313 len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
314 if (copy_from_user(desc, buffer, len))
315 {
316 return 0;
317 }
318 desc[len] = '\0';
319
320 if (sscanf(desc, "%d", &test1) == 1)
321 {
322 g_test1 = test1;
323 return count;
324 }
325 else
326 {
327 HOTPLUG_INFO("mt_hotplug_mechanism_write_test1, bad argument\n");
328 }
329
330 return -EINVAL;
331 }
332
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,
337 .read = seq_read,
338 .llseek = seq_lseek,
339 .release = single_release,
340 };
341
342 /*******************************
343 * kernel module init function
344 ********************************/
345 static int __init mt_hotplug_mechanism_init(void)
346 {
347 struct proc_dir_entry *entry = NULL;
348 struct proc_dir_entry *mt_hotplug_dir = NULL;
349 int r = 0;
350
351 HOTPLUG_INFO("mt_hotplug_mechanism_init");
352
353 mt_hotplug_dir = proc_mkdir("mt_hotplug", NULL);
354 if (!mt_hotplug_dir)
355 {
356 HOTPLUG_INFO("mkdir /proc/mt_hotplug failed");
357 }
358 else
359 {
360 entry = proc_create("test0", S_IRUGO | S_IWUSR, mt_hotplug_dir, &mt_hotplug_mechanism_test0_fops);
361 if (!entry)
362 {
363 pr_err("[%s]: mkdir /proc/mt_hotplug/test0 failed\n", __func__);
364 }
365 entry = proc_create("test1", S_IRUGO | S_IWUSR, mt_hotplug_dir, &mt_hotplug_mechanism_test1_fops);
366 if (!entry)
367 {
368 pr_err("[%s]: mkdir /proc/mt_hotplug/test1 failed\n", __func__);
369 }
370 }
371
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
377
378 r = platform_driver_register(&mt_hotplug_mechanism_pdrv);
379 if (r)
380 HOTPLUG_INFO("platform_driver_register failed (%d)\n", r);
381
382 return r;
383 }
384 module_init(mt_hotplug_mechanism_init);
385
386
387
388 /*******************************
389 * kernel module exit function
390 ********************************/
391 static void __exit mt_hotplug_mechanism_exit(void)
392 {
393 HOTPLUG_INFO("mt_hotplug_mechanism_exit");
394 }
395 module_exit(mt_hotplug_mechanism_exit);
396
397
398
399 /**************************************************************
400 * mt hotplug mechanism control interface for thermal protect
401 ***************************************************************/
402 void mt_hotplug_mechanism_thermal_protect(int limited_cpus)
403 {
404 HOTPLUG_INFO("mt_hotplug_mechanism_thermal_protect\n");
405
406 }
407 EXPORT_SYMBOL(mt_hotplug_mechanism_thermal_protect);
408
409
410
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);
416
417
418
419 MODULE_DESCRIPTION("MediaTek CPU Hotplug Mechanism");
420 MODULE_LICENSE("GPL");