drv_pwm.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. 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. u32 ret;
  109. FPwmVariableConfig pwm_cfg;
  110. u32 channel = configuration->channel;
  111. memset(&pwm_cfg, 0, sizeof(pwm_cfg));
  112. ret = FPwmVariableGet(&pwm_dev->pwm_handle, channel, &pwm_cfg);
  113. if (ret != FPWM_SUCCESS)
  114. {
  115. LOG_E("Pwm variable get failed.\n");
  116. return -RT_ERROR;
  117. }
  118. configuration->period = pwm_cfg.pwm_period * 1000;
  119. configuration->pulse = pwm_cfg.pwm_pulse * 1000;
  120. LOG_D("period = %d\n, pulse = %d\n", configuration->period, configuration->pulse);
  121. return RT_EOK;
  122. }
  123. static rt_err_t drv_pwm_set_dead_time(struct phytium_pwm *pwm_dev, struct rt_pwm_configuration *configuration)
  124. {
  125. RT_ASSERT(pwm_dev);
  126. RT_ASSERT(configuration);
  127. u32 ret;
  128. FPwmDbVariableConfig db_cfg;
  129. u32 channel = configuration->channel;
  130. memset(&db_cfg, 0, sizeof(db_cfg));
  131. db_cfg.db_rise_cycle = configuration->dead_time / 1000;
  132. db_cfg.db_fall_cycle = configuration->dead_time / 1000;
  133. db_cfg.db_polarity_sel = FPWM_DB_AH;
  134. db_cfg.db_in_mode = FPWM_DB_IN_MODE_PWM0;
  135. db_cfg.db_out_mode = FPWM_DB_OUT_MODE_ENABLE_RISE_FALL;
  136. FPwmDisable(&pwm_dev->pwm_handle, channel);
  137. ret = FPwmDbVariableSet(&pwm_dev->pwm_handle, &db_cfg);
  138. if (ret != FPWM_SUCCESS)
  139. {
  140. LOG_E("FPwmDbVariableSet failed.");
  141. return -RT_ERROR;
  142. }
  143. FPwmEnable(&pwm_dev->pwm_handle, channel);
  144. return RT_EOK;
  145. }
  146. static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  147. {
  148. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  149. struct phytium_pwm *pwm_dev;
  150. pwm_dev = (struct phytium_pwm *)(device->parent.user_data);
  151. switch (cmd)
  152. {
  153. case PWM_CMD_ENABLE:
  154. return drv_pwm_enable(pwm_dev, configuration, RT_TRUE);
  155. case PWM_CMD_DISABLE:
  156. return drv_pwm_enable(pwm_dev, configuration, RT_FALSE);
  157. case PWM_CMD_SET:
  158. return drv_pwm_set(pwm_dev, PWM_CMD_SET, configuration);
  159. case PWM_CMD_GET:
  160. return drv_pwm_get(pwm_dev, configuration);
  161. case PWM_CMD_SET_DEAD_TIME:
  162. return drv_pwm_set_dead_time(pwm_dev, configuration);
  163. case PWM_CMD_SET_PERIOD:
  164. return drv_pwm_set(pwm_dev, PWM_CMD_SET_PERIOD, configuration);
  165. case PWM_CMD_SET_PULSE:
  166. return drv_pwm_set(pwm_dev, PWM_CMD_SET_PULSE, configuration);
  167. default:
  168. return -RT_EINVAL;
  169. }
  170. }
  171. static const struct rt_pwm_ops _pwm_ops =
  172. {
  173. _pwm_control,
  174. };
  175. static rt_err_t pwm_controller_init(struct phytium_pwm *pwm_dev)
  176. {
  177. u32 ret = RT_EOK;
  178. ret = drv_pwm_config(pwm_dev);
  179. if (ret != FPWM_SUCCESS)
  180. {
  181. LOG_E("Pwm config failed.\n");
  182. return -RT_ERROR;
  183. }
  184. ret = rt_device_pwm_register(&pwm_dev->device,
  185. pwm_dev->name,
  186. &_pwm_ops,
  187. pwm_dev);
  188. RT_ASSERT(ret == RT_EOK);
  189. return ret;
  190. }
  191. #if defined(RT_USING_PWM0)
  192. static struct phytium_pwm pwm0_dev;
  193. #endif
  194. #if defined(RT_USING_PWM1)
  195. static struct phytium_pwm pwm1_dev;
  196. #endif
  197. #if defined(RT_USING_PWM2)
  198. static struct phytium_pwm pwm2_dev;
  199. #endif
  200. #if defined(RT_USING_PWM3)
  201. static struct phytium_pwm pwm3_dev;
  202. #endif
  203. #if defined(RT_USING_PWM4)
  204. static struct phytium_pwm pwm4_dev;
  205. #endif
  206. #if defined(RT_USING_PWM5)
  207. static struct phytium_pwm pwm5_dev;
  208. #endif
  209. #if defined(RT_USING_PWM6)
  210. static struct phytium_pwm pwm6_dev;
  211. #endif
  212. #if defined(RT_USING_PWM7)
  213. static struct phytium_pwm pwm7_dev;
  214. #endif
  215. int rt_hw_pwm_init(void)
  216. {
  217. #if defined(RT_USING_PWM0)
  218. pwm0_dev.name = "PWM0";
  219. pwm0_dev.pwm_handle.config.instance_id = FPWM0_ID;
  220. pwm_controller_init(&pwm0_dev);
  221. #endif
  222. #if defined(RT_USING_PWM1)
  223. pwm1_dev.name = "PWM1";
  224. pwm1_dev.pwm_handle.config.instance_id = FPWM1_ID;
  225. pwm_controller_init(&pwm1_dev);
  226. #endif
  227. #if defined(RT_USING_PWM2)
  228. pwm2_dev.name = "PWM2";
  229. pwm2_dev.pwm_handle.config.instance_id = FPWM2_ID;
  230. pwm_controller_init(&pwm2_dev);
  231. #endif
  232. #if defined(RT_USING_PWM3)
  233. pwm3_dev.name = "PWM3";
  234. pwm3_dev.pwm_handle.config.instance_id = FPWM3_ID;
  235. pwm_controller_init(&pwm3_dev);
  236. #endif
  237. #if defined(RT_USING_PWM4)
  238. pwm4_dev.name = "PWM4";
  239. pwm4_dev.pwm_handle.config.instance_id = FPWM4_ID;
  240. pwm_controller_init(&pwm4_dev);
  241. #endif
  242. #if defined(RT_USING_PWM5)
  243. pwm5_dev.name = "PWM5";
  244. pwm5_dev.pwm_handle.config.instance_id = FPWM5_ID;
  245. pwm_controller_init(&pwm5_dev);
  246. #endif
  247. #if defined(RT_USING_PWM6)
  248. pwm6_dev.name = "PWM6";
  249. pwm6_dev.pwm_handle.config.instance_id = FPWM6_ID;
  250. pwm_controller_init(&pwm6_dev);
  251. #endif
  252. #if defined(RT_USING_PWM7)
  253. pwm7_dev.name = "PWM7";
  254. pwm7_dev.pwm_handle.config.instance_id = FPWM7_ID;
  255. pwm_controller_init(&pwm7_dev);
  256. #endif
  257. return 0;
  258. }
  259. INIT_DEVICE_EXPORT(rt_hw_pwm_init);