mtk_hibernate_dpm.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #define pr_fmt(fmt) "[HIB/SwSuspHlper] " fmt
  2. #include <linux/module.h>
  3. #include <linux/device.h>
  4. #include <linux/fs.h>
  5. #include <linux/cdev.h>
  6. #include <linux/interrupt.h>
  7. #include <linux/spinlock.h>
  8. #include <linux/uaccess.h>
  9. #include <linux/mm.h>
  10. #include <linux/kfifo.h>
  11. #include <linux/syscalls.h>
  12. #include <linux/uaccess.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/proc_fs.h>
  15. #include <linux/suspend.h>
  16. #include <mtk_hibernate_dpm.h>
  17. #ifdef CONFIG_MTK_SYSENV
  18. #include <env.h> /* for set_env() by MTK */
  19. #endif
  20. #define HIB_SWSUSP_DEBUG 0
  21. #if (HIB_SWSUSP_DEBUG)
  22. #undef hib_log
  23. #define hib_log(fmt, args...) pr_debug(fmt, ##args)
  24. #else
  25. #define hib_log(fmt, args...) ((void)0)
  26. #endif
  27. #undef hib_warn
  28. #define hib_warn(fmt, args...) pr_warn(fmt, ##args)
  29. #undef hib_err
  30. #define hib_err(fmt, args...) pr_err(fmt, ##args)
  31. #define SWSUSP_HELPER_NAME "swsusp-helper"
  32. /* callback APIs helper function table */
  33. static swsusp_cb_func_info restore_noirq_func_table[MAX_CB_FUNCS];
  34. static int initialized;
  35. int register_swsusp_restore_noirq_func(unsigned int id, swsusp_cb_func_t func,
  36. struct device *device)
  37. {
  38. int ret = 0;
  39. swsusp_cb_func_info *info_ptr;
  40. BUG_ON(!initialized);
  41. if ((id >= MAX_CB_FUNCS) || (func == NULL)) {
  42. hib_err("register func fail: func_id: %d!\n", id);
  43. return E_PARAM;
  44. }
  45. info_ptr = &(restore_noirq_func_table[id]);
  46. if (info_ptr->func == NULL) {
  47. info_ptr->id = id;
  48. info_ptr->func = func;
  49. info_ptr->device = device;
  50. hib_warn("reg. func %d:0x%p with device %s%p\n",
  51. restore_noirq_func_table[id].id,
  52. restore_noirq_func_table[id].func,
  53. (device == NULL) ? " " : "0x",
  54. restore_noirq_func_table[id].device);
  55. } else
  56. hib_err("register func fail: func(%d) already registered!\n", id);
  57. return ret;
  58. }
  59. EXPORT_SYMBOL(register_swsusp_restore_noirq_func);
  60. int unregister_swsusp_restore_noirq_func(unsigned int id)
  61. {
  62. int ret = 0;
  63. swsusp_cb_func_info *info_ptr;
  64. BUG_ON(!initialized);
  65. if (id >= MAX_CB_FUNCS || id != restore_noirq_func_table[id].id) {
  66. hib_err("register func fail: func_id: %d!\n", id);
  67. return E_PARAM;
  68. }
  69. info_ptr = &(restore_noirq_func_table[id]);
  70. if (info_ptr->func != NULL) {
  71. info_ptr->id = -1;
  72. info_ptr->func = NULL;
  73. info_ptr->device = NULL;
  74. } else
  75. hib_warn("register func fail: func(%d) already unregistered!\n", id);
  76. return ret;
  77. }
  78. EXPORT_SYMBOL(unregister_swsusp_restore_noirq_func);
  79. int exec_swsusp_restore_noirq_func(unsigned int id)
  80. {
  81. swsusp_cb_func_t func;
  82. struct device *device = NULL;
  83. int ret = 0;
  84. BUG_ON(!initialized);
  85. if (id >= MAX_CB_FUNCS || id != restore_noirq_func_table[id].id) {
  86. hib_err("exec func fail: invalid func id(%d)!\n", id);
  87. return E_PARAM;
  88. }
  89. func = restore_noirq_func_table[id].func;
  90. device = restore_noirq_func_table[id].device;
  91. if (func != NULL) {
  92. ret = func(device);
  93. } else {
  94. ret = E_NO_EXIST;
  95. hib_warn("exec func fail: func id(%d) not register!\n", id);
  96. }
  97. return ret;
  98. }
  99. EXPORT_SYMBOL(exec_swsusp_restore_noirq_func);
  100. static int swsusp_helper_probe(struct platform_device *dev)
  101. {
  102. hib_log("[%s] enter...\n", __func__);
  103. return 0;
  104. }
  105. static int swsusp_helper_remove(struct platform_device *dev)
  106. {
  107. hib_log("[%s] enter...\n", __func__);
  108. return 0;
  109. }
  110. /*---------------------------------------------------------------------------*/
  111. #ifdef CONFIG_PM
  112. /*---------------------------------------------------------------------------*/
  113. int swsusp_helper_pm_suspend(struct device *device)
  114. {
  115. hib_log("[%s] enter...\n", __func__);
  116. return 0;
  117. }
  118. int swsusp_helper_pm_resume(struct device *device)
  119. {
  120. hib_log("[%s] enter...\n", __func__);
  121. return 0;
  122. }
  123. int swsusp_helper_pm_restore_noirq(struct device *device)
  124. {
  125. int id, ret = 0, retall = 0;
  126. hib_log("[%s] enter...\n", __func__);
  127. BUG_ON(!initialized);
  128. for (id = ID_M_BEGIN; id < ID_M_END; id++) {
  129. if (restore_noirq_func_table[id].func != NULL) {
  130. hib_warn("exec func %d:0x%p !\n", restore_noirq_func_table[id].id,
  131. restore_noirq_func_table[id].func);
  132. if (id != restore_noirq_func_table[id].id) {
  133. hib_err("exec func fail: func id miss-matched (%d/%d) !\n",
  134. id, restore_noirq_func_table[id].id);
  135. continue;
  136. }
  137. ret =
  138. restore_noirq_func_table[id].func(restore_noirq_func_table[id].device);
  139. if (ret != 0) {
  140. hib_warn("exec func fail: func id(%d), err code %d !\n",
  141. restore_noirq_func_table[id].id, ret);
  142. retall = ret;
  143. }
  144. }
  145. }
  146. return retall;
  147. }
  148. /*---------------------------------------------------------------------------*/
  149. #else /*CONFIG_PM */
  150. /*---------------------------------------------------------------------------*/
  151. #define swsusp_helper_pm_suspend NULL
  152. #define swsusp_helper_pm_resume NULL
  153. #define swsusp_helper_pm_restore_noirq NULL
  154. /*---------------------------------------------------------------------------*/
  155. #endif /*CONFIG_PM */
  156. /*---------------------------------------------------------------------------*/
  157. const struct dev_pm_ops swsusp_helper_pm_ops = {
  158. .suspend = swsusp_helper_pm_suspend,
  159. .resume = swsusp_helper_pm_resume,
  160. .freeze = swsusp_helper_pm_suspend,
  161. .thaw = swsusp_helper_pm_resume,
  162. .poweroff = swsusp_helper_pm_suspend,
  163. .restore = swsusp_helper_pm_resume,
  164. .restore_noirq = swsusp_helper_pm_restore_noirq,
  165. };
  166. struct platform_device swsusp_helper_device = {
  167. .name = SWSUSP_HELPER_NAME,
  168. .id = -1,
  169. .dev = {},
  170. };
  171. static struct platform_driver swsusp_helper_driver = {
  172. .driver = {
  173. .name = SWSUSP_HELPER_NAME,
  174. #ifdef CONFIG_PM
  175. .pm = &swsusp_helper_pm_ops,
  176. #endif
  177. .owner = THIS_MODULE,
  178. },
  179. .probe = swsusp_helper_probe,
  180. .remove = swsusp_helper_remove,
  181. };
  182. static int swsusp_pm_event(struct notifier_block *notifier, unsigned long pm_event, void *unused)
  183. {
  184. switch (pm_event) {
  185. case PM_HIBERNATION_PREPARE: /* Going to hibernate */
  186. #ifdef CONFIG_MTK_SYSENV
  187. /* for lk */
  188. set_env("hibboot", "1");
  189. #endif
  190. return NOTIFY_DONE;
  191. case PM_POST_HIBERNATION: /* Hibernation finished */
  192. #ifdef CONFIG_MTK_SYSENV
  193. /* from lk */
  194. hib_log("hibboot = %s\n", get_env("hibboot"));
  195. set_env("hibboot", "0");
  196. #endif
  197. return NOTIFY_DONE;
  198. }
  199. return NOTIFY_OK;
  200. }
  201. static struct notifier_block swsusp_pm_notifier_block = {
  202. .notifier_call = swsusp_pm_event,
  203. .priority = 0,
  204. };
  205. static int __init swsusp_helper_init(void)
  206. {
  207. int ret;
  208. hib_log("[%s] enter...\n", __func__);
  209. /* init restore_noirq callback function table */
  210. memset((void *)restore_noirq_func_table, 0, sizeof(restore_noirq_func_table));
  211. ret = platform_device_register(&swsusp_helper_device);
  212. if (ret) {
  213. hib_err("swsusp_helper_device register fail(%d)\n", ret);
  214. return ret;
  215. }
  216. ret = platform_driver_register(&swsusp_helper_driver);
  217. if (ret) {
  218. hib_err("swsusp_helper_driver register fail(%d)\n", ret);
  219. return ret;
  220. }
  221. ret = register_pm_notifier(&swsusp_pm_notifier_block);
  222. if (ret)
  223. hib_err("failed to register PM notifier %d\n", ret);
  224. initialized = 1;
  225. return 0;
  226. }
  227. arch_initcall(swsusp_helper_init);
  228. MODULE_LICENSE("GPL");
  229. MODULE_AUTHOR("MTK");
  230. MODULE_DESCRIPTION("The swsusp helper function");