import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / arm / mach-mt8127 / mt_pm_init.c
CommitLineData
6fa3eb70
S
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
32extern int mt_clkmgr_bringup_init(void);
33extern void mt_idle_init(void);
34extern void mt_power_off(void);
35/*********************************************************************
36 * FUNCTION DEFINATIONS
37 ********************************************************************/
38
39unsigned 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}
75EXPORT_SYMBOL(mt_get_emi_freq);
76
77unsigned 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}
169EXPORT_SYMBOL(mt_get_bus_freq);
170
171unsigned 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}
207EXPORT_SYMBOL(mt_get_cpu_freq);
208
209
210static 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
217static 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
223static 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
233static 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
240static 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
246static 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
256static 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
263static 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
269static 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
279static 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
351arch_initcall(mt_power_management_init);
352
353MODULE_DESCRIPTION("MTK Power Management Init Driver");
354MODULE_LICENSE("GPL");