import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mt_emifreq.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 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/sched.h>
11 #include <linux/init.h>
12 #include <linux/delay.h>
13 #include <linux/slab.h>
14 #include <linux/proc_fs.h>
15 #include <linux/miscdevice.h>
16 #include <linux/platform_device.h>
17 #include <linux/earlysuspend.h>
18 #include <linux/spinlock.h>
19 #include <linux/kthread.h>
20 #include <linux/hrtimer.h>
21 #include <linux/ktime.h>
22 #include <linux/xlog.h>
23 #include <linux/jiffies.h>
24
25 #include <linux/version.h>
26 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
27 #include <linux/seq_file.h>
28 #endif
29
30 #include <asm/system.h>
31 #include <asm/uaccess.h>
32
33 #include "mach/mt_typedefs.h"
34 #include "mach/mt_freqhopping.h"
35 #include "mach/mt_emifreq.h"
36 #include "mach/upmu_common.h"
37
38 /***************************
39 * debug message
40 ****************************/
41 #define dprintk(fmt, args...) \
42 do { \
43 if (mt_emifreq_debug) { \
44 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", fmt, ##args); \
45 } \
46 } while(0)
47
48 #ifdef CONFIG_HAS_EARLYSUSPEND
49 static struct early_suspend mt_emifreq_early_suspend_handler =
50 {
51 .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 200,
52 .suspend = NULL,
53 .resume = NULL,
54 };
55 #endif
56
57 /**************************
58 * Global variable
59 ***************************/
60 static bool mt_emifreq_debug = false;
61 static bool mt_emifreq_pause = true;
62
63 /******************************
64 * Extern Function Declaration
65 *******************************/
66
67
68 /******************************
69 * show current EMI DFS stauts
70 *******************************/
71 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
72 static int mt_emifreq_state_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
73 {
74 int len = 0;
75 char *p = buf;
76
77 if (!mt_emifreq_pause)
78 p += sprintf(p, "EMI DFS enabled\n");
79 else
80 p += sprintf(p, "EMI DFS disabled\n");
81
82 len = p - buf;
83 return len;
84 }
85 #endif
86
87 /****************************************
88 * set EMI DFS stauts by sysfs interface
89 *****************************************/
90 static ssize_t mt_emifreq_state_write(struct file *file, const char *buffer, size_t count, loff_t *data)
91 {
92 int enabled = 0;
93
94 if (sscanf(buffer, "%d", &enabled) == 1)
95 {
96 if (enabled == 1)
97 {
98 mt_emifreq_pause = false;
99 }
100 else if (enabled == 0)
101 {
102 mt_emifreq_pause = true;
103 }
104 else
105 {
106 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", "bad argument!! argument should be \"1\" or \"0\"\n");
107 }
108 }
109 else
110 {
111 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", "bad argument!! argument should be \"1\" or \"0\"\n");
112 }
113
114 return count;
115 }
116
117 /***************************
118 * show current debug status
119 ****************************/
120 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
121 static int mt_emifreq_debug_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
122 {
123 int len = 0;
124 char *p = buf;
125
126 if (mt_emifreq_debug)
127 p += sprintf(p, "emifreq debug enabled\n");
128 else
129 p += sprintf(p, "emifreq debug disabled\n");
130
131 len = p - buf;
132 return len;
133 }
134 #endif
135
136 /***********************
137 * enable debug message
138 ************************/
139 static ssize_t mt_emifreq_debug_write(struct file *file, const char *buffer, size_t count, loff_t *data)
140 {
141 int debug = 0;
142
143 if (sscanf(buffer, "%d", &debug) == 1)
144 {
145 if (debug == 0)
146 {
147 mt_emifreq_debug = 0;
148 return count;
149 }
150 else if (debug == 1)
151 {
152 mt_emifreq_debug = 1;
153 return count;
154 }
155 else
156 {
157 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", "bad argument!! should be 0 or 1 [0: disable, 1: enable]\n");
158 }
159 }
160 else
161 {
162 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", "bad argument!! should be 0 or 1 [0: disable, 1: enable]\n");
163 }
164
165 return -EINVAL;
166 }
167
168
169 /*********************************
170 * early suspend callback function
171 **********************************/
172 void mt_emifreq_early_suspend(struct early_suspend *h)
173 {
174 if(mt_emifreq_pause == false)
175 {
176 mt_h2l_dvfs_mempll();
177 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", "mt_emifreq_early_suspend\n");
178 }
179 }
180
181 /*******************************
182 * late resume callback function
183 ********************************/
184 void mt_emifreq_late_resume(struct early_suspend *h)
185 {
186 if(mt_emifreq_pause == false)
187 {
188 mt_l2h_dvfs_mempll();
189 xlog_printk(ANDROID_LOG_INFO, "Power/EMI_DFS", "mt_emifreq_late_resume\n");
190 }
191 }
192
193 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
194 static int mt_emifreq_debug_show(struct seq_file* s, void* v)
195 {
196 if (mt_emifreq_debug)
197 seq_printf(s, "emifreq debug enabled\n");
198 else
199 seq_printf(s, "emifreq debug disabled\n");
200
201
202 return 0;
203 }
204
205 static int mt_emifreq_debug_open(struct inode *inode, struct file *file)
206 {
207 return single_open(file, mt_emifreq_debug_show, NULL);
208 }
209
210
211 static const struct file_operations mt_emifreq_debug_fops = {
212 .owner = THIS_MODULE,
213 .write = mt_emifreq_debug_write,
214 .open = mt_emifreq_debug_open,
215 .read = seq_read,
216 .llseek = seq_lseek,
217 .release = single_release,
218 };
219
220 static int mt_emifreq_state_show(struct seq_file* s, void* v)
221 {
222 if (mt_emifreq_debug)
223 seq_printf(s, "emifreq debug enabled\n");
224 else
225 seq_printf(s, "emifreq debug disabled\n");
226
227
228 return 0;
229 }
230
231 static int mt_emifreq_state_open(struct inode *inode, struct file *file)
232 {
233 return single_open(file, mt_emifreq_state_show, NULL);
234 }
235
236
237 static const struct file_operations mt_emifreq_state_fops = {
238 .owner = THIS_MODULE,
239 .write = mt_emifreq_state_write,
240 .open = mt_emifreq_state_open,
241 .read = seq_read,
242 .llseek = seq_lseek,
243 .release = single_release,
244 };
245 #endif
246
247 /**********************************
248 * mediatek emifreq initialization
249 ***********************************/
250 static int __init mt_emifreq_init(void)
251 {
252 struct proc_dir_entry *mt_entry = NULL;
253 struct proc_dir_entry *mt_emifreq_dir = NULL;
254
255 #ifdef CONFIG_HAS_EARLYSUSPEND
256 mt_emifreq_early_suspend_handler.suspend = mt_emifreq_early_suspend;
257 mt_emifreq_early_suspend_handler.resume = mt_emifreq_late_resume;
258 register_early_suspend(&mt_emifreq_early_suspend_handler);
259 #endif
260
261 mt_emifreq_dir = proc_mkdir("emifreq", NULL);
262 if (!mt_emifreq_dir)
263 {
264 pr_err("[%s]: mkdir /proc/emifreq failed\n", __FUNCTION__);
265 }
266 else
267 {
268 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
269 mt_entry = proc_create("emifreq_debug", S_IRUGO | S_IWUSR | S_IWGRP, mt_emifreq_dir, &mt_emifreq_debug_fops);
270 if (!mt_entry)
271 {
272 pr_err("[%s]: mkdir /proc/emifreq/emifreq_debug failed\n", __FUNCTION__);
273 }
274
275 mt_entry = proc_create("emifreq_state", S_IRUGO | S_IWUSR | S_IWGRP, mt_emifreq_dir, &mt_emifreq_state_fops);
276 if (!mt_entry)
277 {
278 pr_err("[%s]: mkdir /proc/emifreq/emifreq_state failed\n", __FUNCTION__);
279 }
280 #else
281 mt_entry = create_proc_entry("emifreq_debug", S_IRUGO | S_IWUSR | S_IWGRP, mt_emifreq_dir);
282 if (mt_entry)
283 {
284 mt_entry->read_proc = mt_emifreq_debug_read;
285 mt_entry->write_proc = mt_emifreq_debug_write;
286 }
287
288 mt_entry = create_proc_entry("emifreq_state", S_IRUGO | S_IWUSR | S_IWGRP, mt_emifreq_dir);
289 if (mt_entry)
290 {
291 mt_entry->read_proc = mt_emifreq_state_read;
292 mt_entry->write_proc = mt_emifreq_state_write;
293 }
294 #endif
295 }
296
297 return 0;
298 }
299
300 static void __exit mt_emifreq_exit(void)
301 {
302
303 }
304
305 module_init(mt_emifreq_init);
306 module_exit(mt_emifreq_exit);
307 MODULE_DESCRIPTION("MediaTek EMI Frequency Scaling driver");
308 MODULE_LICENSE("GPL");