123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /*
- * Copyright (c) 2006-2024, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024/02/19 flyingcys first version
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "drv_pwm.h"
- #include "drv_pinmux.h"
- #include "drv_ioremap.h"
- #define DBG_LEVEL DBG_LOG
- #include <rtdbg.h>
- #define LOG_TAG "DRV.PWM"
- struct cvi_pwm_dev
- {
- struct rt_device_pwm device;
- const char *name;
- rt_ubase_t reg_base;
- };
- static const uint64_t count_unit = 100000000; // 100M count per second
- static const uint64_t NSEC_COUNT = 1000000000; // ns
- static void cvi_pwm_set_config(rt_ubase_t reg_base, struct rt_pwm_configuration *cfg)
- {
- unsigned long long duty_clk, period_clk;
- cvi_pwm_set_polarity_high_ch(reg_base, (cfg->channel & PWM_MAX_CH));
- duty_clk = (cfg->pulse * count_unit) / NSEC_COUNT;
- cvi_pwm_set_high_period_ch(reg_base, (cfg->channel & PWM_MAX_CH), duty_clk);
- period_clk = (cfg->period * count_unit) / NSEC_COUNT;
- cvi_pwm_set_period_ch(reg_base, (cfg->channel & PWM_MAX_CH), period_clk);
- cvi_pwm_output_en_ch(reg_base, cfg->channel & PWM_MAX_CH);
- }
- static void cvi_pwm_get_config(rt_ubase_t reg_base, struct rt_pwm_configuration *cfg)
- {
- unsigned long long duty_clk, period_clk;
- duty_clk = cvi_pwm_get_high_period_ch(reg_base, (cfg->channel & PWM_MAX_CH));
- cfg->pulse = duty_clk * NSEC_COUNT / count_unit;
- period_clk = cvi_pwm_get_period_ch(reg_base, (cfg->channel & PWM_MAX_CH));
- cfg->period = period_clk * NSEC_COUNT / count_unit;
- }
- static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
- {
- struct rt_pwm_configuration *cfg = (struct rt_pwm_configuration *)arg;
- struct cvi_pwm_dev *pwm_dev = (struct cvi_pwm_dev *)device->parent.user_data;
- unsigned long long duty_clk, period_clk;
- const uint64_t count_unit = 100000000; // 100M count per second
- const uint64_t NSEC_COUNT = 1000000000; // ns
- if (cfg->channel >= PWM_CHANNEL_NUM)
- return -RT_EINVAL;
- switch (cmd)
- {
- case PWM_CMD_ENABLE:
- cvi_pwm_start_en_ch(pwm_dev->reg_base, cfg->channel & PWM_MAX_CH);
- break;
- case PWM_CMD_DISABLE:
- cvi_pwm_start_dis_ch(pwm_dev->reg_base, cfg->channel & PWM_MAX_CH);
- break;
- case PWM_CMD_SET:
- cvi_pwm_set_config(pwm_dev->reg_base, cfg);
- break;
- case PWM_CMD_GET:
- cvi_pwm_get_config(pwm_dev->reg_base, cfg);
- break;
- case PWM_CMD_SET_PERIOD:
- period_clk = (cfg->period * count_unit) / NSEC_COUNT;
- cvi_pwm_set_period_ch(pwm_dev->reg_base, (cfg->channel & PWM_MAX_CH), period_clk);
- break;
- case PWM_CMD_SET_PULSE:
- duty_clk = (cfg->pulse * count_unit) / NSEC_COUNT;
- cvi_pwm_set_high_period_ch(pwm_dev->reg_base, (cfg->channel & PWM_MAX_CH), duty_clk);
- break;
- default:
- LOG_D("cmd: %x channel: %d period: %d pulse: %d", cmd, cfg->channel, cfg->period, cfg->pulse);
- break;
- }
- return RT_EOK;
- }
- const static struct rt_pwm_ops cvi_pwm_ops =
- {
- .control = &_pwm_control
- };
- static struct cvi_pwm_dev cvi_pwm[] =
- {
- #ifdef BSP_USING_PWM0
- {
- .name = "pwm0",
- .reg_base = CVI_PWM0_BASE,
- },
- #endif
- #ifdef BSP_USING_PWM1
- {
- .name = "pwm1",
- .reg_base = CVI_PWM1_BASE,
- },
- #endif
- #ifdef BSP_USING_PWM2
- {
- .name = "pwm2",
- .reg_base = CVI_PWM2_BASE,
- },
- #endif
- #ifdef BSP_USING_PWM3
- {
- .name = "pwm3",
- .reg_base = CVI_PWM3_BASE,
- },
- #endif
- };
- #if defined(BOARD_TYPE_MILKV_DUO)
- #ifdef BSP_USING_PWM0
- static const char *pinname_whitelist_pwm0[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm1[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm2[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm3[] = {
- NULL,
- };
- #endif
- #ifdef BSP_USING_PWM1
- static const char *pinname_whitelist_pwm4[] = {
- "SD1_D3",
- "UART0_TX",
- NULL,
- };
- static const char *pinname_whitelist_pwm5[] = {
- "SD1_D2",
- "UART0_RX",
- NULL,
- };
- static const char *pinname_whitelist_pwm6[] = {
- "SD1_D1",
- NULL,
- };
- static const char *pinname_whitelist_pwm7[] = {
- "SD1_D0",
- NULL,
- };
- #endif
- #ifdef BSP_USING_PWM2
- static const char *pinname_whitelist_pwm8[] = {
- "SD1_CMD",
- NULL,
- };
- static const char *pinname_whitelist_pwm9[] = {
- "SD1_CLK",
- NULL,
- };
- static const char *pinname_whitelist_pwm10[] = {
- "SD1_GPIO1",
- NULL,
- };
- static const char *pinname_whitelist_pwm11[] = {
- "SD1_GPIO0",
- NULL,
- };
- #endif
- #ifdef BSP_USING_PWM3
- static const char *pinname_whitelist_pwm12[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm13[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm14[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm15[] = {
- NULL,
- };
- #endif
- #elif defined(BOARD_TYPE_MILKV_DUO256M)
- #ifdef BSP_USING_PWM0
- static const char *pinname_whitelist_pwm0[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm1[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm2[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm3[] = {
- NULL,
- };
- #endif
- #ifdef BSP_USING_PWM1
- static const char *pinname_whitelist_pwm4[] = {
- "SD1_D3",
- "UART0_TX",
- NULL,
- };
- static const char *pinname_whitelist_pwm5[] = {
- "SD1_D2",
- "UART0_RX",
- NULL,
- };
- static const char *pinname_whitelist_pwm6[] = {
- "JTAG_CPU_TCK",
- "SD1_D1",
- NULL,
- };
- static const char *pinname_whitelist_pwm7[] = {
- "JTAG_CPU_TMS",
- "SD1_D0",
- NULL,
- };
- #endif
- #ifdef BSP_USING_PWM2
- static const char *pinname_whitelist_pwm8[] = {
- "SD1_CMD",
- NULL,
- };
- static const char *pinname_whitelist_pwm9[] = {
- "SD1_CLK",
- NULL,
- };
- static const char *pinname_whitelist_pwm10[] = {
- "PAD_MIPI_TXM1",
- NULL,
- };
- static const char *pinname_whitelist_pwm11[] = {
- "PAD_MIPI_TXP1",
- NULL,
- };
- #endif
- #ifdef BSP_USING_PWM3
- static const char *pinname_whitelist_pwm12[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm13[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm14[] = {
- NULL,
- };
- static const char *pinname_whitelist_pwm15[] = {
- NULL,
- };
- #endif
- #else
- #error "Unsupported board type!"
- #endif
- static void rt_hw_pwm_pinmux_config()
- {
- #ifdef BSP_USING_PWM0
- pinmux_config(BSP_PWM0_0_PINNAME, PWM_0, pinname_whitelist_pwm0);
- pinmux_config(BSP_PWM0_1_PINNAME, PWM_1, pinname_whitelist_pwm1);
- pinmux_config(BSP_PWM0_2_PINNAME, PWM_2, pinname_whitelist_pwm2);
- pinmux_config(BSP_PWM0_3_PINNAME, PWM_3, pinname_whitelist_pwm3);
- #endif /* BSP_USING_PWM0 */
- #ifdef BSP_USING_PWM1
- pinmux_config(BSP_PWM1_4_PINNAME, PWM_4, pinname_whitelist_pwm4);
- pinmux_config(BSP_PWM1_5_PINNAME, PWM_5, pinname_whitelist_pwm5);
- pinmux_config(BSP_PWM1_6_PINNAME, PWM_6, pinname_whitelist_pwm6);
- pinmux_config(BSP_PWM1_7_PINNAME, PWM_7, pinname_whitelist_pwm7);
- #endif /* BSP_USING_PWM1 */
- #ifdef BSP_USING_PWM2
- pinmux_config(BSP_PWM2_8_PINNAME, PWM_8, pinname_whitelist_pwm8);
- pinmux_config(BSP_PWM2_9_PINNAME, PWM_9, pinname_whitelist_pwm9);
- pinmux_config(BSP_PWM2_10_PINNAME, PWM_10, pinname_whitelist_pwm10);
- pinmux_config(BSP_PWM2_11_PINNAME, PWM_11, pinname_whitelist_pwm11);
- #endif /* BSP_USING_PWM2 */
- #ifdef BSP_USING_PWM3
- pinmux_config(BSP_PWM3_12_PINNAME, PWM_12, pinname_whitelist_pwm12);
- pinmux_config(BSP_PWM3_13_PINNAME, PWM_13, pinname_whitelist_pwm13);
- pinmux_config(BSP_PWM3_14_PINNAME, PWM_14, pinname_whitelist_pwm14);
- pinmux_config(BSP_PWM3_15_PINNAME, PWM_15, pinname_whitelist_pwm15);
- #endif /* BSP_USING_PWM3 */
- }
- int rt_hw_pwm_init(void)
- {
- int result = RT_EOK;
- uint8_t i;
- rt_hw_pwm_pinmux_config();
- for (i = 0; i < sizeof(cvi_pwm) / sizeof(cvi_pwm[0]); i++)
- {
- cvi_pwm[i].device.base = (rt_ubase_t)DRV_IOREMAP((void *)cvi_pwm[i].device.base, 0x1000);
- result = rt_device_pwm_register(&cvi_pwm[i].device, cvi_pwm[i].name, &cvi_pwm_ops, &cvi_pwm[i]);
- if (result != RT_EOK)
- {
- LOG_E("device %s register failed", cvi_pwm[i].name);
- return -RT_ERROR;
- }
- }
- return RT_EOK;
- }
- INIT_DEVICE_EXPORT(rt_hw_pwm_init);
|