sys_wakelock.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file system wakelock
  8. */
  9. #include <kernel.h>
  10. #include <device.h>
  11. #include <string.h>
  12. #include <sys_wakelock.h>
  13. #include <assert.h>
  14. struct wakelock_user_info_t {
  15. uint16_t ref_cnt;
  16. };
  17. struct wakelock_t {
  18. uint8_t wake_lock_type;
  19. uint16_t ref_cnt;
  20. struct wakelock_user_info_t user_info[MAX_WAKE_LOCK_USER];
  21. uint32_t free_timestamp;
  22. };
  23. struct wakelocks_manager_context_t {
  24. struct wakelock_t wakelocks[MAX_WAKE_LOCK_TYPE];
  25. };
  26. struct wakelocks_manager_context_t wakelocks_manager;
  27. static struct k_sem wakelocks_sem;
  28. static struct wakelock_t *_sys_wakelock_lookup(int wake_lock_type)
  29. {
  30. for (int i = 0; i < MAX_WAKE_LOCK_TYPE; i++) {
  31. if (wakelocks_manager.wakelocks[i].wake_lock_type == wake_lock_type) {
  32. return &wakelocks_manager.wakelocks[i];
  33. }
  34. }
  35. return NULL;
  36. }
  37. int sys_wake_lock(int wake_lock_type)
  38. {
  39. return sys_wake_lock_ext(wake_lock_type,APP_WAKE_LOCK_USER);
  40. }
  41. int sys_wake_lock_ext(int wake_lock_type, int wake_lock_user)
  42. {
  43. int res = 0;
  44. struct wakelock_t *wakelock = NULL;
  45. uint32_t key = irq_lock();
  46. wakelock = _sys_wakelock_lookup(wake_lock_type);
  47. if (!wakelock) {
  48. printk("err, holder: %d", wake_lock_type);
  49. res = -EEXIST;
  50. goto exit;
  51. }
  52. assert(wakelock->ref_cnt < 0xFFFF);
  53. wakelock->ref_cnt++;
  54. wakelock->user_info[wake_lock_user].ref_cnt++;
  55. wakelock->free_timestamp = 0;
  56. exit:
  57. irq_unlock(key);
  58. return res;
  59. }
  60. int sys_wake_unlock(int wake_lock_type)
  61. {
  62. return sys_wake_unlock_ext(wake_lock_type, APP_WAKE_LOCK_USER);
  63. }
  64. extern void system_clear_fast_standby(void);
  65. int sys_wake_unlock_ext(int wake_lock_type, int wake_lock_user)
  66. {
  67. int res = 0;
  68. struct wakelock_t *wakelock = NULL;
  69. uint32_t key = irq_lock();
  70. wakelock = _sys_wakelock_lookup(wake_lock_type);
  71. if (!wakelock) {
  72. printk("err, holder: %d", wake_lock_type);
  73. res = -ESRCH;
  74. goto exit;
  75. }
  76. assert(wakelock->ref_cnt > 0);
  77. wakelock->user_info[wake_lock_user].ref_cnt--;
  78. if (wakelock->ref_cnt--) {
  79. /** reset all wake lock timestamp */
  80. if (wake_lock_type == FULL_WAKE_LOCK) {
  81. for (int i = 0; i < MAX_WAKE_LOCK_TYPE; i++) {
  82. wakelocks_manager.wakelocks[i].free_timestamp = k_uptime_get_32();
  83. }
  84. } else {
  85. wakelock->free_timestamp = k_uptime_get_32();
  86. }
  87. }
  88. if (wake_lock_type == FULL_WAKE_LOCK) {
  89. #ifdef CONFIG_SYS_STANDBY
  90. system_clear_fast_standby();
  91. #endif
  92. }
  93. exit:
  94. if (wakelock && wakelock->ref_cnt == 0) {
  95. sys_wakelocks_wake(wake_lock_type);
  96. }
  97. irq_unlock(key);
  98. return res;
  99. }
  100. void sys_wakelocks_dump(void)
  101. {
  102. struct wakelock_t *wakelock = NULL;
  103. printk("wlock info: \n");
  104. wakelock = _sys_wakelock_lookup(PARTIAL_WAKE_LOCK);
  105. if (wakelock) {
  106. printk("type : PARTIAL_WAKE_LOCK (%d)\n",wakelock->ref_cnt);
  107. printk(" BT_WAKE_LOCK_USER :%d\n",wakelock->user_info[BT_WAKE_LOCK_USER].ref_cnt);
  108. printk(" MEDIA_WAKE_LOCK_USER :%d\n",wakelock->user_info[MEDIA_WAKE_LOCK_USER].ref_cnt);
  109. printk(" USB_WAKE_LOCK_USER :%d\n",wakelock->user_info[USB_WAKE_LOCK_USER].ref_cnt);
  110. printk(" POWER_WAKE_LOCK_USER :%d\n",wakelock->user_info[POWER_WAKE_LOCK_USER].ref_cnt);
  111. printk(" SYS_WAKE_LOCK_USER :%d\n",wakelock->user_info[SYS_WAKE_LOCK_USER].ref_cnt);
  112. printk(" APP_WAKE_LOCK_USER :%d\n",wakelock->user_info[APP_WAKE_LOCK_USER].ref_cnt);
  113. printk("DISPLAY_WAKE_LOCK_USER :%d\n",wakelock->user_info[DISPLAY_WAKE_LOCK_USER].ref_cnt);
  114. }
  115. wakelock = _sys_wakelock_lookup(FULL_WAKE_LOCK);
  116. if (wakelock) {
  117. printk("type : FULL_WAKE_LOCK total (%d)\n",wakelock->ref_cnt);
  118. printk(" BT_WAKE_LOCK_USER : %d\n",wakelock->user_info[BT_WAKE_LOCK_USER].ref_cnt);
  119. printk(" MEDIA_WAKE_LOCK_USER: %d\n",wakelock->user_info[MEDIA_WAKE_LOCK_USER].ref_cnt);
  120. printk(" USB_WAKE_LOCK_USER : %d\n",wakelock->user_info[USB_WAKE_LOCK_USER].ref_cnt);
  121. printk(" POWER_WAKE_LOCK_USER: %d\n",wakelock->user_info[POWER_WAKE_LOCK_USER].ref_cnt);
  122. printk(" SYS_WAKE_LOCK_USER : %d\n",wakelock->user_info[SYS_WAKE_LOCK_USER].ref_cnt);
  123. printk(" APP_WAKE_LOCK_USER : %d\n",wakelock->user_info[APP_WAKE_LOCK_USER].ref_cnt);
  124. printk("DISPLAY_WAKE_LOCK_USER : %d\n",wakelock->user_info[DISPLAY_WAKE_LOCK_USER].ref_cnt);
  125. }
  126. }
  127. static int sys_wakelocks_init(const struct device *arg)
  128. {
  129. uint32_t current_timestamp = k_uptime_get_32();
  130. memset(&wakelocks_manager, 0 , sizeof(struct wakelocks_manager_context_t));
  131. k_sem_init(&wakelocks_sem, 0, 1);
  132. for (int i = 0; i < MAX_WAKE_LOCK_TYPE; i++) {
  133. wakelocks_manager.wakelocks[i].wake_lock_type = i;
  134. wakelocks_manager.wakelocks[i].free_timestamp = current_timestamp;
  135. wakelocks_manager.wakelocks[i].ref_cnt = 0;
  136. }
  137. /** only for debug*/
  138. sys_wake_lock(FULL_WAKE_LOCK);
  139. return 0;
  140. }
  141. SYS_INIT(sys_wakelocks_init, POST_KERNEL, 50);
  142. int sys_wakelocks_check(int wake_lock_type)
  143. {
  144. int ref_cnt = 0;
  145. struct wakelock_t *wakelock = NULL;
  146. uint32_t key = irq_lock();
  147. wakelock = _sys_wakelock_lookup(wake_lock_type);
  148. if (!wakelock) {
  149. printk("err, holder: %d", wake_lock_type);
  150. goto exit;
  151. }
  152. ref_cnt = wakelock->ref_cnt;
  153. exit:
  154. irq_unlock(key);
  155. return ref_cnt;
  156. }
  157. uint32_t sys_wakelocks_get_free_time(int wake_lock_type)
  158. {
  159. int free_time = 0;
  160. struct wakelock_t *wakelock = NULL;
  161. uint32_t key = irq_lock();
  162. wakelock = _sys_wakelock_lookup(wake_lock_type);
  163. if (!wakelock) {
  164. printk("err, holder: %d", wake_lock_type);
  165. goto exit;
  166. }
  167. if (!wakelock->ref_cnt) {
  168. free_time = k_uptime_get_32() - wakelock->free_timestamp + 1;
  169. }
  170. exit:
  171. irq_unlock(key);
  172. return free_time;
  173. }
  174. int sys_wakelocks_wait(int wake_lock_type)
  175. {
  176. k_sem_take(&wakelocks_sem, K_FOREVER);
  177. return 0;
  178. }
  179. int sys_wakelocks_wake(int wake_lock_type)
  180. {
  181. k_sem_give(&wakelocks_sem);
  182. return 0;
  183. }