inwudriver-weibo/bsp/drivers/pwm/pwm_drv.c

244 lines
6.8 KiB
C

/*
* Copyright (c) CompanyNameMagicTag 2012-2019. All rights reserved.
* Description: [New requirements for platform group] Added pwm secondary development interface pwm_drv.c code
* Author: CompanyName
* Create: 2012-12-18
*/
#ifndef PWM_DRV_H
#define PWM_DRV_H
#include "pwm_drv.h"
#include <soc_ft_nv.h>
#include <soc_mdm_ver.h>
#include <soc_mdm_isr.h>
#include <soc_mdm_sem.h>
#include <soc_stdlib.h>
#include <dw21_platform_rom.h>
EXT_CPP_START
pwm_ctx g_pwm_ctx = { 0 };
td_u32 uapi_pwm_init(ext_pwm_port port)
{
td_u32 ret;
pwm_ctl *pwm_ctrl = TD_NULL;
if (pwm_check_port(port) != EXT_ERR_SUCCESS) {
return EXT_ERR_INVALID_PARAMETER;
}
pwm_ctrl = pwm_get_ctl(port);
if (pwm_ctrl->is_init == TD_FALSE) {
if (port == EXT_PWM_PORT_PWM0) {
ret = uapi_sem_bcreate(&(pwm_ctrl->pwm_sem), "pwm0", EXT_SEM_ONE);
} else {
ret = uapi_sem_bcreate(&(pwm_ctrl->pwm_sem), "pwm1", EXT_SEM_ONE);
}
if (ret == EXT_ERR_SUCCESS) {
pwm_ctrl->is_init = TD_TRUE;
}
} else {
ret = EXT_ERR_INITILIZATION_ALREADY;
}
return ret;
}
td_u32 uapi_pwm_deinit(ext_pwm_port port)
{
td_u32 ret;
pwm_ctl *pwm_ctl_point = TD_NULL;
if (pwm_check_port(port) != EXT_ERR_SUCCESS) {
return EXT_ERR_INVALID_PARAMETER;
}
pwm_ctl_point = pwm_get_ctl(port);
if (pwm_ctl_point->is_init == TD_TRUE) {
ret = uapi_sem_delete(pwm_ctl_point->pwm_sem);
if (ret == EXT_ERR_SUCCESS) {
(td_void)memset_s((void *)pwm_ctl_point, sizeof(pwm_ctl), 0, sizeof(pwm_ctl));
}
} else {
ret = EXT_ERR_NO_OS_RES_INIT;
}
return ret;
}
__isr td_u32 uapi_pwm_set_clock(ext_pwm_clk_source clk_type)
{
td_u32 int_val;
td_u32 reg_val;
if (clk_type >= PWM_CLK_MAX) {
return EXT_ERR_INVALID_PARAMETER;
}
int_val = uapi_int_lock();
reg_val = UAPI_REG_READ_VAL32(DW21_CRG_REG_SC_PERI_CLKSEL_REG);
if (clk_type == PWM_CLK_APB) {
reg_val &= (~(1 << CRG_REG_PWM_CLK_SEL_OFFSET));
UAPI_REG_WRITE32(DW21_CRG_REG_SC_PERI_CLKSEL_REG, reg_val);
} else {
reg_val |= (1 << CRG_REG_PWM_CLK_SEL_OFFSET);
UAPI_REG_WRITE32(DW21_CRG_REG_SC_PERI_CLKSEL_REG, reg_val);
}
uapi_int_restore(int_val);
return EXT_ERR_SUCCESS;
}
td_u32 uapi_pwm_start(ext_pwm_port port, td_u16 duty, td_u16 freq)
{
td_u32 ret;
if ((pwm_check_port(port) != EXT_ERR_SUCCESS) || (duty == 0) || (freq == 0)) {
return EXT_ERR_INVALID_PARAMETER;
}
if (pwm_is_init(port) == TD_FALSE) {
return EXT_ERR_NO_OS_RES_INIT;
}
ret = pwm_lock(port);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
pwm_set_enable(port, TD_TRUE);
pwm_set_freq(port, freq);
pwm_set_duty(port, duty);
pwm_take_effect(port);
return pwm_unlock(port);
}
td_u32 uapi_pwm_stop(ext_pwm_port port)
{
td_u32 ret;
if (pwm_check_port(port) != EXT_ERR_SUCCESS) {
return EXT_ERR_INVALID_PARAMETER;
}
if (pwm_is_init(port) == TD_FALSE) {
return EXT_ERR_NO_OS_RES_INIT;
}
ret = pwm_lock(port);
if (ret != EXT_ERR_SUCCESS) {
return ret;
}
pwm_set_enable(port, TD_FALSE);
pwm_take_effect(port);
return pwm_unlock(port);
}
/* *********************** The following is an internal function *************************************** */
td_u32 pwm_check_port(ext_pwm_port port)
{
ext_ftm_chip_type chip_type = uapi_get_hw_chip_type();
/* E chip only supports PWM1 module */
if ((port >= EXT_PWM_PORT_MAX) || ((chip_type == EXT_FTM_CHIP_TYPE_21EV) && (port <= EXT_PWM_PORT_PWM0))) {
return EXT_ERR_INVALID_PARAMETER;
}
return EXT_ERR_SUCCESS;
}
td_void pwm_set_enable(ext_pwm_port port, td_bool flag)
{
td_u32 reg_val;
/* Enable */
if (flag == TD_TRUE) {
if (port == EXT_PWM_PORT_PWM0) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM_EN_REG);
reg_val |= (1 << PWM_REG_PWM_EN_OFFSET);
UAPI_REG_WRITE32(DW21_PWM_EN_REG, reg_val);
} else if (port == EXT_PWM_PORT_PWM1) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM1_EN_REG);
reg_val |= (1 << PWM1_REG_PWM_EN_OFFSET);
UAPI_REG_WRITE32(DW21_PWM1_EN_REG, reg_val);
}
return;
}
/* Disenable */
if (port == EXT_PWM_PORT_PWM0) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM_EN_REG);
reg_val &= (~(1 << PWM_REG_PWM_EN_OFFSET));
UAPI_REG_WRITE32(DW21_PWM_EN_REG, reg_val);
} else if (port == EXT_PWM_PORT_PWM1) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM1_EN_REG);
reg_val &= (~(1 << PWM1_REG_PWM_EN_OFFSET));
UAPI_REG_WRITE32(DW21_PWM1_EN_REG, reg_val);
}
}
td_void pwm_set_freq(ext_pwm_port port, td_u16 freq)
{
td_u32 reg_val;
if (port == EXT_PWM_PORT_PWM0) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM_FREQ_REG);
reg_val &= (~PWM_FREQ_MASK);
reg_val |= (td_u32)freq;
UAPI_REG_WRITE32(DW21_PWM_FREQ_REG, reg_val);
} else {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM1_FREQ_REG);
reg_val &= (~PWM_FREQ_MASK);
reg_val |= (td_u32)freq;
UAPI_REG_WRITE32(DW21_PWM1_FREQ_REG, reg_val);
}
}
td_void pwm_set_duty(ext_pwm_port port, td_u16 duty)
{
td_u32 reg_val;
if (port == EXT_PWM_PORT_PWM0) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM_DUTY_REG);
reg_val &= (~PWM_DUTY_MASK);
reg_val |= (td_u32)duty;
UAPI_REG_WRITE32(DW21_PWM_DUTY_REG, reg_val);
} else {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM1_DUTY_REG);
reg_val &= (~PWM_DUTY_MASK);
reg_val |= (td_u32)duty;
UAPI_REG_WRITE32(DW21_PWM1_DUTY_REG, reg_val);
}
}
td_void pwm_take_effect(ext_pwm_port port)
{
td_u32 reg_val;
if (port == EXT_PWM_PORT_PWM0) {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM_START_REG);
reg_val |= (1 << PWM_REG_PWM_START_OFFSET);
UAPI_REG_WRITE32(DW21_PWM_START_REG, reg_val);
} else {
reg_val = UAPI_REG_READ_VAL32(DW21_PWM1_START_REG);
reg_val |= (1 << PWM1_REG_PWM_START_OFFSET);
UAPI_REG_WRITE32(DW21_PWM1_START_REG, reg_val);
}
}
td_bool pwm_is_init(ext_pwm_port port)
{
return g_pwm_ctx.pwm[port].is_init;
}
td_u32 pwm_lock(ext_pwm_port port)
{
pwm_ctl *pwm_ctrl = pwm_get_ctl(port);
return uapi_sem_wait(pwm_ctrl->pwm_sem, EXT_SYS_WAIT_FOREVER);
}
td_u32 pwm_unlock(ext_pwm_port port)
{
pwm_ctl *pwm_ctrl = pwm_get_ctl(port);
return uapi_sem_signal(pwm_ctrl->pwm_sem);
}
pwm_ctl *pwm_get_ctl(ext_pwm_port port)
{
return &(g_pwm_ctx.pwm[port]);
}
EXT_CPP_END
#endif