mt_pm_init.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. #include <linux/pm.h>
  2. #include <linux/module.h>
  3. #include <linux/proc_fs.h>
  4. #include <linux/seq_file.h>
  5. #include <linux/kernel.h>
  6. #include <linux/init.h>
  7. #include <linux/delay.h>
  8. #include <linux/gpio.h>
  9. #include <linux/spinlock.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/types.h>
  12. /* #include <linux/xlog.h> */
  13. #include <asm/io.h>
  14. #include <asm/uaccess.h>
  15. /* #include "mach/irqs.h" */
  16. #include <mt-plat/sync_write.h>
  17. /* #include "mach/mt_reg_base.h" */
  18. /* #include "mach/mt_typedefs.h" */
  19. #include "mt_spm.h"
  20. #include "mt_sleep.h"
  21. #include "mt_dcm.h"
  22. #include "mt_clkmgr.h"
  23. #include "mt_cpufreq.h"
  24. #include "mt_gpufreq.h"
  25. /* #include "mach/mt_sleep.h" */
  26. /* #include "mach/mt_dcm.h" */
  27. #include <mach/mt_clkmgr.h>
  28. /* #include "mach/mt_cpufreq.h" */
  29. /* #include "mach/mt_gpufreq.h" */
  30. #include "mt_cpuidle.h"
  31. #include <mt_clkbuf_ctl.h>
  32. /* #include "mach/mt_clkbuf_ctl.h" */
  33. /* #include "mach/mt_chip.h" */
  34. #include "mt-plat/mtk_rtc.h"
  35. #define pminit_write(addr, val) mt_reg_sync_writel((val), ((void *)(addr)))
  36. #define pminit_read(addr) __raw_readl(IOMEM(addr))
  37. #ifndef DRV_WriteReg32
  38. #define DRV_WriteReg32(addr, val) \
  39. mt_reg_sync_writel(val, addr)
  40. #endif
  41. #define TOPCK_LDVT
  42. #ifdef TOPCK_LDVT
  43. /***************************
  44. *For TOPCKGen Meter LDVT Test
  45. ****************************/
  46. static unsigned int ckgen_meter(int val)
  47. {
  48. int output = 0;
  49. int i = 0;
  50. unsigned int temp, clk26cali_0, clk_cfg_9, clk_misc_cfg_1;
  51. clk26cali_0 = readl(CLK26CALI_0);
  52. DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
  53. clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
  54. DRV_WriteReg32(CLK_MISC_CFG_1, 0x00FFFFFF); /* select divider */
  55. clk_cfg_9 = readl(CLK_CFG_9);
  56. DRV_WriteReg32(CLK_CFG_9, (val << 16)); /* select ckgen_cksw */
  57. temp = readl(CLK26CALI_0);
  58. DRV_WriteReg32(CLK26CALI_0, temp | 0x10); /* start fmeter */
  59. /* wait frequency meter finish */
  60. while (readl(CLK26CALI_0) & 0x10) {
  61. mdelay(10);
  62. i++;
  63. if (i > 10)
  64. break;
  65. }
  66. temp = readl(CLK26CALI_2) & 0xFFFF;
  67. output = (temp * 26000) / 1024; /* Khz */
  68. DRV_WriteReg32(CLK_CFG_9, clk_cfg_9);
  69. DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1);
  70. DRV_WriteReg32(CLK26CALI_0, clk26cali_0);
  71. if (i > 10)
  72. return 0;
  73. else
  74. return output;
  75. }
  76. static unsigned int abist_meter(int val)
  77. {
  78. int output = 0;
  79. int i = 0;
  80. unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
  81. clk26cali_0 = readl(CLK26CALI_0);
  82. DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
  83. clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
  84. DRV_WriteReg32(CLK_MISC_CFG_1, 0xFFFFFF00); /* select divider */
  85. clk_cfg_8 = readl(CLK_CFG_8);
  86. DRV_WriteReg32(CLK_CFG_8, (val << 8)); /* select abist_cksw */
  87. temp = readl(CLK26CALI_0);
  88. DRV_WriteReg32(CLK26CALI_0, temp | 0x1); /* start fmeter */
  89. /* wait frequency meter finish */
  90. while (readl(CLK26CALI_0) & 0x1) {
  91. mdelay(10);
  92. i++;
  93. if (i > 10)
  94. break;
  95. }
  96. temp = readl(CLK26CALI_1) & 0xFFFF;
  97. output = (temp * 26000) / 1024; /* Khz */
  98. DRV_WriteReg32(CLK_CFG_8, clk_cfg_8);
  99. DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1);
  100. DRV_WriteReg32(CLK26CALI_0, clk26cali_0);
  101. if (i > 10)
  102. return 0;
  103. else
  104. return output;
  105. }
  106. #if defined(CONFIG_ARCH_MT6753)
  107. const char *ckgen_array[] = {
  108. "hf_faxi_ck", "hd_faxi_ck", "hf_fdpi0_ck", "hf_fddrphycfg_ck", "hf_fmm_ck",
  109. "f_fpwm_ck", "hf_fvdec_ck", "hf_fmfg_ck", "hf_fcamtg_ck", "f_fuart_ck",
  110. "hf_fspi_ck", "f_fusb20_ck", "hf_fmsdc30_0_ck", "hf_fmsdc30_1_ck", "hf_fmsdc30_2_ck",
  111. "hf_faudio_ck", "hf_faud_intbus_ck", "hf_fpmicspi_ck", "f_frtc_ck", "f_f26m_ck",
  112. "f_f32k_md1_ck", "f_frtc_conn_ck", "hf_fmsdc30_3_ck", "hg_fmipicfg_ck", "NULL",
  113. "hd_qaxidcm_ck", "NULL", "hf_fscam_ck", "f_fckbus_scan", " f_fckrtc_scan",
  114. "hf_fatb_ck", "hf_faud_1_ck", "hf_faud_2_ck", "hf_fmsdc50_0_ck", "hf_firda_ck",
  115. " hf_firtx_ck", "hf_fdisppwm_ck", "hs_fmfg13m_ck"
  116. };
  117. #else
  118. const char *ckgen_array[] = {
  119. "hf_faxi_ck", "hd_faxi_ck", "hf_fdpi0_ck", "hf_fddrphycfg_ck", "hf_fmm_ck",
  120. "f_fpwm_ck", "hf_fvdec_ck", "hf_fmfg_ck", "hf_fcamtg_ck", "f_fuart_ck",
  121. "hf_fspi_ck", "f_fusb20_ck", "hf_fmsdc30_0_ck", "hf_fmsdc30_1_ck", "hf_fmsdc30_2_ck",
  122. "hf_faudio_ck", "hf_faud_intbus_ck", "hf_fpmicspi_ck", "f_frtc_ck", "f_f26m_ck",
  123. "f_f32k_md1_ck", "f_frtc_conn_ck", "f_fusb20p1_ck", "hg_fmipicfg_ck", "NULL",
  124. "hd_qaxidcm_ck", "NULL", "hf_fscam_ck", "f_fckbus_scan", " f_fckrtc_scan",
  125. "hf_fatb_ck", "hf_faud_1_ck", "hf_faud_2_ck", "hf_fmsdc50_0_ck", "hf_firda_ck",
  126. " hf_firtx_ck", "hf_fdisppwm_ck", "hs_fmfg13m_ck"
  127. };
  128. #endif
  129. static int ckgen_meter_read(struct seq_file *m, void *v)
  130. {
  131. int i;
  132. for (i = 1; i < 39; i++)
  133. seq_printf(m, "%s: %d\n", ckgen_array[i-1], ckgen_meter(i));
  134. return 0;
  135. }
  136. static ssize_t ckgen_meter_write(struct file *file, const char __user *buffer,
  137. size_t count, loff_t *data)
  138. {
  139. char desc[128];
  140. int len = 0;
  141. /*int val;*/
  142. len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
  143. if (copy_from_user(desc, buffer, len))
  144. return 0;
  145. desc[len] = '\0';
  146. /*if (sscanf(desc, "%d", &val) == 1)*/
  147. /*if (kstrtoint(desc, "%d", &val) == 1)
  148. pr_debug("ckgen_meter %d is %d\n", val, ckgen_meter(val));*/
  149. return count;
  150. }
  151. static int abist_meter_read(struct seq_file *m, void *v)
  152. {
  153. int i;
  154. for (i = 1; i < 59; i++)
  155. seq_printf(m, "%d\n", abist_meter(i));
  156. return 0;
  157. }
  158. static ssize_t abist_meter_write(struct file *file, const char __user *buffer,
  159. size_t count, loff_t *data)
  160. {
  161. char desc[128];
  162. int len = 0;
  163. /*int val;*/
  164. len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1);
  165. if (copy_from_user(desc, buffer, len))
  166. return 0;
  167. desc[len] = '\0';
  168. /*if (sscanf(desc, "%d", &val) == 1)*/
  169. /*if (kstrtoint(desc, "%d", &val) == 1)
  170. pr_debug("abist_meter %d is %d\n", val, abist_meter(val)); */
  171. return count;
  172. }
  173. static int proc_abist_meter_open(struct inode *inode, struct file *file)
  174. {
  175. return single_open(file, abist_meter_read, NULL);
  176. }
  177. static const struct file_operations abist_meter_fops = {
  178. .owner = THIS_MODULE,
  179. .open = proc_abist_meter_open,
  180. .read = seq_read,
  181. .write = abist_meter_write,
  182. };
  183. static int proc_ckgen_meter_open(struct inode *inode, struct file *file)
  184. {
  185. return single_open(file, ckgen_meter_read, NULL);
  186. }
  187. static const struct file_operations ckgen_meter_fops = {
  188. .owner = THIS_MODULE,
  189. .open = proc_ckgen_meter_open,
  190. .read = seq_read,
  191. .write = ckgen_meter_write,
  192. };
  193. #endif
  194. /*********************************************************************
  195. * FUNCTION DEFINATIONS
  196. ********************************************************************/
  197. static unsigned int mt_get_emi_freq(void)
  198. {
  199. int output = 0;
  200. int i = 0;
  201. unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
  202. clk26cali_0 = readl(CLK26CALI_0);
  203. DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
  204. clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
  205. DRV_WriteReg32(CLK_MISC_CFG_1, 0xFFFFFF00); /* select divider */
  206. clk_cfg_8 = readl(CLK_CFG_8);
  207. DRV_WriteReg32(CLK_CFG_8, (14 << 8)); /* select abist_cksw */
  208. temp = readl(CLK26CALI_0);
  209. DRV_WriteReg32(CLK26CALI_0, temp | 0x1); /* start fmeter */
  210. /* wait frequency meter finish */
  211. while (readl(CLK26CALI_0) & 0x1) {
  212. mdelay(10);
  213. i++;
  214. if (i > 10)
  215. break;
  216. }
  217. temp = readl(CLK26CALI_1) & 0xFFFF;
  218. output = (temp * 26000) / 1024; /* Khz */
  219. DRV_WriteReg32(CLK_CFG_8, clk_cfg_8);
  220. DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1);
  221. DRV_WriteReg32(CLK26CALI_0, clk26cali_0);
  222. if (i > 10)
  223. return 0;
  224. else
  225. return output;
  226. }
  227. EXPORT_SYMBOL(mt_get_emi_freq);
  228. unsigned int mt_check_bus_freq(void)
  229. {
  230. unsigned int axi_bus_sel = 0;
  231. unsigned int bus_clk = 273000;
  232. axi_bus_sel = (readl(CLK_CFG_0) & 0x00000007);
  233. switch (axi_bus_sel) {
  234. case 0: /* 26M */
  235. bus_clk = 26000;
  236. break;
  237. case 1: /* SYSPLL1_D2: 273M */
  238. bus_clk = 273000;
  239. break;
  240. case 2: /* SYSPLL_D5: 218.4M */
  241. bus_clk = 218400;
  242. break;
  243. case 3: /* SYSPLL1_D4: 136.5M */
  244. bus_clk = 136500;
  245. break;
  246. case 4: /* UNIVPLL_D5: 249.6M */
  247. bus_clk = 249600;
  248. break;
  249. case 5: /* UNIVPLL2_D2: 208M */
  250. bus_clk = 208000;
  251. break;
  252. default:
  253. break;
  254. }
  255. return bus_clk; /* Khz */
  256. }
  257. EXPORT_SYMBOL(mt_check_bus_freq);
  258. unsigned int mt_get_bus_freq(void)
  259. {
  260. int output = 0;
  261. int i = 0;
  262. unsigned int temp, clk26cali_0, clk_cfg_9, clk_misc_cfg_1;
  263. clk26cali_0 = readl(CLK26CALI_0);
  264. DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
  265. clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
  266. DRV_WriteReg32(CLK_MISC_CFG_1, 0x00FFFFFF); /* select divider */
  267. clk_cfg_9 = readl(CLK_CFG_9);
  268. DRV_WriteReg32(CLK_CFG_9, (1 << 16)); /* select ckgen_cksw */
  269. temp = readl(CLK26CALI_0);
  270. DRV_WriteReg32(CLK26CALI_0, temp | 0x10); /* start fmeter */
  271. /* wait frequency meter finish */
  272. while (readl(CLK26CALI_0) & 0x10) {
  273. udelay(10);
  274. i++;
  275. if (i > 1000)
  276. break;
  277. }
  278. temp = readl(CLK26CALI_2) & 0xFFFF;
  279. output = (temp * 26000) / 1024; /* Khz */
  280. DRV_WriteReg32(CLK_CFG_9, clk_cfg_9);
  281. DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1);
  282. DRV_WriteReg32(CLK26CALI_0, clk26cali_0);
  283. if (i > 1000)
  284. return 0;
  285. else
  286. return output;
  287. }
  288. EXPORT_SYMBOL(mt_get_bus_freq);
  289. static unsigned int mt_get_cpu_freq(void)
  290. {
  291. int output = 0;
  292. int i = 0;
  293. unsigned int temp, clk26cali_0, clk_cfg_8, clk_misc_cfg_1;
  294. clk26cali_0 = readl(CLK26CALI_0);
  295. DRV_WriteReg32(CLK26CALI_0, clk26cali_0 | 0x80); /* enable fmeter_en */
  296. clk_misc_cfg_1 = readl(CLK_MISC_CFG_1);
  297. DRV_WriteReg32(CLK_MISC_CFG_1, 0xFFFF0300); /* select divider */
  298. clk_cfg_8 = readl(CLK_CFG_8);
  299. DRV_WriteReg32(CLK_CFG_8, (39 << 8)); /* select abist_cksw */
  300. temp = readl(CLK26CALI_0);
  301. DRV_WriteReg32(CLK26CALI_0, temp | 0x1); /* start fmeter */
  302. /* wait frequency meter finish */
  303. while (readl(CLK26CALI_0) & 0x1) {
  304. mdelay(10);
  305. i++;
  306. if (i > 10)
  307. break;
  308. }
  309. temp = readl(CLK26CALI_1) & 0xFFFF;
  310. output = ((temp * 26000) / 1024) * 4; /* Khz */
  311. DRV_WriteReg32(CLK_CFG_8, clk_cfg_8);
  312. DRV_WriteReg32(CLK_MISC_CFG_1, clk_misc_cfg_1);
  313. DRV_WriteReg32(CLK26CALI_0, clk26cali_0);
  314. if (i > 10)
  315. return 0;
  316. else
  317. return output;
  318. }
  319. EXPORT_SYMBOL(mt_get_cpu_freq);
  320. static int cpu_speed_dump_read(struct seq_file *m, void *v)
  321. {
  322. seq_printf(m, "%d\n", mt_get_cpu_freq());
  323. return 0;
  324. }
  325. static int emi_speed_dump_read(struct seq_file *m, void *v)
  326. {
  327. seq_printf(m, "%d\n", mt_get_emi_freq());
  328. return 0;
  329. }
  330. static int bus_speed_dump_read(struct seq_file *m, void *v)
  331. {
  332. seq_printf(m, "%d\n", mt_get_bus_freq());
  333. return 0;
  334. }
  335. #if 0
  336. static int mmclk_speed_dump_read(struct seq_file *m, void *v)
  337. {
  338. seq_printf(m, "%d\n", mt_get_mmclk_freq());
  339. return 0;
  340. }
  341. static int mfgclk_speed_dump_read(struct seq_file *m, void *v)
  342. {
  343. seq_printf(m, "%d\n", mt_get_mfgclk_freq());
  344. return 0;
  345. }
  346. #endif
  347. static int proc_cpu_open(struct inode *inode, struct file *file)
  348. {
  349. return single_open(file, cpu_speed_dump_read, NULL);
  350. }
  351. static const struct file_operations cpu_fops = {
  352. .owner = THIS_MODULE,
  353. .open = proc_cpu_open,
  354. .read = seq_read,
  355. };
  356. static int proc_emi_open(struct inode *inode, struct file *file)
  357. {
  358. return single_open(file, emi_speed_dump_read, NULL);
  359. }
  360. static const struct file_operations emi_fops = {
  361. .owner = THIS_MODULE,
  362. .open = proc_emi_open,
  363. .read = seq_read,
  364. };
  365. static int proc_bus_open(struct inode *inode, struct file *file)
  366. {
  367. return single_open(file, bus_speed_dump_read, NULL);
  368. }
  369. static const struct file_operations bus_fops = {
  370. .owner = THIS_MODULE,
  371. .open = proc_bus_open,
  372. .read = seq_read,
  373. };
  374. #if 0
  375. static int proc_mmclk_open(struct inode *inode, struct file *file)
  376. {
  377. return single_open(file, mmclk_speed_dump_read, NULL);
  378. }
  379. static const struct file_operations mmclk_fops = {
  380. .owner = THIS_MODULE,
  381. .open = proc_mmclk_open,
  382. .read = seq_read,
  383. };
  384. static int proc_mfgclk_open(struct inode *inode, struct file *file)
  385. {
  386. return single_open(file, mfgclk_speed_dump_read, NULL);
  387. }
  388. static const struct file_operations mfgclk_fops = {
  389. .owner = THIS_MODULE,
  390. .open = proc_mfgclk_open,
  391. .read = seq_read,
  392. };
  393. #endif
  394. static int __init mt_power_management_init(void)
  395. {
  396. struct proc_dir_entry *entry = NULL;
  397. struct proc_dir_entry *pm_init_dir = NULL;
  398. /* unsigned int code = mt_get_chip_hw_code(); */
  399. pm_power_off = mt_power_off;
  400. #if !defined(CONFIG_MTK_FPGA)
  401. /* cpu dormant driver init */
  402. mt_cpu_dormant_init();
  403. spm_module_init();
  404. slp_module_init();
  405. mt_clkmgr_init();
  406. /* mt_pm_log_init(); // power management log init */
  407. /* mt_dcm_init(); // dynamic clock management init */
  408. pm_init_dir = proc_mkdir("pm_init", NULL);
  409. /* pm_init_dir = proc_mkdir("pm_init", NULL); */
  410. if (!pm_init_dir) {
  411. pr_debug("[%s]: mkdir /proc/pm_init failed\n", __func__);
  412. } else {
  413. entry = proc_create("cpu_speed_dump", S_IRUGO, pm_init_dir, &cpu_fops);
  414. /* entry = proc_create("bigcpu_speed_dump", S_IRUGO, pm_init_dir, &bigcpu_fops); */
  415. entry = proc_create("emi_speed_dump", S_IRUGO, pm_init_dir, &emi_fops);
  416. entry = proc_create("bus_speed_dump", S_IRUGO, pm_init_dir, &bus_fops);
  417. /* entry = proc_create("mmclk_speed_dump", S_IRUGO, pm_init_dir, &mmclk_fops); */
  418. /* entry = proc_create("mfgclk_speed_dump", S_IRUGO, pm_init_dir, &mfgclk_fops); */
  419. #ifdef TOPCK_LDVT
  420. entry = proc_create("abist_meter_test", S_IRUGO|S_IWUSR, pm_init_dir, &abist_meter_fops);
  421. entry = proc_create("ckgen_meter_test", S_IRUGO|S_IWUSR, pm_init_dir, &ckgen_meter_fops);
  422. #endif
  423. }
  424. #endif
  425. return 0;
  426. }
  427. arch_initcall(mt_power_management_init);
  428. #if !defined(MT_DORMANT_UT)
  429. static int __init mt_pm_late_init(void)
  430. {
  431. #ifndef CONFIG_MTK_FPGA
  432. /* mt_idle_init(); */
  433. clk_buf_init();
  434. #endif
  435. return 0;
  436. }
  437. late_initcall(mt_pm_late_init);
  438. #endif /* #if !defined (MT_DORMANT_UT) */
  439. MODULE_DESCRIPTION("MTK Power Management Init Driver");
  440. MODULE_LICENSE("GPL");