soc_pmu.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. /*
  2. * Copyright (c) 2021 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief Actions LEOPARD 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. #include <drivers/adc.h>
  19. #include <sys/byteorder.h>
  20. #include <soc_atp.h>
  21. #include <dvfs.h>
  22. #include <linker/linker-defs.h>
  23. LOG_MODULE_REGISTER(pmu0, CONFIG_LOG_DEFAULT_LEVEL);
  24. #define PMU_INTMASK_COUNTER8HZ_INTEN BIT(14)
  25. #define PMU_INTMASK_REMOTE_INTEN BIT(12)
  26. #define PMU_INTMASK_BATLV_INTEN BIT(11)
  27. #define PMU_INTMASK_DC5VLV_INTEN BIT(10)
  28. #define PMU_INTMASK_WIO1LV_INTEN BIT(7)
  29. #define PMU_INTMASK_WIO0LV_INTEN BIT(6)
  30. #define PMU_INTMASK_ALARM8HZ_INTEN BIT(4)
  31. #define PMU_INTMASK_DC5VOUT_INTEN BIT(3)
  32. #define PMU_INTMASK_DC5VIN_INTEN BIT(2)
  33. #define PMU_INTMASK_ONOFF_S_INTEN BIT(1)
  34. #define PMU_INTMASK_ONOFF_L_INTEN BIT(0)
  35. #define WAKE_CTL_SVCC_BATLV_VOL_SHIFT (27) /* Battery voltage level wakeup threshold */
  36. #define WAKE_CTL_SVCC_BATLV_VOL_MASK (0x7 << WAKE_CTL_SVCC_BATLV_VOL_SHIFT)
  37. #define WAKE_CTL_SVCC_DC5VLV_VOL_SHIFT (24) /* DC5V voltage level wakeup threshold */
  38. #define WAKE_CTL_SVCC_DC5VLV_VOL_MASK (0x7 << WAKE_CTL_SVCC_DC5VLV_VOL_SHIFT)
  39. #define WAKE_CTL_SVCC_WIO1LV_VOL_SHIFT (22)
  40. #define WAKE_CTL_SVCC_WIO1LV_VOL_MASK (0x3 << WAKE_CTL_SVCC_WIO1LV_VOL_SHIFT)
  41. #define WAKE_CTL_SVCC_WIO0LV_VOL_SHIFT (20)
  42. #define WAKE_CTL_SVCC_WIO0LV_VOL_MASK (0x3 << WAKE_CTL_SVCC_WIO0LV_VOL_SHIFT)
  43. #define WAKE_CTL_SVCC_REMOTE_WKEN BIT(12)
  44. #define WAKE_CTL_SVCC_BATLV_WKEN BIT(11)
  45. #define WAKE_CTL_SVCC_DC5VLV_WKEN BIT(10)
  46. #define WAKE_CTL_SVCC_WIO1LV_DETEN BIT(9)
  47. #define WAKE_CTL_SVCC_WIO0LV_DETEN BIT(8)
  48. #define WAKE_CTL_SVCC_WIO1LV_WKEN BIT(7)
  49. #define WAKE_CTL_SVCC_WIO0LV_WKEN BIT(6)
  50. #define WAKE_CTL_SVCC_WIO_WKEN BIT(5)
  51. #define WAKE_CTL_SVCC_ALARM8HZ_WKEN BIT(4)
  52. #define WAKE_CTL_SVCC_DC5VOUT_WKEN BIT(3)
  53. #define WAKE_CTL_SVCC_DC5VIN_WKEN BIT(2)
  54. #define WAKE_CTL_SVCC_SHORT_WKEN BIT(1)
  55. #define WAKE_CTL_SVCC_LONG_WKEN BIT(0)
  56. #define WAKE_PD_SVCC_REG_SVCC_SHIFT (24)
  57. #define WAKE_PD_SVCC_REG_SVCC_MASK (0xFF << WAKE_PD_SVCC_REG_SVCC_SHIFT)
  58. #define WAKE_PD_SVCC_SYSRESET_PD BIT(20)
  59. #define WAKE_PD_SVCC_POWEROK_PD BIT(19)
  60. #define WAKE_PD_SVCC_LB_PD BIT(18)
  61. #define WAKE_PD_SVCC_OC_PD BIT(17)
  62. #define WAKE_PD_SVCC_LVPRO_PD BIT(16)
  63. #define WAKE_PD_TK_PD BIT(15)
  64. #define WAKE_PD_SVCC_BATWK_PD BIT(13)
  65. #define WAKE_PD_SVCC_REMOTE_PD BIT(12)
  66. #define WAKE_PD_SVCC_BATLV_PD BIT(11)
  67. #define WAKE_PD_SVCC_DC5VLV_PD BIT(10)
  68. #define WAKE_PD_SVCC_WIO1LV_PD BIT(7)
  69. #define WAKE_PD_SVCC_WIO0LV_PD BIT(6)
  70. #define WAKE_PD_SVCC_WIO_PD BIT(5)
  71. #define WAKE_PD_SVCC_ALARM8HZ_PD BIT(4)
  72. #define WAKE_PD_SVCC_DC5VOUT_PD BIT(3)
  73. #define WAKE_PD_SVCC_DC5VIN_PD BIT(2)
  74. #define WAKE_PD_SVCC_ONOFF_S_PD BIT(1)
  75. #define WAKE_PD_SVCC_ONOFF_L_PD BIT(0)
  76. #define SYSTEM_SET_SVCC_ONOFF_SEL_SHIFT (25)
  77. #define SYSTEM_SET_SVCC_ONOFF_SEL_MASK (0x3 << SYSTEM_SET_SVCC_ONOFF_SEL_SHIFT)
  78. #define SYSTEM_SET_SVCC_SIM_A_EN BIT(24)
  79. #define SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_SHIFT (21)
  80. #define SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_MASK (0x7 << SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_SHIFT)
  81. #define SYSTEM_SET_SVCC_ONOFF_PRESS_TIME(x) ((x) << SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_SHIFT)
  82. #define SYSTEM_SET_SVCC_ONOFF_RST_EN_SHIFT (19)
  83. #define SYSTEM_SET_SVCC_ONOFF_RST_EN_MASK (0x3 << SYSTEM_SET_SVCC_ONOFF_RST_EN_SHIFT)
  84. #define SYSTEM_SET_SVCC_ONOFF_RST_EN(x) ((x) << SYSTEM_SET_SVCC_ONOFF_RST_EN_SHIFT)
  85. #define SYSTEM_SET_SVCC_ONOFF_RST_TIME BIT(18)
  86. #define SYSTEM_SET_SVCC_ONOFF_PRES BIT(17)
  87. #define CHG_CTL_SVCC_CV_3V3 BIT(19)
  88. #define CHG_CTL_SVCC_CV_OFFSET_SHIFT (5)
  89. #define CHG_CTL_SVCC_CV_OFFSET_MASK (0x1F << CHG_CTL_SVCC_CV_OFFSET_SHIFT)
  90. #define CHG_CTL_SVCC_CV_OFFSET(x) ((x) << CHG_CTL_SVCC_CV_OFFSET_SHIFT)
  91. #define PMU_DET_COUNTR8HZ_PD BIT(12)
  92. #define PMU_DET_DC5VIN_DET BIT(0)
  93. #define VOUT_CTL0_VC18_SW BIT(18)
  94. #define VOUT_CTL0_VD12_SW BIT(17)
  95. #define VOUT_CTL0_VD12_25X_BITI 1
  96. #define REG_SENSOR_EFUSE_SHIFT (26)
  97. #define REG_SENSOR_EFUSE_MASK (0x3F << REG_SENSOR_EFUSE_SHIFT)
  98. #define PMU_COUNTER8HZ_SVCC_CLK_SEL_SHIFT (27)
  99. #define PMU_COUNTER8HZ_SVCC_CLK_SEL_MASK (1 << PMU_COUNTER8HZ_SVCC_CLK_SEL_SHIFT)
  100. #define PMU_COUNTER8HZ_SVCC_CLK_SEL_LOSC BIT(27)
  101. #define PMU_COUNTER8HZ_SVCC_COUNTER_EN BIT(26)
  102. #define PMU_COUNTER8HZ_SVCC_COUNTER_VAL (0x3FFFFFF)
  103. #define PMU_ALARM8HZ_SVCC_PD BIT(26)
  104. #define PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK (0x3FFFFFF)
  105. #define PMU_MONITOR_DEV_INVALID(x) (((x) != PMU_DETECT_DEV_DC5V) \
  106. && ((x) != PMU_DETECT_DEV_REMOTE) \
  107. && ((x) != PMU_DETECT_DEV_ONOFF) \
  108. && ((x) != PMU_DETECT_DEV_COUNTER8HZ) \
  109. && ((x) != PMU_DETECT_DEV_ALARM8HZ) \
  110. && ((x) != PMU_DETECT_DEV_BAT))
  111. /*
  112. * @struct acts_pmuvdd
  113. * @brief Actions PMUVDD controller hardware register
  114. */
  115. struct acts_pmuvdd {
  116. volatile uint32_t vout_ctl0;
  117. volatile uint32_t vout_ctl1_s1;
  118. volatile uint32_t vout_ctl1_s2;
  119. volatile uint32_t vout_ctl1_s3;
  120. volatile uint32_t pmu_det;
  121. volatile uint32_t reserved0[3];
  122. volatile uint32_t dcdc_vc18_ctl;
  123. volatile uint32_t dcdc_vd12_ctl;
  124. volatile uint32_t dcdc_vdd_ctl;
  125. volatile uint32_t reserved1;
  126. volatile uint32_t pwrgate_dig;
  127. volatile uint32_t pwrgate_dig_ack;
  128. volatile uint32_t pwrgate_ram;
  129. volatile uint32_t pwrgate_ram_ack;
  130. volatile uint32_t pmu_intmask;
  131. };
  132. /*
  133. * @struct acts_pmusvcc
  134. * @brief Actions PMUSVCC controller hardware register
  135. */
  136. struct acts_pmusvcc {
  137. volatile uint32_t chg_ctl_svcc;
  138. volatile uint32_t bdg_ctl_svcc;
  139. volatile uint32_t system_set_svcc;
  140. volatile uint32_t power_ctl_svcc;
  141. volatile uint32_t wake_ctl_svcc;
  142. volatile uint32_t wake_pd_svcc;
  143. volatile uint32_t counter8hz_svcc;
  144. volatile uint32_t alarm8hz_svcc;
  145. };
  146. /**
  147. * struct pmu_drv_data
  148. * @brief The meta data which related to Actions PMU module.
  149. */
  150. struct pmu_context_t {
  151. struct detect_param_t detect_devs[PMU_DETECT_MAX_DEV]; /* PMU monitor peripheral devices */
  152. uint32_t pmuvdd_base; /* PMUVDD register base address */
  153. uint32_t pmusvcc_base; /* PMUSVCC register base address */
  154. uint8_t onoff_short_detect : 1; /* if 1 to enable onoff key short press detection */
  155. uint8_t onoff_remote_same_wio : 1; /* if 1 to indicate that onoff key and remote key use the same WIO source */
  156. };
  157. /* @brief get the PMU management context handler */
  158. static inline struct pmu_context_t *get_pmu_context(void)
  159. {
  160. static struct pmu_context_t pmu_context = {0};
  161. static struct pmu_context_t *p_pmu_context = NULL;
  162. if (!p_pmu_context) {
  163. pmu_context.pmuvdd_base = PMUVDD_BASE;
  164. pmu_context.pmusvcc_base = CHG_CTL_SVCC;
  165. pmu_context.onoff_short_detect = CONFIG_PMU_ONOFF_SHORT_DETECT;
  166. pmu_context.onoff_remote_same_wio = CONFIG_PMU_ONOFF_REMOTE_SAME_WIO;
  167. p_pmu_context = &pmu_context;
  168. }
  169. return p_pmu_context;
  170. }
  171. /* @brief get the base address of PMUVDD register */
  172. static inline struct acts_pmuvdd *get_pmuvdd_reg_base(struct pmu_context_t *ctx)
  173. {
  174. return (struct acts_pmuvdd *)ctx->pmuvdd_base;
  175. }
  176. /* @brief get the base address of PMUSVCC register */
  177. static inline struct acts_pmusvcc *get_pmusvcc_reg_base(struct pmu_context_t *ctx)
  178. {
  179. return (struct acts_pmusvcc *)ctx->pmusvcc_base;
  180. }
  181. /* @brief find the monitor device parameters by given detect_dev */
  182. static struct detect_param_t *soc_pmu_find_detect_dev(struct pmu_context_t *ctx, uint8_t detect_dev)
  183. {
  184. uint8_t i;
  185. for (i = 0; i < PMU_DETECT_MAX_DEV; i++) {
  186. if (ctx->detect_devs[i].detect_dev == detect_dev) {
  187. return &ctx->detect_devs[i];
  188. }
  189. LOG_DBG("dev slot[%d]:%d", i, ctx->detect_devs[i].detect_dev);
  190. }
  191. return NULL;
  192. }
  193. /* @brief register the function will be called when the state of monitor device change */
  194. int soc_pmu_register_notify(struct detect_param_t *param)
  195. {
  196. struct pmu_context_t *ctx = get_pmu_context();
  197. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  198. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  199. uint8_t i;
  200. if (!param)
  201. return -EINVAL;
  202. if (PMU_MONITOR_DEV_INVALID(param->detect_dev)) {
  203. LOG_ERR("Invalid monitor dev:%d", param->detect_dev);
  204. return -EINVAL;
  205. }
  206. for (i = 0; i < PMU_DETECT_MAX_DEV; i++) {
  207. /* new or update a monitor device into PMU context */
  208. if ((!(ctx->detect_devs[i].detect_dev))
  209. || (ctx->detect_devs[i].detect_dev == param->detect_dev)) {
  210. ctx->detect_devs[i].detect_dev = param->detect_dev;
  211. ctx->detect_devs[i].cb_data = param->cb_data;
  212. ctx->detect_devs[i].notify = param->notify;
  213. break;
  214. } else {
  215. LOG_DBG("Busy slot[%d]:%d", i, ctx->detect_devs[i].detect_dev);
  216. }
  217. }
  218. if (i == PMU_DETECT_MAX_DEV) {
  219. LOG_ERR("no space for dev:0x%x", param->detect_dev);
  220. return -ENOMEM;
  221. }
  222. /* enable detect device interrupt and DC5V is already enabled at the stage of initialization */
  223. if (PMU_DETECT_DEV_ONOFF == param->detect_dev) {
  224. if (ctx->onoff_short_detect) {
  225. pmusvcc_reg->wake_ctl_svcc |= (WAKE_CTL_SVCC_SHORT_WKEN | WAKE_CTL_SVCC_LONG_WKEN);
  226. pmuvdd_reg->pmu_intmask |= (PMU_INTMASK_ONOFF_S_INTEN | PMU_INTMASK_ONOFF_L_INTEN);
  227. } else {
  228. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_LONG_WKEN;
  229. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_ONOFF_L_INTEN;
  230. }
  231. } else if (PMU_DETECT_DEV_REMOTE == param->detect_dev) {
  232. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_REMOTE_WKEN;
  233. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_REMOTE_INTEN;
  234. } else if (PMU_DETECT_DEV_COUNTER8HZ == param->detect_dev) {
  235. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_COUNTER8HZ_INTEN;
  236. }
  237. LOG_DBG("pmu register dev:%d", param->detect_dev);
  238. return 0;
  239. }
  240. /* @brief unregister the notify function for specified monitor device */
  241. void soc_pmu_unregister_notify(uint8_t detect_dev)
  242. {
  243. struct pmu_context_t *ctx = get_pmu_context();
  244. uint8_t i;
  245. uint32_t key;
  246. for (i = 0; i < PMU_DETECT_MAX_DEV; i++) {
  247. if (ctx->detect_devs[i].detect_dev == detect_dev) {
  248. key = irq_lock();
  249. ctx->detect_devs[i].detect_dev = 0;
  250. ctx->detect_devs[i].notify = 0;
  251. ctx->detect_devs[i].cb_data = NULL;
  252. irq_unlock(key);
  253. }
  254. }
  255. }
  256. #ifdef CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_EXTERNAL
  257. #define DET_DC5VIN 0x1
  258. extern uint8_t get_external_dc5v_state(void);
  259. #endif
  260. /* @brief get the current DC5V status of plug in or out */
  261. bool soc_pmu_get_dc5v_status(void)
  262. {
  263. bool status;
  264. /* DC5VIN indicator, 0: DC5V < BAT +33mV; 1: DC5V > BAT + 80mV */
  265. #ifdef CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_EXTERNAL
  266. if (get_external_dc5v_state() == DET_DC5VIN) {
  267. status = true;
  268. } else {
  269. status = false;
  270. }
  271. #else
  272. struct pmu_context_t *ctx = get_pmu_context();
  273. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  274. if (pmuvdd_reg->pmu_det & PMU_DET_DC5VIN_DET) {
  275. status = true;
  276. } else {
  277. status = false;
  278. }
  279. #endif
  280. return status;
  281. }
  282. /* @brief return the wakeup pending by system startup */
  283. uint32_t soc_pmu_get_wakeup_source(void)
  284. {
  285. struct pmu_context_t *ctx = get_pmu_context();
  286. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  287. static uint32_t pmu_wakeup_pending;
  288. if (!pmu_wakeup_pending) {
  289. pmu_wakeup_pending = pmusvcc_reg->wake_pd_svcc;
  290. LOG_INF("pmu wakeup pending:0x%x", pmu_wakeup_pending);
  291. }
  292. return pmu_wakeup_pending;
  293. }
  294. /* @brief return the wakeup setting by system startup */
  295. uint32_t soc_pmu_get_wakeup_setting(void)
  296. {
  297. struct pmu_context_t *ctx = get_pmu_context();
  298. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  299. static uint32_t pmu_wakeup_ctl;
  300. if (!pmu_wakeup_ctl) {
  301. pmu_wakeup_ctl = pmusvcc_reg->wake_ctl_svcc;
  302. LOG_INF("pmu wakeup setting:0x%x", pmu_wakeup_ctl);
  303. }
  304. return pmu_wakeup_ctl;
  305. }
  306. /* @brief check if system wakeup by RTC alarm */
  307. bool soc_pmu_is_alarm_wakeup(void)
  308. {
  309. uint32_t wk_pd;
  310. wk_pd = soc_pmu_get_wakeup_source();
  311. if (wk_pd & WAKE_CTL_SVCC_ALARM8HZ_WKEN)
  312. return true;
  313. return false;
  314. }
  315. /* @brief set the max constant current */
  316. void soc_pmu_set_max_current(uint16_t cur_ma)
  317. {
  318. struct pmu_context_t *ctx = get_pmu_context();
  319. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  320. uint8_t level;
  321. if (cur_ma <= 100) {
  322. level = (cur_ma + 9) / 10 - 1;
  323. } else if (cur_ma < 240) {
  324. level = (cur_ma + 19) / 20 + 4;
  325. } else {
  326. level = 15;
  327. }
  328. pmusvcc_reg->chg_ctl_svcc = (pmusvcc_reg->chg_ctl_svcc & ~0xF) | level;
  329. }
  330. /* @brief get the max constant current */
  331. uint16_t soc_pmu_get_max_current(void)
  332. {
  333. struct pmu_context_t *ctx = get_pmu_context();
  334. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  335. uint8_t level, cur_ma;
  336. level = pmusvcc_reg->chg_ctl_svcc & 0xF;
  337. if (level >= 10) {
  338. cur_ma = (level - 4) * 20;
  339. } else {
  340. cur_ma = (level + 1) * 10;
  341. }
  342. return cur_ma;
  343. }
  344. /* @brief lock(stop) DC5V charging for reading battery voltage */
  345. void soc_pmu_read_bat_lock(void)
  346. {
  347. struct pmu_context_t *ctx = get_pmu_context();
  348. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  349. pmusvcc_reg->chg_ctl_svcc |= CHG_CTL_SVCC_CV_3V3;
  350. k_busy_wait(300);
  351. }
  352. /* @brief unlock(resume) and restart DC5V charging */
  353. void soc_pmu_read_bat_unlock(void)
  354. {
  355. struct pmu_context_t *ctx = get_pmu_context();
  356. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  357. pmusvcc_reg->chg_ctl_svcc &= ~CHG_CTL_SVCC_CV_3V3;
  358. k_busy_wait(300);
  359. }
  360. /* @brief set const voltage value */
  361. void soc_pmu_set_const_voltage(uint8_t cv)
  362. {
  363. struct pmu_context_t *ctx = get_pmu_context();
  364. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  365. if (cv <= 0x1F) {
  366. pmusvcc_reg->chg_ctl_svcc = \
  367. (pmusvcc_reg->chg_ctl_svcc & ~CHG_CTL_SVCC_CV_OFFSET_MASK) | CHG_CTL_SVCC_CV_OFFSET(cv);
  368. k_busy_wait(300);
  369. }
  370. }
  371. /* @brief configure the long press on-off key time */
  372. void soc_pmu_config_onoffkey_time(uint8_t val)
  373. {
  374. unsigned int val_reg;
  375. struct pmu_context_t *ctx = get_pmu_context();
  376. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  377. if (val > 7)
  378. return ;
  379. val_reg = pmusvcc_reg->system_set_svcc & (~SYSTEM_SET_SVCC_ONOFF_PRESS_TIME_MASK);
  380. pmusvcc_reg->system_set_svcc = val_reg | SYSTEM_SET_SVCC_ONOFF_PRESS_TIME(val);
  381. k_busy_wait(300);
  382. }
  383. /* @brief configure the long press on-off key time */
  384. void soc_pmu_config_onoffkey_function(uint8_t val)
  385. {
  386. unsigned int val_reg;
  387. struct pmu_context_t *ctx = get_pmu_context();
  388. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  389. /**
  390. * ONOFF long pressed function
  391. * 0: no function
  392. * 1: reset
  393. * 2: restart (S1 => S4 => S1)
  394. */
  395. if (val > 2)
  396. return ;
  397. val_reg = pmusvcc_reg->system_set_svcc &(~SYSTEM_SET_SVCC_ONOFF_RST_EN_MASK);
  398. pmusvcc_reg->system_set_svcc = val_reg | SYSTEM_SET_SVCC_ONOFF_RST_EN(val);
  399. k_busy_wait(300);
  400. }
  401. void soc_pmu_check_onoff_reset_func(void)
  402. {
  403. struct pmu_context_t *ctx = get_pmu_context();
  404. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  405. if(!(pmusvcc_reg->system_set_svcc & SYSTEM_SET_SVCC_ONOFF_RST_EN_MASK))
  406. soc_pmu_config_onoffkey_function(1);
  407. }
  408. /* @brief check if the onoff key has been pressed or not */
  409. bool soc_pmu_is_onoff_key_pressed(void)
  410. {
  411. struct pmu_context_t *ctx = get_pmu_context();
  412. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  413. /* if 1 indicates that onoff key has been pressed */
  414. if (pmusvcc_reg->system_set_svcc & SYSTEM_SET_SVCC_ONOFF_PRES)
  415. return true;
  416. return false;
  417. }
  418. /* @brief configure the long press on-off key reset/restart time */
  419. void soc_pmu_config_onoffkey_reset_time(uint8_t val)
  420. {
  421. struct pmu_context_t *ctx = get_pmu_context();
  422. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  423. if (val) {
  424. pmusvcc_reg->system_set_svcc |= SYSTEM_SET_SVCC_ONOFF_RST_TIME; /* 12s */
  425. } else {
  426. pmusvcc_reg->system_set_svcc &= ~SYSTEM_SET_SVCC_ONOFF_RST_TIME; /* 8s */
  427. }
  428. k_busy_wait(300);
  429. }
  430. #ifdef CONFIG_PMU_COUNTER8HZ_SYNC_TIMEOUT_US
  431. /* @brief counter 8hz clock enable */
  432. void soc_pmu_counter8hz_enable(void)
  433. {
  434. struct pmu_context_t *ctx = get_pmu_context();
  435. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  436. LOG_DBG("counter8hz_svcc:0x%x", pmusvcc_reg->counter8hz_svcc);
  437. /* clock source select LOSC */
  438. if (!(pmusvcc_reg->counter8hz_svcc & PMU_COUNTER8HZ_SVCC_COUNTER_EN)) {
  439. #if (CONFIG_RTC_CLK_SOURCE == 1)
  440. pmusvcc_reg->counter8hz_svcc |= \
  441. (PMU_COUNTER8HZ_SVCC_CLK_SEL_LOSC | PMU_COUNTER8HZ_SVCC_COUNTER_EN);
  442. #else
  443. pmusvcc_reg->counter8hz_svcc |= PMU_COUNTER8HZ_SVCC_COUNTER_EN;
  444. #endif
  445. k_busy_wait(300);
  446. }
  447. }
  448. /* @brief get counter8hz and the retval is by cycles */
  449. int soc_pmu_get_counter8hz_cycles(bool is_sync)
  450. {
  451. struct pmu_context_t *ctx = get_pmu_context();
  452. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  453. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  454. if (!(pmusvcc_reg->counter8hz_svcc
  455. & PMU_COUNTER8HZ_SVCC_COUNTER_EN)) {
  456. LOG_ERR("counter8hz does not enable yet");
  457. return -EACCES;
  458. }
  459. if (is_sync) {
  460. /* clear counter8hz pending */
  461. pmuvdd_reg->pmu_det |= PMU_DET_COUNTR8HZ_PD;
  462. /* wait a new counter8hz pending */
  463. uint32_t cur_time = k_cycle_get_32();
  464. while (!(pmuvdd_reg->pmu_det & PMU_DET_COUNTR8HZ_PD)) {
  465. if (k_cyc_to_us_floor32(k_cycle_get_32() - cur_time) >=
  466. CONFIG_PMU_COUNTER8HZ_SYNC_TIMEOUT_US) {
  467. LOG_ERR("wait counter8hz pending timeout");
  468. return -ETIMEDOUT;
  469. }
  470. k_sleep(K_MSEC(1));
  471. }
  472. }
  473. return (pmusvcc_reg->counter8hz_svcc & PMU_COUNTER8HZ_SVCC_COUNTER_VAL);
  474. }
  475. #if (CONFIG_RTC_CLK_SOURCE == 2)
  476. /*@brief 8hzchcle cal to ms by rc32k
  477. rc32k_sum = rc32k_old + rc32k_new
  478. */
  479. uint32_t sys_pmu_8hzcycle_to_ms(uint32_t cycle, uint32_t rc32k_sum)
  480. {
  481. uint64_t cal = cycle;
  482. uint32_t ms;
  483. ms = cal*(32768*125*2)/rc32k_sum; // cal interval ms
  484. return ms;
  485. }
  486. #endif
  487. /* @brief enable PMU alarm 8hz */
  488. int soc_pmu_alarm8hz_enable(uint32_t alarm_msec)
  489. {
  490. struct pmu_context_t *ctx = get_pmu_context();
  491. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  492. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  493. uint32_t alarm8hz_cycles, new_alarm8hz_cycles, reg;
  494. int ret;
  495. /* clear alarm 8Hz pending */
  496. if (pmusvcc_reg->wake_pd_svcc & WAKE_PD_SVCC_ALARM8HZ_PD) {
  497. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_SVCC_ALARM8HZ_PD;
  498. k_busy_wait(300);
  499. }
  500. alarm8hz_cycles = (alarm_msec + 124) / 125;
  501. #if (CONFIG_RTC_CLK_SOURCE == 2) // rc32k inaccurate, need calibration
  502. uint32_t rc32k_freq;
  503. rc32k_freq = soc_rc32K_freq();
  504. printk("rc32k_freq=%d set 8hz=%d,", rc32k_freq, alarm8hz_cycles);
  505. alarm8hz_cycles = (uint64_t)alarm8hz_cycles*rc32k_freq/32768;
  506. printk("cal alarm8hz=%d cur_8hz=%d\n", alarm8hz_cycles, soc_pmu_get_counter8hz_cycles(false));
  507. #endif
  508. if (alarm8hz_cycles < 3) {
  509. LOG_ERR("invalid alarm8hz msec:%d", alarm_msec);
  510. return -EINVAL;
  511. }
  512. ret = soc_pmu_get_counter8hz_cycles(true);
  513. if (ret < 0) {
  514. LOG_ERR("failed to get counter8hz");
  515. return ret;
  516. }
  517. new_alarm8hz_cycles = ret + alarm8hz_cycles;
  518. /* 8Hz counter overflow */
  519. if (new_alarm8hz_cycles > 0x3FFFFFF)
  520. new_alarm8hz_cycles = new_alarm8hz_cycles - 0x3FFFFFF;
  521. reg = pmusvcc_reg->alarm8hz_svcc;
  522. reg &= ~PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK;
  523. reg |= (new_alarm8hz_cycles & PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK);
  524. pmusvcc_reg->alarm8hz_svcc = reg;
  525. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_ALARM8HZ_WKEN;
  526. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_ALARM8HZ_INTEN;
  527. k_busy_wait(300);
  528. return 0;
  529. }
  530. /* @brief disable PMU alarm8hz */
  531. void soc_pmu_alarm8hz_disable(void)
  532. {
  533. struct pmu_context_t *ctx = get_pmu_context();
  534. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  535. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  536. /* clear alarm 8Hz pending */
  537. if (pmusvcc_reg->wake_pd_svcc & WAKE_PD_SVCC_ALARM8HZ_PD) {
  538. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_SVCC_ALARM8HZ_PD;
  539. k_busy_wait(300);
  540. }
  541. pmuvdd_reg->pmu_intmask &= ~PMU_INTMASK_ALARM8HZ_INTEN;
  542. pmusvcc_reg->wake_ctl_svcc &= ~WAKE_CTL_SVCC_ALARM8HZ_WKEN;
  543. pmusvcc_reg->alarm8hz_svcc &= ~PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK;
  544. k_busy_wait(300);
  545. }
  546. /* @brief get alarm8hz cycles */
  547. int soc_pmu_get_alarm8hz(void)
  548. {
  549. struct pmu_context_t *ctx = get_pmu_context();
  550. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  551. return pmusvcc_reg->alarm8hz_svcc & PMU_ALARM8HZ_SVCC_ALARM_VAL_MASK;
  552. }
  553. #endif
  554. static void soc_pmu_isr(void *arg)
  555. {
  556. struct pmu_context_t *ctx = get_pmu_context();
  557. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  558. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  559. struct detect_param_t *detect_param = NULL;
  560. ARG_UNUSED(arg);
  561. uint32_t pending = pmusvcc_reg->wake_pd_svcc;
  562. LOG_DBG("pmu pending:0x%x", pending);
  563. if (pending & WAKE_PD_SVCC_REMOTE_PD) {
  564. /* Both REMOTE and ONOFF key are connected with WIO0.
  565. * Once the ONOFF key are pressed, the REMOTE key pending will also trigger.
  566. */
  567. if (pending & WAKE_PD_SVCC_WIO0LV_PD) {
  568. if (ctx->onoff_short_detect) {
  569. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  570. if (detect_param)
  571. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  572. }
  573. /* If ONOFF and REMOTE key use the same WIO pin, ignore the REMOTE key pending when WIO low voltage. */
  574. if (ctx->onoff_remote_same_wio)
  575. goto out;
  576. }
  577. /* disable remote interrupt and the remote device will enable interrupt through register interface again */
  578. pmuvdd_reg->pmu_intmask &= ~PMU_INTMASK_REMOTE_INTEN;
  579. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_REMOTE);
  580. if (detect_param)
  581. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  582. } else if (pending & WAKE_PD_SVCC_ONOFF_L_PD) {
  583. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  584. if (detect_param)
  585. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_LONG_PRESSED);
  586. } else if (pending & WAKE_PD_SVCC_ONOFF_S_PD) {
  587. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  588. if (detect_param)
  589. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  590. } else if (pending & WAKE_PD_SVCC_WIO0LV_PD) {
  591. if (ctx->onoff_short_detect) {
  592. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ONOFF);
  593. if (detect_param)
  594. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_PRESSED);
  595. }
  596. }
  597. if (pending & WAKE_PD_SVCC_DC5VOUT_PD) {
  598. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_DC5V);
  599. if (detect_param)
  600. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_OUT);
  601. }
  602. if (pending & WAKE_PD_SVCC_DC5VIN_PD) {
  603. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_DC5V);
  604. if (detect_param)
  605. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_IN);
  606. }
  607. #ifdef CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_INTERNAL
  608. /* check whether bat protect pending */
  609. if (pending & WAKE_PD_TK_PD) {
  610. /* clear bat protect pending */
  611. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_TK_PD;
  612. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_BAT);
  613. if (detect_param)
  614. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_BAT_PROTECT);
  615. }
  616. #endif
  617. /* check whether counter8hz pending */
  618. if (pmuvdd_reg->pmu_det & PMU_DET_COUNTR8HZ_PD) {
  619. /* clear counter8hz pending */
  620. pmuvdd_reg->pmu_det |= PMU_DET_COUNTR8HZ_PD;
  621. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_COUNTER8HZ);
  622. if (detect_param)
  623. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_TIME_ON);
  624. }
  625. /* check whether alarm8hz pending */
  626. if (pmusvcc_reg->alarm8hz_svcc & PMU_ALARM8HZ_SVCC_PD) {
  627. /* clear alarm8hz pending */
  628. pmusvcc_reg->wake_pd_svcc |= WAKE_PD_SVCC_ALARM8HZ_PD;
  629. detect_param = soc_pmu_find_detect_dev(ctx, PMU_DETECT_DEV_ALARM8HZ);
  630. if (detect_param)
  631. detect_param->notify(detect_param->cb_data, PMU_NOTIFY_STATE_TIME_ON);
  632. }
  633. out:
  634. /* counter8Hz irq pending is shared with WAKE_PD_SVCC */
  635. if (pending)
  636. pmusvcc_reg->wake_pd_svcc = pending;
  637. }
  638. static void soc_pmu_irq_config(void)
  639. {
  640. IRQ_CONNECT(IRQ_ID_PMU, CONFIG_PMU_IRQ_PRI,
  641. soc_pmu_isr,
  642. NULL, 0);
  643. irq_enable(IRQ_ID_PMU);
  644. }
  645. /*return rc32k freq*/
  646. uint32_t acts_clock_rc32k_set_cal_cyc(uint32_t cal_cyc)
  647. {
  648. uint32_t cnt;
  649. uint64_t tmp = 32000000;
  650. sys_write32(0, RC32K_CAL);
  651. soc_udelay(300);
  652. sys_write32((cal_cyc << 8)|1, RC32K_CAL);
  653. soc_udelay(300);
  654. /* wait calibration done */
  655. while (!(sys_read32(RC32K_CAL) & (1 << 4))){}
  656. cnt = sys_read32(RC32K_COUNT);
  657. if(cnt){
  658. cnt = tmp*cal_cyc/cnt;
  659. }
  660. LOG_INF("cal freq=%d, ctl=0x%x\n", cnt, sys_read32(RC32K_CTL)>>1);
  661. return cnt;
  662. }
  663. static uint32_t g_rc32_mul;
  664. static __act_s2_sleep_data uint32_t g_rc32_freq;
  665. static void acts_clock_rc32k_calibrate(void)
  666. {
  667. uint32_t freq;
  668. //uint32_t freqs, freqe, setf;
  669. //sys_write32((0x2c << 1), RC32K_CTL);// defaut set
  670. //soc_udelay(300);
  671. freq = acts_clock_rc32k_set_cal_cyc(100);
  672. LOG_INF("cur freq=%d\n", freq);
  673. #if 0
  674. if(freq < 32768){
  675. freqs = 44;
  676. freqe = 63;
  677. }else{
  678. freqs = 10;
  679. freqe = 44;
  680. }
  681. while(freqs < (freqe-1)){
  682. setf = (freqs + freqe)/2;
  683. sys_write32((setf << 1), RC32K_CTL);
  684. soc_udelay(300);
  685. freq = acts_clock_rc32k_set_cal_cyc(100);
  686. if(freq < 32768){
  687. freqs = setf;
  688. }else{
  689. freqe = setf;
  690. }
  691. }
  692. #endif
  693. if(freq){
  694. g_rc32_mul = (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC/freq);
  695. g_rc32_freq = freq;
  696. }else{
  697. g_rc32_mul = (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC/32768);
  698. g_rc32_freq = 32768;
  699. }
  700. LOG_INF("calibrate freq=%d, mul=%d, ctl=0x%x\n", freq, g_rc32_mul, sys_read32(RC32K_CTL) >> 1);
  701. }
  702. #define CALC_CYCLE_NUM 16
  703. #define CMU_ANADEBUG (0x40000100+0x60)
  704. #define RC4M_ADJUST_HZ 4000000
  705. #define RC4M_STEP_ONE_HZ 80000
  706. static void soc_pmu_rc4m_cal(void)
  707. {
  708. uint32_t fr_val,reg_val, cm_reg_dbg_bak, step, step_num;
  709. uint64_t tmp = 32000000;
  710. sys_write32(0, RC32K_CAL);
  711. cm_reg_dbg_bak = sys_read32(CMU_ANADEBUG);
  712. reg_val = cm_reg_dbg_bak&(~(0xf<<16));
  713. sys_write32(reg_val , CMU_ANADEBUG);
  714. sys_write32(reg_val|(3<<16) , CMU_ANADEBUG);
  715. reg_val = sys_read32(RC4M_CTL);
  716. step = (reg_val>>1) & 0x3f;
  717. reg_val &= ~(0x3f<<1);
  718. while(1){
  719. soc_udelay(100);
  720. sys_write32(0x01|(CALC_CYCLE_NUM<<8) , RC32K_CAL); //cal 16 cycle of 32K
  721. soc_udelay(300);
  722. /* wait calibration done */
  723. while (!(sys_read32(RC32K_CAL) & (1 << 4))){}
  724. fr_val = sys_read32(RC32K_COUNT);
  725. if(fr_val){
  726. fr_val = tmp*CALC_CYCLE_NUM*1024/fr_val;
  727. }
  728. sys_write32(0, RC32K_CAL);
  729. printk("fr=0x%x, rc4m=%d HZ\n", step, fr_val);
  730. if(fr_val <= RC4M_ADJUST_HZ)
  731. break;
  732. if(step == 0)
  733. break;
  734. step_num = (fr_val - RC4M_ADJUST_HZ)/RC4M_STEP_ONE_HZ;
  735. if(step_num == 0)
  736. step--;
  737. else if(step_num > step)
  738. step = 0;
  739. else
  740. step -= step_num;
  741. sys_write32(reg_val | (step<<1), RC4M_CTL);
  742. }
  743. sys_write32(cm_reg_dbg_bak , CMU_ANADEBUG);
  744. }
  745. uint32_t soc_rc32K_mutiple_hosc(void)
  746. {
  747. return g_rc32_mul;
  748. }
  749. uint32_t soc_rc32K_freq(void)
  750. {
  751. return g_rc32_freq;
  752. }
  753. uint32_t soc_pmu_get_vdd_voltage(void)
  754. {
  755. uint32_t sel, volt_mv;
  756. sel = sys_read32(VOUT_CTL1_S1M) & 0xf;
  757. volt_mv = 550 + sel * 50;
  758. return volt_mv;
  759. }
  760. void soc_pmu_set_vdd_voltage(uint32_t volt_mv)
  761. {
  762. unsigned int sel;
  763. if (volt_mv < 550 || volt_mv > 1300)
  764. return ;
  765. sel = (volt_mv - 550) / 50;
  766. sel = (sel << 4) | sel; // set vdd s1 adn s1ml
  767. sys_write32((sys_read32(VOUT_CTL1_S1M) & ~(0xff)) | (sel), VOUT_CTL1_S1M);
  768. k_busy_wait(33);
  769. }
  770. void soc_pmu_set_vd12_voltage(uint32_t volt_mv)
  771. {
  772. unsigned int sel;
  773. if (volt_mv < 600 || volt_mv > 1400)
  774. return ;
  775. sel = (volt_mv - 600) / 50;
  776. if (sel > 0xff)
  777. sel = 0xff;
  778. sys_write32((sys_read32(VOUT_CTL1_S1M) & ~(0xf<<8)) | (sel<<8), VOUT_CTL1_S1M);
  779. k_busy_wait(33);
  780. }
  781. #if defined(CONFIG_S1ML_LITTLE_BIAS)
  782. #define EN_LGBIAS_S1ML (1<<21)
  783. #define CLOCK0_ID_HPWR ((1<<CLOCK_ID_GPU) \
  784. |(1<<CLOCK_ID_JPEG) \
  785. |(1<<CLOCK_ID_DE) \
  786. |(1<<CLOCK_ID_LRADC))
  787. #define CLOCK1_ID_HPWR ((1<<(CLOCK_ID_DSP-32)))
  788. /* run in sram, so no need take care of nor and psram delaychain */
  789. __sleepfunc void soc_change_s1ml_bias(void)
  790. {
  791. /* <true: enter s1ml; false: exit s1ml> */
  792. static __act_s2_sleep_data bool enter_s1ml = true;
  793. /* before entering s1ml/wfi */
  794. if (enter_s1ml) {
  795. /* when high pwr periphers all not work, we can use little bias in s1ml state */
  796. if ((!(sys_read32(CMU_DEVCLKEN0) & CLOCK0_ID_HPWR))
  797. && (!(sys_read32(CMU_DEVCLKEN1) & CLOCK1_ID_HPWR))){
  798. /* disable large bias in s1ml to reduce consumption */
  799. sys_write32(sys_read32(VOUT_CTL1_S1M) & ~EN_LGBIAS_S1ML, VOUT_CTL1_S1M);
  800. }
  801. enter_s1ml = false;
  802. }
  803. /* after exiting s1ml/wfi */
  804. if (!enter_s1ml) {
  805. /* resume large bias for s1ml state */
  806. sys_write32(sys_read32(VOUT_CTL1_S1M) | EN_LGBIAS_S1ML, VOUT_CTL1_S1M);
  807. enter_s1ml = true;
  808. }
  809. }
  810. #endif
  811. /* @brief get temperature degrees (multiply 10) in centigrade and if retval is negative will get error */
  812. int soc_pmu_get_temperature(void)
  813. {
  814. static uint8_t is_pmu_temperature_init = 0;
  815. const struct device* adc_dev = device_get_binding(CONFIG_PMUADC_NAME);
  816. struct adc_sequence adc_data = {0};
  817. uint8_t adc_buf[2];
  818. uint16_t adc_temp;
  819. int ret;
  820. if (adc_dev == NULL) {
  821. LOG_ERR("cannot get pmuadc device");
  822. return -1;
  823. }
  824. if (!is_pmu_temperature_init) {
  825. struct adc_channel_cfg adc_cfg = {0};
  826. adc_cfg.channel_id = PMUADC_ID_SENSOR;
  827. adc_channel_setup(adc_dev, &adc_cfg);
  828. is_pmu_temperature_init = 1;
  829. }
  830. adc_data.channels = BIT(PMUADC_ID_SENSOR);
  831. adc_data.buffer = adc_buf;
  832. adc_data.buffer_size = sizeof(adc_buf);
  833. ret = adc_read(adc_dev, &adc_data);
  834. if (ret) {
  835. LOG_ERR("ADC read temperature error %d", ret);
  836. return -1;
  837. }
  838. adc_temp = sys_get_le16(adc_data.buffer);
  839. /* sample temerature formula: temperature = 4532 - (adc_temp x 1751 / 1024);
  840. * precision: 0.1degree
  841. * sample result multiply 10
  842. */
  843. ret = 4532 - (1751 * adc_temp / 1024);
  844. return ret;
  845. }
  846. /* @brief set pmu reg CHG_CTL_SVCC */
  847. void soc_pmu_set_chg_ctl_svcc(uint32_t mask, uint32_t value)
  848. {
  849. sys_write32(((sys_read32(CHG_CTL_SVCC) & ~mask) | (value & mask)), CHG_CTL_SVCC);
  850. k_busy_wait(300);
  851. }
  852. /* @brief get pmu reg CHG_CTL_SVCC */
  853. uint32_t soc_pmu_get_chg_ctl_svcc(void)
  854. {
  855. return sys_read32(CHG_CTL_SVCC);
  856. }
  857. /* @brief set pmu reg POWER_CTL_SVCC */
  858. void soc_pmu_sys_poweroff(void)
  859. {
  860. sys_write32(0, POWER_CTL_SVCC);
  861. k_busy_wait(300);
  862. }
  863. /* @brief set pmu reg BDG_CTL_SVCC */
  864. void soc_pmu_set_bdg_ctl_svcc(uint32_t mask, uint32_t value)
  865. {
  866. sys_write32(((sys_read32(BDG_CTL_SVCC) & ~mask) | (value & mask)), BDG_CTL_SVCC);
  867. k_busy_wait(300);
  868. }
  869. /* @brief get pmu reg BDG_CTL_SVCC */
  870. uint32_t soc_pmu_get_bdg_ctl_svcc(void)
  871. {
  872. return sys_read32(BDG_CTL_SVCC);
  873. }
  874. /* @brief set pmu reg PMUADC_CTL */
  875. void soc_pmu_set_pmuadc_ctl(uint32_t mask, uint32_t value)
  876. {
  877. sys_write32(((sys_read32(PMUADC_CTL) & ~mask) | (value & mask)), PMUADC_CTL);
  878. if ((value & mask) & REG_SENSOR_EFUSE_MASK) {
  879. k_busy_wait(300);
  880. }
  881. }
  882. /* @brief get pmu reg PMUADC_CTL */
  883. uint32_t soc_pmu_get_pmuadc_ctl(void)
  884. {
  885. return sys_read32(PMUADC_CTL);
  886. }
  887. /* @brief set pmu reg PMUADCDIG_CTL */
  888. void soc_pmu_set_pmuadcdig_ctl(uint32_t mask, uint32_t value)
  889. {
  890. sys_write32(((sys_read32(PMUADCDIG_CTL) & ~mask) | (value & mask)), PMUADCDIG_CTL);
  891. }
  892. /* @brief get pmu reg PMUADC_CTL */
  893. uint32_t soc_pmu_get_pmuadcdig_ctl(void)
  894. {
  895. return sys_read32(PMUADCDIG_CTL);
  896. }
  897. /* @brief set pmu reg VOUT_CTL0 */
  898. void soc_pmu_set_vout_ctl0(uint32_t mask, uint32_t value)
  899. {
  900. sys_write32(((sys_read32(VOUT_CTL0) & ~mask) | (value & mask)), VOUT_CTL0);
  901. }
  902. /* @brief get pmu reg VOUT_CTL0 */
  903. uint32_t soc_pmu_get_vout_ctl0(void)
  904. {
  905. return sys_read32(VOUT_CTL0);
  906. }
  907. /* @brief clear PMUADC_PD */
  908. void soc_pmu_clear_pmuadc_pd(void)
  909. {
  910. sys_write32(sys_read32(PMUADC_PD), PMUADC_PD);
  911. }
  912. /* @brief clear PMUADC_INTMASK */
  913. void soc_pmu_clear_pmuadc_intmask(void)
  914. {
  915. sys_write32(0x0, PMUADC_INTMASK);
  916. }
  917. /* @brief get PMUADC_PD */
  918. uint32_t soc_pmu_get_pmuadc_pd(void)
  919. {
  920. return sys_read32(PMUADC_PD);
  921. }
  922. /* @brief get CHARGI_DATA */
  923. uint32_t soc_pmu_get_chargi_data(void)
  924. {
  925. return (sys_read32(CHARGI_DATA) & 0x1FFF);
  926. }
  927. /* @brief get BATADC_DATA */
  928. uint32_t soc_pmu_get_batadc_data(void)
  929. {
  930. return (sys_read32(BATADC_DATA) & 0x3FFF);
  931. }
  932. /* @brief get DC5VADC_DATA */
  933. uint32_t soc_pmu_get_dc5vadc_data(void)
  934. {
  935. return (sys_read32(DC5VADC_DATA) & 0xFFF);
  936. }
  937. /* @brief get LRADCx_DATA */
  938. uint32_t soc_pmu_get_lradcxadc_data(uint8_t chn)
  939. {
  940. return (sys_read32(LRADC1_DATA + 4 * (chn - PMUADC_ID_LRADC1)) & 0x3FFF);
  941. }
  942. #if defined(CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_EXTERNAL) || defined(CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_INTERNAL)
  943. extern bool battery_is_lowpower(void);
  944. #endif
  945. bool soc_pmu_lowpower_check(void)
  946. {
  947. #if defined(CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_EXTERNAL) || defined(CONFIG_ACTS_LEOPARD_BATTERY_SUPPLY_INTERNAL)
  948. return battery_is_lowpower();
  949. #else
  950. return false;
  951. #endif
  952. }
  953. /* @brief PMUVDD and PMUSVCC initialization */
  954. static int soc_pmu_init(const struct device *dev)
  955. {
  956. struct pmu_context_t *ctx = get_pmu_context();
  957. struct acts_pmusvcc *pmusvcc_reg = get_pmusvcc_reg_base(ctx);
  958. struct acts_pmuvdd *pmuvdd_reg = get_pmuvdd_reg_base(ctx);
  959. unsigned int val = 0;
  960. ARG_UNUSED(dev);
  961. soc_pmu_get_wakeup_source();
  962. /* by default to enable DC5V plug in/out detection */
  963. pmusvcc_reg->wake_ctl_svcc |= (WAKE_CTL_SVCC_DC5VOUT_WKEN | WAKE_CTL_SVCC_DC5VIN_WKEN);
  964. pmuvdd_reg->pmu_intmask |= (PMU_INTMASK_DC5VIN_INTEN | PMU_INTMASK_DC5VOUT_INTEN);
  965. if (ctx->onoff_short_detect) {
  966. pmusvcc_reg->wake_ctl_svcc |= WAKE_CTL_SVCC_WIO0LV_WKEN;
  967. pmuvdd_reg->pmu_intmask |= PMU_INTMASK_WIO0LV_INTEN;
  968. }
  969. pmusvcc_reg->wake_pd_svcc = pmusvcc_reg->wake_pd_svcc;
  970. //if (!ctx->onoff_remote_same_wio)
  971. //sys_write32(0, WIO0_CTL);
  972. if (!soc_atp_get_pmu_calib(11, &val)){ // cali vd12
  973. val &= 0x3;
  974. printk("soc cali vd12 =%d\n", val);
  975. pmuvdd_reg->vout_ctl0 = (pmuvdd_reg->vout_ctl0 & (~(0x3<<VOUT_CTL0_VD12_25X_BITI))) | (val << VOUT_CTL0_VD12_25X_BITI);
  976. }else{
  977. printk("soc get cali vd12 fail\n");
  978. }
  979. soc_pmu_irq_config();
  980. acts_clock_rc32k_calibrate();
  981. soc_pmu_rc4m_cal();
  982. return 0;
  983. }
  984. SYS_INIT(soc_pmu_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS);