You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
519 lines
17 KiB
519 lines
17 KiB
/*
|
|
* Copyright (c) Hisilicon Technologies Co., Ltd.. 2021-2021. All rights reserved.
|
|
* Description: pwm driver for reserved13/reserved9 cs chip.
|
|
* Author:
|
|
* Create: 2021-05-12
|
|
* Note: es chip has no common pwm.
|
|
*/
|
|
|
|
/********************************************************************************************/
|
|
/* Includes */
|
|
/********************************************************************************************/
|
|
#include "osal_ext.h"
|
|
#include "drv_mem_ext.h"
|
|
#include "soc_module.h"
|
|
|
|
#include "pwm_common.h"
|
|
#include "pwm_v1.h"
|
|
|
|
/********************************************************************************************/
|
|
/* Structure */
|
|
/********************************************************************************************/
|
|
typedef union {
|
|
struct {
|
|
td_u32 gpio_dir : 8;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_dir_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 gpio0_pwm_out_en : 1;
|
|
td_u32 gpio1_pwm_out_en : 1;
|
|
td_u32 gpio2_pwm_out_en : 1;
|
|
td_u32 gpio3_pwm_out_en : 1;
|
|
td_u32 gpio4_pwm_out_en : 1;
|
|
td_u32 gpio5_pwm_out_en : 1;
|
|
td_u32 gpio6_pwm_out_en : 1;
|
|
td_u32 gpio7_pwm_out_en : 1;
|
|
td_u32 reserved : 24;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_out_en_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 gpio_pwm_out_en_lock : 1; /* 0: unlock, 1:lock */
|
|
td_u32 reserved : 31;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_out_en_lock_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 reserved : 2;
|
|
td_u32 period : 30;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_cfg_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 enable : 1;
|
|
td_u32 inv : 1;
|
|
td_u32 duty : 30;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_ctrl_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 period : 30;
|
|
td_u32 reserved : 2;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_state0_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 duty : 30;
|
|
td_u32 reserved : 2;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _gpio_pwm_state1_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 reserved : 4;
|
|
td_u32 period : 28;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _moto_pwm_cfg_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 enable : 1;
|
|
td_u32 inv : 1;
|
|
td_u32 reserved : 2;
|
|
td_u32 duty : 28;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _moto_pwm_ctrl_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 cnt : 32;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _moto_pwm_cnt_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 period : 28;
|
|
td_u32 reserved : 4;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _moto_pwm_state0_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 duty : 28;
|
|
td_u32 reserved : 4;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _moto_pwm_state1_v1;
|
|
|
|
typedef union {
|
|
struct {
|
|
td_u32 cnt : 32;
|
|
} bits;
|
|
td_u32 u32;
|
|
} _moto_pwm_state2_v1;
|
|
|
|
/*
|
|
gpio_pwm num : 31 (GPIO0-24 下电区, AON_GPIO0-5 长电区)
|
|
moto_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; /* 24MHz */
|
|
td_u16 gpio_pwm_group_num; /* 31 */
|
|
td_u16 gpio_pwm_bit_num; /* 8 */
|
|
td_u16 gpio_pwm_offset_dir; /* 0x400 */
|
|
td_u16 gpio_pwm_offset_out_en; /* 0x700 */
|
|
td_u16 gpio_pwm_offset_out_en_lock; /* 0x710 */
|
|
td_u16 gpio_pwm_offset_cfg; /* 0x800 */
|
|
td_u16 gpio_pwm_offset_ctrl; /* 0x804 */
|
|
td_u16 gpio_pwm_offset_state0_period; /* 0x808 */
|
|
td_u16 gpio_pwm_offset_state1_duty; /* 0x80C */
|
|
|
|
td_u32 moto_pwm_phy_addr; /* 0x00A18000 */
|
|
td_u32 moto_pwm_addr_space_size; /* 0x1000 */
|
|
volatile td_void *moto_pwm_base_addr;
|
|
td_u32 moto_pwm_clk_freq; /* 24MHz */
|
|
td_u16 moto_pwm_num; /* 1 */
|
|
td_u16 moto_pwm_no; /* 47: GPIO5_7 */
|
|
td_u16 moto_pwm_offset_cfg; /* 0x0 */
|
|
td_u16 moto_pwm_offset_ctrl; /* 0x4 */
|
|
td_u16 moto_pwm_offset_cnt; /* 0x8 */
|
|
td_u16 moto_pwm_offset_state0_period; /* 0xC */
|
|
td_u16 moto_pwm_offset_state1_duty; /* 0x10 */
|
|
td_u16 moto_pwm_offset_state2_cnt; /* 0x14 */
|
|
|
|
td_u32 pwm_freq_critical; /* 10Hz */
|
|
} pwm_info_v1;
|
|
|
|
/********************************************************************************************/
|
|
/* Globals */
|
|
/********************************************************************************************/
|
|
static pwm_info_v1 g_pwm_info_v1 = {0};
|
|
static td_u32 g_gpio_pwm_cfg = 0; /* for fix logic bug can't read the register cfg */
|
|
static td_u32 g_gpio_pwm_ctrl = 0; /* for fix logic bug can't read the registe ctrl */
|
|
|
|
/********************************************************************************************
|
|
Function Implementation
|
|
********************************************************************************************/
|
|
static td_s32 _pwm_get_gpio_pwm_reg_addr_v1(td_void)
|
|
{
|
|
td_s32 ret, len, i;
|
|
td_u32 gpio_group_num = 0;
|
|
td_u32 *gpio_phy_addr = TD_NULL;
|
|
pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
|
|
pwm_func_call(ret, osal_dts_get_u32_byname("huanglong,gpioinfo", "groupnum", &gpio_group_num), goto out);
|
|
v1->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);
|
|
|
|
v1->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, v1->gpio_pwm_base_addr == TD_NULL, goto free_gpio_phy_addr);
|
|
for (i = 0; i < (td_s32)gpio_group_num; i++) {
|
|
v1->gpio_pwm_base_addr[i] = (td_u8 *)osal_ioremap_nocache(gpio_phy_addr[i], v1->gpio_pwm_addr_space_size);
|
|
pwm_check_param(ret, TD_FAILURE, v1->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_moto_pwm_reg_addr_v1(td_void)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
|
|
v1->moto_pwm_base_addr = osal_ioremap_nocache(v1->moto_pwm_phy_addr, v1->moto_pwm_addr_space_size);
|
|
pwm_check_param(ret, TD_FAILURE, v1->moto_pwm_base_addr == TD_NULL, goto out);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 _pwm_get_regs_v1(td_u32 pwm_no, pwm_reg_s *reg)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
td_u32 group_no, bit_no;
|
|
const pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
|
|
pwm_check_param(ret, TD_FAILURE, pwm_no >= (v1->gpio_pwm_group_num * v1->gpio_pwm_bit_num), goto out);
|
|
pwm_check_param(ret, TD_FAILURE, reg == TD_NULL, goto out);
|
|
|
|
pwm_func_call(ret, pwm_gpio_convert(pwm_no, v1->gpio_pwm_bit_num, &group_no, &bit_no), goto out);
|
|
|
|
reg->gpio_pwm_out_en = (uintptr_t)(v1->gpio_pwm_base_addr[group_no] + v1->gpio_pwm_offset_out_en);
|
|
reg->gpio_pwm_direction = (uintptr_t)(v1->gpio_pwm_base_addr[group_no] + v1->gpio_pwm_offset_dir);
|
|
reg->cfg = (uintptr_t)(v1->gpio_pwm_base_addr[group_no] + v1->gpio_pwm_offset_cfg);
|
|
reg->ctrl = (uintptr_t)(v1->gpio_pwm_base_addr[group_no] + v1->gpio_pwm_offset_ctrl);
|
|
reg->state0 = (uintptr_t)(v1->gpio_pwm_base_addr[group_no] + v1->gpio_pwm_offset_state0_period);
|
|
reg->state1 = (uintptr_t)(v1->gpio_pwm_base_addr[group_no] + v1->gpio_pwm_offset_state1_duty);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static td_s32 _pwm_get_freq_v1(td_u32 pwm_no, td_u32 *freq)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
|
|
pwm_check_param(ret, TD_FAILURE, freq == TD_NULL, goto out);
|
|
|
|
*freq = v1->gpio_pwm_clk_freq; /* both of gpio_pwm and moto_pwm's freq is 24MHz */
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
td_s32 pwm_deinit_v1(td_void)
|
|
{
|
|
pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
td_u32 i;
|
|
|
|
if (v1->moto_pwm_base_addr != TD_NULL) {
|
|
osal_iounmap((td_void *)v1->moto_pwm_base_addr, OSAL_IOUNMAP_SIZE);
|
|
v1->moto_pwm_base_addr = TD_NULL;
|
|
}
|
|
|
|
if (v1->gpio_pwm_base_addr != TD_NULL) {
|
|
for (i = 0; i < v1->gpio_pwm_group_num; i++) {
|
|
if (v1->gpio_pwm_base_addr[i] != TD_NULL) {
|
|
osal_iounmap((td_void *)v1->gpio_pwm_base_addr[i], OSAL_IOUNMAP_SIZE);
|
|
v1->gpio_pwm_base_addr[i] = TD_NULL;
|
|
}
|
|
}
|
|
SOC_KFREE(SOC_ID_PWM, v1->gpio_pwm_base_addr);
|
|
v1->gpio_pwm_base_addr = TD_NULL;
|
|
}
|
|
|
|
return TD_SUCCESS;
|
|
}
|
|
|
|
td_s32 pwm_init_v1(td_void)
|
|
{
|
|
td_s32 ret;
|
|
pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
|
|
v1->gpio_pwm_addr_space_size = 0x1000; /* gpio pwm addr space size : 0x1000 */
|
|
pwm_func_call(ret, _pwm_get_gpio_pwm_reg_addr_v1(), goto deinit);
|
|
v1->gpio_pwm_clk_freq = 24000000; /* 24000000 MHz */
|
|
v1->gpio_pwm_bit_num = 8; /* gpio_pwm_bit_num : 8 */
|
|
v1->gpio_pwm_offset_dir = 0x400; /* GPIO_DIR : 0x400 */
|
|
v1->gpio_pwm_offset_out_en = 0x700; /* GPIO_PWM_OUT_EN : 0x700 */
|
|
v1->gpio_pwm_offset_out_en_lock = 0x710; /* GPIO_PWM_OUT_EN_LOCK : 0x710 */
|
|
v1->gpio_pwm_offset_cfg = 0x800; /* PWM0_CFG : 0x800 */
|
|
v1->gpio_pwm_offset_ctrl = 0x804; /* PWM0_CTRL : 0x804 */
|
|
v1->gpio_pwm_offset_state0_period = 0x808; /* PWM0_STAT0 : 0x808 */
|
|
v1->gpio_pwm_offset_state1_duty = 0x80C; /* PWM0_STAT1 : 0x80C */
|
|
|
|
v1->moto_pwm_phy_addr = 0x00A18000; /* moto pwm physical addr : 0x00A18000 */
|
|
v1->moto_pwm_addr_space_size = 0x1000; /* moto pwm addr space size : 0x1000 */
|
|
pwm_func_call(ret, _pwm_get_moto_pwm_reg_addr_v1(), goto deinit);
|
|
v1->moto_pwm_clk_freq = 24000000; /* 24000000 MHz */
|
|
v1->moto_pwm_num = 1; /* moto_pwm_num : 1 */
|
|
v1->moto_pwm_no = 47; /* GPIO5_7 : 47 */
|
|
v1->moto_pwm_offset_cfg = 0x0; /* moto pwm cfg reg offset : 0x0 */
|
|
v1->moto_pwm_offset_ctrl = 0x4; /* moto pwm ctrl reg offset : 0x4 */
|
|
v1->moto_pwm_offset_cnt = 0x8; /* moto pwm cnt reg offset : 0x8 */
|
|
v1->moto_pwm_offset_state0_period = 0xC; /* moto pwm state0 reg offset : 0xC */
|
|
v1->moto_pwm_offset_state1_duty = 0x10; /* moto pwm state1 reg offset : 0x10 */
|
|
v1->moto_pwm_offset_state2_cnt = 0x14; /* moto pwm state2 reg offset : 0x14 */
|
|
|
|
v1->pwm_freq_critical = 10; /* 10 Hz */
|
|
|
|
goto out;
|
|
|
|
deinit:
|
|
pwm_func_call(ret, pwm_deinit_v1(), goto out);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
/* only used for gpio_pwm */
|
|
td_s32 pwm_get_state_v1(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr)
|
|
{
|
|
td_s32 ret;
|
|
pwm_reg_s reg = {0};
|
|
td_u32 freq;
|
|
_gpio_pwm_state0_v1 state0;
|
|
_gpio_pwm_state1_v1 state1;
|
|
_gpio_pwm_ctrl_v1 ctrl;
|
|
|
|
pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out);
|
|
|
|
pwm_func_call(ret, _pwm_get_regs_v1(pwm_no, ®), goto out);
|
|
|
|
pwm_func_call(ret, _pwm_get_freq_v1(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);
|
|
ctrl.u32 = g_gpio_pwm_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;
|
|
}
|
|
|
|
/* only used for gpio_pwm */
|
|
td_s32 pwm_get_attr_v1(td_u32 pwm_no, ext_drv_pwm_attr *pwm_attr)
|
|
{
|
|
td_s32 ret;
|
|
pwm_reg_s reg = {0};
|
|
td_u32 freq;
|
|
_gpio_pwm_cfg_v1 cfg;
|
|
_gpio_pwm_ctrl_v1 ctrl;
|
|
|
|
pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out);
|
|
|
|
pwm_func_call(ret, _pwm_get_regs_v1(pwm_no, ®), goto out);
|
|
|
|
pwm_func_call(ret, _pwm_get_freq_v1(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);
|
|
cfg.u32 = g_gpio_pwm_cfg;
|
|
ctrl.u32 = g_gpio_pwm_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;
|
|
}
|
|
|
|
/* only used for gpio_pwm */
|
|
td_s32 pwm_set_attr_v1(td_u32 pwm_no, const ext_drv_pwm_attr *pwm_attr)
|
|
{
|
|
td_s32 ret;
|
|
const pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
pwm_reg_s reg = {0};
|
|
pwm_info info = {0};
|
|
_gpio_pwm_cfg_v1 pwm_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_v1(pwm_no, ®), goto out);
|
|
|
|
pwm_func_call(ret, _pwm_get_freq_v1(pwm_no, &info.pwm_clk_freq), goto out);
|
|
info.pwm_freq_critical = v1->pwm_freq_critical;
|
|
info.period_duty_offset = pwm_get_bit_count(pwm_cfg.u32) - pwm_get_bit_count(pwm_cfg.bits.period);
|
|
info.pwm_attr = pwm_attr;
|
|
info.pwm_reg = ®
|
|
|
|
pwm_func_call(ret, pwm_set_attr(&info), goto out);
|
|
|
|
g_gpio_pwm_cfg = info.cfg_reg_value;
|
|
g_gpio_pwm_ctrl = info.ctrl_reg_value;
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
/* only used for gpio_pwm */
|
|
td_s32 pwm_set_enable_v1(td_u32 pwm_no, td_bool enable)
|
|
{
|
|
td_s32 ret;
|
|
const pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
pwm_reg_s reg = {0};
|
|
_gpio_pwm_dir_v1 pwm_dir;
|
|
_gpio_pwm_out_en_v1 pwm_out_en;
|
|
_gpio_pwm_ctrl_v1 pwm_ctrl;
|
|
|
|
pwm_func_call(ret, _pwm_get_regs_v1(pwm_no, ®), goto out);
|
|
|
|
pwm_dir.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.gpio_pwm_direction);
|
|
pwm_out_en.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.gpio_pwm_out_en);
|
|
pwm_ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl);
|
|
pwm_ctrl.u32 = g_gpio_pwm_ctrl;
|
|
|
|
if (enable == TD_TRUE) {
|
|
pwm_dir.u32 |= 0x1 << (pwm_no % v1->gpio_pwm_bit_num);
|
|
pwm_out_en.u32 |= 0x1 << (pwm_no % v1->gpio_pwm_bit_num);
|
|
} else {
|
|
pwm_dir.u32 &= ~(0x1 << (pwm_no % v1->gpio_pwm_bit_num));
|
|
pwm_out_en.u32 &= ~(0x1 << (pwm_no % v1->gpio_pwm_bit_num));
|
|
}
|
|
pwm_ctrl.bits.enable = enable;
|
|
|
|
osal_writel(pwm_dir.u32, (td_void *)(uintptr_t)reg.gpio_pwm_direction);
|
|
osal_writel(pwm_out_en.u32, (td_void *)(uintptr_t)reg.gpio_pwm_out_en);
|
|
osal_writel(pwm_ctrl.u32, (td_void *)(uintptr_t)reg.ctrl);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
td_s32 pwm_get_enable_v1(td_u32 pwm_no, td_bool *enable)
|
|
{
|
|
td_s32 ret;
|
|
pwm_reg_s reg = {0};
|
|
_gpio_pwm_ctrl_v1 pwm_ctrl;
|
|
|
|
pwm_check_param(ret, TD_FAILURE, enable == TD_NULL, goto out);
|
|
|
|
pwm_func_call(ret, _pwm_get_regs_v1(pwm_no, ®), goto out);
|
|
|
|
pwm_ctrl.u32 = (uintptr_t)osal_readl((td_void *)(uintptr_t)reg.ctrl);
|
|
|
|
*enable = pwm_ctrl.bits.enable;
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
td_s32 pwm_send_signal_v1(td_u32 pwm_no, td_u32 carrier_signal_duration_us, td_u32 low_level_signal_duration_us)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
const pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
|
|
if (pwm_no == v1->moto_pwm_no) {
|
|
soc_log_info("moto_pwm_num not support pwm_send_signal!\n");
|
|
return 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_v1(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_v1(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;
|
|
}
|
|
|
|
td_s32 pwm_moto_trigger_v1(td_u32 pwm_no, const ext_drv_pwm_attr *pwm_attr, td_u32 time_us)
|
|
{
|
|
td_s32 ret = TD_SUCCESS;
|
|
const pwm_info_v1 *v1 = &g_pwm_info_v1;
|
|
pwm_reg_s reg = {0};
|
|
pwm_info info = {0};
|
|
_moto_pwm_cfg_v1 cfg = {
|
|
.bits.period = ~0,
|
|
.u32 = ~0
|
|
};
|
|
_moto_pwm_ctrl_v1 ctrl;
|
|
_moto_pwm_cnt_v1 cnt;
|
|
|
|
pwm_check_param(ret, TD_FAILURE, pwm_no != v1->moto_pwm_no, goto out);
|
|
pwm_check_param(ret, TD_FAILURE, pwm_attr == TD_NULL, goto out);
|
|
pwm_check_param(ret, TD_FAILURE, pwm_attr->duty_ratio > 1000, goto out); /* 1000:duty_ratio max */
|
|
|
|
reg.cfg = (uintptr_t)(v1->moto_pwm_base_addr + v1->moto_pwm_offset_cfg);
|
|
reg.ctrl = (uintptr_t)(v1->moto_pwm_base_addr + v1->moto_pwm_offset_ctrl);
|
|
reg.cnt = (uintptr_t)(v1->moto_pwm_base_addr + v1->moto_pwm_offset_cnt);
|
|
|
|
info.pwm_clk_freq = v1->moto_pwm_clk_freq;
|
|
info.pwm_freq_critical = v1->pwm_freq_critical;
|
|
info.period_duty_offset = pwm_get_bit_count(cfg.u32) - pwm_get_bit_count(cfg.bits.period);
|
|
info.time_us = time_us;
|
|
info.pwm_attr = pwm_attr;
|
|
info.pwm_reg = ®
|
|
pwm_func_call(ret, pwm_set_attr(&info), goto out);
|
|
|
|
cfg.u32 = info.cfg_reg_value;
|
|
ctrl.u32 = info.ctrl_reg_value;
|
|
cnt.u32 = info.cnt_reg_value;
|
|
|
|
osal_writel(cnt.u32, (td_void *)(uintptr_t)reg.cnt);
|
|
|
|
cfg.u32 = 0;
|
|
ctrl.bits.enable = 1;
|
|
osal_writel(ctrl.u32, (td_void *)(uintptr_t)reg.ctrl);
|
|
osal_writel(cfg.u32, (td_void *)(uintptr_t)reg.cfg);
|
|
|
|
out:
|
|
return ret;
|
|
}
|