/* * Copyright (c) Hisilicon Technologies Co., Ltd.. 2021-2021. All rights reserved. * Description: pwm driver for reserved17/reserved19 chip. * Author: * Create: 2021-05-12 * Note: */ /******************************************************************************/ /* Includes */ /******************************************************************************/ #include "osal_ext.h" #include "drv_mem_ext.h" #include "soc_module.h" #include "pwm_common.h" #include "pwm_v3.h" /******************************************************************************/ /* Structure */ /******************************************************************************/ typedef union { struct { td_u32 gpio_dir : 8; } bits; td_u32 u32; } _gpio_pwm_dir_v3; typedef union { struct { td_u32 reserved : 2; td_u32 period : 30; } bits; td_u32 u32; } _gpio_pwm_cfg_v3; typedef union { struct { td_u32 enable : 1; td_u32 inv : 1; td_u32 duty : 30; } bits; td_u32 u32; } _gpio_pwm_ctrl_v3; typedef union { struct { td_u32 period : 30; td_u32 reserved : 2; } bits; td_u32 u32; } _gpio_pwm_state0_v3; typedef union { struct { td_u32 duty : 30; td_u32 reserved : 2; } bits; td_u32 u32; } _gpio_pwm_state1_v3; typedef union { struct { td_u32 reserved : 4; td_u32 period : 28; } bits; td_u32 u32; } _led_pwm_cfg_v3; typedef union { struct { td_u32 enable : 1; td_u32 inv : 1; td_u32 reserved : 2; td_u32 duty : 28; } bits; td_u32 u32; } _led_pwm_ctrl_v3; typedef union { struct { td_u32 period : 28; td_u32 reserved : 4; } bits; td_u32 u32; } _led_pwm_state0_v3; typedef union { struct { td_u32 duty : 28; td_u32 reserved : 4; } bits; td_u32 u32; } _led_pwm_state1_v3; /* pwm num : 21 led_pwm num : 1 */ typedef struct { td_u32 gpio_pwm_addr_space_size; /* 0x1000 */ td_u8 **gpio_pwm_base_addr; td_u32 gpio_pwm_clk_freq; /* 54MHz */ td_u16 gpio_pwm_group_num; /* 21 */ td_u16 gpio_pwm_bit_num; /* 8 */ td_u16 gpio_pwm_offset_dir; /* 0x400 */ td_u16 gpio_pwm_reg_start; /* 0x800 */ td_u16 gpio_pwm_reg_offset; /* 0x10 */ td_u32 led_pwm_phy_addr; /* 0xF800A000 */ td_u32 led_pwm_addr_space_size; /* 0x1000 */ volatile td_void *led_pwm_base_addr; td_u32 led_pwm_clk_freq; /* 24MHz */ td_u16 led_pwm_num; /* 1 */ td_u32 pwm_freq_critical; /* 10Hz */ td_u16 offset_cfg; /* 0x0 */ td_u16 offset_ctrl; /* 0x4 */ td_u16 offset_state0_period; /* 0x8 */ td_u16 offset_state1_duty; /* 0xC */ } pwm_info_v3; /******************************************************************************/ /* Globals */ /******************************************************************************/ static pwm_info_v3 g_pwm_info_v3 = {0}; /******************************************************************************* Function Implementation *******************************************************************************/ // 0xF8B20000, /* GPIO_PWM 0 */ // 0xF8B21000, /* GPIO_PWM 1 */ // 0xF8B22000, /* GPIO_PWM 2 */ // 0xF8B23000, /* GPIO_PWM 3 */ // 0xF8B24000, /* GPIO_PWM 4 */ // 0xF8B25000, /* GPIO_PWM 5 */ // 0xF8B26000, /* GPIO_PWM 6 */ // 0xF8B27000, /* GPIO_PWM 7 */ // 0xF8B28000, /* GPIO_PWM 8 */ // 0xF8B29000, /* GPIO_PWM 9 */ // 0xF8B2A000, /* GPIO_PWM 10 */ // 0xF8B2B000, /* GPIO_PWM 11 */ // 0xF8B2C000, /* GPIO_PWM 12 */ // 0xF8B2D000, /* GPIO_PWM 13 */ // 0xF8B2E000, /* GPIO_PWM 14 */ // 0xF8B2F000, /* GPIO_PWM 15 */ // /* GPIO_PWM 16 UNUSED !!! */ // /* GPIO_PWM 17 UNUSED !!! */ // 0xF8004000, /* STB_GPIO_PWM 18 */ /* STB_GPIO_PWM 18 is named gpio16 in dts */ // 0xF8009000, /* STB_GPIO_PWM 19 */ /* STB_GPIO_PWM 19 is named gpio17 in dts */ // 0xF800B000, /* STB_GPIO_PWM 20 */ /* STB_GPIO_PWM 20 is named gpio18 in dts */ // 0xF800C000, /* STB_GPIO_PWM 21 */ /* STB_GPIO_PWM 21 is named gpio19 in dts */ // 0xF8036000, /* STB_GPIO_PWM 22 */ /* STB_GPIO_PWM 22 is named gpio20 in dts */ static td_s32 _pwm_get_gpio_pwm_reg_addr_v3(td_void) { td_s32 ret, len, i; td_u32 gpio_group_num = 0; td_u32 *gpio_phy_addr = TD_NULL; pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_func_call(ret, osal_dts_get_u32_byname("huanglong,gpioinfo", "groupnum", &gpio_group_num), goto out); v3->gpio_pwm_group_num = gpio_group_num; gpio_phy_addr = (td_u32 *)SOC_KZALLOC(SOC_ID_PWM, sizeof(td_u32) * gpio_group_num, GFP_KERNEL); pwm_check_param(ret, TD_FAILURE, gpio_phy_addr == TD_NULL, goto out); len = osal_dts_get_array_byname("huanglong,gpioinfo", "gpio_addrs", gpio_phy_addr, gpio_group_num); pwm_check_param(ret, TD_FAILURE, len != gpio_group_num, goto free_gpio_phy_addr); v3->gpio_pwm_base_addr = (td_u8 **)SOC_KZALLOC(SOC_ID_PWM, sizeof(td_u8 *) * gpio_group_num, GFP_KERNEL); pwm_check_param(ret, TD_FAILURE, v3->gpio_pwm_base_addr == TD_NULL, goto free_gpio_phy_addr); for (i = 0; i < (td_s32)gpio_group_num; i++) { v3->gpio_pwm_base_addr[i] = (td_u8 *)osal_ioremap_nocache(gpio_phy_addr[i], v3->gpio_pwm_addr_space_size); pwm_check_param(ret, TD_FAILURE, v3->gpio_pwm_base_addr[i] == TD_NULL, goto free_gpio_phy_addr); } free_gpio_phy_addr: SOC_KFREE(SOC_ID_PWM, gpio_phy_addr); gpio_phy_addr = TD_NULL; out: return ret; } static td_s32 _pwm_get_led_pwm_reg_addr_v3(td_void) { td_s32 ret = TD_SUCCESS; pwm_info_v3 *v3 = &g_pwm_info_v3; v3->led_pwm_base_addr = osal_ioremap_nocache(v3->led_pwm_phy_addr, v3->led_pwm_addr_space_size); pwm_check_param(ret, TD_FAILURE, v3->led_pwm_base_addr == TD_NULL, goto out); out: return ret; } static td_s32 _pwm_get_regs_v3(td_u32 pwm_no, pwm_reg_s *reg) { td_s32 ret = TD_SUCCESS; td_u32 group_no, bit_no; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_check_param(ret, TD_FAILURE, reg == TD_NULL, goto out); pwm_func_call(ret, pwm_gpio_convert(pwm_no, v3->gpio_pwm_bit_num, &group_no, &bit_no), goto out); if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ reg->gpio_pwm_direction = (uintptr_t)(v3->gpio_pwm_base_addr[group_no] + v3->gpio_pwm_offset_dir); reg->cfg = (uintptr_t)(v3->gpio_pwm_base_addr[group_no] + v3->gpio_pwm_reg_start + v3->gpio_pwm_reg_offset * bit_no + v3->offset_cfg); reg->ctrl = (uintptr_t)(v3->gpio_pwm_base_addr[group_no] + v3->gpio_pwm_reg_start + v3->gpio_pwm_reg_offset * bit_no + v3->offset_ctrl); reg->state0 = (uintptr_t)(v3->gpio_pwm_base_addr[group_no] + v3->gpio_pwm_reg_start + v3->gpio_pwm_reg_offset * bit_no + v3->offset_state0_period); reg->state1 = (uintptr_t)(v3->gpio_pwm_base_addr[group_no] + v3->gpio_pwm_reg_start + v3->gpio_pwm_reg_offset * bit_no + v3->offset_state1_duty); } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ reg->cfg = (uintptr_t)(v3->led_pwm_base_addr + v3->offset_cfg); reg->ctrl = (uintptr_t)(v3->led_pwm_base_addr + v3->offset_ctrl); reg->state0 = (uintptr_t)(v3->led_pwm_base_addr + v3->offset_state0_period); reg->state1 = (uintptr_t)(v3->led_pwm_base_addr + v3->offset_state1_duty); } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } static td_s32 _pwm_get_freq_v3(td_u32 pwm_no, td_u32 *freq) { td_s32 ret = TD_SUCCESS; pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_check_param(ret, TD_FAILURE, freq == TD_NULL, goto out); if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ *freq = v3->gpio_pwm_clk_freq; } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ *freq = v3->led_pwm_clk_freq; } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } static td_s32 _gpio_pwm_get_state_v3(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr) { td_s32 ret; pwm_reg_s reg = {0}; td_u32 freq; _gpio_pwm_state0_v3 state0; _gpio_pwm_state1_v3 state1; _gpio_pwm_ctrl_v3 ctrl; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_freq_v3(pwm_no, &freq), goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); state0.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.state0); state1.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.state1); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); pwm_func_call(ret, pwm_get_attr(freq, state0.bits.period, state1.bits.duty, ctrl.bits.inv, pwm_attr), goto out); out: return ret; } static td_s32 _led_pwm_get_state_v3(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr) { td_s32 ret; pwm_reg_s reg = {0}; td_u32 freq; _led_pwm_state0_v3 state0; _led_pwm_state1_v3 state1; _led_pwm_ctrl_v3 ctrl; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); pwm_func_call(ret, _pwm_get_freq_v3(pwm_no, &freq), goto out); state0.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.state0); state1.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.state1); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); pwm_func_call(ret, pwm_get_attr(freq, state0.bits.period, state1.bits.duty, ctrl.bits.inv, pwm_attr), goto out); out: return ret; } static td_s32 _gpio_pwm_get_attr_v3(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr) { td_s32 ret; pwm_reg_s reg = {0}; td_u32 freq; _gpio_pwm_cfg_v3 cfg; _gpio_pwm_ctrl_v3 ctrl; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); pwm_func_call(ret, _pwm_get_freq_v3(pwm_no, &freq), goto out); cfg.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.cfg); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); pwm_func_call(ret, pwm_get_attr(freq, cfg.bits.period, ctrl.bits.duty, ctrl.bits.inv, pwm_attr), goto out); out: return ret; } static td_s32 _led_pwm_get_attr_v3(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr) { td_s32 ret; pwm_reg_s reg = {0}; td_u32 freq; _led_pwm_cfg_v3 cfg; _led_pwm_ctrl_v3 ctrl; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); pwm_func_call(ret, _pwm_get_freq_v3(pwm_no, &freq), goto out); cfg.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.cfg); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); pwm_func_call(ret, pwm_get_attr(freq, cfg.bits.period, ctrl.bits.duty, ctrl.bits.inv, pwm_attr), goto out); out: return ret; } static td_s32 _gpio_pwm_set_attr_v3(td_u32 pwm_no, const ext_drv_pwm_attr *pwm_attr) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_reg_s reg = {0}; pwm_info info = {0}; _gpio_pwm_cfg_v3 cfg = { .bits.period = ~0, .u32 = ~0 }; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); pwm_func_call(ret, _pwm_get_freq_v3(pwm_no, &info.pwm_clk_freq), goto out); info.pwm_freq_critical = v3->pwm_freq_critical; info.period_duty_offset = pwm_get_bit_count(cfg.u32) - pwm_get_bit_count(cfg.bits.period); info.pwm_reg = ® info.pwm_attr = pwm_attr; pwm_func_call(ret, pwm_set_attr(&info), goto out); out: return ret; } static td_s32 _led_pwm_set_attr_v3(td_u32 pwm_no, const ext_drv_pwm_attr *pwm_attr) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_reg_s reg = {0}; pwm_info info = {0}; _led_pwm_cfg_v3 cfg = { .bits.period = ~0, .u32 = ~0 }; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); pwm_func_call(ret, _pwm_get_freq_v3(pwm_no, &info.pwm_clk_freq), goto out); info.pwm_freq_critical = v3->pwm_freq_critical; info.period_duty_offset = pwm_get_bit_count(cfg.u32) - pwm_get_bit_count(cfg.bits.period); info.pwm_attr = pwm_attr; info.pwm_reg = ® pwm_func_call(ret, pwm_set_attr(&info), goto out); out: return ret; } static td_s32 _gpio_pwm_set_enable_v3(td_u32 pwm_no, td_bool enable) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_reg_s reg = {0}; _gpio_pwm_dir_v3 dir; _gpio_pwm_ctrl_v3 ctrl; pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); dir.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.gpio_pwm_direction); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); if (enable == TD_TRUE) { /* reserved17 need set dir out */ dir.u32 |= 0x1 << (pwm_no % v3->gpio_pwm_bit_num); } else { dir.u32 &= ~(0x1 << (pwm_no % v3->gpio_pwm_bit_num)); } ctrl.bits.enable = enable; osal_writel(dir.u32, (td_void *)(uintptr_t)reg.gpio_pwm_direction); osal_writel(ctrl.u32, (td_void *)(uintptr_t)reg.ctrl); out: return ret; } static td_s32 _led_pwm_set_enable_v3(td_u32 pwm_no, td_bool enable) { td_s32 ret; pwm_reg_s reg = {0}; _led_pwm_ctrl_v3 ctrl; pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); ctrl.bits.enable = enable; osal_writel(ctrl.u32, (td_void *)(uintptr_t)reg.ctrl); out: return ret; } static td_s32 _gpio_pwm_get_enable_v3(td_u32 pwm_no, td_bool *enable) { td_s32 ret; pwm_reg_s reg = {0}; _gpio_pwm_ctrl_v3 ctrl; pwm_check_param(ret, TD_FAILURE, enable == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); *enable = ctrl.bits.enable; out: return ret; } static td_s32 _led_pwm_get_enable_v3(td_u32 pwm_no, td_bool *enable) { td_s32 ret; pwm_reg_s reg = {0}; _led_pwm_ctrl_v3 ctrl; pwm_check_param(ret, TD_FAILURE, enable == TD_NULL, goto out); pwm_func_call(ret, _pwm_get_regs_v3(pwm_no, ®), goto out); ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl); *enable = ctrl.bits.enable; out: return ret; } td_s32 pwm_deinit_v3(td_void) { pwm_info_v3 *v3 = &g_pwm_info_v3; td_u32 i; if (v3->led_pwm_base_addr != TD_NULL) { osal_iounmap((td_void *)v3->led_pwm_base_addr, OSAL_IOUNMAP_SIZE); v3->led_pwm_base_addr = TD_NULL; } if (v3->gpio_pwm_base_addr != TD_NULL) { for (i = 0; i < v3->gpio_pwm_group_num; i++) { if (v3->gpio_pwm_base_addr[i] != TD_NULL) { osal_iounmap((td_void *)v3->gpio_pwm_base_addr[i], OSAL_IOUNMAP_SIZE); v3->gpio_pwm_base_addr[i] = TD_NULL; } } SOC_KFREE(SOC_ID_PWM, v3->gpio_pwm_base_addr); v3->gpio_pwm_base_addr = TD_NULL; } return TD_SUCCESS; } td_s32 pwm_init_v3(td_void) { td_s32 ret; pwm_info_v3 *v3 = &g_pwm_info_v3; v3->gpio_pwm_addr_space_size = 0x1000; /* gpio pwm addr space size : 0x1000 */ pwm_func_call(ret, _pwm_get_gpio_pwm_reg_addr_v3(), goto deinit); v3->gpio_pwm_clk_freq = 54000000; /* 54000000 MHz */ v3->gpio_pwm_bit_num = 8; /* gpio_pwm_bit_num : 8 */ v3->gpio_pwm_offset_dir = 0x400; /* gpio_pwm_offset_dir : 0x400 */ v3->gpio_pwm_reg_start = 0x800; /* gpio_pwm_reg_start : 0x800 */ v3->gpio_pwm_reg_offset = 0x10; /* gpio_pwm_reg_offset : 0x10 */ v3->led_pwm_phy_addr = 0xF800A000; /* led pwm physical addr : 0xF800A000 */ v3->led_pwm_addr_space_size = 0x1000; /* led pwm addr space size : 0x1000 */ pwm_func_call(ret, _pwm_get_led_pwm_reg_addr_v3(), goto deinit); v3->led_pwm_clk_freq = 24000000; /* 24000000 MHz */ v3->led_pwm_num = 1; /* led_pwm_num : 1 */ v3->pwm_freq_critical = 10; /* 10 Hz */ v3->offset_cfg = 0x0; /* led_pwm_offset_cfg : 0x0 */ v3->offset_ctrl = 0x4; /* led_pwm_offset_ctrl : 0x4 */ v3->offset_state0_period = 0x8; /* led_pwm_offset_state0_period : 0x8 */ v3->offset_state1_duty = 0xC; /* led_pwm_offset_state1_duty : 0xC */ goto out; deinit: pwm_func_call(ret, pwm_deinit_v3(), goto out); out: return ret; } td_s32 pwm_get_state_v3(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ pwm_func_call(ret, _gpio_pwm_get_state_v3(pwm_no, pwm_attr), goto out); } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ pwm_func_call(ret, _led_pwm_get_state_v3(pwm_no, pwm_attr), goto out); } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } td_s32 pwm_get_attr_v3(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ pwm_func_call(ret, _gpio_pwm_get_attr_v3(pwm_no, pwm_attr), goto out); } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ pwm_func_call(ret, _led_pwm_get_attr_v3(pwm_no, pwm_attr), goto out); } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } td_s32 pwm_set_attr_v3(td_u32 pwm_no, const ext_drv_pwm_attr *pwm_attr) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out); if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ pwm_func_call(ret, _gpio_pwm_set_attr_v3(pwm_no, pwm_attr), goto out); } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ pwm_func_call(ret, _led_pwm_set_attr_v3(pwm_no, pwm_attr), goto out); } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } td_s32 pwm_set_enable_v3(td_u32 pwm_no, td_bool enable) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ pwm_func_call(ret, _gpio_pwm_set_enable_v3(pwm_no, enable), goto out); } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ pwm_func_call(ret, _led_pwm_set_enable_v3(pwm_no, enable), goto out); } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } td_s32 pwm_get_enable_v3(td_u32 pwm_no, td_bool *enable) { td_s32 ret; const pwm_info_v3 *v3 = &g_pwm_info_v3; pwm_check_param(ret, TD_FAILURE, enable == TD_NULL, goto out); if (pwm_no < (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no < 168 is gpio pwm */ pwm_func_call(ret, _gpio_pwm_get_enable_v3(pwm_no, enable), goto out); } else if (pwm_no == (v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num)) { /* pwm_no = 168 is led pwm */ pwm_func_call(ret, _led_pwm_get_enable_v3(pwm_no, enable), goto out); } else { soc_log_err("Invalid pwm_no %u for v3! The range is 0~%u\n", pwm_no, v3->gpio_pwm_group_num * v3->gpio_pwm_bit_num); ret = TD_FAILURE; goto out; } out: return ret; } td_s32 pwm_send_signal_v3(td_u32 pwm_no, td_u32 carrier_signal_duration_us, td_u32 low_level_signal_duration_us) { td_s32 ret = TD_SUCCESS; pwm_func_call(ret, pwm_check_carrier_signal_duration_us(carrier_signal_duration_us), goto out); pwm_func_call(ret, pwm_check_low_level_signal_duration_us(low_level_signal_duration_us), goto out); pwm_func_call(ret, pwm_set_enable_v3(pwm_no, TD_TRUE), goto out); pwm_func_call(ret, pwm_output_carrier_signal(carrier_signal_duration_us), goto out); pwm_func_call(ret, pwm_set_enable_v3(pwm_no, TD_FALSE), goto out); pwm_func_call(ret, pwm_output_low_level_signal(low_level_signal_duration_us), goto out); out: return ret; }