Commit | Line | Data |
---|---|---|
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 | |
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"); |