soc_pmu.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. /*
  2. * Copyright (c) 2021 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Actions LARK family PMUVDD and PMUSVCC Implementation
  9. */
  10. #include <kernel.h>
  11. #include <device.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include <soc.h>
  15. #include <board_cfg.h>
  16. #include <soc_pmu.h>
  17. #include <logging/log.h>
  18. LOG_MODULE_REGISTER(pmu0, CONFIG_LOG_DEFAULT_LEVEL);
  19. #define PMU_INTMASK_COUNTER8HZ_INTEN BIT(14)
  20. #define PMU_INTMASK_REMOTE_INTEN BIT(12)
  21. #define PMU_INTMASK_BATLV_INTEN BIT(11)
  22. #define PMU_INTMASK_DC5VLV_INTEN BIT(10)
  23. #define PMU_INTMASK_WIO1LV_INTEN BIT(7)
  24. #define PMU_INTMASK_WIO0LV_INTEN BIT(6)
  25. #define PMU_INTMASK_ALARM8HZ_INTEN BIT(4)
  26. #define PMU_INTMASK_DC5VOUT_INTEN BIT(3)
  27. #define PMU_INTMASK_DC5VIN_INTEN BIT(2)
  28. #define PMU_INTMASK_ONOFF_S_INTEN BIT(1)
  29. #define PMU_INTMASK_ONOFF_L_INTEN BIT(0)
  30. #define WAKE_CTL_SVCC_BATLV_VOL_SHIFT (27) /* Battery voltage level wakeup threshold */
  31. #define WAKE_CTL_SVCC_BATLV_VOL_MASK (0x7 << WAKE_CTL_SVCC_BATLV_VOL_SHIFT)
  32. #define WAKE_CTL_SVCC_DC5VLV_VOL_SHIFT (24) /* DC5V voltage level wakeup threshold */
  33. #define WAKE_CTL_SVCC_DC5VLV_VOL_MASK (0x7 << WAKE_CTL_SVCC_DC5VLV_VOL_SHIFT)
  34. #define WAKE_CTL_SVCC_WIO1LV_VOL_SHIFT (22)
  35. #define WAKE_CTL_SVCC_WIO1LV_VOL_MASK (0x3 << WAKE_CTL_SVCC_WIO1LV_VOL_SHIFT)
  36. #define WAKE_CTL_SVCC_WIO0LV_VOL_SHIFT (20)
  37. #define WAKE_CTL_SVCC_WIO0LV_VOL_MASK (0x3 << WAKE_CTL_SVCC_WIO0LV_VOL_SHIFT)
  38. #define WAKE_CTL_SVCC_REMOTE_WKEN BIT(12)
  39. #define WAKE_CTL_SVCC_BATLV_WKEN BIT(11)
  40. #define WAKE_CTL_SVCC_DC5VLV_WKEN BIT(10)
  41. #define WAKE_CTL_SVCC_WIO1LV_DETEN BIT(9)
  42. #define WAKE_CTL_SVCC_WIO0LV_DETEN BIT(8)
  43. #define WAKE_CTL_SVCC_WIO1LV_WKEN BIT(7)
  44. #define WAKE_CTL_SVCC_WIO0LV_WKEN BIT(6)
  45. #define WAKE_CTL_SVCC_WIO_WKEN BIT(5)
  46. #define WAKE_CTL_SVCC_ALARM8HZ_WKEN BIT(4)
  47. #define WAKE_CTL_SVCC_DC5VOUT_WKEN BIT(3)
  48. #define WAKE_CTL_SVCC_DC5VIN_WKEN BIT(2)
  49. #define WAKE_CTL_SVCC_SHORT_WKEN BIT(1)
  50. #define WAKE_CTL_SVCC_LONG_WKEN BIT(0)
  51. #define WAKE_PD_SVCC_REG_SVCC_SHIFT (24)
  52. #define WAKE_PD_SVCC_REG_SVCC_MASK (0xFF << WAKE_PD_SVCC_REG_SVCC_SHIFT)
  53. #define WAKE_PD_SVCC_SYSRESET_PD BIT(20)
  54. #define WAKE_PD_SVCC_POWEROK_PD BIT(19)
  55. #define WAKE_PD_SVCC_LB_PD BIT(18)
  56. #define WAKE_PD_SVCC_OC_PD BIT(17)
  57. #define WAKE_PD_SVCC_LVPRO_PD BIT(16)
  58. #define WAKE_PD_SVCC_BATWK_PD BIT(13)
  59. #define WAKE_PD_SVCC_REMOTE_PD BIT(12)
  60. #define WAKE_PD_SVCC_BATLV_PD BIT(11)
  61. #define WAKE_PD_SVCC_DC5VLV_PD BIT(10)
  62. #define WAKE_PD_SVCC_WIO1LV_PD BIT(7)
  63. #define WAKE_PD_SVCC_WIO0LV_PD BIT(6)
  64. #define WAKE_PD_SVCC_WIO_PD BIT(5)
  65. #define WAKE_PD_SVCC_ALARM8HZ_PD BIT(4)
  66. #define WAKE_PD_SVCC_DC5VOUT_PD BIT(3)
  67. #define WAKE_PD_SVCC_DC5VIN_PD BIT(2)
  68. #define WAKE_PD_SVCC_ONOFF_S_PD BIT(1)
  69. #define WAKE_PD_SVCC_ONOFF_L_PD BIT(0)
  70. #define SYSTEM_SET_SVCC_ONOFF_SEL_SHIFT (25)
  71. #define SYSTEM_SET_SVCC_ONOFF_SEL_MASK (0x3 << SYSTEM_SET_SVCC_ONOFF_SEL_SHIFT)
  72. #define SYSTEM_SET_SVCC_SIM_A_EN BIT(24)
  73. #define SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_SHIFT (21)
  74. #define SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_MASK (0x7 << SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_SHIFT)
  75. #define SYSTEM_SET_SVCC_ONOFF_PRESS_TIME(x) ((x) << SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_SHIFT)
  76. #define SYSTEM_SET_SVCC_ONOFF_RST_EN_SHIFT (19)
  77. #define SYSTEM_SET_SVCC_ONOFF_RST_EN_MASK (0x3 << SYSTEM_SET_SVCC_ONOFF_RST_EN_SHIFT)
  78. #define SYSTEM_SET_SVCC_ONOFF_RST_EN(x) ((x) << SYSTEM_SET_SVCC_ONOFF_RST_EN_SHIFT)
  79. #define SYSTEM_SET_SVCC_ONOFF_RST_TIME BIT(18)
  80. #define SYSTEM_SET_SVCC_ONOFF_PRES BIT(17)
  81. #define CHG_CTL_SVCC_CV_3V3 BIT(19)
  82. #define CHG_CTL_SVCC_CV_OFFSET_SHIFT (5)
  83. #define CHG_CTL_SVCC_CV_OFFSET_MASK (0x1F << CHG_CTL_SVCC_CV_OFFSET_SHIFT)
  84. #define CHG_CTL_SVCC_CV_OFFSET(x) ((x) << CHG_CTL_SVCC_CV_OFFSET_SHIFT)
  85. #define PMU_DET_COUNTR8HZ_PD BIT(12)
  86. #define PMU_DET_DC5VIN_DET BIT(0)
  87. #define PMU_COUNTER8HZ_SVCC_CLK_SEL_SHIFT (27)
  88. #define PMU_COUNTER8HZ_SVCC_CLK_SEL_MASK (1 << PMU_COUNTER8HZ_SVCC_CLK_SEL_SHIFT)
  89. #define PMU_COUNTER8HZ_SVCC_CLK_SEL_LOSC BIT(27)
  90. #define PMU_COUNTER8HZ_SVCC_COUNTER_EN BIT(26)
  91. #define PMU_COUNTER8HZ_SVCC_COUNTER_VAL (0x3FFFFFF)
  92. #define PMU_ALARM8HZ_SVCC_PD BIT(26)
  93. #define PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK (0x3FFFFFF)
  94. #define PMU_MONITOR_DEV_INVALID(x) (((x) != PMU_DETECT_DEV_DC5V) \
  95. && ((x) != PMU_DETECT_DEV_REMOTE) \
  96. && ((x) != PMU_DETECT_DEV_ONOFF) \
  97. && ((x) != PMU_DETECT_DEV_COUNTER8HZ) \
  98. && ((x) != PMU_DETECT_DEV_ALARM8HZ))
  99. /*
  100. * @struct acts_pmuvdd
  101. * @brief Actions PMUVDD controller hardware register
  102. */
  103. struct acts_pmuvdd {
  104. volatile uint32_t vout_ctl0;
  105. volatile uint32_t vout_ctl1_s1;
  106. volatile uint32_t vout_ctl1_s2;
  107. volatile uint32_t vout_ctl1_s3;
  108. volatile uint32_t pmu_det;
  109. volatile uint32_t reserved0[3];
  110. volatile uint32_t dcdc_vc18_ctl;
  111. volatile uint32_t dcdc_vd12_ctl;
  112. volatile uint32_t dcdc_vdd_ctl;
  113. volatile uint32_t reserved1;
  114. volatile uint32_t pwrgate_dig;
  115. volatile uint32_t pwrgate_dig_ack;
  116. volatile uint32_t pwrgate_ram;
  117. volatile uint32_t pwrgate_ram_ack;
  118. volatile uint32_t pmu_intmask;
  119. };
  120. /*
  121. * @struct acts_pmusvcc
  122. * @brief Actions PMUSVCC controller hardware register
  123. */
  124. struct acts_pmusvcc {
  125. volatile uint32_t chg_ctl_svcc;
  126. volatile uint32_t bdg_ctl_svcc;
  127. volatile uint32_t system_set_svcc;
  128. volatile uint32_t power_ctl_svcc;
  129. volatile uint32_t wake_ctl_svcc;
  130. volatile uint32_t wake_pd_svcc;
  131. volatile uint32_t counter8hz_svcc;
  132. volatile uint32_t alarm8hz_svcc;
  133. };
  134. /**
  135. * struct pmu_drv_data
  136. * @brief The meta data which related to Actions PMU module.
  137. */
  138. struct pmu_context_t {
  139. struct detect_param_t detect_devs[PMU_DETECT_MAX_DEV]; /* PMU monitor peripheral devices */
  140. uint32_t pmuvdd_base; /* PMUVDD register base address */
  141. uint32_t pmusvcc_base; /* PMUSVCC register base address */
  142. uint8_t onoff_short_detect : 1; /* if 1 to enable onoff key short press detection */
  143. uint8_t onoff_remote_same_wio : 1; /* if 1 to indicate that onoff key and remote key use the same WIO source */
  144. };
  145. /* @brief get the PMU management context handler */
  146. static inline struct pmu_context_t *get_pmu_context(void)
  147. {
  148. static struct pmu_context_t pmu_context = {0};
  149. static struct pmu_context_t *p_pmu_context = NULL;
  150. if (!p_pmu_context) {
  151. pmu_context.pmuvdd_base = PMUVDD_BASE;
  152. pmu_context.pmusvcc_base = CHG_CTL_SVCC;
  153. pmu_context.onoff_short_detect = CONFIG_PMU_ONOFF_SHORT_DETECT;
  154. pmu_context.onoff_remote_same_wio = CONFIG_PMU_ONOFF_REMOTE_SAME_WIO;
  155. p_pmu_context = &pmu_context;
  156. }
  157. return p_pmu_context;
  158. }
  159. /* @brief get the base address of PMUVDD register */
  160. static inline struct acts_pmuvdd *get_pmuvdd_reg_base(struct pmu_context_t *ctx)
  161. {
  162. return (struct acts_pmuvdd *)ctx->pmuvdd_base;
  163. }
  164. /* @brief get the base address of PMUSVCC register */
  165. static inline struct acts_pmusvcc *get_pmusvcc_reg_base(struct pmu_context_t *ctx)
  166. {
  167. return (struct acts_pmusvcc *)ctx->pmusvcc_base;
  168. }
  169. #if 0
  170. /* @brief find the monitor device parameters by given detect_dev */
  171. static struct detect_param_t *soc_pmu_find_detect_dev(struct pmu_context_t *ctx, uint8_t detect_dev)
  172. {
  173. uint8_t i;
  174. for (i = 0; i < PMU_DETECT_MAX_DEV; i++) {
  175. if (ctx->detect_devs[i].detect_dev == detect_dev) {
  176. return &ctx->detect_devs[i];
  177. }
  178. LOG_DBG("dev slot[%d]:%d", i, ctx->detect_devs[i].detect_dev);
  179. }
  180. return NULL;
  181. }
  182. #endif
  183. /* @brief register the function will be called when the state of monitor device change */
  184. int soc_pmu_register_notify(struct detect_param_t *param)
  185. {
  186. struct pmu_context_t *ctx = get_pmu_context();
  187. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  188. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  189. uint8_t i;
  190. if (!param)
  191. return -EINVAL;
  192. if (PMU_MONITOR_DEV_INVALID(param->detect_dev)) {
  193. LOG_ERR("Invalid monitor dev:%d", param->detect_dev);
  194. return -EINVAL;
  195. }
  196. for (i = 0; i < PMU_DETECT_MAX_DEV; i++) {
  197. /* new or update a monitor device into PMU context */
  198. if ((!(ctx->detect_devs[i].detect_dev))
  199. || (ctx->detect_devs[i].detect_dev == param->detect_dev)) {
  200. ctx->detect_devs[i].detect_dev = param->detect_dev;
  201. ctx->detect_devs[i].cb_data = param->cb_data;
  202. ctx->detect_devs[i].notify = param->notify;
  203. break;
  204. } else {
  205. LOG_DBG("Busy slot[%d]:%d", i, ctx->detect_devs[i].detect_dev);
  206. }
  207. }
  208. if (i == PMU_DETECT_MAX_DEV) {
  209. LOG_ERR("no space for dev:0x%x", param->detect_dev);
  210. return -ENOMEM;
  211. }
  212. /* enable detect device interrupt and DC5V is already enabled at the stage of initialization */
  213. if (PMU_DETECT_DEV_ONOFF == param->detect_dev) {
  214. if (ctx->onoff_short_detect) {
  215. pmusvcc_reg->wake_ctl_svcc |= (WAKE_CTL_SVCC_SHORT_WKEN | WAKE_CTL_SVCC_LONG_WKEN);
  216. pmuvdd_reg->pmu_intmask |= (PMU_INTMASK_ONOFF_S_INTEN | PMU_INTMASK_ONOFF_L_INTEN);
  217. } else {
  218. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_LONG_WKEN;
  219. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_ONOFF_L_INTEN;
  220. }
  221. } else if (PMU_DETECT_DEV_REMOTE == param->detect_dev) {
  222. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_REMOTE_WKEN;
  223. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_REMOTE_INTEN;
  224. } else if (PMU_DETECT_DEV_COUNTER8HZ == param->detect_dev) {
  225. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_COUNTER8HZ_INTEN;
  226. }
  227. LOG_DBG("pmu register dev:%d", param->detect_dev);
  228. return 0;
  229. }
  230. /* @brief unregister the notify function for specified monitor device */
  231. void soc_pmu_unregister_notify(uint8_t detect_dev)
  232. {
  233. struct pmu_context_t *ctx = get_pmu_context();
  234. uint8_t i;
  235. uint32_t key;
  236. for (i = 0; i < PMU_DETECT_MAX_DEV; i++) {
  237. if (ctx->detect_devs[i].detect_dev == detect_dev) {
  238. key = irq_lock();
  239. ctx->detect_devs[i].detect_dev = 0;
  240. ctx->detect_devs[i].notify = 0;
  241. ctx->detect_devs[i].cb_data = NULL;
  242. irq_unlock(key);
  243. }
  244. }
  245. }
  246. /* @brief get the current DC5V status of plug in or out */
  247. bool soc_pmu_get_dc5v_status(void)
  248. {
  249. bool status;
  250. struct pmu_context_t *ctx = get_pmu_context();
  251. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  252. /* DC5VIN indicator, 0: DC5V < BAT +33mV; 1: DC5V > BAT + 80mV */
  253. if (pmuvdd_reg->pmu_det & PMU_DET_DC5VIN_DET)
  254. status = true;
  255. else
  256. status = false;
  257. return status;
  258. }
  259. /* @brief return the wakeup pending by system startup */
  260. uint32_t soc_pmu_get_wakeup_source(void)
  261. {
  262. struct pmu_context_t *ctx = get_pmu_context();
  263. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  264. static uint32_t pmu_wakeup_pending;
  265. if (!pmu_wakeup_pending) {
  266. pmu_wakeup_pending = pmusvcc_reg->wake_pd_svcc;
  267. LOG_INF("pmu wakeup pending:0x%x", pmu_wakeup_pending);
  268. }
  269. return pmu_wakeup_pending;
  270. }
  271. /* @brief return the wakeup setting by system startup */
  272. uint32_t soc_pmu_get_wakeup_setting(void)
  273. {
  274. struct pmu_context_t *ctx = get_pmu_context();
  275. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  276. static uint32_t pmu_wakeup_ctl;
  277. if (!pmu_wakeup_ctl) {
  278. pmu_wakeup_ctl = pmusvcc_reg->wake_ctl_svcc;
  279. LOG_INF("pmu wakeup setting:0x%x", pmu_wakeup_ctl);
  280. }
  281. return pmu_wakeup_ctl;
  282. }
  283. /* @brief check if system wakeup by RTC alarm */
  284. bool soc_pmu_is_alarm_wakeup(void)
  285. {
  286. uint32_t wk_pd;
  287. wk_pd = soc_pmu_get_wakeup_source();
  288. if (wk_pd & WAKE_CTL_SVCC_ALARM8HZ_WKEN)
  289. return true;
  290. return false;
  291. }
  292. /* @brief set the max constant current */
  293. void soc_pmu_set_max_current(uint16_t cur_ma)
  294. {
  295. struct pmu_context_t *ctx = get_pmu_context();
  296. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  297. uint8_t level;
  298. if (cur_ma <= 100) {
  299. level = (cur_ma + 9) / 10 - 1;
  300. } else if (cur_ma < 240) {
  301. level = (cur_ma + 19) / 20 + 4;
  302. } else {
  303. level = 15;
  304. }
  305. pmusvcc_reg->chg_ctl_svcc = (pmusvcc_reg->chg_ctl_svcc & ~0xF) | level;
  306. }
  307. /* @brief get the max constant current */
  308. uint16_t soc_pmu_get_max_current(void)
  309. {
  310. struct pmu_context_t *ctx = get_pmu_context();
  311. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  312. uint8_t level, cur_ma;
  313. level = pmusvcc_reg->chg_ctl_svcc & 0xF;
  314. if (level >= 10) {
  315. cur_ma = (level - 4) * 20;
  316. } else {
  317. cur_ma = (level + 1) * 10;
  318. }
  319. return cur_ma;
  320. }
  321. /* @brief lock(stop) DC5V charging for reading battery voltage */
  322. void soc_pmu_read_bat_lock(void)
  323. {
  324. struct pmu_context_t *ctx = get_pmu_context();
  325. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  326. pmusvcc_reg->chg_ctl_svcc |= CHG_CTL_SVCC_CV_3V3;
  327. k_busy_wait(300);
  328. }
  329. /* @brief unlock(resume) and restart DC5V charging */
  330. void soc_pmu_read_bat_unlock(void)
  331. {
  332. struct pmu_context_t *ctx = get_pmu_context();
  333. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  334. pmusvcc_reg->chg_ctl_svcc &= ~CHG_CTL_SVCC_CV_3V3;
  335. k_busy_wait(300);
  336. }
  337. /* @brief set const voltage value */
  338. void soc_pmu_set_const_voltage(uint8_t cv)
  339. {
  340. struct pmu_context_t *ctx = get_pmu_context();
  341. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  342. if (cv <= 0x1F) {
  343. pmusvcc_reg->chg_ctl_svcc = \
  344. (pmusvcc_reg->chg_ctl_svcc & ~CHG_CTL_SVCC_CV_OFFSET_MASK) | CHG_CTL_SVCC_CV_OFFSET(cv);
  345. k_busy_wait(300);
  346. }
  347. }
  348. /* @brief configure the long press on-off key time */
  349. void soc_pmu_config_onoffkey_time(uint8_t val)
  350. {
  351. unsigned int val_reg;
  352. struct pmu_context_t *ctx = get_pmu_context();
  353. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  354. if (val > 7)
  355. return ;
  356. val_reg = pmusvcc_reg->system_set_svcc & (~SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_MASK);
  357. pmusvcc_reg->system_set_svcc = val_reg | SYSTEM_SET_SVCC_ONOFF_PRESS_TIME(val);
  358. k_busy_wait(300);
  359. }
  360. /* @brief configure the long press on-off key time */
  361. void soc_pmu_config_onoffkey_function(uint8_t val)
  362. {
  363. unsigned int val_reg;
  364. struct pmu_context_t *ctx = get_pmu_context();
  365. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  366. /**
  367. * ONOFF long pressed function
  368. * 0: no function
  369. * 1: reset
  370. * 2: restart (S1 => S4 => S1)
  371. */
  372. if (val > 2)
  373. return ;
  374. val_reg = pmusvcc_reg->system_set_svcc &(~SYSTEM_SET_SVCC_ONOFF_RST_EN_MASK);
  375. pmusvcc_reg->system_set_svcc = val_reg | SYSTEM_SET_SVCC_ONOFF_RST_EN(val);
  376. k_busy_wait(300);
  377. }
  378. /* @brief check if the onoff key has been pressed or not */
  379. bool soc_pmu_is_onoff_key_pressed(void)
  380. {
  381. struct pmu_context_t *ctx = get_pmu_context();
  382. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  383. /* if 1 indicates that onoff key has been pressed */
  384. if (pmusvcc_reg->system_set_svcc & SYSTEM_SET_SVCC_ONOFF_PRES)
  385. return true;
  386. return false;
  387. }
  388. /* @brief configure the long press on-off key reset/restart time */
  389. void soc_pmu_config_onoffkey_reset_time(uint8_t val)
  390. {
  391. struct pmu_context_t *ctx = get_pmu_context();
  392. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  393. if (val) {
  394. pmusvcc_reg->system_set_svcc |= SYSTEM_SET_SVCC_ONOFF_RST_TIME; /* 12s */
  395. } else {
  396. pmusvcc_reg->system_set_svcc &= ~SYSTEM_SET_SVCC_ONOFF_RST_TIME; /* 8s */
  397. }
  398. k_busy_wait(300);
  399. }
  400. #ifdef CONFIG_PMU_COUNTER8HZ_SYNC_TIMEOUT_US
  401. /* @brief counter 8hz clock enable */
  402. void soc_pmu_counter8hz_enable(void)
  403. {
  404. struct pmu_context_t *ctx = get_pmu_context();
  405. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  406. LOG_DBG("counter8hz_svcc:0x%x", pmusvcc_reg->counter8hz_svcc);
  407. /* clock source select LOSC */
  408. if (!(pmusvcc_reg->counter8hz_svcc & PMU_COUNTER8HZ_SVCC_COUNTER_EN)) {
  409. #if (CONFIG_RTC_CLK_SOURCE == 1)
  410. pmusvcc_reg->counter8hz_svcc |= \
  411. (PMU_COUNTER8HZ_SVCC_CLK_SEL_LOSC | PMU_COUNTER8HZ_SVCC_COUNTER_EN);
  412. #else
  413. pmusvcc_reg->counter8hz_svcc |= PMU_COUNTER8HZ_SVCC_COUNTER_EN;
  414. #endif
  415. k_busy_wait(300);
  416. }
  417. }
  418. /* @brief get counter8hz and the retval is by cycles */
  419. int soc_pmu_get_counter8hz_cycles(bool is_sync)
  420. {
  421. struct pmu_context_t *ctx = get_pmu_context();
  422. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  423. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  424. if (!(pmusvcc_reg->counter8hz_svcc
  425. & PMU_COUNTER8HZ_SVCC_COUNTER_EN)) {
  426. LOG_ERR("counter8hz does not enable yet");
  427. return -EACCES;
  428. }
  429. if (is_sync) {
  430. /* clear counter8hz pending */
  431. pmuvdd_reg->pmu_det |= PMU_DET_COUNTR8HZ_PD;
  432. /* wait a new counter8hz pending */
  433. uint32_t cur_time = k_cycle_get_32();
  434. while (!(pmuvdd_reg->pmu_det & PMU_DET_COUNTR8HZ_PD)) {
  435. if (k_cyc_to_us_floor32(k_cycle_get_32() - cur_time) >=
  436. CONFIG_PMU_COUNTER8HZ_SYNC_TIMEOUT_US) {
  437. LOG_ERR("wait counter8hz pending timeout");
  438. return -ETIMEDOUT;
  439. }
  440. k_sleep(K_MSEC(1));
  441. }
  442. }
  443. return (pmusvcc_reg->counter8hz_svcc & PMU_COUNTER8HZ_SVCC_COUNTER_VAL);
  444. }
  445. /* @brief enable PMU alarm 8hz */
  446. int soc_pmu_alarm8hz_enable(uint32_t alarm_msec)
  447. {
  448. struct pmu_context_t *ctx = get_pmu_context();
  449. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  450. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  451. uint32_t alarm8hz_cycles, new_alarm8hz_cycles, reg;
  452. int ret;
  453. /* clear alarm 8Hz pending */
  454. if (pmusvcc_reg->wake_pd_svcc & WAKE_PD_SVCC_ALARM8HZ_PD) {
  455. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_SVCC_ALARM8HZ_PD;
  456. k_busy_wait(300);
  457. }
  458. alarm8hz_cycles = (alarm_msec + 124) / 125;
  459. #if (CONFIG_RTC_CLK_SOURCE == 2) // rc32k inaccurate, need calibration
  460. uint32_t rc32k_freq;
  461. rc32k_freq = acts_clock_rc32k_set_cal_cyc(100);
  462. printk("rc32k_freq=%d set 8hz=%d,", rc32k_freq, alarm8hz_cycles);
  463. alarm8hz_cycles = (uint64_t)alarm8hz_cycles*rc32k_freq/32768;
  464. printk("cal alarm8hz=%d cur_8hz=%d\n", alarm8hz_cycles, soc_pmu_get_counter8hz_cycles(false));
  465. #endif
  466. if (alarm8hz_cycles < 3) {
  467. LOG_ERR("invalid alarm8hz msec:%d", alarm_msec);
  468. return -EINVAL;
  469. }
  470. ret = soc_pmu_get_counter8hz_cycles(false);
  471. if (ret < 0) {
  472. LOG_ERR("failed to get counter8hz");
  473. return ret;
  474. }
  475. new_alarm8hz_cycles = ret + alarm8hz_cycles;
  476. /* 8Hz counter overflow */
  477. if (new_alarm8hz_cycles > 0x3FFFFFF)
  478. new_alarm8hz_cycles = new_alarm8hz_cycles - 0x3FFFFFF;
  479. reg = pmusvcc_reg->alarm8hz_svcc;
  480. reg &= ~PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK;
  481. reg |= (new_alarm8hz_cycles & PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK);
  482. pmusvcc_reg->alarm8hz_svcc = reg;
  483. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_ALARM8HZ_WKEN;
  484. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_ALARM8HZ_INTEN;
  485. k_busy_wait(300);
  486. return 0;
  487. }
  488. /* @brief disable PMU alarm8hz */
  489. void soc_pmu_alarm8hz_disable(void)
  490. {
  491. struct pmu_context_t *ctx = get_pmu_context();
  492. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  493. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  494. /* clear alarm 8Hz pending */
  495. if (pmusvcc_reg->wake_pd_svcc & WAKE_PD_SVCC_ALARM8HZ_PD) {
  496. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_SVCC_ALARM8HZ_PD;
  497. k_busy_wait(300);
  498. }
  499. pmuvdd_reg->pmu_intmask &= ~PMU_INTMASK_ALARM8HZ_INTEN;
  500. pmusvcc_reg->wake_ctl_svcc &= ~WAKE_CTL_SVCC_ALARM8HZ_WKEN;
  501. pmusvcc_reg->alarm8hz_svcc &= ~PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK;
  502. k_busy_wait(300);
  503. }
  504. /* @brief get alarm8hz cycles */
  505. int soc_pmu_get_alarm8hz(void)
  506. {
  507. struct pmu_context_t *ctx = get_pmu_context();
  508. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  509. return pmusvcc_reg->alarm8hz_svcc & PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK;
  510. }
  511. /*return rc32k freq*/
  512. uint32_t acts_clock_rc32k_set_cal_cyc(uint32_t cal_cyc)
  513. {
  514. uint32_t cnt;
  515. uint64_t tmp = 32000000;
  516. sys_write32(0, RC32K_CAL);
  517. soc_udelay(300);
  518. sys_write32((cal_cyc << 8)|1, RC32K_CAL);
  519. soc_udelay(300);
  520. /* wait calibration done */
  521. while (!(sys_read32(RC32K_CAL) & (1 << 4))){}
  522. cnt = sys_read32(RC32K_COUNT);
  523. if(cnt){
  524. cnt = tmp*cal_cyc/cnt;
  525. }
  526. LOG_INF("cal freq=%d\n", cnt);
  527. return cnt;
  528. }
  529. void soc_pmu_set_vdd_voltage(uint32_t volt_mv)
  530. {
  531. unsigned int sel;
  532. if (volt_mv < 550 || volt_mv > 1300)
  533. return ;
  534. sel = (volt_mv - 550) / 50;
  535. sel = (sel << 4) | sel; // set vdd s1 adn s1ml
  536. sys_write32((sys_read32(VOUT_CTL1_S1M) & ~(0xff)) | (sel), VOUT_CTL1_S1M);
  537. soc_udelay(33);
  538. }
  539. #endif
  540. #if 0
  541. static void soc_pmu_isr(void *arg)
  542. {
  543. struct pmu_context_t *ctx = get_pmu_context();
  544. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  545. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  546. struct detect_param_t *detect_param = NULL;
  547. ARG_UNUSED(arg);
  548. uint32_t pending = pmusvcc_reg->wake_pd_svcc;
  549. LOG_DBG("pmu pending:0x%x", pending);
  550. if (pending & WAKE_PD_SVCC_REMOTE_PD) {
  551. /* Both REMOTE and ONOFF key are connected with WIO0.
  552. * Once the ONOFF key are pressed, the REMOTE key pending will also trigger.
  553. */
  554. if (pending & WAKE_PD_SVCC_WIO0LV_PD) {
  555. if (ctx->onoff_short_detect) {
  556. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  557. if (detect_param)
  558. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  559. }
  560. /* If ONOFF and REMOTE key use the same WIO pin, ignore the REMOTE key pending when WIO low voltage. */
  561. if (ctx->onoff_remote_same_wio)
  562. goto out;
  563. }
  564. /* disable remote interrupt and the remote device will enable interrupt through register interface again */
  565. pmuvdd_reg->pmu_intmask &= ~PMU_INTMASK_REMOTE_INTEN;
  566. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_REMOTE);
  567. if (detect_param)
  568. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  569. } else if (pending & WAKE_PD_SVCC_ONOFF_L_PD) {
  570. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  571. if (detect_param)
  572. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_LONG_PRESSED);
  573. } else if (pending & WAKE_PD_SVCC_ONOFF_S_PD) {
  574. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  575. if (detect_param)
  576. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  577. } else if (pending & WAKE_PD_SVCC_WIO0LV_PD) {
  578. if (ctx->onoff_short_detect) {
  579. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  580. if (detect_param)
  581. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  582. }
  583. }
  584. if (pending & WAKE_PD_SVCC_DC5VOUT_PD) {
  585. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_DC5V);
  586. if (detect_param)
  587. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_OUT);
  588. }
  589. if (pending & WAKE_PD_SVCC_DC5VIN_PD) {
  590. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_DC5V);
  591. if (detect_param)
  592. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_IN);
  593. }
  594. /* check whether counter8hz pending */
  595. if (pmuvdd_reg->pmu_det & PMU_DET_COUNTR8HZ_PD) {
  596. /* clear counter8hz pending */
  597. pmuvdd_reg->pmu_det |= PMU_DET_COUNTR8HZ_PD;
  598. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_COUNTER8HZ);
  599. if (detect_param)
  600. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_TIME_ON);
  601. }
  602. /* check whether alarm8hz pending */
  603. if (pmusvcc_reg->alarm8hz_svcc & PMU_ALARM8HZ_SVCC_PD) {
  604. /* clear alarm8hz pending */
  605. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_SVCC_ALARM8HZ_PD;
  606. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ALARM8HZ);
  607. if (detect_param)
  608. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_TIME_ON);
  609. }
  610. out:
  611. /* counter8Hz irq pending is shared with WAKE_PD_SVCC */
  612. if (pending)
  613. pmusvcc_reg->wake_pd_svcc = pending;
  614. }
  615. static void soc_pmu_irq_config(void)
  616. {
  617. IRQ_CONNECT(IRQ_ID_PMU, CONFIG_PMU_IRQ_PRI,
  618. soc_pmu_isr,
  619. NULL, 0);
  620. irq_enable(IRQ_ID_PMU);
  621. }
  622. /* @brief PMUVDD and PMUSVCC initialization */
  623. static int soc_pmu_init(const struct device *dev)
  624. {
  625. struct pmu_context_t *ctx = get_pmu_context();
  626. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  627. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  628. ARG_UNUSED(dev);
  629. soc_pmu_get_wakeup_source();
  630. /* by default to enable DC5V plug in/out detection */
  631. pmusvcc_reg->wake_ctl_svcc |= (WAKE_CTL_SVCC_DC5VOUT_WKEN | WAKE_CTL_SVCC_DC5VIN_WKEN);
  632. pmuvdd_reg->pmu_intmask |= (PMU_INTMASK_DC5VIN_INTEN | PMU_INTMASK_DC5VOUT_INTEN);
  633. if (ctx->onoff_short_detect) {
  634. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_WIO0LV_WKEN;
  635. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_WIO0LV_INTEN;
  636. }
  637. pmusvcc_reg->wake_pd_svcc = pmusvcc_reg->wake_pd_svcc;
  638. if (!ctx->onoff_remote_same_wio)
  639. sys_write32(0, WIO0_CTL);
  640. soc_pmu_irq_config();
  641. return 0;
  642. }
  643. /*bootloader not init pmu*/
  644. //SYS_INIT(soc_pmu_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);
  645. #endif