Files
2025-08-27 09:51:58 +01:00

1825 lines
49 KiB
C

/**
* @file hgadc_v0.c
* @author bxd
* @brief AD_KEY
* @version
* TXW80X; TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#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_v0.h"
#include "hgadc_v0_hw.h"
#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
#define _ADC_CHANNEL_RF_VDD_PFD 7
/**********************************************************************************/
/* LOW LAYER FUNCTION */
/**********************************************************************************/
/* List opreation */
static int32 hgadc_v0_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++;
os_printf("*** add success: ADC channel cnt = %d, name:%d\n\r", head_node->channel_amount, new_node->data.channel);
return RET_OK;
}
static int32 hgadc_v0_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--;
os_printf("*** delete success: ADC channel cnt = %d\n\r", head_node->channel_amount);
break;
}
temp_node = temp_node->next;
}
return RET_OK;
}
static int32 hgadc_v0_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_v0_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_v0_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_v0_list_delete_all(adc_channel_node *head_node, struct hgadc_v0 *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--;
os_printf("*** delete success: ADC channel cnt = %d\n\r", head_node->channel_amount);
}
return RET_OK;
}
static int32 hgadc_v0_list_get_channel_amount(adc_channel_node *head_node) {
return head_node->channel_amount;
}
static int32 hgadc_v0_switch_hal_adc_ioctl_cmd(enum adc_ioctl_cmd param) {
switch (param) {
default:
return -1;
break;
}
}
static int32 hgadc_v0_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_v0_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;
case ADC_CHANNEL_VDD_PFD:
return _ADC_CHANNEL_RF_VDD_PFD;
break;
default :
return RET_ERR;
break;
}
}
/* channel configuration */
#ifdef TXW81X
static inline int32 hgadc_v0_adc_channel_txw81x_confirm_io(uint32 channel)
{
/*!
* confirm gpio channel is correct
* ADKEY can't support above PC15 and the range from PB0 to PB5
*/
if ( (channel > PC_15) ||
( (channel >= PB_0) && (channel <= PB_5) )
) {
os_printf("ADKEY can't support above PC15 and the range from PB0 to PB5\r\n");
return RET_ERR;
}
return RET_OK;
}
static int32 hgadc_v0_adc_channel_txw81x_io_class(struct hgadc_v0 *dev, uint32 channel, uint32 enable) {
//BIT(26) enable channel
//BIT(27) suspend channel
//BIT(28) disable channel
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
int32 ret = 0;
if (ADC_CHANNEL_ENABLE == enable) {
ret = hgadc_v0_adc_channel_txw81x_confirm_io(channel);
if (ret == RET_ERR) {
return RET_ERR;
}
/* pin config */
ret = pin_func(dev->dev.dev.dev_id , BIT(26) | channel);
if (ret == RET_ERR) {
return RET_ERR;
}
/*!
* ADKEY_CON.bit4 (PA0-PA7、PA15)
* N port
*/
if (((channel>=PA_0)&&(channel<=PA_7))||\
(channel==PA_15)) {
hw->ADKEY_CON &= ~(0x7F << 4);
//N port && enable channel
hw->ADKEY_CON |= (1<<24) | (1<<4);
}
/*!
* ADKEY_CON.bit5 (PA8-PA14)
* N port
*/
else if (((channel>=PA_8)&&(channel<=PA_14))) {
hw->ADKEY_CON &= ~(0x7F << 4);
//N port && enable channel
hw->ADKEY_CON |= (1<<24) | (1<<5);
}
/*!
* ADKEY_CON.bit6 (PB6-PB15)
* N port
*/
else if (((channel>=PB_6)&&(channel<=PB_15))) {
hw->ADKEY_CON &= ~(0x7F << 4);
//N port && enable channel
hw->ADKEY_CON |= (1<<24) | (1<<6);
}
/*!
* ADKEY_CON.bit8 (PC0-PC5)
* P port
*/
else if (((channel>=PC_0)&&(channel<=PC_5))) {
hw->ADKEY_CON &= ~((0x7F << 4) | ((1<<24)));
//P port && enable channel
hw->ADKEY_CON |= (1<<8);
}
/*!
* ADKEY_CON.bit9 (PC8-PC15)
* P port
*/
else if (((channel>=PC_8)&&(channel<=PC_15))) {
hw->ADKEY_CON &= ~((0x7F << 4) | ((1<<24)));
//P port && enable channel
hw->ADKEY_CON |= (1<<9);
}
/* Wait stable */
__NOP();__NOP();__NOP();__NOP();
} else if (ADC_CHANNEL_SUSPEND == enable) {
/* pin config */
ret = pin_func(dev->dev.dev.dev_id , BIT(27) | channel);
/* disable current channel */
/* turn to P port */
hw->ADKEY_CON &= ~((0x7F << 4) | ((1<<24)));
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
if (ret == RET_ERR) {
return RET_ERR;
}
} else if (ADC_CHANNEL_DISABLE == enable) {
/* pin config */
ret = pin_func(dev->dev.dev.dev_id , BIT(28) | channel);
/* disable current channel */
/* turn to P port */
hw->ADKEY_CON &= ~((0x7F << 4) | ((1<<24)));
if (ret == RET_ERR) {
return RET_ERR;
}
}
return RET_OK;
}
#endif
#ifdef TXW80X
static int32 hgadc_v0_adc_channel_txw80x_io_class(struct hgadc_v0 *dev, uint32 channel, uint32 enable) {
//BIT(26) enable channel
//BIT(27) suspend channel
//BIT(28) disable channel
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
int32 ret = 0;
if (ADC_CHANNEL_ENABLE == enable) {
/* pin config, return gpiox addr */
ret = pin_func(dev->dev.dev.dev_id , BIT(26) | channel);
if (ret == RET_ERR) {
return RET_ERR;
}
/* GPIO0_EN/GPIO1_EN */
if (BIT(25) == ret) {
if (ADKEY1_BASE == dev->hw) {
//GPIOA
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) ) | (0x1 << 8);
} else {
//GPIOA
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) ) | (0x2 << 8);
}
} else {
//GPIOB /
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) ) | (0x1 << 8);
}
/* Wait stable */
__NOP();__NOP();__NOP();__NOP();
} else if (ADC_CHANNEL_SUSPEND == enable) {
/* pin config, return gpiox addr */
ret = pin_func(dev->dev.dev.dev_id , BIT(27) | channel);
/* disable current channel */
hw->ADKEY_CON &= ~ (0xF << 8);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
if (ret == RET_ERR) {
return RET_ERR;
}
} else if (ADC_CHANNEL_DISABLE == enable) {
/* pin config, return gpiox addr */
ret = pin_func(dev->dev.dev.dev_id , BIT(28) | channel);
/* disable current channel */
hw->ADKEY_CON &= ~ (0xF << 8);
if (ret == RET_ERR) {
return RET_ERR;
}
}
return RET_OK;
}
#endif
static int32 hgadc_v0_adc_channel_pll_vref(struct hgadc_v0 *dev, uint32 channel, uint32 enable) {
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
uint32 pmu_con5 = 0;
if (ADC_CHANNEL_ENABLE == enable) {
/* open pll_vref */
pmu_con5 = PMU->PMUCON5;
pmu_con5 = ( pmu_con5 &~ (0xF << 15) ) | (5 << 15);
pmu_reg_write((uint32)&PMU->PMUCON5, pmu_con5);
/* ATOUT EN */
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) ) | (0x8 << 8);
} else if (ADC_CHANNEL_SUSPEND == enable) {
/* close pll_vref */
pmu_con5 = PMU->PMUCON5;
pmu_con5 &= ~(0xF << 15);
pmu_reg_write((uint32)&PMU->PMUCON5, pmu_con5);
/* ATOUT DISABLE */
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) );
} else if (ADC_CHANNEL_DISABLE == enable) {
/* close pll_vref */
pmu_con5 = PMU->PMUCON5;
pmu_con5 &= ~(0xF << 15);
pmu_reg_write((uint32)&PMU->PMUCON5, pmu_con5);
/* ATOUT DISABLE */
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0xF << 8) );
}
return RET_OK;
}
#ifdef TXW81X
static int32 hgadc_v0_adc_channel_txw81x_rf_temperature(struct hgadc_v0 *dev, uint32 channel, uint32 enable) {
#define GPIOC(offset) (*((uint32 *)(0x40020C00+offset)))
#define IO_NUM (8)
struct hgadc_v0_hw *hw = (struct hgadc_v0_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) {
/* connect to rf_temperature channel */
*((uint32 *)(0x40019000 + 0x18)) = ( *((uint32 *)(0x40019000 + 0x18)) & ~(0xf<<27) ) | 0x8<<27;
//*((uint32 *)(0x40019000 + 0x1C)) |= 0x1;
#if 0
//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
/* RF_TOUT */
hw->ADKEY_CON = ( hw->ADKEY_CON &~ (0x7F << 4) ) | (0x1 << 10);
/* Wait stable */
for (i = 0; i < 20; i++) {
__NOP();
}
} else if (ADC_CHANNEL_SUSPEND == enable) {
/*!
* 关闭通路
*/
*((uint32 *)(0x40019000 + 0x18)) &= ~(0xf<<27);
hw->ADKEY_CON &= ~(0x7F << 4);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
} else if (ADC_CHANNEL_DISABLE == enable) {
/*!
* 关闭通路
*/
*((uint32 *)(0x40019000 + 0x18)) &= ~(0xf<<27);
hw->ADKEY_CON &= ~(0x7F << 4);
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
#endif
#ifdef TXW80X
static int32 hgadc_v0_adc_channel_txw80x_rf_temperature(struct hgadc_v0 *dev, uint32 channel, uint32 enable) {
struct hgadc_v0_hw *hw = (struct hgadc_v0_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) {
/* connect to rf_temperature channel */
*((uint32 *)(0x40019000 + 0x18)) = ( *((uint32 *)(0x40019000 + 0x18)) & ~(0xf<<27) ) | 0x8<<27;
//*((uint32 *)(0x40019000 + 0x1C)) |= 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) {
/*!
* 关闭通路
*/
*((uint32 *)(0x40019000 + 0x18)) &= ~(0xf<<27);
hw->ADKEY_CON &= ~(0xF << 8);
/* clear the data */
hw->ADKEY_DATA &= ~(0xFFF);
} else if (ADC_CHANNEL_DISABLE == enable) {
/*!
* 关闭通路
*/
*((uint32 *)(0x40019000 + 0x18)) &= ~(0xf<<27);
hw->ADKEY_CON &= ~(0xF << 8);
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
#endif
/*
* 将VDDI从PB8放出
*/
static void lo_dc_test(struct hgadc_v0 *dev)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
#define RFSYS_REG7 (*((uint32 *)0x4001901C))
#define RFSYS_REG6 (*((uint32 *)0x40019018))
#define GPIOB(offset) (*((uint32 *)(0x40020B00+offset)))
// uint32 vddi_trim_bit = 0;
// uint32 tmp1 = 0;
//
// uint32 trim_ok = 0;
// uint32 trim_cmd = 0;
//
// uint32 efuse_ts_dat = 0;
// uint32 efuse_vddi_dat = 0;
// float vddi_dec_dat = 0;
pmu_reg_write(PMU->PMUCON11, PMU->PMUCON11 | (BIT(9)|BIT(10)));
pmu_reg_write(PMU->PMUCON11, PMU->PMUCON11 | (BIT(14)));
//enable mac & rf
SYSCTRL->SYS_CON1 |= 1<<21;
SYSCTRL->SYS_CON3 |= 1<<3 | 1<<5;
//enable rf power
// RFDIGCAL->SOFT_RFIF_CON |= 0x1; //软件使能RF_EN
//ADCEN = 1; DAOUTEN = 1 & open interrupt
hw->ADKEY_CON |= (1 << 0) | (1 << 2);
//software kict
hw->ADKEY_CON &= ~(0xF << 15);
//clear the DATA, config baud
hw->ADKEY_DATA = ( hw->ADKEY_DATA &~ (0xFFFF << 16) ) | (0xB3 << 16);
GPIOB(0x0000) = (0x3 << (8)*2);
GPIOB(0x0074) = 0;
GPIOB(0x0078) = 0;
GPIOB(0x007C) = 0;
GPIOB(0x0080) = 0;
GPIOB(0x0010) = 0;
GPIOB(0x0014) = 0;
GPIOB(0x0008) = 0;
GPIOB(0x000C) = 0;
GPIOB(0x0050)&= ~(1<<8);
GPIOB(0x0068) = (1<<8);
RFSYS_REG7 |= 0x1;
hw->ADKEY_CON = (hw->ADKEY_CON &~ (0xF << 8)) | (5 << 8);
//PB8 output VDDI
//RF_TOUT to PB8
RFSYS_REG6 = (RFSYS_REG6 & ~(0xf<<27)) | 0x9<<27 | 0x1<<31; //select VDDI to PB8
}
struct _rf_pmu_dc_for_adc {
uint8 rf_vref : 4,
rf_lo_vref : 4;
uint8 rf_ibpt : 4,
rf_ibct : 4;
};
#define EFUSE_RF_PMU_SIZE_FOR_ADC 3
#define EFUSE_RF_PMU_OFFSET_FOR_ADC 52
static int32 rf_pmu_dc_efuse_read_for_adc(struct _rf_pmu_dc_for_adc *p_pmu)
{
uint8 efuse_buf[EFUSE_RF_PMU_SIZE_FOR_ADC];
sysctrl_efuse_config_and_read(EFUSE_RF_PMU_OFFSET_FOR_ADC, (void *)efuse_buf, EFUSE_RF_PMU_SIZE_FOR_ADC);
p_pmu->rf_lo_vref = efuse_buf[2] & 0x0F;
p_pmu->rf_ibpt = efuse_buf[1] & 0x0F;
p_pmu->rf_ibct = (efuse_buf[1]>>4) & 0x0F;
p_pmu->rf_vref = (efuse_buf[0]>>4) & 0x0F;
if(efuse_buf[0]) {
return RET_OK;
}
return RET_ERR;
}
///EFUSE RF相关的偏移
#define EFUSE_PACK_OFFSET_FOR_ADC 257
static inline uint8 get_chip_pack_for_adc(void)
{
uint8 pack = 0;
sysctrl_efuse_config_and_read(EFUSE_PACK_OFFSET_FOR_ADC, &pack, 1);
return pack;
}
static int32 hgadc_v0_adc_channel_rf_vddi_config(struct hgadc_v0 *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_v0_adc_channel_rf_vddi(struct hgadc_v0 *dev, uint32 channel, uint32 enable) {
#define RFSYS_REG7 (*((uint32 *)0x4001901C))
#define RFSYS_REG6 (*((uint32 *)0x40019018))
struct hgadc_v0_hw *hw = (struct hgadc_v0_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_v0_adc_channel_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;
}
static int32 hgadc_v0_adc_channel_rf_vtune(struct hgadc_v0 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_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_v0_adc_channel_rf_vco_vdd(struct hgadc_v0 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_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_v0_adc_channel_rf_vdd_div(struct hgadc_v0 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_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_v0_adc_channel_rf_vdd_pfd(struct hgadc_v0 *dev, uint32 channel, uint32 enable)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_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采样pfd电压*/
(*(uint32 *)(0x40019000)) = ((*(uint32 *)(0x40019000)) & ~(15<< 7)) | 0x0<<7 | 0x1<<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_v0_txw80x_raw_data_handle(struct hgadc_v0 *dev, uint32 channel, uint32 *adc_data) {
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
uint32 delay_cnt = 0, cnt = 0;
//volatile float data_temp1 = 0.0;
int32 data_temp = 0;
uint64 __time = 0;
/* Sample the pll_vref to verify the ADC data, beacause the VCC is shaking */
hgadc_v0_adc_channel_rf_vddi(dev, _ADC_CHANNEL_RF_VDDI, ADC_CHANNEL_ENABLE);
/* Close the interrupt */
hw->ADKEY_CON &= ~(1 << 20);
/* Read the div of adc clk to delay after sample done */
delay_cnt = (hw->ADKEY_DATA >> 16);
/* Clear the last "done" pending */
hw->ADKEY_DATA |= (1 << 12);
//kick start to sample
hw->ADKEY_CON |= (1 << 19);
__time = os_jiffies();
while(!(hw->ADKEY_CON & (0x1 <<31))) {
/* 100ms超时时间 */
if ((os_jiffies() - __time) > 100) {
/* 清除此时错误状态下的PENDING */
hw->ADKEY_DATA |= (1 << 12);
os_printf("*** adc module info: ADC sample err2 !!!!\r\n");
goto __adc_err;
}
}
hw->ADKEY_DATA |= (1 << 12);
/* Waitting for the ADC circuit ready for the next sample */
for (cnt = 0; cnt < delay_cnt; cnt++) {
__NOP();
}
data_temp = (hw->ADKEY_DATA & 0xFFF);
/* 防止采集VDDI值为0,导致下面除数为0,引发CPU异常中断 */
if (!data_temp) {
data_temp = dev->refer_vddi_adc_data;
}
//os_printf("1--->%d\r\n", data_temp);
//os_printf("2--->%d\r\n", *adc_data);
if (ADC_CHANNEL_RF_TEMPERATURE == channel) {
//os_printf("--Debug---->1 :%d\r\n", dev->refer_vddi);
//os_printf("--Debug---->2 :%d\r\n", (*adc_data << 17) / data_temp);
//os_printf("--Debug---->3 :%d\r\n", (dev->refer_tsensor << 17) / 4096);
data_temp = ( ( (*adc_data << 12) / data_temp ) - (dev->refer_tsensor) ) * dev->refer_vddi;
//os_printf("3--->%d\r\n", data_temp);
//os_printf("--Debug---->4 :%d\r\n", ((data_temp * 1000) / 4) >> 25);
data_temp = ((data_temp * 250 ) >> 20) + 25;
//data_temp1 = (hw->ADKEY_DATA & 0xFFF);
//data_temp1 *= 2;
//os_printf("Debug---->1 :%.3f\r\n", (float)dev->refer_vddi / (float)128);
//os_printf("Debug---->2 :%.3f\r\n", (float)(*adc_data) / data_temp1);
//os_printf("Debug---->3 :%.3f\r\n", (float)(dev->refer_tsensor / 2) / (float)4096);
//os_printf("vddi gears: %d\r\n", ((*((uint32 *)(0x40019000 + 0x1C))) & (0xF << 9) ) >> 9);
//data_temp1 = ( ( (float)(*adc_data) / data_temp1) - ( (float)(dev->refer_tsensor / 2) / (float)4096) ) * (float)((float)dev->refer_vddi / (float)128);
//os_printf("4--->%.3f\r\n", data_temp1);
//data_temp1 = ((data_temp1) / (float)(0.004)) + 25;
//os_printf("temp data: %d\r\n", data_temp);
//os_printf("temp1 data :%f\r\n", data_temp1);
*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 {
//data_temp = ( ( (*adc_data) * 1464 ) << 15) / data_temp;
//os_printf("1----> = %d\r\n", data_temp); //A'
//os_printf("2----> = %d\r\n", *adc_data); //B'
data_temp = ( ( (*adc_data) * dev->refer_vddi_adc_data) << 9) / data_temp;
//os_printf("3----> = %d\r\n", data_temp);
*adc_data = data_temp >> 9;
if (*adc_data >= 4095) {
*adc_data = 4095;
}
//os_printf("4----> = %d\r\n", *adc_data);
}
__adc_err:
hgadc_v0_adc_channel_rf_vddi(dev, _ADC_CHANNEL_RF_VDDI, ADC_CHANNEL_DISABLE);
/* Open the interrupt */
hw->ADKEY_CON |= (1 << 20);
return RET_OK;
}
void hgadc_v0_txw81x_raw_data_handle(struct hgadc_v0 *dev, uint32 channel, uint32 *adc_data)
{
#define RAW_DATA_DBG (0)
volatile int32 data_temp = 0;
if (ADC_CHANNEL_RF_TEMPERATURE == channel) {
/*!
* formula:
* { {2.7/4096} * 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 = *adc_data - (dev->refer_tsensor);
#if RAW_DATA_DBG
os_printf("tsensor diff-> = %d\r\n", data_temp);
#endif
//{(2.7*1024)*diff*1000}
data_temp = dev->refer_adda_vref * data_temp * 1000;
#if RAW_DATA_DBG
os_printf("tsensor 1----> = %d\r\n", data_temp);
#endif
// {(2.7*1024)*diff*1000} / {4096*4}
data_temp = data_temp >> 14;
#if RAW_DATA_DBG
os_printf("tsensor 2----> = %d\r\n", data_temp);
#endif
// {(2.7*1024)*diff*1000} / {4096*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 + 30;
#if RAW_DATA_DBG
os_printf("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) || (ADC_CHANNEL_VDD_PFD == 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 >= 4095) {
*adc_data = 4095;
}
}
}
void hgadc_v0_txw80x_open_data_handler(struct hgadc_v0 *dev)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
uint32 i = 0;
uint32 _refer_vddi = 0;
uint32 _refer_tsensor = 0;
uint32 _vddi_gears = 0;
uint32 _rfsys_reg7 = 0;
_vddi_gears = sysctrl_efuse_vddi_gears_get();
_refer_vddi = sysctrl_efuse_vddi_get();
_refer_tsensor = sysctrl_efuse_tsensor_get();
/* calibrate vddi to 1.18v by efuse vaule of vddi gears */
if (_vddi_gears) {
os_printf("*** ADC module info: vddi gears value = 0x%x\r\n", _vddi_gears);
_rfsys_reg7 = *((uint32 *)(0x40019000 + 0x1C));
_rfsys_reg7 = ( _rfsys_reg7 &~ (0xF << 9) ) | (_vddi_gears << 9);
*((uint32 *)(0x40019000 + 0x1C)) = _rfsys_reg7;
}
if (0 == _refer_vddi) {
os_printf("*** ADC module info: vddi don't calibrate!!, vddi will use default: 1.27v adc dat=1580.\r\n");
//(1+0.27)*256
dev->refer_vddi = (256 + 69);
dev->refer_vddi_adc_data = 1580;
} else {
//(1+vddi from efuse) * 256, \"vddi from efuse\" already multiply by 256
os_printf("*** ADC module info: ideal:1464, (1+.)*256, note: .*256\r\n");
os_printf("*** ADC module info: vddi calibrated value = 0x%x\r\n", _refer_vddi);
dev->refer_vddi = 256 + _refer_vddi;
dev->refer_vddi_adc_data = ( ( (dev->refer_vddi) * 10) / 33 ) * 4095;
dev->refer_vddi_adc_data = dev->refer_vddi_adc_data >> 8;
os_printf("*** ADC module info: vddi adc_data = %d(D)\r\n", dev->refer_vddi_adc_data);
}
if (0 == _refer_tsensor) {
//efuse: ( (vptat_adc_data/vddi_adc_data) / 2 ) * 4096
os_printf("*** ADC module info: ideal:2238+-, ( (vptat_adc_data/vddi_adc_data) / 2 ) * 4096\r\n");
os_printf("*** ADC module info: tsensor don't calibrate!!, tsensor will use default: 4012\r\n");
dev->refer_tsensor = 4012;
} else {
//efuse: ( (vptat_adc_data/vddi_adc_data) / 2 ) * 4096"
os_printf("*** ADC module info: ideal:2238+-, ( (vptat_adc_data/vddi_adc_data) / 2 ) * 4096\r\n");
os_printf("*** ADC module info: tsensor calibrated value = 0x%x\r\n", _refer_tsensor);
dev->refer_tsensor = _refer_tsensor * 2;
}
//ADCEN = 1; DAOUTEN = 1 & open interrupt
hw->ADKEY_CON |= (1 << 0) | (1 << 2) | BIT(20);
//software kict
hw->ADKEY_CON &= ~(0xF << 15);
//clear the DATA, config baud
hw->ADKEY_DATA = ( hw->ADKEY_DATA &~ (0xFFFF << 16) ) | (0xB3 << 16);
/* Wait for ADC init done */
for (i = 0; i < 200; i++) {
__NOP();
};
/* 硬件要求:开启就kick一下和重新开关一下,防止意外复位动作将ADC搞挂 */
hw->ADKEY_CON |= (1 << 19);
//等30个ADC时钟
for (i = 0; i < ((hw->ADKEY_DATA >> 16) * 30); i++) {
__NOP();
};
hw->ADKEY_CON &= ~ BIT(0);
hw->ADKEY_CON |= BIT(0);
/* Wait for ADC init done */
for (i = 0; i < 200; i++) {
__NOP();
};
}
void hgadc_v0_txw81x_open_data_handler(struct hgadc_v0 *dev)
{
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
uint32 i = 0;
uint32 div = 0;
dev->refer_adda_vref = ((2*1024) + sysctrl_efuse_adda_vref_get());
dev->refer_tsensor = sysctrl_efuse_tsensor_get();
//open power for ldo 2.7v
pmu_reg_write((uint32)&PMU->PMUCON11, PMU->PMUCON11 | (BIT(27)));
//ADCEN = 1; DAOUTEN = 1 & open interrupt
hw->ADKEY_CON |= (1 << 0) | (1 << 2) | BIT(20);
//reference choose LDO 2.7v
hw->ADKEY_CON |= BIT(23);
//open FILTER
//hw->ADKEY_CON |= BIT(25);
//software kict
hw->ADKEY_CON &= ~(0xF << 15);
//clear the DATA, config baud
div = (peripheral_clock_get(HG_APB1_PT_ADKEY)/ (1000000)) - 1;
if (div<2) {
div = 2;
}
os_printf("ADKEY baud:%d\r\n", div);
hw->ADKEY_DATA = ( hw->ADKEY_DATA &~ (0xFFFF << 16) ) | (div << 16);
hw->ADKEY_CON &= ~ BIT(0);
hw->ADKEY_CON |= BIT(0);
/* Wait for ADC init done */
for (i = 0; i < 200; i++) {
__NOP();
};
}
/**********************************************************************************/
/* ATTCH FUNCTION */
/**********************************************************************************/
static int32 hgadc_v0_open(struct adc_device *adc) {
struct hgadc_v0 *dev = (struct hgadc_v0 *)adc;
uint32 mask = 0;
mask = disable_irq();
if (dev->opened) {
/* Enable interrupt */
enable_irq(mask);
return -EBUSY;
}
#if TXW80X
hgadc_v0_txw80x_open_data_handler(dev);
#endif
#if TXW81X
hgadc_v0_txw81x_open_data_handler(dev);
#endif
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;
os_printf("*** open ADC success!\n\r");
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v0_close(struct adc_device *adc) {
uint32 mask = 0;
struct hgadc_v0 *dev = (struct hgadc_v0 *)adc;
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
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_v0_list_get_channel_amount(&dev->head_node)) {
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
hgadc_v0_list_delete_all(&dev->head_node, dev);
/* Enable interrupt */
enable_irq(mask);
irq_disable(dev->irq_num);
dev->head_node.channel_amount = 0;
dev->head_node.next = NULL;
dev->head_node.data.channel = -1;
dev->head_node.data.func = NULL;
hw->ADKEY_CON = 0;
hw->ADKEY_DATA = 0;
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_v0_add_channel(struct adc_device *adc, uint32 channel) {
int32 _class = 0;
uint32 mask = 0;
struct hgadc_v0 *dev = (struct hgadc_v0 *)adc;
adc_channel_node *new_node = NULL;
if (!dev->opened) {
return RET_ERR;
}
/* ADKEY1 P channel cant't support current adc sample channel, limited by hardware */
if ((ADKEY1_BASE == dev->hw) && (PA_15 < channel) && (channel < 0x100)) {
os_printf("*** ADC module info: ADKEY1 can't support the %d channel!!!\r\n", channel);
return RET_ERR;
}
/* Close the interrupt to protect the list opreation */
mask = disable_irq();
/* Check for the channel which repeated */
if (RET_ERR == hgadc_v0_list_check_repetition(&dev->head_node, channel)) {
os_printf("*** ADC module info: ADC channel repeat!!!\n\r");
enable_irq(mask);
return RET_OK;
}
_class = hgadc_v0_switch_param_channel(channel);
if (RET_ERR == _class) {
enable_irq(mask);
return RET_ERR;
}
/* save the adkey configuration by channel */
switch (_class) {
case _ADC_CHANNEL_IO_CLASS:
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
#ifdef TXW80X
new_node->data.func = hgadc_v0_adc_channel_txw80x_io_class;
#endif
#ifdef TXW81X
new_node->data.func = hgadc_v0_adc_channel_txw81x_io_class;
#endif
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_TEMPERATURE:
new_node = (adc_channel_node *)os_malloc(sizeof(adc_channel_node));
if (!new_node) {
enable_irq(mask);
return RET_ERR;
}
#ifdef TXW80X
new_node->data.func = hgadc_v0_adc_channel_txw80x_rf_temperature;
#endif
#ifdef TXW81X
new_node->data.func = hgadc_v0_adc_channel_txw81x_rf_temperature;
#endif
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VTUNE:
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_v0_adc_channel_rf_vtune;
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VCO_VDD:
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_v0_adc_channel_rf_vco_vdd;
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VDD_DIV:
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_v0_adc_channel_rf_vdd_div;
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VDDI:
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_v0_adc_channel_rf_vddi;
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
case _ADC_CHANNEL_RF_VDD_PFD:
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_v0_adc_channel_rf_vdd_pfd;
new_node->data.channel = channel;
new_node->next = NULL;
hgadc_v0_list_insert(&dev->head_node, new_node);
break;
}
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v0_delete_channel(struct adc_device *adc, uint32 channel) {
uint32 mask = 0;
adc_channel_node *get_node = NULL;
struct hgadc_v0 *dev = (struct hgadc_v0 *)adc;
if (!dev->opened) {
return RET_ERR;
}
/* Close the interrupt to protect the list opreation */
mask = disable_irq();
if (RET_ERR == hgadc_v0_list_get_by_channel(&dev->head_node, channel, &get_node)) {
os_printf("*** ADC module info: Delete func: No this ADC channel!!!\n\r");
enable_irq(mask);
return RET_ERR;
}
get_node->data.func(dev, channel, ADC_CHANNEL_DISABLE);
hgadc_v0_list_delete(&dev->head_node, channel);
/* Enable interrupt */
enable_irq(mask);
return RET_OK;
}
static int32 hgadc_v0_get_value(struct adc_device *adc, uint32 channel, uint32 *raw_data) {
struct hgadc_v0 *dev = (struct hgadc_v0 *)adc;
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
adc_channel_node *get_node = NULL;
uint32 mask = 0;
uint32 delay_cnt = 0, cnt = 0;
if (!dev->opened) {
return RET_ERR;
}
os_mutex_lock(&dev->adc_lock, osWaitForever);
if (RET_ERR == hgadc_v0_list_get_by_channel(&dev->head_node, channel, &get_node)) {
os_printf("*** ADC module info: get_value func: No this ADC channel!!!\n\r");
os_mutex_unlock(&dev->adc_lock);
return RET_ERR;
}
/* Read the div of adc clk to delay after sample done */
delay_cnt = (hw->ADKEY_DATA >> 16);
/* 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();
/* Clear the last "done" pending */
LL_ADKEY_CLEAR_DONE_PENDING(hw);
//kick start to sample
LL_ADKEY_SOTF_KICK(hw);
/* Waitting for the ADC circuit ready for the next sample */
for (cnt = 0; cnt < (delay_cnt + 300); cnt++) {
__NOP();
}
enable_irq(mask);
/* 超时5s */
if (os_sema_down(&dev->adc_done, 5000) <= 0){
/* Clear the last "done" pending */
LL_ADKEY_CLEAR_DONE_PENDING(hw);
os_printf("*** adc module info: ADC sample err1 !!!!");
}
//os_printf("*** down!!\n\r");
*raw_data = LL_ADKEY_GET_DATA(hw);
//os_printf("** %d channel raw_data: %d\n\r", get_node->data.channel, *raw_data);
get_node->data.func(dev, channel, ADC_CHANNEL_SUSPEND);
#if TXW80X
hgadc_v0_txw80x_raw_data_handle(dev, channel, raw_data);
#endif
#if TXW81X
hgadc_v0_txw81x_raw_data_handle(dev, channel, raw_data);
#endif
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_v0_ioctl(struct adc_device *adc, enum adc_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) {
return RET_OK;
}
static void hgadc_v0_irq_handler(void *data) {
struct hgadc_v0 *dev = (struct hgadc_v0 *)data;
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)dev->hw;
//os_printf("*** interrupt!!\n\r");
if ((LL_ADKEY_GET_IRQ_EN_SAMPLE_DONE(hw)) && (LL_ADKEY_GET_IRQ_EN_SAMPLE_DONE(hw))) {
LL_ADKEY_CLEAR_DONE_PENDING(hw);
os_sema_up(&dev->adc_done);
//os_printf("*** up!!\n\r");
}
}
static int32 hgadc_v0_request_irq(struct adc_device *adc, enum adc_irq_flag irq_flag, adc_irq_hdl irq_hdl, uint32 irq_data) {
struct hgadc_v0 *dev = (struct hgadc_v0 *)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_v0_release_irq(struct adc_device *adc, enum adc_irq_flag irq_flag) {
struct hgadc_v0 *dev = (struct hgadc_v0 *)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_v0_open,
.close = hgadc_v0_close,
.add_channel = hgadc_v0_add_channel,
.delete_channel = hgadc_v0_delete_channel,
.get_value = hgadc_v0_get_value,
.ioctl = hgadc_v0_ioctl,
.request_irq = hgadc_v0_request_irq,
.release_irq = hgadc_v0_release_irq,
};
int32 hgadc_v0_attach(uint32 dev_id, struct hgadc_v0 *adc) {
struct hgadc_v0_hw *hw = (struct hgadc_v0_hw *)adc->hw;
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->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_v0_irq_handler, adc);
hw->ADKEY_CON |= BIT(20);
irq_enable(adc->irq_num);
dev_register(dev_id, (struct dev_obj *)adc);
return RET_OK;
}