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>
15 #include <asm/uaccess.h>
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"
29 #define pminit_write(addr, val) mt65xx_reg_sync_writel((val), ((void *)addr))
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 ********************************************************************/
39 unsigned int mt_get_emi_freq(void)
42 unsigned int temp
, clk26cali_0
, clk_cfg_8
, clk_misc_cfg_1
;
44 clk26cali_0
= DRV_Reg32(CLK26CALI_0
);
45 pminit_write(CLK26CALI_0
, clk26cali_0
| 0x80); // enable fmeter_en
47 clk_misc_cfg_1
= DRV_Reg32(CLK_MISC_CFG_1
);
48 pminit_write(CLK_MISC_CFG_1
, 0xFFFFFF00); // select divider
50 clk_cfg_8
= DRV_Reg32(CLK_CFG_8
);
51 pminit_write(CLK_CFG_8
, (14 << 8)); // select abist_cksw
53 temp
= DRV_Reg32(CLK26CALI_0
);
54 pminit_write(CLK26CALI_0
, temp
| 0x1); // start fmeter
56 /* wait frequency meter finish */
57 while (DRV_Reg32(CLK26CALI_0
) & 0x1)
59 printk("wait for emi frequency meter finish, CLK26CALI = 0x%x\n", DRV_Reg32(CLK26CALI_0
));
63 temp
= DRV_Reg32(CLK26CALI_1
) & 0xFFFF;
65 output
= (temp
* 26000) / 1024; // Khz
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
);
71 //printk("CLK26CALI = 0x%x, mem frequency = %d Khz\n", temp, output);
75 EXPORT_SYMBOL(mt_get_emi_freq
);
77 unsigned int mt_get_bus_freq(void)
81 unsigned int temp
, clk26cali_0
, clk_cfg_9
, clk_misc_cfg_1
, clk26cali_2
;
83 clk26cali_0
= DRV_Reg32(CLK26CALI_0
);
84 pminit_write(CLK26CALI_0
, clk26cali_0
| 0x80); // enable fmeter_en
86 clk_misc_cfg_1
= DRV_Reg32(CLK_MISC_CFG_1
);
87 pminit_write(CLK_MISC_CFG_1
, 0x00FFFFFF); // select divider
89 clk_cfg_9
= DRV_Reg32(CLK_CFG_9
);
90 pminit_write(CLK_CFG_9
, (1 << 16)); // select ckgen_cksw
92 temp
= DRV_Reg32(CLK26CALI_0
);
93 pminit_write(CLK26CALI_0
, temp
| 0x10); // start fmeter
95 /* wait frequency meter finish */
96 while (DRV_Reg32(CLK26CALI_0
) & 0x10)
98 //printk("wait for bus frequency meter finish, CLK26CALI = 0x%x\n", DRV_Reg32(CLK26CALI_0));
102 temp
= DRV_Reg32(CLK26CALI_2
) & 0xFFFF;
104 output
= (temp
* 26000) / 1024; // Khz
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
);
110 //printk("CLK26CALI = 0x%x, bus frequency = %d Khz\n", temp, output);
114 unsigned int mainpll_con0
, mainpll_con1
, main_diff
;
115 unsigned int clk_cfg_0
, bus_clk
;
116 unsigned int output_freq
= 0;
118 clk_cfg_0
= DRV_Reg32(CLK_CFG_0
);
120 mainpll_con0
= DRV_Reg32(MAINPLL_CON0
);
121 mainpll_con1
= DRV_Reg32(MAINPLL_CON1
);
123 //main_diff = ((mainpll_con1 >> 12) - 0x8009A) / 2;
124 main_diff
= (((mainpll_con1
& 0x1FFFFF) >> 12) - 0x9A) / 2;
126 if ((mainpll_con0
& 0xFF) == 0x01)
128 output_freq
= 1001 + (main_diff
* 13); // Mhz
131 if ((clk_cfg_0
& 0x7) == 1) // SYSPLL1_D2 = MAINPLL / 2 / 2
133 bus_clk
= ((output_freq
* 1000) / 2) / 2;
135 else if ((clk_cfg_0
& 0x7) == 2) // SYSPLL_D5 = MAINPLL / 5
137 bus_clk
= (output_freq
* 1000) / 5;
139 else if ((clk_cfg_0
& 0x7) == 3) // SYSPLL1_D4 = MAINPLL / 2 / 4
141 bus_clk
= ((output_freq
* 1000) / 2) / 4;
143 else if ((clk_cfg_0
& 0x7) == 4) // UNIVPLL_D5 = UNIVPLL / 5
145 bus_clk
= (1248 * 1000) / 5;
147 else if ((clk_cfg_0
& 0x7) == 5) // UNIVPLL2_D2 = UNIVPLL / 3 / 2
149 bus_clk
= ((1248 * 1000) / 3) / 2;
151 else if ((clk_cfg_0
& 0x7) == 6) // DMPLL_CK = DMPLL /2
153 bus_clk
= (533 * 1000) / 2;
155 else if ((clk_cfg_0
& 0x7) == 7) // DMPLL_D2 = DMPLL / 2 /2
157 bus_clk
= ((533 * 1000) / 2) / 2 ;
164 //printk("bus frequency = %d Khz\n", bus_clk);
166 return bus_clk
; // Khz
169 EXPORT_SYMBOL(mt_get_bus_freq
);
171 unsigned int mt_get_cpu_freq(void)
174 unsigned int temp
, clk26cali_0
, clk_cfg_8
, clk_misc_cfg_1
;
176 clk26cali_0
= DRV_Reg32(CLK26CALI_0
);
177 pminit_write(CLK26CALI_0
, clk26cali_0
| 0x80); // enable fmeter_en
179 clk_misc_cfg_1
= DRV_Reg32(CLK_MISC_CFG_1
);
180 pminit_write(CLK_MISC_CFG_1
, 0xFFFF0300); // select divider
182 clk_cfg_8
= DRV_Reg32(CLK_CFG_8
);
183 pminit_write(CLK_CFG_8
, (39 << 8)); // select abist_cksw
185 temp
= DRV_Reg32(CLK26CALI_0
);
186 pminit_write(CLK26CALI_0
, temp
| 0x1); // start fmeter
188 /* wait frequency meter finish */
189 while (DRV_Reg32(CLK26CALI_0
) & 0x1)
191 printk("wait for cpu frequency meter finish, CLK26CALI = 0x%x\n", DRV_Reg32(CLK26CALI_0
));
195 temp
= DRV_Reg32(CLK26CALI_1
) & 0xFFFF;
197 output
= ((temp
* 26000) / 1024) * 4; // Khz
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
);
203 //printk("CLK26CALI = 0x%x, cpu frequency = %d Khz\n", temp, output);
207 EXPORT_SYMBOL(mt_get_cpu_freq
);
210 static int cpu_speed_dump_show(struct seq_file
* s
, void* v
)
212 seq_printf(s
, "%d\n", mt_get_cpu_freq());
217 static int cpu_speed_dump_open(struct inode
*inode
, struct file
*file
)
219 return single_open(file
, cpu_speed_dump_show
, NULL
);
223 static const struct file_operations cpu_speed_dump_fops
=
225 .owner
= THIS_MODULE
,
226 .open
= cpu_speed_dump_open
,
229 .release
= single_release
,
233 static int emi_speed_dump_show(struct seq_file
* s
, void* v
)
235 seq_printf(s
, "%d\n", mt_get_emi_freq());
240 static int emi_speed_dump_open(struct inode
*inode
, struct file
*file
)
242 return single_open(file
, emi_speed_dump_show
, NULL
);
246 static const struct file_operations emi_speed_dump_fops
=
248 .owner
= THIS_MODULE
,
249 .open
= emi_speed_dump_open
,
252 .release
= single_release
,
256 static int bus_speed_dump_show(struct seq_file
* s
, void* v
)
258 seq_printf(s
, "%d\n", mt_get_bus_freq());
263 static int bus_speed_dump_open(struct inode
*inode
, struct file
*file
)
265 return single_open(file
, bus_speed_dump_show
, NULL
);
269 static const struct file_operations bus_speed_dump_fops
=
271 .owner
= THIS_MODULE
,
272 .open
= bus_speed_dump_open
,
275 .release
= single_release
,
279 static int __init
mt_power_management_init(void)
281 struct proc_dir_entry
*entry
= NULL
;
282 struct proc_dir_entry
*pm_init_dir
= NULL
;
284 pm_power_off
= mt_power_off
;
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());
289 //cpu dormant driver init
295 // Sleep driver init (for suspend)
299 //mt_clk_mgr_init(); // clock manager init, including clock gating init
300 mt_clkmgr_bringup_init();
303 //mt_pm_log_init(); // power management log init
305 mt_dcm_init(); // dynamic clock management init
308 pm_init_dir
= proc_mkdir("pm_init", NULL
);
311 pr_err("[%s]: mkdir /proc/pm_init failed\n", __FUNCTION__
);
317 entry
= proc_create("cpu_speed_dump", S_IRUGO
, pm_init_dir
, &cpu_speed_dump_fops
);
319 entry
= create_proc_entry("cpu_speed_dump", S_IRUGO
, pm_init_dir
);
322 entry
->read_proc
= cpu_speed_dump_read
;
327 entry
= proc_create("emi_speed_dump", S_IRUGO
, pm_init_dir
, &emi_speed_dump_fops
);
329 entry
= create_proc_entry("emi_speed_dump", S_IRUGO
, pm_init_dir
);
332 entry
->read_proc
= emi_speed_dump_read
;
337 entry
= proc_create("bus_speed_dump", S_IRUGO
, pm_init_dir
, &bus_speed_dump_fops
);
339 entry
= create_proc_entry("bus_speed_dump", S_IRUGO
, pm_init_dir
);
342 entry
->read_proc
= bus_speed_dump_read
;
351 arch_initcall(mt_power_management_init
);
353 MODULE_DESCRIPTION("MTK Power Management Init Driver");
354 MODULE_LICENSE("GPL");