298 lines
8.3 KiB
C
298 lines
8.3 KiB
C
|
/*
|
|||
|
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
|||
|
* All Rights Reserved.
|
|||
|
*
|
|||
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
|||
|
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
|||
|
* either version 1.0 of the License, or (at your option) any later version.
|
|||
|
*
|
|||
|
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
|||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|||
|
* See the Phytium Public License for more details.
|
|||
|
*
|
|||
|
*
|
|||
|
* FilePath: ftacho.c
|
|||
|
* Date: 2022-02-10 14:53:42
|
|||
|
* LastEditTime: 2022-05-20 09:08:52
|
|||
|
* Description: This files is for
|
|||
|
*
|
|||
|
* Modify History:
|
|||
|
* Ver Who Date Changes
|
|||
|
* ----- ------ -------- --------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
/***************************** Include Files *********************************/
|
|||
|
|
|||
|
#include <string.h>
|
|||
|
#include "fassert.h"
|
|||
|
#include "fkernel.h"
|
|||
|
#include "fsleep.h"
|
|||
|
#include "ftimer_tacho_hw.h"
|
|||
|
#include "ftimer_tacho.h"
|
|||
|
#include "fparameters.h"
|
|||
|
|
|||
|
/************************** Function Prototypes ******************************/
|
|||
|
/**
|
|||
|
* @name: FTachoInit
|
|||
|
* @msg: 初始化Tacho,并且使能计数器和tachometer
|
|||
|
* @return {FError} 驱动初始化的错误码信息,FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
* @param {FTimerTachoConfig} *config_p 驱动配置数据结构
|
|||
|
*/
|
|||
|
FError FTachoInit(FTimerTachoCtrl *instance_p, const FTimerTachoConfig *config_p)
|
|||
|
{
|
|||
|
FASSERT(instance_p && config_p);
|
|||
|
|
|||
|
u32 reg_val = 0;
|
|||
|
|
|||
|
if (instance_p->isready == FT_COMPONENT_IS_READY)
|
|||
|
{
|
|||
|
FTIMER_INFO("device is already initialized.!!!\r\n");
|
|||
|
return FTIMER_TACHO_ERR_IS_READ;
|
|||
|
}
|
|||
|
|
|||
|
/* set work mode */
|
|||
|
if (FTIMER_WORK_MODE_TACHO == config_p->work_mode)
|
|||
|
{
|
|||
|
reg_val |= FTIMER_REG_TACHO_MODE_TACHO;
|
|||
|
reg_val |= FTACHO_REG_CAP_IN_ENABLE;
|
|||
|
/* plus num of rpm calculate period */
|
|||
|
FTIMER_CMPL_WRITE(instance_p, config_p->plus_num);
|
|||
|
}
|
|||
|
else if (FTIMER_WORK_MODE_CAPTURE == config_p->work_mode)
|
|||
|
{
|
|||
|
reg_val |= FTIMER_REG_TACHO_MODE_CAPTURE;
|
|||
|
reg_val |= FTIMER_REG_TACHO_CAPTURE_ENABLE;
|
|||
|
/* set capture cnt to assert capture intr */
|
|||
|
reg_val |= FTIMER_REG_TACHO_CAPTURE_CNT_MASK & (config_p->captue_cnt << FTIMER_REG_TACHO_CAPTURE_CNT_SHIFT);
|
|||
|
reg_val |= FTIMER_REG_ENABLE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
FTACHO_ERROR("not support work_mode.");
|
|||
|
return FTIMER_TACHO_ERR_INVAL_PARM;
|
|||
|
}
|
|||
|
|
|||
|
/* set timer bits */
|
|||
|
if (FTIMER_32_BITS == config_p->timer_bits)
|
|||
|
{
|
|||
|
reg_val &= (~FTIMER_REG_CNT_SERIES_64BIT);
|
|||
|
}
|
|||
|
else if (FTIMER_64_BITS == config_p->timer_bits)
|
|||
|
{
|
|||
|
reg_val |= FTIMER_REG_CNT_SERIES_64BIT;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
FTACHO_ERROR("invalid input 32/64bits.");
|
|||
|
return FTIMER_TACHO_ERR_INVAL_PARM;
|
|||
|
}
|
|||
|
|
|||
|
/* set edge mode */
|
|||
|
if (FTACHO_FALLING_EDGE == config_p->edge_mode)
|
|||
|
{
|
|||
|
reg_val &= ~FTACHO_REG_MODE_MASK;
|
|||
|
reg_val |= FTACHO_REG_MODE_FALLING_EDGE;
|
|||
|
}
|
|||
|
else if (FTACHO_RISING_EDGE == config_p->edge_mode)
|
|||
|
{
|
|||
|
reg_val &= ~FTACHO_REG_MODE_MASK;
|
|||
|
reg_val |= FTACHO_REG_MODE_RISING_EDGE;
|
|||
|
}
|
|||
|
else if (FTACHO_DOUBLE_EDGE == config_p->edge_mode)
|
|||
|
{
|
|||
|
reg_val &= ~FTACHO_REG_MODE_MASK;
|
|||
|
reg_val |= FTACHO_REG_MODE_DOUBLE_EDGE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
FTACHO_ERROR("invalid input edge.");
|
|||
|
return FTIMER_TACHO_ERR_INVAL_PARM;
|
|||
|
}
|
|||
|
|
|||
|
/* set jitter level */
|
|||
|
reg_val |= FTACHO_REG_ANTI_JITTER_MASK &
|
|||
|
(config_p->jitter_level << FTACHO_REG_ANTI_JITTER_SHIFT);
|
|||
|
|
|||
|
//use input config
|
|||
|
if (config_p != &instance_p->config)
|
|||
|
{
|
|||
|
instance_p->config = *config_p;
|
|||
|
}
|
|||
|
|
|||
|
FTIMER_CTRL_WRITE(instance_p, reg_val);
|
|||
|
instance_p->isready = FT_COMPONENT_IS_READY;
|
|||
|
|
|||
|
return FTIMER_TACHO_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTachoGetFanRPM
|
|||
|
* @msg: 获取风扇的转速值
|
|||
|
* @return {FError} 驱动初始化的错误码信息,FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
* @param {u32} *rpm 将获取到的数值写入到此地址
|
|||
|
*/
|
|||
|
FError FTachoGetFanRPM(FTimerTachoCtrl *instance_p, u32 *rpm)
|
|||
|
{
|
|||
|
u32 loop_cnt;
|
|||
|
u32 raw_dat;
|
|||
|
|
|||
|
FASSERT(instance_p);
|
|||
|
|
|||
|
if (instance_p->isready != FT_COMPONENT_IS_READY || instance_p->config.work_mode != FTIMER_WORK_MODE_TACHO)
|
|||
|
{
|
|||
|
FTIMER_ERROR("device is not already or not work on TACHO_MODE!!!");
|
|||
|
return FTIMER_TACHO_ERR_NOT_READY;
|
|||
|
}
|
|||
|
|
|||
|
u32 cnt_num = FTIMER_CMPL_READ(instance_p);
|
|||
|
|
|||
|
for (loop_cnt = 0;; loop_cnt++)
|
|||
|
{
|
|||
|
raw_dat = FTACHO_RESU_READ(instance_p);
|
|||
|
/* wait for tacho result */
|
|||
|
if (raw_dat & FTACHO_REG_RESU_ISVALID)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (loop_cnt < 300)
|
|||
|
{
|
|||
|
fsleep_millisec(20); //20ms
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return FTIMER_TACHO_ERR_ABORT;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
raw_dat &= FTACHO_REG_RESU_MASK;
|
|||
|
if (0 == raw_dat)
|
|||
|
{
|
|||
|
*rpm = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
/* calculate rpm */
|
|||
|
/* (60(second) * freq * tacho) / (2 * (cmp_l + 1)) cmp_l */
|
|||
|
*rpm = (TIMER_CLK_FREQ_HZ * 60 * raw_dat) / (2 * (cnt_num + 1));
|
|||
|
}
|
|||
|
|
|||
|
return FTIMER_TACHO_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTachoGetCaptureCnt
|
|||
|
* @msg: 获取capture模式下,tacho输入脉冲的个数
|
|||
|
* @return {u32}返回获取到的数值
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
*/
|
|||
|
u32 FTachoGetCaptureCnt(FTimerTachoCtrl *instance_p)
|
|||
|
{
|
|||
|
u32 cap_cnt = FTIMER_TACHO_SUCCESS;
|
|||
|
|
|||
|
FASSERT(instance_p);
|
|||
|
|
|||
|
if (instance_p->isready != FT_COMPONENT_IS_READY || instance_p->config.work_mode != FTIMER_WORK_MODE_CAPTURE)
|
|||
|
{
|
|||
|
FTIMER_ERROR("device is not already or not work on CAPTURE_MODE!!!");
|
|||
|
return FTIMER_TACHO_ERR_NOT_READY;
|
|||
|
}
|
|||
|
|
|||
|
/* read cap cnt */
|
|||
|
cap_cnt = FTIMER_CNTL_READ(instance_p);
|
|||
|
|
|||
|
return cap_cnt;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTimerSwithMode
|
|||
|
* @msg: 切换定时器模式和tachometer-capture模式
|
|||
|
* @return {FError} 驱动初始化的错误码信息,FTIMER_TACHO_SUCCESS 表示初始化成功,其它返回值表示初始化失败
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
* @param {FTimerTachoConfig} *pNewConfig 新的驱动配置数据结构
|
|||
|
*/
|
|||
|
FError FTimerSwithMode(FTimerTachoCtrl *instance_p, FTimerTachoConfig *pNewConfig)
|
|||
|
{
|
|||
|
FASSERT(instance_p && pNewConfig);
|
|||
|
|
|||
|
u32 ret = FTIMER_TACHO_SUCCESS;
|
|||
|
|
|||
|
if (instance_p->config.work_mode == pNewConfig->work_mode)
|
|||
|
{
|
|||
|
return FTIMER_TACHO_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
/* disable and clear timer */
|
|||
|
u32 reg_val = FTIMER_CTRL_READ(instance_p);
|
|||
|
reg_val &= (~FTIMER_REG_ENABLE);
|
|||
|
reg_val |= FTIMER_REG_CNT_CLR;
|
|||
|
FTIMER_CTRL_WRITE(instance_p, reg_val);
|
|||
|
|
|||
|
if (FTIMER_WORK_MODE_TIMER == pNewConfig->work_mode)
|
|||
|
{
|
|||
|
ret = FTimerInit(instance_p, pNewConfig);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ret = FTachoInit(instance_p, pNewConfig);
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTachoSetCntPeriod
|
|||
|
* @msg: 配置 tach计数周期 = pulse_num
|
|||
|
* @return {void}
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
* @param {u32}计数ticks
|
|||
|
*/
|
|||
|
void FTachoSetCntPeriod(FTimerTachoCtrl *instance_p, u32 ticks)
|
|||
|
{
|
|||
|
FTIMER_CMPL_WRITE(instance_p, ticks);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTachoSetOverLimit
|
|||
|
* @msg: 预设tacho的最大值
|
|||
|
* @return {void}
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
* @param {u32}上限值
|
|||
|
*/
|
|||
|
void FTachoSetOverLimit(FTimerTachoCtrl *instance_p, u32 overLim)
|
|||
|
{
|
|||
|
FTACHO_OVER_WRITE(instance_p, overLim);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTachoSetUnderLimit
|
|||
|
* @msg: 预设tacho的最小值
|
|||
|
* @return {void}
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
* @param {u32}下限值
|
|||
|
*/
|
|||
|
void FTachoSetUnderLimit(FTimerTachoCtrl *instance_p, u32 underLim)
|
|||
|
{
|
|||
|
FTACHO_UNDER_WRITE(instance_p, underLim);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @name: FTachoDeInit
|
|||
|
* @msg: 去初始化,寄存器复位,结构体参数置0
|
|||
|
* @return {void}
|
|||
|
* @param {FTimerTachoCtrl} *instance_p 驱动控制数据结构
|
|||
|
*/
|
|||
|
void FTachoDeInit(FTimerTachoCtrl *instance_p)
|
|||
|
{
|
|||
|
FASSERT(instance_p);
|
|||
|
|
|||
|
/* reset reg*/
|
|||
|
FTimerSoftwareReset(instance_p);
|
|||
|
|
|||
|
instance_p->isready = 0;
|
|||
|
memset(instance_p, 0, sizeof(*instance_p));
|
|||
|
|
|||
|
return;
|
|||
|
}
|