1825 lines
49 KiB
C
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;
|
|
}
|