Files
TAIXIN/sdk/driver/adc/hgadc_v1.c

1819 lines
56 KiB
C
Raw Normal View History

/**
* @file hgadc_v1.c
* @author bxd
* @brief AD_KEY
* @version
* TXW82X
* @date 2025-04-16
*
* @copyright Copyright (c) 2025
*
*/
#include "typesdef.h"
#include "list.h"
#include "errno.h"
#include "dev.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/irq.h"
#include "hal/adc.h"
#include "dev/adc/hgadc_v1.h"
#include "hgadc_v1_hw.h"
#define REG_CONFIG(ADDR,BIT_NUM,POST_NUM,DATA) do{ADDR = (ADDR & ~(((0x1 << BIT_NUM) - 1) << POST_NUM)) | (DATA << POST_NUM);}while(0)
#define MODULE_DEBUG(fmt, args...) _os_printf(fmt, ##args)
#define MODULE_NAME "adc"
#define MODULE_INFO(fmt, ...) \
do{ \
os_printf(MODULE_NAME); \
_os_printf(KERN_INFO" info:"fmt, ##__VA_ARGS__);\
}while(0);
#define MODULE_ERR(fmt, ...) \
do{ \
os_printf(MODULE_NAME); \
_os_printf(KERN_ERR" err:"fmt,##__VA_ARGS__); \
os_printf("Func:%s Line:%d LR=0x%x\r\n", \
__func__,__LINE__, (uint32)RETURN_ADDR()); \
}while(0);
#define MODULE_WARNING(fmt, ...) \
do{ \
os_printf(MODULE_NAME); \
_os_printf(KERN_WARNING" warning:"fmt,##__VA_ARGS__);\
}while(0);
#define MODULE_ASSERT(expr, info) \
do { \
if (expr) { \
AUSYS_ERR(info); \
return RET_ERR; \
} \
} while(0);
#define MODULE_PRINT_ARRAY(buf, len) do{\
uint8 *p_print = (uint8 *)buf;\
_os_printf("\r\n");\
for (uint32 __ii=1; __ii<=len; __ii++) {\
_os_printf("%02x ", p_print[__ii-1]);\
if (((__ii)%16 == 0)) _os_printf("\r\n");\
}\
_os_printf("\r\n");\
}while(0);
//单次使用的优先级通道
#define SINGLE_PRI_CHANNEL (0)
#define ADC_CHANNEL_ENABLE (1)
#define ADC_CHANNEL_SUSPEND (2)
#define ADC_CHANNEL_DISABLE (3)
/* ADC channel type, must start at 0 & unique value & less than 32*/
/* Table */
// I/O class
#define _ADC_CHANNEL_IO_CLASS (0)
//RF sensor of temperature
#define _ADC_CHANNEL_RF_TEMPERATURE (1)
#define _ADC_CHANNEL_RF_VDDI (2)
//Internal voltage
#define _ADC_CHANNEL_PLL_VREF (3)
#define _ADC_CHANNEL_RF_VTUNE (4)
#define _ADC_CHANNEL_RF_VCO_VDD (5)
#define _ADC_CHANNEL_RF_VDD_DIV (6)
//PMU sensor of temperature
#define _ADC_CHANNEL_PMU_TEMPERATURE (7)
#define _ADC_CHANNEL_CORE_VDD (8)
#define RFATO (0xfffffff0)
#define ANAATO (0xfffffff1)
extern void delay_us(uint32 n);
/**********************************************************************************/
/* LOW LAYER FUNCTION */
/**********************************************************************************/
/* List opreation */
static int32 hgadc_v1_list_insert(adc_channel_node *head_node, adc_channel_node *new_node) {
adc_channel_node *temp_node = head_node;
/* find the last node */
while (temp_node->next) {
temp_node = temp_node->next;
}
temp_node->next = new_node;
new_node->next = NULL;
/* channel amount */
head_node->channel_amount++;
MODULE_INFO("add success: ADC channel cnt = %d, name:%d\n\r", head_node->channel_amount, new_node->data.channel);
return RET_OK;
}
static int32 hgadc_v1_list_delete(adc_channel_node *head_node, uint32 channel) {
adc_channel_node *temp_node = head_node;
adc_channel_node *delete_node = NULL;
/* find the node */
while (temp_node->next) {
if (channel == temp_node->next->data.channel) {
delete_node = temp_node->next;
temp_node->next = temp_node->next->next;
os_free(delete_node);
head_node->channel_amount--;
MODULE_INFO("delete success: ADC channel cnt = %d\n\r", head_node->channel_amount);
break;
}
temp_node = temp_node->next;
}
return RET_OK;
}
static int32 hgadc_v1_list_get_by_channel(adc_channel_node *head_node, uint32 channel, adc_channel_node **get_node) {
adc_channel_node *temp_node = head_node;
/* find the node */
while (temp_node->next) {
if (channel == temp_node->next->data.channel) {
*get_node = temp_node->next;
return RET_OK;
}
temp_node = temp_node->next;
}
return RET_ERR;
}
static int32 hgadc_v1_list_get_by_index(adc_channel_node *head_node, uint32 index, adc_channel_node **get_node) {
adc_channel_node *temp_node = head_node;
uint32 i = 0;
/* find the node */
for (i = 0; i < head_node->channel_amount; i++) {
if ((i == index) && (temp_node->next)) {
*get_node = temp_node->next;
return RET_OK;
}
temp_node = temp_node->next;
}
return RET_ERR;
}
static int32 hgadc_v1_list_check_repetition(adc_channel_node *head_node, uint32 channel) {
adc_channel_node *temp_node = head_node;
uint32 i = 0;
/* find the node which repeated */
for (i = 0; i < head_node->channel_amount; i++) {
if (temp_node->next) {
if (channel == temp_node->next->data.channel) {
return RET_ERR;
}
}
temp_node = temp_node->next;
}
return RET_OK;
}
static int32 hgadc_v1_list_delete_all(adc_channel_node *head_node, struct hgadc_v1 *dev) {
adc_channel_node *temp_node = head_node;
adc_channel_node *delete_node = NULL;
while (temp_node->next) {
delete_node = temp_node->next;
/* disable adc channel */
delete_node->data.func(dev, delete_node->data.channel, ADC_CHANNEL_DISABLE);
temp_node->next = temp_node->next->next;
os_free(delete_node);
head_node->channel_amount--;
MODULE_INFO("delete success: ADC channel cnt = %d\n\r", head_node->channel_amount);
}
return RET_OK;
}
static int32 hgadc_v1_list_get_channel_amount(adc_channel_node *head_node) {
return head_node->channel_amount;
}
static int32 hgadc_v1_switch_hal_adc_ioctl_cmd(enum adc_ioctl_cmd param) {
switch (param) {
default:
return -1;
break;
}
}
static int32 hgadc_v1_switch_hal_adc_irq_flag(enum adc_irq_flag param) {
switch (param) {
case (ADC_IRQ_FLAG_SAMPLE_DONE):
return 0;
break;
default:
return -1;
break;
}
}
static int32 hgadc_v1_switch_param_channel(uint32 channel) {
/* I/O class under 0x101*/
if (channel < 0x101) {
return _ADC_CHANNEL_IO_CLASS;
}
switch (channel) {
case ADC_CHANNEL_RF_TEMPERATURE:
return _ADC_CHANNEL_RF_TEMPERATURE;
break;
case ADC_CHANNEL_VTUNE:
return _ADC_CHANNEL_RF_VTUNE;
break;
case ADC_CHANNEL_VCO_VDD:
return _ADC_CHANNEL_RF_VCO_VDD;
break;
case ADC_CHANNEL_VDD_DIV:
return _ADC_CHANNEL_RF_VDD_DIV;
break;
//case ADC_CHANNEL_VDDI:
// return _ADC_CHANNEL_RF_VDDI;
// break;
case ADC_CHANNEL_PMU_TEMPERATURE:
return _ADC_CHANNEL_PMU_TEMPERATURE;
break;
case ADC_CHANNEL_CORE_VDD:
return _ADC_CHANNEL_CORE_VDD;
break;
default :
return RET_ERR;
break;
}
}
static void hgadc_v1_chn_to_sel(uint32 channel, uint32 *SEL, uint32 *SCH_VDD)
{
switch(channel) {
case(PA_6 ): *SEL=0x00; *SCH_VDD=0x04; break;
case(PA_11): *SEL=0x01; *SCH_VDD=0x04; break;
case(PA_12): *SEL=0x02; *SCH_VDD=0x04; break;
case(PA_13): *SEL=0x03; *SCH_VDD=0x04; break;
case(PA_14): *SEL=0x04; *SCH_VDD=0x04; break;
case(PA_7 ): *SEL=0x05; *SCH_VDD=0x08; break;
case(PA_8 ): *SEL=0x06; *SCH_VDD=0x08; break;
case(PA_15): *SEL=0x07; *SCH_VDD=0x08; break;
case(PA_0 ): *SEL=0x08; *SCH_VDD=0x10; break;
case(PA_1 ): *SEL=0x09; *SCH_VDD=0x10; break;
case(PA_2 ): *SEL=0x0a; *SCH_VDD=0x10; break;
case(PA_3 ): *SEL=0x0b; *SCH_VDD=0x10; break;
case(PA_4 ): *SEL=0x0c; *SCH_VDD=0x10; break;
case(PA_5 ): *SEL=0x0d; *SCH_VDD=0x10; break;
case(PD_0 ): *SEL=0x0e; *SCH_VDD=0x10; break;
case(PD_1 ): *SEL=0x0f; *SCH_VDD=0x10; break;
case(PD_2 ): *SEL=0x10; *SCH_VDD=0x10; break;
case(PD_3 ): *SEL=0x11; *SCH_VDD=0x10; break;
case(PD_4 ): *SEL=0x12; *SCH_VDD=0x10; break;
case(PD_5 ): *SEL=0x13; *SCH_VDD=0x10; break;
case(PD_6 ): *SEL=0x14; *SCH_VDD=0x10; break;
case(PD_7 ): *SEL=0x15; *SCH_VDD=0x10; break;
case(PD_8 ): *SEL=0x16; *SCH_VDD=0x10; break;
case(PD_9 ): *SEL=0x17; *SCH_VDD=0x10; break;
case(PD_10): *SEL=0x18; *SCH_VDD=0x10; break;
case(PD_11): *SEL=0x19; *SCH_VDD=0x10; break;
case(PD_12): *SEL=0x1a; *SCH_VDD=0x10; break;
case(PD_13): *SEL=0x1b; *SCH_VDD=0x10; break;
case(PC_8 ): *SEL=0x1c; *SCH_VDD=0x20; break;
case(PC_9 ): *SEL=0x1d; *SCH_VDD=0x20; break;
case(PC_10): *SEL=0x1e; *SCH_VDD=0x20; break;
case(PC_11): *SEL=0x1f; *SCH_VDD=0x20; break;
case(PC_12): *SEL=0x20; *SCH_VDD=0x20; break;
case(PC_13): *SEL=0x21; *SCH_VDD=0x20; break;
case(PC_14): *SEL=0x22; *SCH_VDD=0x40; break;
case(PC_15): *SEL=0x23; *SCH_VDD=0x40; break;
case(PD_14): *SEL=0x24; *SCH_VDD=0x40; break;
case(PD_15): *SEL=0x25; *SCH_VDD=0x40; break;
case(PE_0 ): *SEL=0x26; *SCH_VDD=0x40; break;
case(PE_1 ): *SEL=0x27; *SCH_VDD=0x40; break;
case(PE_2 ): *SEL=0x28; *SCH_VDD=0x40; break;
case(PE_3 ): *SEL=0x29; *SCH_VDD=0x40; break;
case(PB_6 ): *SEL=0x2a; *SCH_VDD=0x80; break;
case(PB_7 ): *SEL=0x2b; *SCH_VDD=0x80; break;
case(PB_8 ): *SEL=0x2c; *SCH_VDD=0x80; break;
case(PB_9 ): *SEL=0x2d; *SCH_VDD=0x80; break;
case(PB_10): *SEL=0x2e; *SCH_VDD=0x80; break;
case(PB_11): *SEL=0x2f; *SCH_VDD=0x80; break;
case(PB_12): *SEL=0x30; *SCH_VDD=0x80; break;
case(PB_13): *SEL=0x31; *SCH_VDD=0x80; break;
case(PB_14): *SEL=0x32; *SCH_VDD=0x80; break;
case(PB_15): *SEL=0x33; *SCH_VDD=0x80; break;
case(PC_0 ): *SEL=0x34; *SCH_VDD=0x80; break;
case(PC_1 ): *SEL=0x35; *SCH_VDD=0x80; break;
case(PC_2 ): *SEL=0x36; *SCH_VDD=0x80; break;
case(PC_3 ): *SEL=0x37; *SCH_VDD=0x80; break;
case(PC_4 ): *SEL=0x38; *SCH_VDD=0x80; break;
case(PC_5 ): *SEL=0x39; *SCH_VDD=0x80; break;
case(RFATO): *SEL=0x3a; *SCH_VDD=0x01; break;
case(ANAATO):*SEL=0x3b; *SCH_VDD=0x02; break;
default: *SEL=0xff; *SCH_VDD=0xff; break;
}
}
/************模拟配置***************/
void saradc_ana_config(struct hgadc_v1_hw *hw, uint32 enable)
{
if (enable) {
// 内部时钟电源使能
REG_CONFIG(hw->ADC_ANA_CTRL1, 1,16, 1); // BIAS_EN--------ADC_ANA_CTRL1[16]
REG_CONFIG(hw->ADC_CON_EN , 1,27, 1); // SCLK_EN--------ADC_CON_EN[27]
} else {
// 内部时钟电源失能
REG_CONFIG(hw->ADC_CON_EN , 1,27, 0); // SCLK_EN--------ADC_CON_EN[27]
REG_CONFIG(hw->ADC_ANA_CTRL1, 1,16, 0); // BIAS_EN--------ADC_ANA_CTRL1[16]
}
}
/************采样率配置*************/
void saradc_smp_cofig(struct hgadc_v1_hw *hw, uint8 adc_baud,uint8 conv_cyc,uint16 slow_cyc,uint16 fast_cyc)
{
/*******************ADC采样率计算*******************/
//时钟频率 ADC_CLK=240M/(ADC_BAUD+1) ----时钟最高不能超过16MHz
//波特率 ADC_BAUD ≥14 ----保证ADC时钟频率不高于16MHz
//转换时钟数ADC_CONV_CYC≥11 ----转换时钟数不小于12个ADC时钟
//采样周期数SMP_CYC ≥3 ----采样时钟数不小于4个ADC时钟
//采样率 ADC_SAMPLE=ADC_CLK/((ADC_CONV_CYC+1)+(SMP_CYC+1)) ----采样率最高不能超过1M
REG_CONFIG(hw->ADC_CON_FUN, 8, 0,adc_baud); // ADC_BAUD-------ADC_CON_FUN[7:0]
REG_CONFIG(hw->ADC_CON_FUN, 8, 8,conv_cyc); // ADC_CONV_CYC---ADC_CON_FUN[15:8]
REG_CONFIG(hw->ADC_CON_SMP,10, 0,slow_cyc); // SLOW_SMP_CYC---ADC_CON_SMP[9:0] 慢速采样率配置
REG_CONFIG(hw->ADC_CON_SMP,10,11,fast_cyc); // FAST_SMP_CYC---ADC_CON_SMP[20:11]快速采样率配置
}
/************非优先级通道配置*******/
void saradc_channel_config(struct hgadc_v1_hw *hw, uint8 chanx_en,uint8 smp_mode_sel,uint8 chan_sel,uint8 trg_sel)
{
REG_CONFIG(hw->ADC_CON_EN, 1,(2+chanx_en), 1); // ADC_CON_EN[7:2]
//非优先级通道采样率选择:快速、慢速选择。优先级通道无法选择,默认为慢速的采样率。
REG_CONFIG(hw->ADC_CON_SMP, 1,(26+chanx_en),smp_mode_sel); // SAMP_MOD_SEL---ADC_CON_SMP[31:26]
if(chanx_en<4){
REG_CONFIG(hw->ADC_CON_SEL0, 7,(8*chanx_en), chan_sel); // CHAN_SEL--ADC_CON_SEL0[31:0]
}else{
REG_CONFIG(hw->ADC_CON_SEL1, 7,(8*(chanx_en-4)), chan_sel); // CHAN_SEL--ADC_CON_SEL1[15:0]
}
REG_CONFIG(hw->ADC_CON_EXTEND0 , 4, 6,trg_sel); // TRG_SEL---ADC_CON_EXTEND0[9:6]
}
/************优先级通道失能*********/
void saradc_channel_disable(struct hgadc_v1_hw *hw, uint8 chanx_en)
{
REG_CONFIG(hw->ADC_CON_EN, 1,(2+chanx_en), 0); // ADC_CON_EN[7:2]
if(chanx_en<4){
REG_CONFIG(hw->ADC_CON_SEL0, 7,(8*chanx_en), 0x7F); // CHAN_SEL--ADC_CON_SEL0[31:0]
}else{
REG_CONFIG(hw->ADC_CON_SEL1, 7,(8*(chanx_en-4)), 0x7F); // CHAN_SEL--ADC_CON_SEL1[15:0]
}
}
/************优先级通道配置*********/
void saradc_pri_channel_config(struct hgadc_v1_hw *hw, uint8 pri_chanx_en,uint8 pri_chan_sel,uint8 pri_trg_sel)
{
REG_CONFIG(hw->ADC_CON_EXTEND0, 1,(16+pri_chanx_en), 1); // HIGHSET_PRI--ADC_CON_EXTEND0[17:16]
REG_CONFIG(hw->ADC_CON_SEL1 , 7,(24-(8*pri_chanx_en)), pri_chan_sel);// PRI_CHAN0_SEL--ADC_CON_SEL1[30:24]
REG_CONFIG(hw->ADC_CON_EXTEND0, 4, 10, pri_trg_sel); // PRI_TRG_SEL---ADC_CON_EXTEND0[13:10]
}
/************优先级通道失能*********/
void saradc_pri_channel_disable(struct hgadc_v1_hw *hw, uint8 pri_chanx_en)
{
REG_CONFIG(hw->ADC_CON_EXTEND0, 1,(16+pri_chanx_en), 0); // HIGHSET_PRI--ADC_CON_EXTEND0[17:16]
REG_CONFIG(hw->ADC_CON_SEL1 , 7,(24-(8*pri_chanx_en)), 0x7F);// PRI_CHAN0_SEL--ADC_CON_SEL1[30:24]
}
/************数字配置**************/
//多点连续采样配置
// 9bit、8bit功能不建议使用默认关闭
// 关闭通道码输出16bit存储格式3bit通道码 +3bit 0 +10bit ADC数据
// ADC数字电路使能
void saradc_dig_config(struct hgadc_v1_hw *hw, uint16 chan_scan_num)
{
REG_CONFIG(hw->ADC_CON_FUN,16,16,chan_scan_num);// CHAN_SCANS_NUM--ADC_CON_FUN[31:16]
REG_CONFIG(hw->ADC_CON_EN,1,26,0); // FORMAT_9BIT---ADC_CON_EN[26]
REG_CONFIG(hw->ADC_CON_EN,1,25,0); // FORMAT_8BIT---ADC_CON_EN[25]
REG_CONFIG(hw->ADC_CON_EXTEND0, 1,15, 1); // CHAN_CODE_BYPASS--ADC_CON_EXTEND0[15]
REG_CONFIG(hw->ADC_CON_EXTEND0, 1,14, 1); // DAT_FORMAT_SEL--ADC_CON_EXTEND0[14]
REG_CONFIG(hw->ADC_CON_EN, 1, 0, 1); // ADC_EN--ADC_CON_EN[0]
}
/**********非优先级通道单次采样触发***********/
//这个是单独某个通道,单次采样触发
//如果是多个非优先级通道同时采样pending需要改为BIT(6)
static uint16 g_chan_data[3] = {0xA1A1, 0x0, 0xA5A5};
uint16 saradc_one_channel_single_kick(struct hgadc_v1_hw *hw)
{
// uint16 chanx_data = 0;
if ((0xA1A1 != g_chan_data[0]) || (0xA5A5 != g_chan_data[2])) {
while(1) {
MODULE_ERR("sram flag was changed!\r\n");
};
}
//写一下DMA地址寄存器用于复位ADKEY的DMA CNT
hw->ADC_DMA_STADR = (uint32)&g_chan_data[1];
//REG_CONFIG(hw->ADC_CON_KICK,1,0,1); // ADC_KICK--ADC_CON_KICK[0]
hw->ADC_CON_KICK = BIT(0);
// while(!(hw->ADC_CON_STA & BIT(chan_en)));
// chanx_data = (hw->ADC_ANA_CTRL0 & (0xffff << 4)) >> 4; // ADC_DATA----ADC_ANA_CTRL0[19:4]
// //REG_CONFIG(hw->ADC_CON_STA,1,chan_en,1);
// hw->ADC_CON_STA = BIT(chan_en);
if ((0xA1A1 != g_chan_data[0]) || (0xA5A5 != g_chan_data[2])) {
while(1) {
MODULE_ERR("sram flag was changed!\r\n");
};
}
return 0;
}
/**********非优先级通道获取pending***********/
uint16 saradc_channel_get_pending(struct hgadc_v1_hw *hw, uint8 chan_en)
{
if ((hw->ADC_CON_STA & BIT(chan_en))) {
return 1;
} else {
return 0;
}
}
/**********非优先级通道清除pending***********/
void saradc_channel_clr_pending(struct hgadc_v1_hw *hw, uint8 chan_en)
{
hw->ADC_CON_STA = BIT(chan_en);
}
/**********非优先级通道获取采样值***********/
uint16 saradc_channel_get_raw_data(struct hgadc_v1_hw *hw, uint8 chan_en)
{
uint16 pri_chanx_data = 0;
pri_chanx_data = (hw->ADC_ANA_CTRL0 & (0xffff << 4)) >> 4; // ADC_DATA----ADC_ANA_CTRL0[19:4]
return pri_chanx_data;
}
/**********优先级通道单次采样触发***********/
void saradc_pri_channel_kick(struct hgadc_v1_hw *hw)
{
REG_CONFIG(hw->ADC_CON_KICK,1,1,1); // ADC_PRI_KICK--ADC_CON_KICK[1]
}
/**********优先级通道获取pending***********/
uint16 saradc_pri_channel_get_pending(struct hgadc_v1_hw *hw, uint8 pri_chan_sel)
{
if ((hw->ADC_CON_STA & BIT(25-pri_chan_sel))) {
return 1;
} else {
return 0;
}
}
/**********优先级通道清除pending***********/
void saradc_pri_channel_clr_pending(struct hgadc_v1_hw *hw, uint8 pri_chan_sel)
{
//REG_CONFIG(hw->ADC_CON_STA,1,(25-pri_chan_sel),1);
hw->ADC_CON_STA = (1<<(25-pri_chan_sel));
}
/**********优先级通道获取采样值***********/
uint16 saradc_pri_channel_get_raw_data(struct hgadc_v1_hw *hw, uint8 pri_chan_sel)
{
uint16 pri_chanx_data = 0;
pri_chanx_data = (hw->ADC_CON_EXTEND1 & (0xffff<<(16-16*pri_chan_sel))) >> (16-16*pri_chan_sel); // PRI_CHANx_DATA--ADC_CON_EXTEND1[31:0]
return pri_chanx_data;
}
/**********优先级通道配置采样完成中断***********/
void saradc_pri_channel_config_done_irq(struct hgadc_v1_hw *hw, uint8 pri_chan_sel, uint8 en)
{
if (en) {
REG_CONFIG(hw->ADC_CON_EXTEND0,1,(0+pri_chan_sel),1);
} else {
REG_CONFIG(hw->ADC_CON_EXTEND0,1,(0+pri_chan_sel),0);
}
}
/**********优先级通道获取采样完成中断使能位***********/
uint16 saradc_pri_channel_get_done_irq_en(struct hgadc_v1_hw *hw, uint8 pri_chan_sel)
{
if (hw->ADC_CON_EXTEND0 & BIT(0+pri_chan_sel)) {
return 1;
} else {
return 0;
}
}
static int32 hgadc_v1_adc_channel_txw82x_io_class(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
adc_channel_node *cur_node = dev->cur_node;
if (!cur_node) {
MODULE_ERR("cur_node pointer is NULL\r\n");
return RET_ERR;
}
if (ADC_CHANNEL_ENABLE == enable) {
//配置优先级通道,软件触发
saradc_pri_channel_config(hw, SINGLE_PRI_CHANNEL, cur_node->data.sel, 0);
} else if (ADC_CHANNEL_SUSPEND == enable) {
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
} else if (ADC_CHANNEL_DISABLE == enable) {
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
}
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_rf_temperature(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
#define GPIOC(offset) (*((uint32 *)(GPIOC_BASE+offset)))
#define IO_NUM (0)
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
adc_channel_node *cur_node = dev->cur_node;
uint32 mask = 0;
uint32 i = 0;
if (!cur_node) {
MODULE_ERR("cur_node pointer is NULL\r\n");
return RET_ERR;
}
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
/* connect to rf_temperature channel */
*((uint32 *)(0x40019000 + 0x18)) = ( *((uint32 *)(0x40019000 + 0x18)) & ~(0xf<<27) ) | 0x8<<27;
#if 0
*((uint32 *)(0x40019000 + 0x1C)) |= 0x1;
//IO MODE = analog
GPIOC(0x00) |= (3 << (IO_NUM *2));
//IO MODE = analog
GPIOC(0x50) |= (1 << (IO_NUM *1));
/*!
* only PC0-PC5 by hw->ADKEY_CON.BIT8
* **/
//RF_TOUT & IO_OUT
//hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0x7F << 4) ) | ((0x1<<10) | (0x1<<9));//PC8
#endif
//配置优先级通道,软件触发
saradc_pri_channel_config(hw, SINGLE_PRI_CHANNEL, cur_node->data.sel, 0);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
/*!
*
*/
*((uint32 *)(0x40019000 + 0x18)) &= ~(0xf<<27);
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
} else if (ADC_CHANNEL_DISABLE == enable) {
/*!
*
*/
*((uint32 *)(0x40019000 + 0x18)) &= ~(0xf<<27);
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_pmu_temperature(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
adc_channel_node *cur_node = dev->cur_node;
uint32 mask = 0;
uint32 i = 0;
if (!cur_node) {
MODULE_ERR("cur_node pointer is NULL\r\n");
return RET_ERR;
}
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
/* connect to rf_temperature channel */
//bit13为温度传感器使能位bit14为温度传感器采样通道使能
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6 | (0x1 <<13) | (0x1 <<14)));
//配置优先级通道,软件触发
saradc_pri_channel_config(hw, SINGLE_PRI_CHANNEL, cur_node->data.sel, 0);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
/*!
*
*/
//bit13为温度传感器使能位bit14为温度传感器采样通道使能
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6 &~ ((0x1 <<13) | (0x1 <<14))));
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
} else if (ADC_CHANNEL_DISABLE == enable) {
/*!
*
*/
//bit13为温度传感器使能位bit14为温度传感器采样通道使能
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6 &~ ((0x1 <<13) | (0x1 <<14))));
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_core_vdd(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
adc_channel_node *cur_node = dev->cur_node;
uint32 mask = 0;
uint32 i = 0;
if (!cur_node) {
MODULE_ERR("cur_node pointer is NULL\r\n");
return RET_ERR;
}
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6&~(7<<6))|(2<<6));
//配置优先级通道,软件触发
saradc_pri_channel_config(hw, SINGLE_PRI_CHANNEL, cur_node->data.sel, 0);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
/*!
*
*/
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6&~(7<<6))|(0<<6));
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
} else if (ADC_CHANNEL_DISABLE == enable) {
/*!
*
*/
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6&~(7<<6))|(0<<6));
//失能优先级通道
saradc_pri_channel_disable(hw, SINGLE_PRI_CHANNEL);
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
#if 0
static int32 hgadc_v1_adc_channel_txw82x_rf_vtune(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
uint32 mask = 0;
uint32 i = 0;
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
//LO的模拟测试使能信号开启 select vtune to RF_TOUT (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7)) | 0x1<<7 | 0x4<<8;
//AUXPEN选择 RF_TOUT放到ADKEY0
hw->ADKEY_CON = (hw->ADKEY_CON &~ (0xF << 8) ) | (0x4 << 8);
/* Wait stable */
for (i = 0; i < 50; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
//关闭测试通路清0
//LO的模拟测试使能信号关闭 (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7));
hw->ADKEY_CON &= ~(0xF << 8);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
/* Wait stable */
for (i = 0; i < 50; i++) {
__NOP();
}
} else if (ADC_CHANNEL_DISABLE == enable) {
//关闭测试通路清0
//LO的模拟测试使能信号关闭 (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7));
hw->ADKEY_CON &= ~(0xF << 8);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_rf_vco_vdd(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
uint32 mask = 0;
uint32 i = 0;
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
/*ADKEY0采样vco_vdd电压*/
(*(uint32 *)(0x40019000)) = ((*(uint32 *)(0x40019000)) & ~(15<< 7)) | 0x1<<7 | 0x0<<8;
//AUXPEN选择 RF_TOUT放到ADKEY0
hw->ADKEY_CON = (hw->ADKEY_CON &~ (0xF << 8) ) | (0x4 << 8);
/* Wait stable */
for (i = 0; i < 50; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
//关闭测试通路清0
//LO的模拟测试使能信号关闭 (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7));
hw->ADKEY_CON &= ~(0xF << 8);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
/* Wait stable */
for (i = 0; i < 50; i++) {
__NOP();
}
} else if (ADC_CHANNEL_DISABLE == enable) {
//关闭测试通路清0
//LO的模拟测试使能信号关闭 (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7));
hw->ADKEY_CON &= ~(0xF << 8);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_rf_vdd_div(struct hgadc_v1 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
uint32 mask = 0;
uint32 i = 0;
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
/*ADKEY0采样vco_vdd电压*/
(*(uint32 *)(0x40019000)) = ((*(uint32 *)(0x40019000)) & ~(15<< 7)) | 0x1<<7 | 0x2<<8;
//AUXPEN选择 RF_TOUT放到ADKEY0
hw->ADKEY_CON = (hw->ADKEY_CON &~ (0xF << 8) ) | (0x4 << 8);
/* Wait stable */
for (i = 0; i < 50; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
//关闭测试通路清0
//LO的模拟测试使能信号关闭 (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7));
hw->ADKEY_CON &= ~(0xF << 8);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
/* Wait stable */
for (i = 0; i < 50; i++) {
__NOP();
}
} else if (ADC_CHANNEL_DISABLE == enable) {
//关闭测试通路清0
//LO的模拟测试使能信号关闭 (RFSYS_REG0:0x40019000)
(*(uint32 *)0x40019000) = ((*(uint32 *)0x40019000) & ~(15<< 7));
hw->ADKEY_CON &= ~(0xF << 8);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_rf_vddi_config(struct hgadc_v1 *dev)
{
#define SOFT_RFIF_CON (*((uint32 *)0x4001d0cc))
#define RFSYS_REG7 (*((uint32 *)0x4001901C))
#define RFSYS_REG4 (*((uint32 *)0x40019010))
#define RFIDLEDIS0 (*((uint32 *)0x40019054))
struct _rf_pmu_dc_for_adc p_pmu;
//没开VDDI则要开VDDI
if ((0==( (SOFT_RFIF_CON) & BIT(0) ) ) && (dev->rf_vddi_en==0) ) {
os_printf("Open VDDI!\r\n");
sysctrl_unlock();
SYSCTRL->SYS_CON3 &= ~(1 << 3); //RF_POR=0 to reset RFDIG register
SYSCTRL->SYS_CON3 |= (1 << 3); //RF_POR=1 to wakeup RFDIG
(SOFT_RFIF_CON) |= 0x7f<<7; //software control //这里是将RF的关键控制信号切换成软件控制
(SOFT_RFIF_CON) |= BIT(0); //RF_EN为1
(SOFT_RFIF_CON) |= BIT(25); // bbgclk is always generated
if(rf_pmu_dc_efuse_read_for_adc(&p_pmu)==RET_OK) {
if(get_chip_pack_for_adc() == 0) { //for QFN58 RFDC config
p_pmu.rf_vref = 8;
p_pmu.rf_ibpt = 0xa;
p_pmu.rf_ibct = 0xa;
p_pmu.rf_lo_vref = 0x8;
}
(RFSYS_REG7) &= ~((0xf<<9)|(0xf<<5)|(0xf<<1));
(RFSYS_REG7) |= (p_pmu.rf_vref<<9)|(p_pmu.rf_ibpt<<5)|(p_pmu.rf_ibct<<1);
(RFSYS_REG4) = 0x2a6f7c3c; //LO_VREFCP_VDD=10, LO_VREFLO_VDD=11
(RFSYS_REG4) &= ~(0xf<<11);
(RFSYS_REG4) |= (p_pmu.rf_lo_vref<<11);
}
else {
(RFSYS_REG7) = 0x13099f10; //RF_VREF=15
}
(RFIDLEDIS0) = 0x02000803;
//disable status
(SOFT_RFIF_CON) &= ~ BIT(0); //RF_EN为0
//enable mac & rf
SYSCTRL->SYS_CON3 |= 1<<3 | 1<<5;
dev->rf_vddi_en = 1;
}
#if 0
lo_dc_test(dev);
#endif
return RET_OK;
}
static int32 hgadc_v1_adc_channel_txw82x_rf_vddi(struct hgadc_v1 *dev, uint32 channel, uint32 enable) {
#define RFSYS_REG7 (*((uint32 *)0x4001901C))
#define RFSYS_REG6 (*((uint32 *)0x40019018))
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
uint32 mask = 0;
uint32 i = 0;
/* Close the interrupt to protect the RF register opreation */
mask = disable_irq();
if (ADC_CHANNEL_ENABLE == enable) {
/*
* VDDI是否已经开启
*/
hgadc_v1_adc_channel_txw82x_rf_vddi_config(dev);
//os_printf("ADC module info: vddi gears: %d\r\n", ((*((uint32 *)(0x40019000 + 0x1C))) & (0xF << 9) ) >> 9);
/* connect to rf_vddi channel */
RFSYS_REG6 = ( RFSYS_REG6 & ~(0xf<<27) ) | 0x9<<27 | 0x1<<31;
//vddi to PC0
//RFSYS_REG7 |= 0x1;
/* RF_TOUT */
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) ) | (0x4 << 8);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
/*!
*
*/
RFSYS_REG6 &= ~((0xf<<27) | (0x1<<31));
hw->ADKEY_CON &= ~(0xF << 8);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
} else if (ADC_CHANNEL_DISABLE == enable) {
/*!
*
*/
RFSYS_REG6 &= ~((0xf<<27) | (0x1<<31));
hw->ADKEY_CON &= ~(0xF << 8);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
#endif
void hgadc_v1_txw82x_raw_data_handle(struct hgadc_v1 *dev, uint32 channel, uint32 *adc_data)
{
#define RAW_DATA_DBG (0)
volatile int32 data_temp = 0;
uint32 base_temp = dev->ref_temp;
if (ADC_CHANNEL_RF_TEMPERATURE == channel) {
/*!
* formula:
* { {vref/adkey_range} * diff } / 0.004
*/
#if RAW_DATA_DBG
os_printf("tsensor ldo-> = %d\r\n", dev->refer_adda_vref);
os_printf("tsensor tsd-> = %d\r\n", dev->refer_tsensor);
os_printf("tsensor raw-> = %d\r\n", *adc_data);
#endif
//diff = tsensor - (effuse_tsensor)
data_temp = (int32)*adc_data - (int32)(dev->refer_tsensor);
#if RAW_DATA_DBG
os_printf("tsensor diff-> = %d\r\n", data_temp);
#endif
//{(vref*1024)*diff*1000}
data_temp = dev->refer_adda_vref * 1024 * data_temp * 1000;
#if RAW_DATA_DBG
os_printf("tsensor 1----> = %d\r\n", data_temp);
#endif
// {(vref*1024)*diff*1000} / {adkey_range*4}
data_temp = data_temp / (dev->adkey_range * 4);
#if RAW_DATA_DBG
os_printf("tsensor 2----> = %d\r\n", data_temp);
#endif
// {(vref*1024)*diff*1000} / {adkey_range*4} / {1024}
data_temp = data_temp >> 10;
#if RAW_DATA_DBG
os_printf("tsensor 3----> = %d\r\n", data_temp);
#endif
//室温25度 + 5度待定
data_temp = data_temp + base_temp;
#if RAW_DATA_DBG
os_printf("tsensor 4----> = %d\r\n", data_temp);
#endif
*adc_data = data_temp;
}else if (ADC_CHANNEL_PMU_TEMPERATURE == channel) {
/*!
*
* 25 + [(-1) * (delta/range) * ref * (1/3mV)]
*/
#if RAW_DATA_DBG
os_printf("pmu tsensor ldo-> = %d\r\n", dev->refer_adda_vref);
os_printf("pmu tsensor tsd-> = %d\r\n", dev->refer_pmu_tsensor);
os_printf("pmu tsensor raw-> = %d\r\n", *adc_data);
#endif
//delta = tsensor - (efuse_tsensor)
data_temp = (int32)*adc_data - (int32)(dev->refer_pmu_tsensor);
#if RAW_DATA_DBG
os_printf("pmu tsensor delta-> = %d\r\n", data_temp);
#endif
//vref * delta * 1000
data_temp = dev->refer_adda_vref * data_temp * 1000;
#if RAW_DATA_DBG
os_printf("pmu tsensor 1----> = %d\r\n", data_temp);
#endif
// vref * delta * 1000 * (1/3) * (1/range)
// 3mV代表1摄氏度
data_temp = data_temp / (dev->adkey_range * 3);
#if RAW_DATA_DBG
os_printf("pmu tsensor 2----> = %d\r\n", data_temp);
#endif
// (-1) * vref * delta * 1000 * (1/3) * (1/range)
data_temp = data_temp * (-1);
#if RAW_DATA_DBG
os_printf("pmu tsensor 3----> = %d\r\n", data_temp);
#endif
//室温25度 + 5度待定
data_temp = data_temp + base_temp;
#if RAW_DATA_DBG
os_printf("pmu tsensor 4----> = %d\r\n", data_temp);
#endif
*adc_data = data_temp;
} else if ((ADC_CHANNEL_VCO_VDD == channel) || (ADC_CHANNEL_VDD_DIV == channel)) {
//os_printf("1----> = %d\r\n", data_temp); //A'
//os_printf("2----> = %d\r\n", *adc_data); //B'
//返回的是:电压值*256*256
// data_temp = ((((dev->refer_vddi) * (*adc_data)) * 256) / data_temp);
//
// *adc_data = data_temp;
//os_printf("3----> = %drn", data_temp);
} else if (ADC_CHANNEL_VTUNE == channel) {
/*!
* formula:
* { {2.7*65536} * adc_vtune } / 4096
*/
*adc_data = (((*adc_data) * (dev->refer_adda_vref) * (64))/4096);
} else {
/*!
* fromulation: (adda_ref / 2.7) * raw_data
*/
// //(adda_ref*10 / 27)
// data_temp = ((dev->refer_adda_vref * 10) / (27));
//
// //(adda_ref*10 / 27) * raw_data
// data_temp = data_temp * (*adc_data);
//
// //((adda_ref*10 / 27) * raw_data) / 1024
// *adc_data = (data_temp) >> 10;
//
if (*adc_data > 2047) {
*adc_data = 2047;
}
//os_printf("adkey raw data:%d\n\r", *adc_data);
}
}
void sar_adc_sample_one_channel(uint32 channel, uint32 *raw_data)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)ADKEY_BASE;
uint32 saradc_gain = sysctrl_efuse_saradc_gain();
uint32 saradc_offset = sysctrl_efuse_saradc_offset();
uint32 i = 0;
uint32 timeout = 1000;
sysctrl_adkey_clk_open();
saradc_ana_config(hw, 1);
saradc_dig_config(hw, 0);
if (saradc_gain==0 && saradc_offset==0) {
saradc_gain = 2048;
saradc_offset = 0;
}
//gain
REG_CONFIG(hw->ADC_ANA_CTRL1,12, 0,saradc_gain);
//offset
REG_CONFIG(hw->ADC_ANA_CTRL1, 9,17,saradc_offset);
//ADC_CON_EN[1]----CALIB_EN
REG_CONFIG(hw->ADC_CON_EN, 1,1,1);
//配置采样率500k
saradc_smp_cofig(hw, (15-1), (12-1), (20-1), (20-1));
//等待ADKEY稳定
delay_us(1);
/*!
*
*/
switch (channel) {
case (ADC_CHANNEL_CORE_VDD):
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6&~(7<<6))|(2<<6));
//配置优先级通道,软件触发
saradc_pri_channel_config(hw, SINGLE_PRI_CHANNEL, 0x3B, 0);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
break;
}
/* 清除通道的pending */
saradc_pri_channel_clr_pending(hw, SINGLE_PRI_CHANNEL);
//kick start to sample
saradc_pri_channel_kick(hw);
i = 0;
while (!saradc_pri_channel_get_pending(hw, SINGLE_PRI_CHANNEL)) {
delay_us(1);
i++;
if (i>timeout) {break;}
}
saradc_pri_channel_clr_pending(hw, SINGLE_PRI_CHANNEL);
*raw_data = saradc_pri_channel_get_raw_data(hw, SINGLE_PRI_CHANNEL);
/*!
*
*/
switch (channel) {
case (ADC_CHANNEL_CORE_VDD):
pmu_reg_write((uint32)&PMU->PMUCON6, (PMU->PMUCON6&~(7<<6))|(0<<6));
break;
}
//关闭ADKEY
saradc_ana_config(hw, 0);
sysctrl_adkey_clk_close();
}
void hgadc_v1_txw82x_open_handler(struct hgadc_v1 *dev)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
uint32 saradc_gain = sysctrl_efuse_saradc_gain();
uint32 saradc_offset = sysctrl_efuse_saradc_offset();
dev->refer_adda_vref = 3;
dev->refer_tsensor = sysctrl_efuse_tsensor_get();
dev->refer_pmu_tsensor = sysctrl_efuse_pmu_tsensor_get();
dev->adkey_range = 2048;
dev->ref_temp = 30;
sysctrl_adkey_clk_open();
saradc_ana_config(hw, 1);
saradc_dig_config(hw, 0);
if (saradc_gain==0 && saradc_offset==0) {
saradc_gain = 2048;
saradc_offset = 0;
MODULE_INFO("calib invalid, gain=%d, offset=%d\n\r", saradc_gain, saradc_offset);
}
//gain
REG_CONFIG(hw->ADC_ANA_CTRL1,12, 0,saradc_gain);
//offset
REG_CONFIG(hw->ADC_ANA_CTRL1, 9,17,saradc_offset);
//ADC_CON_EN[1]----CALIB_EN
REG_CONFIG(hw->ADC_CON_EN, 1,1,1);
MODULE_INFO("calib valid, gain=%d, offset=%d, vptat:%d, pmu_vptat:%d\n\r", saradc_gain, saradc_offset, dev->refer_tsensor, dev->refer_pmu_tsensor);
//配置采样率500k
saradc_smp_cofig(hw, (15-1), (12-1), (20-1), (20-1));
//配置优先级通道采样完成中断
saradc_pri_channel_config_done_irq(hw, SINGLE_PRI_CHANNEL, 1);
}
void hgadc_v1_txw82x_close_handler(struct hgadc_v1 *dev)
{
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
saradc_ana_config(hw, 0);
sysctrl_adkey_clk_close();
}
/**********************************************************************************/
/* ATTCH FUNCTION */
/**********************************************************************************/
static int32 hgadc_v1_open(struct adc_device *adc) {
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
uint32 mask = 0;
mask = disable_irq();
if (dev->opened) {
/* Enable interrupt */
enable_irq(mask);
return -EBUSY;
}
hgadc_v1_txw82x_open_handler(dev);
irq_enable(dev->irq_num);
/* init head node */
dev->head_node.channel_amount = 0;
dev->head_node.data.channel = -1;
dev->head_node.data.func = NULL;
dev->head_node.next = NULL;
dev->opened = 1;
dev->irq_en = 0;
dev->rf_vddi_en = 0;
/* Enable interrupt */
enable_irq(mask);
MODULE_INFO("open success!\n\r");
return RET_OK;
}
static int32 hgadc_v1_close(struct adc_device *adc) {
uint32 mask = 0;
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
if (!dev->opened) {
return RET_OK;
}
/* Close the interrupt to protect the list opreation */
mask = disable_irq();
/* keep ADC open, when channel is still in use */
if (hgadc_v1_list_get_channel_amount(&dev->head_node)) {
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
hgadc_v1_list_delete_all(&dev->head_node, dev);
/* Enable interrupt */
enable_irq(mask);
irq_disable(dev->irq_num);
hgadc_v1_txw82x_close_handler(dev);
dev->head_node.channel_amount = 0;
dev->head_node.next = NULL;
dev->head_node.data.channel = -1;
dev->head_node.data.func = NULL;
dev->refer_tsensor = 0;
dev->refer_vddi = 0;
dev->irq_en = 0;
dev->opened = 0;
dev->rf_vddi_en = 0;
dev->refer_vddi_adc_data = 0;
return RET_OK;
}
static int32 hgadc_v1_add_channel(struct adc_device *adc, uint32 channel) {
int32 _class = 0;
uint32 mask = 0;
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
adc_channel_node *new_node = NULL;
uint32 sel = 0, sch_vdd = 0;
if (!dev->opened) {
return RET_ERR;
}
/* Close the interrupt to protect the list opreation */
mask = disable_irq();
/* Check for the channel which repeated */
if (RET_ERR == hgadc_v1_list_check_repetition(&dev->head_node, channel)) {
enable_irq(mask);
MODULE_ERR("channel repeat\n\r");
return RET_OK;
}
_class = hgadc_v1_switch_param_channel(channel);
if (RET_ERR == _class) {
enable_irq(mask);
MODULE_ERR("%x channel don't support\n\r", channel);
return RET_ERR;
}
/* save the adkey configuration by channel */
switch (_class) {
case _ADC_CHANNEL_IO_CLASS:
hgadc_v1_chn_to_sel(channel, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x io don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = hgadc_v1_adc_channel_txw82x_io_class;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_TEMPERATURE:
hgadc_v1_chn_to_sel(RFATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = hgadc_v1_adc_channel_txw82x_rf_temperature;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VTUNE:
hgadc_v1_chn_to_sel(RFATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = NULL;//hgadc_v1_adc_channel_txw82x_rf_vtune;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VCO_VDD:
hgadc_v1_chn_to_sel(RFATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = NULL;//hgadc_v1_adc_channel_txw82x_rf_vco_vdd;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VDD_DIV:
hgadc_v1_chn_to_sel(RFATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = NULL;//hgadc_v1_adc_channel_txw82x_rf_vdd_div;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VDDI:
hgadc_v1_chn_to_sel(RFATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = NULL;//hgadc_v1_adc_channel_txw82x_rf_vddi_config;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case (_ADC_CHANNEL_PMU_TEMPERATURE):
hgadc_v1_chn_to_sel(ANAATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = hgadc_v1_adc_channel_txw82x_pmu_temperature;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
case (_ADC_CHANNEL_CORE_VDD):
hgadc_v1_chn_to_sel(ANAATO, &sel, &sch_vdd);
if (sel==0xFF || sch_vdd==0xFF) {MODULE_ERR("%x don't support\n\r", channel);}
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
new_node->data.func = hgadc_v1_adc_channel_txw82x_core_vdd;
new_node->data.channel = channel;
new_node->data.sel = sel;
new_node->data.sch_vdd = sch_vdd;
new_node->next = NULL;
hgadc_v1_list_insert(&dev->head_node, new_node);
break;
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_delete_channel(struct adc_device *adc, uint32 channel) {
uint32 mask = 0;
adc_channel_node *get_node = NULL;
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
if (!dev->opened) {
return RET_ERR;
}
/* Close the interrupt to protect the list opreation */
mask = disable_irq();
if (RET_ERR == hgadc_v1_list_get_by_channel(&dev->head_node, channel, &get_node)) {
MODULE_ERR("No this channel\n\r");
enable_irq(mask);
return RET_ERR;
}
get_node->data.func(dev, channel, ADC_CHANNEL_DISABLE);
hgadc_v1_list_delete(&dev->head_node, channel);
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v1_get_value(struct adc_device *adc, uint32 channel, uint32 *raw_data) {
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
adc_channel_node *get_node = NULL;
uint32 mask = 0;
if (!dev->opened) {
return RET_ERR;
}
if (!raw_data) {
os_printf("raw_data var is NULL!\r\n");
return RET_ERR;
}
os_mutex_lock(&dev->adc_lock, osWaitForever);
if (RET_ERR == hgadc_v1_list_get_by_channel(&dev->head_node, channel, &get_node)) {
MODULE_ERR("No this channel\n\r");
os_mutex_unlock(&dev->adc_lock);
return RET_ERR;
}
//指向当前节点,便于后续获取当前节点中的配置
dev->cur_node = get_node;
/* config current channel */
if (get_node->data.func) {
get_node->data.func(dev, channel, ADC_CHANNEL_ENABLE);
} else {
os_mutex_unlock(&dev->adc_lock);
return RET_ERR;
}
//防止kick的时候没有done。但系统复位了导致adc重新open无法工作
mask = disable_irq();
/* 清除通道的pending */
saradc_pri_channel_clr_pending(hw, SINGLE_PRI_CHANNEL);
//kick start to sample
saradc_pri_channel_kick(hw);
enable_irq(mask);
/* 超时5s */
if (os_sema_down(&dev->adc_done, 5000) <= 0){
/* 清除通道的pending */
saradc_pri_channel_clr_pending(hw, SINGLE_PRI_CHANNEL);
MODULE_ERR("adkey sample timeout\r\n");
}
//os_printf("*** down!!\n\r");
*raw_data = saradc_pri_channel_get_raw_data(hw, SINGLE_PRI_CHANNEL);
//os_printf("** %d channel raw_data: %d\n\r", get_node->data.channel, *raw_data);
get_node->data.func(dev, channel, ADC_CHANNEL_SUSPEND);
hgadc_v1_txw82x_raw_data_handle(dev, channel, raw_data);
if (dev->irq_en && dev->irq_hdl) {
dev->irq_hdl(ADC_IRQ_FLAG_SAMPLE_DONE, get_node->data.channel, *raw_data);
}
os_mutex_unlock(&dev->adc_lock);
return RET_OK;
}
static int32 hgadc_v1_ioctl(struct adc_device *adc, enum adc_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2)
{
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
if (!dev->opened) {
return RET_ERR;
}
switch (ioctl_cmd) {
case (ADC_IOCTL_SET_REF_TMP):
dev->ref_temp = param1;
break;
case (ADC_IOCTL_GET_VREF):
*(uint32 *)param1 = dev->refer_adda_vref << 8;
break;
}
return RET_OK;
}
static void hgadc_v1_irq_handler(void *data) {
struct hgadc_v1 *dev = (struct hgadc_v1 *)data;
struct hgadc_v1_hw *hw = (struct hgadc_v1_hw *)dev->hw;
//os_printf("*** interrupt!!\n\r");
//优先级通道0
if ((saradc_pri_channel_get_pending(hw, SINGLE_PRI_CHANNEL)) &&
(saradc_pri_channel_get_done_irq_en(hw, SINGLE_PRI_CHANNEL))) {
saradc_pri_channel_clr_pending(hw, SINGLE_PRI_CHANNEL);
os_sema_up(&dev->adc_done);
//os_printf("*** up!!\n\r");
}
}
static int32 hgadc_v1_request_irq(struct adc_device *adc, enum adc_irq_flag irq_flag, adc_irq_hdl irq_hdl, uint32 irq_data) {
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
dev->irq_hdl = irq_hdl;
dev->irq_data = irq_data;
if (irq_flag & ADC_IRQ_FLAG_SAMPLE_DONE) {
dev->irq_en = 1;
}
return RET_OK;
}
static int32 hgadc_v1_release_irq(struct adc_device *adc, enum adc_irq_flag irq_flag) {
struct hgadc_v1 *dev = (struct hgadc_v1 *)adc;
if (irq_flag & ADC_IRQ_FLAG_SAMPLE_DONE) {
dev->irq_en = 0;
}
return RET_OK;
}
static const struct adc_hal_ops adcops = {
.open = hgadc_v1_open,
.close = hgadc_v1_close,
.add_channel = hgadc_v1_add_channel,
.delete_channel = hgadc_v1_delete_channel,
.get_value = hgadc_v1_get_value,
.ioctl = hgadc_v1_ioctl,
.request_irq = hgadc_v1_request_irq,
.release_irq = hgadc_v1_release_irq,
};
int32 hgadc_v1_attach(uint32 dev_id, struct hgadc_v1 *adc)
{
adc->opened = 0;
adc->irq_en = 0;
adc->refer_vddi = 0;
adc->refer_tsensor = 0;
adc->refer_adda_vref = 0;
adc->refer_vddi_adc_data= 0;
adc->rf_vddi_en = 0;
adc->irq_hdl = NULL;
adc->cur_node = NULL;
adc->adkey_range = 0;
adc->irq_data = 0;
adc->dev.dev.ops = (const struct devobj_ops *)&adcops;
os_mutex_init(&adc->adc_lock);
os_sema_init(&adc->adc_done, 0);
request_irq(adc->irq_num, hgadc_v1_irq_handler, adc);
irq_enable(adc->irq_num);
dev_register(dev_id, (struct dev_obj *)adc);
return RET_OK;
}