hal_pwm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. /*
  3. * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
  4. */
  5. #include "hal_base.h"
  6. #ifdef HAL_PWM_MODULE_ENABLED
  7. /** @addtogroup RK_HAL_Driver
  8. * @{
  9. */
  10. /** @addtogroup PWM
  11. * @{
  12. */
  13. /** @defgroup PWM_How_To_Use How To Use
  14. * @{
  15. The PWM HAL driver can be used as follows:
  16. - Declare a PWM_Handle handle structure, for example:
  17. ```
  18. PWM_Handle instance;
  19. ```
  20. - Invoke HAL_PWM_Init() API to initialize base address and clock frequency:
  21. - Base register address;
  22. - Input clock frequency.
  23. - Invoke HAL_PWM_SetConfig() API and HAL_PWM_SetEnable() to start/stop:
  24. - Use HAL_PWM_SetConfig() to configurate the request mode;
  25. - Use HAL_PWM_Enable() to start PWM;
  26. - Use HAL_PWM_Disable() to stop PWM.
  27. - Invoke HAL_PWM_DeInit() if necessary.
  28. @} */
  29. /** @defgroup PWM_Private_Definition Private Definition
  30. * @{
  31. */
  32. /********************* Private MACRO Definition ******************************/
  33. #define PWM_CNT_REG(pPWM, ch) (pPWM->pReg->CHANNELS[ch].CNT)
  34. #define PWM_PERIOD_REG(pPWM, ch) (pPWM->pReg->CHANNELS[ch].PERIOD_HPR)
  35. #define PWM_DUTY_REG(pPWM, ch) (pPWM->pReg->CHANNELS[ch].DUTY_LPR)
  36. #define PWM_CTRL_REG(pPWM, ch) (pPWM->pReg->CHANNELS[ch].CTRL)
  37. #define PWM_INT_EN(ch) (1 << (ch))
  38. #define PWM_PWR_INT_EN(ch) (1 << ((ch) + 4 ))
  39. #define PWM_DISABLE (0 << PWM_PWM0_CTRL_PWM_EN_SHIFT)
  40. #define PWM_ENABLE (1 << PWM_PWM0_CTRL_PWM_EN_SHIFT)
  41. #define PWM_MODE_SHIFT (1)
  42. #define PWM_MODE_MASK (0x3U << PWM_MODE_SHIFT)
  43. #define PWM_DUTY_POSTIVE (1 << PWM_PWM0_CTRL_DUTY_POL_SHIFT)
  44. #define PWM_DUTY_NEGATIVE (0 << PWM_PWM0_CTRL_DUTY_POL_SHIFT)
  45. #define PWM_DUTY_MASK (1 << 3)
  46. #define PWM_INACTIVE_POSTIVE (1 << PWM_PWM0_CTRL_INACTIVE_POL_SHIFT)
  47. #define PWM_INACTIVE_NEGATIVE (0 << PWM_PWM0_CTRL_INACTIVE_POL_SHIFT)
  48. #define PWM_INACTIVE_MASK (1 << 4)
  49. #define PWM_OUTPUT_LEFT (0 << PWM_PWM0_CTRL_OUTPUT_MODE_SHIFT)
  50. #define PWM_OUTPUT_CENTER (1 << PWM_PWM0_CTRL_OUTPUT_MODE_SHIFT)
  51. #define PWM_UNLOCK (0 << PWM_PWM0_CTRL_CONLOCK_SHIFT)
  52. #define PWM_LOCK (1 << PWM_PWM0_CTRL_CONLOCK_SHIFT)
  53. #define PWM_LP_DISABLE (0 << PWM_PWM0_CTRL_FORCE_CLK_EN_SHIFT)
  54. #define PWM_LP_ENABLE (1 << PWM_PWM0_CTRL_FORCE_CLK_EN_SHIFT)
  55. #define PWM_SEL_SRC_CLK (0 << PWM_PWM0_CTRL_CLK_SEL_SHIFT)
  56. #define PWM_SEL_SCALE_CLK (1 << PWM_PWM0_CTRL_CLK_SEL_SHIFT)
  57. #define PWM_CTRL_SCALE_SHIFT (PWM_PWM0_CTRL_SCALE_SHIFT)
  58. #define PWM_CTRL_SCALE_MASK (PWM_PWM0_CTRL_SCALE_MASK)
  59. #define PWM_PWRMATCH_MAX_SHIFT (PWM_PWRMATCH_LPRE_CNT_MIN_SHIFT)
  60. /********************* Private Structure Definition **************************/
  61. /********************* Private Variable Definition ***************************/
  62. /********************* Private Function Definition ***************************/
  63. /** @} */
  64. /********************* Public Function Definition ****************************/
  65. /** @defgroup PWM_Exported_Functions_Group3 IO Functions
  66. This section provides functions allowing to IO controlling:
  67. * @{
  68. */
  69. /**
  70. * @brief Handle PWM interrupt for capture/oneshot mode.
  71. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  72. * the information for PWM module.
  73. * @retval HAL status
  74. */
  75. HAL_Status HAL_PWM_IRQHandler(struct PWM_HANDLE *pPWM)
  76. {
  77. uint32_t status = READ_REG(pPWM->pReg->INTSTS);
  78. uint32_t i;
  79. /* clean ipd */
  80. WRITE_REG(pPWM->pReg->INTSTS, status & 0xf);
  81. if (status & 0xf) {
  82. for (i = 0; i < HAL_PWM_NUM_CHANNELS; i++) {
  83. if ((status & (1 << i)) &&
  84. (pPWM->mode[i] == HAL_PWM_CAPTURE)) {
  85. pPWM->result[i].active = true;
  86. pPWM->result[i].pol = status & (1 << (i + 8));
  87. if (pPWM->result[i].pol) {
  88. pPWM->result[i].period = READ_REG(PWM_PERIOD_REG(pPWM, i));
  89. } else {
  90. pPWM->result[i].period = READ_REG(PWM_DUTY_REG(pPWM, i));
  91. }
  92. }
  93. }
  94. }
  95. return HAL_OK;
  96. }
  97. /**
  98. * @brief Configurate PWM mode.
  99. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  100. * the information for PWM module.
  101. * @param channel: PWM channle(0~3).
  102. * @param config: Configuration for PWM.
  103. * @retval HAL status
  104. */
  105. HAL_Status HAL_PWM_SetConfig(struct PWM_HANDLE *pPWM, uint8_t channel,
  106. const struct HAL_PWM_CONFIG *config)
  107. {
  108. unsigned long period, duty;
  109. uint32_t ctrl;
  110. HAL_ASSERT(pPWM != NULL);
  111. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  112. HAL_ASSERT(config != NULL);
  113. HAL_DBG("channel=%d, period_ns=%ld, duty_ns=%ld\n",
  114. channel, config->periodNS, config->dutyNS);
  115. period = HAL_DivU64((uint64_t)pPWM->freq * config->periodNS, 1000000000);
  116. duty = HAL_DivU64((uint64_t)pPWM->freq * config->dutyNS, 1000000000);
  117. ctrl = READ_REG(PWM_CTRL_REG(pPWM, channel));
  118. ctrl |= PWM_LOCK;
  119. WRITE_REG(PWM_CTRL_REG(pPWM, channel), ctrl);
  120. WRITE_REG(PWM_PERIOD_REG(pPWM, channel), period);
  121. WRITE_REG(PWM_DUTY_REG(pPWM, channel), duty);
  122. ctrl &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK);
  123. if (config->polarity) {
  124. ctrl |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE;
  125. } else {
  126. ctrl |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE;
  127. }
  128. ctrl &= ~PWM_LOCK;
  129. WRITE_REG(PWM_CTRL_REG(pPWM, channel), ctrl);
  130. HAL_DBG("channel=%d, period=%lu, duty=%lu, polarity=%d\n",
  131. channel, period, duty, config->polarity);
  132. return HAL_OK;
  133. }
  134. /**
  135. * @brief Configurate PWM oneshot count.
  136. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  137. * the information for PWM module.
  138. * @param channel: PWM channle(0~3).
  139. * @param count: (count + 1)repeated effective periods of output waveform
  140. * @retval HAL status
  141. */
  142. HAL_Status HAL_PWM_SetOneshot(struct PWM_HANDLE *pPWM, uint8_t channel, uint32_t count)
  143. {
  144. uint32_t ctrl;
  145. HAL_ASSERT(pPWM != NULL);
  146. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  147. HAL_DBG("Oneshot count=%ld\n", count);
  148. ctrl = READ_REG(PWM_CTRL_REG(pPWM, channel));
  149. ctrl |= (count << PWM_PWM0_CTRL_RPT_SHIFT) & PWM_PWM0_CTRL_RPT_MASK;
  150. WRITE_REG(PWM_CTRL_REG(pPWM, channel), ctrl);
  151. return HAL_OK;
  152. }
  153. /**
  154. * @brief Configurate PWM captured frequency.
  155. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  156. * the information for PWM module.
  157. * @param channel: PWM channle(0~3).
  158. * @param freq: PWM use the frequency to capture data
  159. * @retval HAL status
  160. */
  161. HAL_Status HAL_PWM_SetCapturedFreq(struct PWM_HANDLE *pPWM, uint8_t channel, uint32_t freq)
  162. {
  163. uint32_t ctrl;
  164. HAL_ASSERT(pPWM != NULL);
  165. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  166. HAL_ASSERT(freq != 0);
  167. HAL_DBG("Captured freq=%ld\n", freq);
  168. ctrl = READ_REG(PWM_CTRL_REG(pPWM, channel));
  169. ctrl &= ~PWM_CTRL_SCALE_MASK;
  170. ctrl |= PWM_LP_ENABLE | PWM_SEL_SCALE_CLK;
  171. ctrl |= ((pPWM->freq / (2 * freq)) << PWM_CTRL_SCALE_SHIFT) & PWM_CTRL_SCALE_MASK;
  172. WRITE_REG(PWM_CTRL_REG(pPWM, channel), ctrl);
  173. return HAL_OK;
  174. }
  175. /**
  176. * @brief Configurate PWM matched setting.
  177. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  178. * the information for PWM module.
  179. * @param channel: PWM channle(0~3).
  180. * @param data: matching configuration.
  181. * @retval HAL status
  182. */
  183. HAL_Status HAL_PWM_SetMatch(struct PWM_HANDLE *pPWM, uint8_t channel, const struct PWM_MATCH *data)
  184. {
  185. uint8_t i;
  186. HAL_ASSERT(pPWM != NULL);
  187. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  188. HAL_ASSERT(data != NULL);
  189. HAL_ASSERT(data->matchCount <= PWM_PWRMATCH_MAX_COUNT);
  190. /* preloader low */
  191. WRITE_REG(pPWM->pReg->PWRMATCH_LPRE, data->lpreMin | (data->lpreMax << PWM_PWRMATCH_MAX_SHIFT));
  192. /* preloader high */
  193. WRITE_REG(pPWM->pReg->PWRMATCH_HPRE, data->hpreMin | (data->hpreMax << PWM_PWRMATCH_MAX_SHIFT));
  194. /* logic 0/1 low */
  195. WRITE_REG(pPWM->pReg->PWRMATCH_LD, data->ldMin | (data->ldMax << PWM_PWRMATCH_MAX_SHIFT));
  196. /* logic 0 high */
  197. WRITE_REG(pPWM->pReg->PWRMATCH_HD_ZERO, data->hdZeroMin | (data->hdZeroMax << PWM_PWRMATCH_MAX_SHIFT));
  198. /* logic 1 high */
  199. WRITE_REG(pPWM->pReg->PWRMATCH_HD_ONE, data->hdOneMin | (data->hdOneMax << PWM_PWRMATCH_MAX_SHIFT));
  200. for (i = 0; i < data->matchCount; i++) {
  201. WRITE_REG(pPWM->pReg->PWRMATCH_VALUE[i], data->match[i]);
  202. }
  203. /* Enable pwr irq */
  204. SET_BIT(pPWM->pReg->INT_EN, PWM_PWR_INT_EN(channel));
  205. /* Enable pwr */
  206. SET_BIT(pPWM->pReg->PWRMATCH_CTRL, channel);
  207. return HAL_OK;
  208. }
  209. /**
  210. * @brief Get PWM mode.
  211. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  212. * the information for PWM module.
  213. * @param channel: PWM channle(0~3).
  214. * @retval ePWM_Mode
  215. */
  216. ePWM_Mode HAL_PWM_GetMode(struct PWM_HANDLE *pPWM, uint8_t channel)
  217. {
  218. uint32_t ctrl;
  219. HAL_ASSERT(pPWM != NULL);
  220. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  221. HAL_DBG("channel=%d\n", channel);
  222. ctrl = READ_REG(PWM_CTRL_REG(pPWM, channel));
  223. return (ePWM_Mode)((ctrl >> PWM_MODE_SHIFT) & PWM_MODE_MASK);
  224. }
  225. /**
  226. * @brief Enable PWM.
  227. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  228. * the information for PWM module.
  229. * @param channel: PWM channle(0~3).
  230. * @param mode: Current mode on for PWM.
  231. * @retval HAL status
  232. */
  233. HAL_Status HAL_PWM_Enable(struct PWM_HANDLE *pPWM, uint8_t channel, ePWM_Mode mode)
  234. {
  235. uint32_t enableConf, intEnable;
  236. HAL_ASSERT(pPWM != NULL);
  237. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  238. HAL_DBG("Enable channel=%d\n", channel);
  239. pPWM->mode[channel] = mode;
  240. if (pPWM->mode[channel] != HAL_PWM_CONTINUOUS) {
  241. intEnable = READ_REG(pPWM->pReg->INT_EN);
  242. /* Enable irq */
  243. intEnable |= PWM_INT_EN(channel);
  244. WRITE_REG(pPWM->pReg->INT_EN, intEnable);
  245. }
  246. enableConf = READ_REG(PWM_CTRL_REG(pPWM, channel));
  247. /* clean mode */
  248. enableConf &= ~PWM_MODE_MASK;
  249. enableConf |= (mode << PWM_MODE_SHIFT) | PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE;
  250. WRITE_REG(PWM_CTRL_REG(pPWM, channel), enableConf);
  251. return HAL_OK;
  252. }
  253. /**
  254. * @brief Disable PWM.
  255. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  256. * the information for PWM module.
  257. * @param channel: PWM channle(0~3).
  258. * @retval HAL status
  259. */
  260. HAL_Status HAL_PWM_Disable(struct PWM_HANDLE *pPWM, uint8_t channel)
  261. {
  262. uint32_t ctrl, intEnable;
  263. HAL_ASSERT(pPWM != NULL);
  264. HAL_ASSERT(channel < HAL_PWM_NUM_CHANNELS);
  265. HAL_DBG("Disable channel=%d\n", channel);
  266. if (pPWM->mode[channel] != HAL_PWM_CONTINUOUS) {
  267. intEnable = READ_REG(pPWM->pReg->INT_EN);
  268. /* Disable irq */
  269. intEnable &= ~PWM_INT_EN(channel);
  270. WRITE_REG(pPWM->pReg->INT_EN, intEnable);
  271. }
  272. ctrl = READ_REG(PWM_CTRL_REG(pPWM, channel));
  273. ctrl &= ~PWM_ENABLE;
  274. WRITE_REG(PWM_CTRL_REG(pPWM, channel), ctrl);
  275. return HAL_OK;
  276. }
  277. /** @} */
  278. /** @defgroup PWM_Exported_Functions_Group4 Init and DeInit Functions
  279. This section provides functions allowing to init and deinit the module:
  280. * @{
  281. */
  282. /**
  283. * @brief Initialize the PWM according to the specified parameters.
  284. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  285. * the information for PWM module.
  286. * @param pReg: PWM controller register base address.
  287. * @param freq: PWM bus input clock frequency.
  288. * @return HAL_Status
  289. */
  290. HAL_Status HAL_PWM_Init(struct PWM_HANDLE *pPWM, struct PWM_REG *pReg, uint32_t freq)
  291. {
  292. HAL_ASSERT(pPWM != NULL);
  293. pPWM->pReg = pReg;
  294. HAL_ASSERT(IS_PWM_INSTANCE(pPWM->pReg));
  295. pPWM->freq = freq;
  296. return HAL_OK;
  297. }
  298. /**
  299. * @brief De Initialize the PWM peripheral.
  300. * @param pPWM: pointer to a PWM_HANDLE structure that contains
  301. * the information for PWM module.
  302. * @return HAL status
  303. */
  304. HAL_Status HAL_PWM_DeInit(struct PWM_HANDLE *pPWM)
  305. {
  306. /* ...to do */
  307. return HAL_OK;
  308. }
  309. /** @} */
  310. /** @} */
  311. /** @} */
  312. #endif /* HAL_PWM_MODULE_ENABLED */