drv_pwm.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Email: opensource_embedded@phytium.com.cn
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2023-10-18 zhangyan first version
  11. *
  12. */
  13. #include "rtconfig.h"
  14. #include <rtdevice.h>
  15. #define LOG_TAG "pwm_drv"
  16. #include "drv_log.h"
  17. #include "drv_pwm.h"
  18. #include "fio_mux.h"
  19. #include "fpwm.h"
  20. #ifdef RT_USING_SMART
  21. #include <ioremap.h>
  22. #endif
  23. struct phytium_pwm
  24. {
  25. const char *name;
  26. FPwmCtrl pwm_handle;
  27. struct rt_device_pwm device; /* inherit from can device */
  28. };
  29. static rt_err_t drv_pwm_config(struct phytium_pwm *pwm_dev)
  30. {
  31. RT_ASSERT(pwm_dev);
  32. u32 ret;
  33. FPwmConfig config;
  34. FPwmCtrl *pwm_handle = &pwm_dev->pwm_handle;
  35. FIOPadSetPwmMux(pwm_handle->config.instance_id, 0);
  36. FIOPadSetPwmMux(pwm_handle->config.instance_id, 1);
  37. config = *FPwmLookupConfig(pwm_handle->config.instance_id);
  38. #ifdef RT_USING_SMART
  39. config.lsd_config_addr = (uintptr)rt_ioremap((void *)config.lsd_config_addr, 0x100);
  40. config.pwm_base_addr = (uintptr)rt_ioremap((void *)config.pwm_base_addr, 0x1000);
  41. config.db_base_addr = (uintptr)rt_ioremap((void *)config.db_base_addr, 0x100);
  42. #endif
  43. ret = FPwmCfgInitialize(pwm_handle, &config);
  44. if (ret != FPWM_SUCCESS)
  45. {
  46. LOG_E("Pwm config init failed.\n");
  47. return -RT_ERROR;
  48. }
  49. return RT_EOK;
  50. }
  51. static rt_err_t drv_pwm_enable(struct phytium_pwm *pwm_dev, struct rt_pwm_configuration *configuration, boolean enable_pwm)
  52. {
  53. RT_ASSERT(pwm_dev);
  54. RT_ASSERT(configuration);
  55. u32 channel = configuration->channel;
  56. if (enable_pwm == RT_TRUE)
  57. {
  58. FPwmEnable(&pwm_dev->pwm_handle, channel);
  59. }
  60. else
  61. {
  62. FPwmDisable(&pwm_dev->pwm_handle, channel);
  63. }
  64. return RT_EOK;
  65. }
  66. static rt_err_t drv_pwm_set(struct phytium_pwm *pwm_dev, int cmd, struct rt_pwm_configuration *configuration)
  67. {
  68. RT_ASSERT(pwm_dev);
  69. RT_ASSERT(configuration);
  70. u32 ret;
  71. FPwmVariableConfig pwm_cfg;
  72. u32 channel = configuration->channel;
  73. rt_memset(&pwm_cfg, 0, sizeof(pwm_cfg));
  74. pwm_cfg.tim_ctrl_mode = FPWM_MODULO;
  75. pwm_cfg.tim_ctrl_div = 50 - 1;
  76. /* Precision set to microseconds */
  77. switch (cmd)
  78. {
  79. case PWM_CMD_SET:
  80. pwm_cfg.pwm_period = configuration->period / 1000;
  81. pwm_cfg.pwm_pulse = configuration->pulse / 1000;
  82. break;
  83. case PWM_CMD_SET_PERIOD:
  84. pwm_cfg.pwm_period = configuration->period / 1000;
  85. break;
  86. case PWM_CMD_SET_PULSE:
  87. pwm_cfg.pwm_pulse = configuration->pulse / 1000;
  88. break;
  89. }
  90. /* Can be modified according to function */
  91. pwm_cfg.pwm_mode = FPWM_OUTPUT_COMPARE;
  92. pwm_cfg.pwm_polarity = FPWM_POLARITY_NORMAL;
  93. pwm_cfg.pwm_duty_source_mode = FPWM_DUTY_CCR;
  94. FPwmDisable(&pwm_dev->pwm_handle, channel);
  95. ret = FPwmVariableSet(&pwm_dev->pwm_handle, channel, &pwm_cfg);
  96. if (ret != FPWM_SUCCESS)
  97. {
  98. LOG_E("Pwm variable set failed.\n");
  99. return -RT_ERROR;
  100. }
  101. FPwmEnable(&pwm_dev->pwm_handle, channel);
  102. return RT_EOK;
  103. }
  104. static rt_err_t drv_pwm_get(struct phytium_pwm *pwm_dev, struct rt_pwm_configuration *configuration)
  105. {
  106. RT_ASSERT(pwm_dev);
  107. RT_ASSERT(configuration);
  108. FPwmVariableConfig pwm_cfg;
  109. u32 channel = configuration->channel;
  110. rt_memset(&pwm_cfg, 0, sizeof(pwm_cfg));
  111. FPwmVariableGet(&pwm_dev->pwm_handle, channel, &pwm_cfg);
  112. configuration->period = pwm_cfg.pwm_period * 1000;
  113. configuration->pulse = pwm_cfg.pwm_pulse * 1000;
  114. LOG_D("period = %d\n, pulse = %d\n", configuration->period, configuration->pulse);
  115. return RT_EOK;
  116. }
  117. static rt_err_t drv_pwm_set_dead_time(struct phytium_pwm *pwm_dev, struct rt_pwm_configuration *configuration)
  118. {
  119. RT_ASSERT(pwm_dev);
  120. RT_ASSERT(configuration);
  121. u32 ret;
  122. FPwmDbVariableConfig db_cfg;
  123. u32 channel = configuration->channel;
  124. rt_memset(&db_cfg, 0, sizeof(db_cfg));
  125. db_cfg.db_rise_cycle = configuration->dead_time / 1000;
  126. db_cfg.db_fall_cycle = configuration->dead_time / 1000;
  127. db_cfg.db_polarity_sel = FPWM_DB_AH;
  128. db_cfg.db_in_mode = FPWM_DB_IN_MODE_PWM0;
  129. db_cfg.db_out_mode = FPWM_DB_OUT_MODE_ENABLE_RISE_FALL;
  130. FPwmDisable(&pwm_dev->pwm_handle, channel);
  131. ret = FPwmDbVariableSet(&pwm_dev->pwm_handle, &db_cfg);
  132. if (ret != FPWM_SUCCESS)
  133. {
  134. LOG_E("FPwmDbVariableSet failed.");
  135. return -RT_ERROR;
  136. }
  137. FPwmEnable(&pwm_dev->pwm_handle, channel);
  138. return RT_EOK;
  139. }
  140. static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  141. {
  142. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  143. struct phytium_pwm *pwm_dev;
  144. pwm_dev = (struct phytium_pwm *)(device->parent.user_data);
  145. switch (cmd)
  146. {
  147. case PWM_CMD_ENABLE:
  148. return drv_pwm_enable(pwm_dev, configuration, RT_TRUE);
  149. case PWM_CMD_DISABLE:
  150. return drv_pwm_enable(pwm_dev, configuration, RT_FALSE);
  151. case PWM_CMD_SET:
  152. return drv_pwm_set(pwm_dev, PWM_CMD_SET, configuration);
  153. case PWM_CMD_GET:
  154. return drv_pwm_get(pwm_dev, configuration);
  155. case PWM_CMD_SET_DEAD_TIME:
  156. return drv_pwm_set_dead_time(pwm_dev, configuration);
  157. case PWM_CMD_SET_PERIOD:
  158. return drv_pwm_set(pwm_dev, PWM_CMD_SET_PERIOD, configuration);
  159. case PWM_CMD_SET_PULSE:
  160. return drv_pwm_set(pwm_dev, PWM_CMD_SET_PULSE, configuration);
  161. default:
  162. return -RT_EINVAL;
  163. }
  164. }
  165. static const struct rt_pwm_ops _pwm_ops =
  166. {
  167. _pwm_control,
  168. };
  169. static rt_err_t pwm_controller_init(struct phytium_pwm *pwm_dev)
  170. {
  171. u32 ret = RT_EOK;
  172. ret = drv_pwm_config(pwm_dev);
  173. if (ret != FPWM_SUCCESS)
  174. {
  175. LOG_E("Pwm config failed.\n");
  176. return -RT_ERROR;
  177. }
  178. ret = rt_device_pwm_register(&pwm_dev->device,
  179. pwm_dev->name,
  180. &_pwm_ops,
  181. pwm_dev);
  182. RT_ASSERT(ret == RT_EOK);
  183. return ret;
  184. }
  185. #if defined(RT_USING_PWM0)
  186. static struct phytium_pwm pwm0_dev;
  187. #endif
  188. #if defined(RT_USING_PWM1)
  189. static struct phytium_pwm pwm1_dev;
  190. #endif
  191. #if defined(RT_USING_PWM2)
  192. static struct phytium_pwm pwm2_dev;
  193. #endif
  194. #if defined(RT_USING_PWM3)
  195. static struct phytium_pwm pwm3_dev;
  196. #endif
  197. #if defined(RT_USING_PWM4)
  198. static struct phytium_pwm pwm4_dev;
  199. #endif
  200. #if defined(RT_USING_PWM5)
  201. static struct phytium_pwm pwm5_dev;
  202. #endif
  203. #if defined(RT_USING_PWM6)
  204. static struct phytium_pwm pwm6_dev;
  205. #endif
  206. #if defined(RT_USING_PWM7)
  207. static struct phytium_pwm pwm7_dev;
  208. #endif
  209. int rt_hw_pwm_init(void)
  210. {
  211. #if defined(RT_USING_PWM0)
  212. pwm0_dev.name = "PWM0";
  213. pwm0_dev.pwm_handle.config.instance_id = FPWM0_ID;
  214. pwm_controller_init(&pwm0_dev);
  215. #endif
  216. #if defined(RT_USING_PWM1)
  217. pwm1_dev.name = "PWM1";
  218. pwm1_dev.pwm_handle.config.instance_id = FPWM1_ID;
  219. pwm_controller_init(&pwm1_dev);
  220. #endif
  221. #if defined(RT_USING_PWM2)
  222. pwm2_dev.name = "PWM2";
  223. pwm2_dev.pwm_handle.config.instance_id = FPWM2_ID;
  224. pwm_controller_init(&pwm2_dev);
  225. #endif
  226. #if defined(RT_USING_PWM3)
  227. pwm3_dev.name = "PWM3";
  228. pwm3_dev.pwm_handle.config.instance_id = FPWM3_ID;
  229. pwm_controller_init(&pwm3_dev);
  230. #endif
  231. #if defined(RT_USING_PWM4)
  232. pwm4_dev.name = "PWM4";
  233. pwm4_dev.pwm_handle.config.instance_id = FPWM4_ID;
  234. pwm_controller_init(&pwm4_dev);
  235. #endif
  236. #if defined(RT_USING_PWM5)
  237. pwm5_dev.name = "PWM5";
  238. pwm5_dev.pwm_handle.config.instance_id = FPWM5_ID;
  239. pwm_controller_init(&pwm5_dev);
  240. #endif
  241. #if defined(RT_USING_PWM6)
  242. pwm6_dev.name = "PWM6";
  243. pwm6_dev.pwm_handle.config.instance_id = FPWM6_ID;
  244. pwm_controller_init(&pwm6_dev);
  245. #endif
  246. #if defined(RT_USING_PWM7)
  247. pwm7_dev.name = "PWM7";
  248. pwm7_dev.pwm_handle.config.instance_id = FPWM7_ID;
  249. pwm_controller_init(&pwm7_dev);
  250. #endif
  251. return 0;
  252. }
  253. INIT_DEVICE_EXPORT(rt_hw_pwm_init);