Merge tag 'v3.10.55' into update
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mt_pm_init.c
1 #include <linux/pm.h>
2 #include <linux/module.h>
3 #include <linux/proc_fs.h>
4 #include <linux/kernel.h>
5 #include <linux/init.h>
6 #include <linux/delay.h>
7 #include <linux/gpio.h>
8 #include <linux/spinlock.h>
9 #include <linux/interrupt.h>
10 #include <linux/types.h>
11 #include <linux/xlog.h>
12 #include <linux/seq_file.h>
13
14 #include <asm/io.h>
15 #include <asm/uaccess.h>
16
17 #include "mach/irqs.h"
18 #include "mach/sync_write.h"
19 #include "mach/mt_reg_base.h"
20 #include "mach/mt_typedefs.h"
21 #include "mach/mt_spm.h"
22 #include "mach/mt_sleep.h"
23 #include "mach/mt_dcm.h"
24 #include "mach/mt_clkmgr.h"
25 #include "mach/mt_cpufreq.h"
26 #include "mach/mt_gpufreq.h"
27 #include "mach/mt_dormant.h"
28
29 #define pminit_write(addr, val) mt65xx_reg_sync_writel((val), ((void *)addr))
30
31 //fix for bring up
32 extern int mt_clkmgr_bringup_init(void);
33 extern void mt_idle_init(void);
34 extern void mt_power_off(void);
35 /*********************************************************************
36 * FUNCTION DEFINATIONS
37 ********************************************************************/
38
39 unsigned int mt_get_emi_freq(void)
40 {
41 int output = 0;
42 unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
43
44 clk26cali_0 = DRV_Reg32(CLK26CALI_0);
45 pminit_write(CLK26CALI_0, clk26cali_0 | 0x80); // enable fmeter_en
46
47 clk_misc_cfg_1 = DRV_Reg32(CLK_MISC_CFG_1);
48 pminit_write(CLK_MISC_CFG_1, 0xFFFFFF00); // select divider
49
50 clk_cfg_8 = DRV_Reg32(CLK_CFG_8);
51 pminit_write(CLK_CFG_8, (14 << 8)); // select abist_cksw
52
53 temp = DRV_Reg32(CLK26CALI_0);
54 pminit_write(CLK26CALI_0, temp | 0x1); // start fmeter
55
56 /* wait frequency meter finish */
57 while (DRV_Reg32(CLK26CALI_0) & 0x1)
58 {
59 printk("wait for emi frequency meter finish, CLK26CALI = 0x%x\n", DRV_Reg32(CLK26CALI_0));
60 mdelay(10);
61 }
62
63 temp = DRV_Reg32(CLK26CALI_1) & 0xFFFF;
64
65 output = (temp * 26000) / 1024; // Khz
66
67 pminit_write(CLK_CFG_8, clk_cfg_8);
68 pminit_write(CLK_MISC_CFG_1, clk_misc_cfg_1);
69 pminit_write(CLK26CALI_0, clk26cali_0);
70
71 //printk("CLK26CALI = 0x%x, mem frequency = %d Khz\n", temp, output);
72
73 return output;
74 }
75 EXPORT_SYMBOL(mt_get_emi_freq);
76
77 unsigned int mt_get_bus_freq(void)
78 {
79 #if 0
80 int output = 0;
81 unsigned int temp, clk26cali_0, clk_cfg_9, clk_misc_cfg_1, clk26cali_2;
82
83 clk26cali_0 = DRV_Reg32(CLK26CALI_0);
84 pminit_write(CLK26CALI_0, clk26cali_0 | 0x80); // enable fmeter_en
85
86 clk_misc_cfg_1 = DRV_Reg32(CLK_MISC_CFG_1);
87 pminit_write(CLK_MISC_CFG_1, 0x00FFFFFF); // select divider
88
89 clk_cfg_9 = DRV_Reg32(CLK_CFG_9);
90 pminit_write(CLK_CFG_9, (1 << 16)); // select ckgen_cksw
91
92 temp = DRV_Reg32(CLK26CALI_0);
93 pminit_write(CLK26CALI_0, temp | 0x10); // start fmeter
94
95 /* wait frequency meter finish */
96 while (DRV_Reg32(CLK26CALI_0) & 0x10)
97 {
98 //printk("wait for bus frequency meter finish, CLK26CALI = 0x%x\n", DRV_Reg32(CLK26CALI_0));
99 mdelay(10);
100 }
101
102 temp = DRV_Reg32(CLK26CALI_2) & 0xFFFF;
103
104 output = (temp * 26000) / 1024; // Khz
105
106 pminit_write(CLK_CFG_9, clk_cfg_9);
107 pminit_write(CLK_MISC_CFG_1, clk_misc_cfg_1);
108 pminit_write(CLK26CALI_0, clk26cali_0);
109
110 //printk("CLK26CALI = 0x%x, bus frequency = %d Khz\n", temp, output);
111
112 return output;
113 #else
114 unsigned int mainpll_con0, mainpll_con1, main_diff;
115 unsigned int clk_cfg_0, bus_clk;
116 unsigned int output_freq = 0;
117
118 clk_cfg_0 = DRV_Reg32(CLK_CFG_0);
119
120 mainpll_con0 = DRV_Reg32(MAINPLL_CON0);
121 mainpll_con1 = DRV_Reg32(MAINPLL_CON1);
122
123 //main_diff = ((mainpll_con1 >> 12) - 0x8009A) / 2;
124 main_diff = (((mainpll_con1 & 0x1FFFFF) >> 12) - 0x9A) / 2;
125
126 if ((mainpll_con0 & 0xFF) == 0x01)
127 {
128 output_freq = 1001 + (main_diff * 13); // Mhz
129 }
130
131 if ((clk_cfg_0 & 0x7) == 1) // SYSPLL1_D2 = MAINPLL / 2 / 2
132 {
133 bus_clk = ((output_freq * 1000) / 2) / 2;
134 }
135 else if ((clk_cfg_0 & 0x7) == 2) // SYSPLL_D5 = MAINPLL / 5
136 {
137 bus_clk = (output_freq * 1000) / 5;
138 }
139 else if ((clk_cfg_0 & 0x7) == 3) // SYSPLL1_D4 = MAINPLL / 2 / 4
140 {
141 bus_clk = ((output_freq * 1000) / 2) / 4;
142 }
143 else if ((clk_cfg_0 & 0x7) == 4) // UNIVPLL_D5 = UNIVPLL / 5
144 {
145 bus_clk = (1248 * 1000) / 5;
146 }
147 else if ((clk_cfg_0 & 0x7) == 5) // UNIVPLL2_D2 = UNIVPLL / 3 / 2
148 {
149 bus_clk = ((1248 * 1000) / 3) / 2;
150 }
151 else if ((clk_cfg_0 & 0x7) == 6) // DMPLL_CK = DMPLL /2
152 {
153 bus_clk = (533 * 1000) / 2;
154 }
155 else if ((clk_cfg_0 & 0x7) == 7) // DMPLL_D2 = DMPLL / 2 /2
156 {
157 bus_clk = ((533 * 1000) / 2) / 2 ;
158 }
159 else // CLKSQ
160 {
161 bus_clk = 26 * 1000;
162 }
163
164 //printk("bus frequency = %d Khz\n", bus_clk);
165
166 return bus_clk; // Khz
167 #endif
168 }
169 EXPORT_SYMBOL(mt_get_bus_freq);
170
171 unsigned int mt_get_cpu_freq(void)
172 {
173 int output = 0;
174 unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
175
176 clk26cali_0 = DRV_Reg32(CLK26CALI_0);
177 pminit_write(CLK26CALI_0, clk26cali_0 | 0x80); // enable fmeter_en
178
179 clk_misc_cfg_1 = DRV_Reg32(CLK_MISC_CFG_1);
180 pminit_write(CLK_MISC_CFG_1, 0xFFFF0300); // select divider
181
182 clk_cfg_8 = DRV_Reg32(CLK_CFG_8);
183 pminit_write(CLK_CFG_8, (39 << 8)); // select abist_cksw
184
185 temp = DRV_Reg32(CLK26CALI_0);
186 pminit_write(CLK26CALI_0, temp | 0x1); // start fmeter
187
188 /* wait frequency meter finish */
189 while (DRV_Reg32(CLK26CALI_0) & 0x1)
190 {
191 printk("wait for cpu frequency meter finish, CLK26CALI = 0x%x\n", DRV_Reg32(CLK26CALI_0));
192 mdelay(10);
193 }
194
195 temp = DRV_Reg32(CLK26CALI_1) & 0xFFFF;
196
197 output = ((temp * 26000) / 1024) * 4; // Khz
198
199 pminit_write(CLK_CFG_8, clk_cfg_8);
200 pminit_write(CLK_MISC_CFG_1, clk_misc_cfg_1);
201 pminit_write(CLK26CALI_0, clk26cali_0);
202
203 //printk("CLK26CALI = 0x%x, cpu frequency = %d Khz\n", temp, output);
204
205 return output;
206 }
207 EXPORT_SYMBOL(mt_get_cpu_freq);
208
209
210 static int cpu_speed_dump_show(struct seq_file* s, void* v)
211 {
212 seq_printf(s, "%d\n", mt_get_cpu_freq());
213 return 0;
214 }
215
216
217 static int cpu_speed_dump_open(struct inode *inode, struct file *file)
218 {
219 return single_open(file, cpu_speed_dump_show, NULL);
220 }
221
222
223 static const struct file_operations cpu_speed_dump_fops =
224 {
225 .owner = THIS_MODULE,
226 .open = cpu_speed_dump_open,
227 .read = seq_read,
228 .llseek = seq_lseek,
229 .release = single_release,
230 };
231
232
233 static int emi_speed_dump_show(struct seq_file* s, void* v)
234 {
235 seq_printf(s, "%d\n", mt_get_emi_freq());
236 return 0;
237 }
238
239
240 static int emi_speed_dump_open(struct inode *inode, struct file *file)
241 {
242 return single_open(file, emi_speed_dump_show, NULL);
243 }
244
245
246 static const struct file_operations emi_speed_dump_fops =
247 {
248 .owner = THIS_MODULE,
249 .open = emi_speed_dump_open,
250 .read = seq_read,
251 .llseek = seq_lseek,
252 .release = single_release,
253 };
254
255
256 static int bus_speed_dump_show(struct seq_file* s, void* v)
257 {
258 seq_printf(s, "%d\n", mt_get_bus_freq());
259 return 0;
260 }
261
262
263 static int bus_speed_dump_open(struct inode *inode, struct file *file)
264 {
265 return single_open(file, bus_speed_dump_show, NULL);
266 }
267
268
269 static const struct file_operations bus_speed_dump_fops =
270 {
271 .owner = THIS_MODULE,
272 .open = bus_speed_dump_open,
273 .read = seq_read,
274 .llseek = seq_lseek,
275 .release = single_release,
276 };
277
278
279 static int __init mt_power_management_init(void)
280 {
281 struct proc_dir_entry *entry = NULL;
282 struct proc_dir_entry *pm_init_dir = NULL;
283
284 pm_power_off = mt_power_off;
285
286 #if !defined (CONFIG_MT8127_FPGA_CA7)
287 xlog_printk(ANDROID_LOG_INFO, "Power/PM_INIT", "Bus Frequency = %d KHz\n", mt_get_bus_freq());
288
289 //cpu dormant driver init
290 cpu_dormant_init();
291
292 // SPM driver init
293 spm_module_init();
294
295 // Sleep driver init (for suspend)
296 slp_module_init();
297
298 //fix for bring up
299 //mt_clk_mgr_init(); // clock manager init, including clock gating init
300 mt_clkmgr_bringup_init();
301 //mt_clkmgr_init();
302
303 //mt_pm_log_init(); // power management log init
304
305 mt_dcm_init(); // dynamic clock management init
306 mt_idle_init();
307
308 pm_init_dir = proc_mkdir("pm_init", NULL);
309 if (!pm_init_dir)
310 {
311 pr_err("[%s]: mkdir /proc/pm_init failed\n", __FUNCTION__);
312 }
313 else
314 {
315 #define NEW_PROC 1
316 #if NEW_PROC
317 entry = proc_create("cpu_speed_dump", S_IRUGO, pm_init_dir, &cpu_speed_dump_fops);
318 #else
319 entry = create_proc_entry("cpu_speed_dump", S_IRUGO, pm_init_dir);
320 if (entry)
321 {
322 entry->read_proc = cpu_speed_dump_read;
323 }
324 #endif
325
326 #if NEW_PROC
327 entry = proc_create("emi_speed_dump", S_IRUGO, pm_init_dir, &emi_speed_dump_fops);
328 #else
329 entry = create_proc_entry("emi_speed_dump", S_IRUGO, pm_init_dir);
330 if (entry)
331 {
332 entry->read_proc = emi_speed_dump_read;
333 }
334 #endif
335
336 #if NEW_PROC
337 entry = proc_create("bus_speed_dump", S_IRUGO, pm_init_dir, &bus_speed_dump_fops);
338 #else
339 entry = create_proc_entry("bus_speed_dump", S_IRUGO, pm_init_dir);
340 if (entry)
341 {
342 entry->read_proc = bus_speed_dump_read;
343 }
344 #endif
345 }
346 #endif
347
348 return 0;
349 }
350
351 arch_initcall(mt_power_management_init);
352
353 MODULE_DESCRIPTION("MTK Power Management Init Driver");
354 MODULE_LICENSE("GPL");