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

1819 lines
56 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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;
}